Thalhammer / jwt-cpp

A header only library for creating and validating json web tokens in c++
https://thalhammer.github.io/jwt-cpp/
MIT License
899 stars 242 forks source link

C++ 4.8.5 build failed #118

Closed laoshanxi closed 3 years ago

laoshanxi commented 3 years ago

When I tried to build on centos 7 with gcc-c++ 4.8.5, it failed with below message:

bash-4.2# g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-redhat-linux/4.8.5/lto-wrapper
Target: x86_64-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --disable-libgcj --with-isl=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/isl-install --with-cloog=/builddir/build/BUILD/gcc-4.8.5-20150702/obj-x86_64-redhat-linux/cloog-install --enable-gnu-indirect-function --with-tune=generic --with-arch_32=x86-64 --build=x86_64-redhat-linux
Thread model: posix
gcc version 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) 
[ 34%] Building CXX object src/cli/CMakeFiles/appc.dir/ArgumentParser.cpp.o
In file included from /root/code/app-mesh/src/cli/ArgumentParser.cpp:22:0:
/root/code/app-mesh/src/cli/../common/jwt-cpp/jwt.h: In instantiation of 'class jwt::basic_claim<jwt::picojson_traits>':
/usr/include/c++/4.8.2/bits/stl_pair.h:102:11:   required from 'struct std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> >'
/usr/include/c++/4.8.2/type_traits:615:28:   required from 'struct std::__is_destructible_impl<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > >'
/usr/include/c++/4.8.2/type_traits:637:12:   required from 'struct std::__is_destructible_safe<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> >, false, false>'
/usr/include/c++/4.8.2/type_traits:652:12:   required from 'struct std::is_destructible<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > >'
/usr/include/c++/4.8.2/type_traits:116:12:   required from 'struct std::__and_<std::is_destructible<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, jwt::basic_claim<jwt::picojson_traits> > >, std::__is_direct_constructible_impl<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, jwt::basic_claim<jwt::picojson_traits> >, const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, jwt::basic_claim<jwt::picojson_traits> >&> >'
/usr/include/c++/4.8.2/type_traits:817:12:   [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/4.8.2/type_traits:974:12:   required from 'struct std::is_copy_constructible<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > >'
/usr/include/c++/4.8.2/bits/alloc_traits.h:540:12:   required from 'struct std::__is_copy_insertable<std::allocator<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > > >'
/usr/include/c++/4.8.2/bits/alloc_traits.h:560:63:   required by substitution of 'template<class _Alloc> using __check_copy_constructible = std::__allow_copy_cons<std::__is_copy_insertable<_Alloc>::value> [with _Alloc = std::allocator<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > >]'
/usr/include/c++/4.8.2/bits/unordered_map.h:97:11:   required from 'class std::unordered_map<std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits>, std::hash<std::basic_string<char> >, std::equal_to<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > > >'
/root/code/app-mesh/src/cli/../common/jwt-cpp/jwt.h:2453:72:   required from 'class jwt::verifier<jwt::default_clock, jwt::picojson_traits>'
/root/code/app-mesh/src/cli/../common/jwt-cpp/jwt.h:2809:50:   required from here
/root/code/app-mesh/src/cli/../common/jwt-cpp/jwt.h:1779:4: error: function 'jwt::basic_claim<json_traits>::basic_claim(jwt::basic_claim<json_traits>&&) [with json_traits = jwt::picojson_traits]' defaulted on its first declaration with an exception-specification that differs from the implicit declaration 'jwt::basic_claim<jwt::picojson_traits>::basic_claim(jwt::basic_claim<jwt::picojson_traits>&&)'
    basic_claim(basic_claim&&) noexcept = default;
    ^
/root/code/app-mesh/src/cli/../common/jwt-cpp/jwt.h:1781:17: error: function 'jwt::basic_claim<json_traits>& jwt::basic_claim<json_traits>::operator=(jwt::basic_claim<json_traits>&&) [with json_traits = jwt::picojson_traits]' defaulted on its first declaration with an exception-specification that differs from the implicit declaration 'jwt::basic_claim<jwt::picojson_traits>& jwt::basic_claim<jwt::picojson_traits>::operator=(jwt::basic_claim<jwt::picojson_traits>&&)'
    basic_claim& operator=(basic_claim&&) noexcept = default;
                 ^
make[2]: *** [src/cli/CMakeFiles/appc.dir/ArgumentParser.cpp.o] Error 1
prince-chrismc commented 3 years ago

Your compiler is 4.8.5 but your stdlibc++ is 4.8.2 which is a little odd.

I can not repro the problem on either of those version of GCC: https://godbolt.org/z/o1sq8T

You might what to make sure these macros are being set correctly.

https://github.com/Thalhammer/jwt-cpp/blob/c83767e8c60db941d6166ce048ce0ea07e21f6b5/include/picojson/picojson.h#L61-L74

prince-chrismc commented 3 years ago

It might be a GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59526 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53901

laoshanxi commented 3 years ago

Centos7 g++ include dir are same for 4.8.2 & 4.8.5:

root@ubuntu-OptiPlex-7070:~# docker run -ti --rm centos:7 bash
[root@aec29af06db4 /]# yum install g++ -y
......
Installed:
  gcc-c++.x86_64 0:4.8.5-44.el7                                                                                                                                                                                                            

Dependency Installed:
  cpp.x86_64 0:4.8.5-44.el7      gcc.x86_64 0:4.8.5-44.el7                glibc-devel.x86_64 0:2.17-317.el7    glibc-headers.x86_64 0:2.17-317.el7    kernel-headers.x86_64 0:3.10.0-1160.11.1.el7    libgomp.x86_64 0:4.8.5-44.el7   
  libmpc.x86_64 0:1.0.1-3.el7    libstdc++-devel.x86_64 0:4.8.5-44.el7    mpfr.x86_64 0:3.1.1-4.el7           

Dependency Updated:
  glibc.x86_64 0:2.17-317.el7                            glibc-common.x86_64 0:2.17-317.el7                            libgcc.x86_64 0:4.8.5-44.el7                            libstdc++.x86_64 0:4.8.5-44.el7                           

Complete!
[root@aec29af06db4 /]# ls -al /usr/include/c++/
total 12
drwxr-xr-x  3 root root 4096 Jan  4 00:31 .
drwxr-xr-x  1 root root 4096 Jan  4 00:31 ..
drwxr-xr-x 12 root root 4096 Jan  4 00:31 4.8.2
lrwxrwxrwx  1 root root    5 Jan  4 00:31 4.8.5 -> 4.8.2

Does this micro PICOJSON_USE_RVALUE_REFERENCE need set explicit?

laoshanxi commented 3 years ago

Tried the hello word sample:

#include <jwt-cpp/jwt.h>
#include <iostream>
int main(int argc, const char** argv) {
    std::string token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXUyJ9.eyJpc3MiOiJhdXRoMCJ9.AbIJTDMFc7yUa5MhvcP03nJPyCPzZtQcGEp-zWfOkEE";
    auto decoded = jwt::decode(token);
    for(auto& e : decoded.get_payload_claims())
        std::cout << e.first << " = " << e.second.to_json() << std::endl;
}

Tried on a clean centos 7 docker container, the issue still exist:

$docker run -ti -v `pwd`:`pwd` --rm centos:7 bash
$yum install gcc-c++ openssl-devel -y
[root@7e64b43c368a test]# g++ --std=c++11 -I. ./jwt.cpp 
In file included from ./jwt.cpp:1:0:
./jwt-cpp/jwt.h: In instantiation of 'class jwt::basic_claim<jwt::picojson_traits>':
/usr/include/c++/4.8.2/bits/stl_pair.h:102:11:   required from 'struct std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> >'
/usr/include/c++/4.8.2/type_traits:615:28:   required from 'struct std::__is_destructible_impl<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > >'
/usr/include/c++/4.8.2/type_traits:637:12:   required from 'struct std::__is_destructible_safe<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> >, false, false>'
/usr/include/c++/4.8.2/type_traits:652:12:   required from 'struct std::is_destructible<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > >'
/usr/include/c++/4.8.2/type_traits:116:12:   required from 'struct std::__and_<std::is_destructible<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, jwt::basic_claim<jwt::picojson_traits> > >, std::__is_direct_constructible_impl<std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, jwt::basic_claim<jwt::picojson_traits> >, const std::pair<const std::basic_string<char, std::char_traits<char>, std::allocator<char> >, jwt::basic_claim<jwt::picojson_traits> >&> >'
/usr/include/c++/4.8.2/type_traits:817:12:   [ skipping 6 instantiation contexts, use -ftemplate-backtrace-limit=0 to disable ]
/usr/include/c++/4.8.2/type_traits:974:12:   required from 'struct std::is_copy_constructible<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > >'
/usr/include/c++/4.8.2/bits/alloc_traits.h:540:12:   required from 'struct std::__is_copy_insertable<std::allocator<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > > >'
/usr/include/c++/4.8.2/bits/alloc_traits.h:560:63:   required by substitution of 'template<class _Alloc> using __check_copy_constructible = std::__allow_copy_cons<std::__is_copy_insertable<_Alloc>::value> [with _Alloc = std::allocator<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > >]'
/usr/include/c++/4.8.2/bits/unordered_map.h:97:11:   required from 'class std::unordered_map<std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits>, std::hash<std::basic_string<char> >, std::equal_to<std::basic_string<char> >, std::allocator<std::pair<const std::basic_string<char>, jwt::basic_claim<jwt::picojson_traits> > > >'
./jwt-cpp/jwt.h:2453:72:   required from 'class jwt::verifier<jwt::default_clock, jwt::picojson_traits>'
./jwt-cpp/jwt.h:2809:50:   required from here
./jwt-cpp/jwt.h:1779:4: error: function 'jwt::basic_claim<json_traits>::basic_claim(jwt::basic_claim<json_traits>&&) [with json_traits = jwt::picojson_traits]' defaulted on its first declaration with an exception-specification that differs from the implicit declaration 'jwt::basic_claim<jwt::picojson_traits>::basic_claim(jwt::basic_claim<jwt::picojson_traits>&&)'
    basic_claim(basic_claim&&) noexcept = default;
    ^
./jwt-cpp/jwt.h:1781:17: error: function 'jwt::basic_claim<json_traits>& jwt::basic_claim<json_traits>::operator=(jwt::basic_claim<json_traits>&&) [with json_traits = jwt::picojson_traits]' defaulted on its first declaration with an exception-specification that differs from the implicit declaration 'jwt::basic_claim<jwt::picojson_traits>& jwt::basic_claim<jwt::picojson_traits>::operator=(jwt::basic_claim<jwt::picojson_traits>&&)'
    basic_claim& operator=(basic_claim&&) noexcept = default;
laoshanxi commented 3 years ago

Tried centos 8 with gcc-c++-8.3.1 works fine.

prince-chrismc commented 3 years ago

Trying to repro, https://hub.docker.com/r/bincrafters/docker-centos-gcc48 I see the same issue.

But it's fixed in GCC 5 https://hub.docker.com/r/bincrafters/gcc5

prince-chrismc commented 3 years ago

Doing more research...

This was a GCC-4 bug which required an ABI break hence why It's not in a later version.

The ISO has the following...

If a virtual function is non-throwing, all declarations, including the definition, of every overrider must be non-throwing as well, unless the overrider is defined as deleted:

struct B {
virtual void f() noexcept;
virtual void g();
virtual void h() noexcept = delete;
};
struct D: B {
void f();              // ill-formed: D::f is potentially-throwing, B::f is non-throwing
void g() noexcept;     // OK
void h() = delete;     // OK
};

... which in GCC-4 had misappropriated onto member types as well.


All that being said,

potentially-throwing functions are functions declared without noexcept specifier except for default constructors, copy constructors, move constructors that are implicitly-declared or defaulted on their first declaration unless

So the noexcept specifier here is just extra

I'll open a PR and merge a fix sortly