$ cmake ../../source/devel
-- The CXX compiler identification is GNU 7.1.1
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/chuckatkins/Code/nljson/build/devel
$ make
Scanning dependencies of target catch_main
[ 2%] Building CXX object test/CMakeFiles/catch_main.dir/src/unit.cpp.o
[ 2%] Built target catch_main
Scanning dependencies of target json_unit
[ 5%] Building CXX object test/CMakeFiles/json_unit.dir/src/unit-algorithms.cpp.o
In file included from /usr/include/c++/7/cassert:44:0,
from /home/chuckatkins/Code/nljson/source/devel/src/json.hpp:34,
from /home/chuckatkins/Code/nljson/source/devel/test/src/unit-algorithms.cpp:31:
/home/chuckatkins/Code/nljson/source/devel/src/json.hpp: In constructor ‘nlohmann::detail::input_adapter::input_adapter(IteratorType, IteratorType)’:
/home/chuckatkins/Code/nljson/source/devel/src/json.hpp:1500:20: error: lambda-expression in unevaluated context
[&first](std::pair<bool, int> res, decltype(*first) val)
^
make[2]: *** [test/CMakeFiles/json_unit.dir/build.make:63: test/CMakeFiles/json_unit.dir/src/unit-algorithms.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:88: test/CMakeFiles/json_unit.dir/all] Error 2
make: *** [Makefile:141: all] Error 2
It's odd I never experienced this error. What kind of compiler flags or Cmake options are you using?
Nothing special. I do tend to use a bleeding edge development build of CMake but that's it. No CFLAGS, or CXX flags, etc. This is a current Fedora 26 machine with my own CMake built from cmake/master and the system gcc 7.1.1. As you can see from the verbose output, no special flags are being passed.
$ cmake --version
cmake version 3.9.20170822-g8a0ed
...
$ echo $CFLAGS $CXXFLAGS
$ cmake ../../source/devel
-- The CXX compiler identification is GNU 7.1.1
-- Check for working CXX compiler: /usr/bin/c++
-- Check for working CXX compiler: /usr/bin/c++ -- works
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/chuckatkins/Code/nljson/build/devel
$ make VERBOSE=1
...
[ 5%] Building CXX object test/CMakeFiles/json_unit.dir/src/unit-algorithms.cpp.o
cd /home/chuckatkins/Code/nljson/build/devel/test && /usr/bin/c++ -I/home/chuckatkins/Code/nljson/source/devel/src -I/home/chuckatkins/Code/nljson/source/devel/test/src -I/home/chuckatkins/Code/nljson/source/devel/test/thirdparty/catch -std=gnu++11 -o CMakeFiles/json_unit.dir/src/unit-algorithms.cpp.o -c /home/chuckatkins/Code/nljson/source/devel/test/src/unit-algorithms.cpp
In file included from /usr/include/c++/7/cassert:44:0,
from /home/chuckatkins/Code/nljson/source/devel/src/json.hpp:34,
from /home/chuckatkins/Code/nljson/source/devel/test/src/unit-algorithms.cpp:31:
/home/chuckatkins/Code/nljson/source/devel/src/json.hpp: In constructor ‘nlohmann::detail::input_adapter::input_adapter(IteratorType, IteratorType)’:
/home/chuckatkins/Code/nljson/source/devel/src/json.hpp:1500:20: error: lambda-expression in unevaluated context
[&first](std::pair<bool, int> res, decltype(*first) val)
^
make[2]: *** [test/CMakeFiles/json_unit.dir/build.make:63: test/CMakeFiles/json_unit.dir/src/unit-algorithms.cpp.o] Error 1
make[2]: Leaving directory '/home/chuckatkins/Code/nljson/build/devel'
make[1]: *** [CMakeFiles/Makefile2:88: test/CMakeFiles/json_unit.dir/all] Error 2
make[1]: Leaving directory '/home/chuckatkins/Code/nljson/build/devel'
make: *** [Makefile:141: all] Error 2
$
FWIW, I believe it's likely an issue with compiler sensitivity since I didn't get this with gcc6 when I was running Fedora 24. I can reproduce this with a dummy example by putting a lamda inside an assert and evaluating it:
// foo.cxx
#include <cassert>
int main(int argc, char **argv)
{
assert([](int x) { return x == 0; }(argc));
return 0;
}
$ c++ -o foo -DDEBUG foo.cxx
In file included from /usr/include/c++/7/cassert:44:0,
from foo.cxx:1:
foo.cxx: In function ‘int main(int, char**)’:
foo.cxx:5:10: error: lambda-expression in unevaluated context
assert([](int x) { return x == 0; }(argc));
^
$
Isn't that a bug of GCC? I don't object to the fix, but it'd be great to report it if it's indeed a bug.
I thought so too at first but it's not. It has to do with how assert( foo ) is implemented and expanded by the preprocessor. The result of the preprocessor expansion of assert(foo) for a failing build is, amongst other things, an expression with sizeof( foo ) and per the C++ standard, the operand to sizeof( ... ) is an _unevaluated expression_. In turn, also per the C++ standard, lambda expressions are not allowed to appear in unevaluated expressions. After digging through the preprocessor output, I've been able to reproduce the error without the assert:
int main(int argc, char **argv)
{
(void) sizeof( [] { return true; } () );
return 0;
}
Which, indeed, is invalid because of the lambda expression being in the unevaluated operand of sizeof. The bug is not actually a gcc/g++ one but a glibc issue in that the implementation of assert() (I just figured this out btw) in assert.h which is incompatible with c++ lambda expressions. I tracked down the issue to a recent glibc commit which introduced the error by changing the assert implementation to use sizeofin order to squelch some pedantic warnings and another about two weeks later that subsequenty fixed it by not using sizeof for the implemention of assert when using C++. Unfortunately the first patch seems to have propagated to many distro's glibc releases while the later has not. So, I guess it's up to you as to whether or not to take #706 which I now realize is really a workaround for a glibc bug in Fedora 26, which is already patched upstream.
Wow, congrats for the impressive digging!
Personally, I would not add a workaround to an already patched issue, but that is up to @nlohmann.
Anyway, thanks a lot for your thorough research :)
Thanks a lot for the research. I think merging the PR makes little sense here. If anyone encounters the same combination of problems, I think Google will send her/him here. :)
And I also was bitten by this bug as well :)
Has this been fixed? I'm unfortunately not on bleeding edge (xtensa gcc 5.2.0), and this error popped up on line 2165 in single_header/nlohmann/json.hpp. Would like to use this library as it looks really good, but can't currently due to this and I'd like to avoid forking it.
Most helpful comment
I thought so too at first but it's not. It has to do with how
assert( foo )is implemented and expanded by the preprocessor. The result of the preprocessor expansion ofassert(foo)for a failing build is, amongst other things, an expression withsizeof( foo )and per the C++ standard, the operand tosizeof( ... )is an _unevaluated expression_. In turn, also per the C++ standard, lambda expressions are not allowed to appear in unevaluated expressions. After digging through the preprocessor output, I've been able to reproduce the error without the assert:Which, indeed, is invalid because of the lambda expression being in the unevaluated operand of
sizeof. The bug is not actually a gcc/g++ one but a glibc issue in that the implementation ofassert()(I just figured this out btw) in assert.h which is incompatible with c++ lambda expressions. I tracked down the issue to a recent glibc commit which introduced the error by changing theassertimplementation to usesizeofin order to squelch some pedantic warnings and another about two weeks later that subsequenty fixed it by not usingsizeoffor the implemention ofassertwhen using C++. Unfortunately the first patch seems to have propagated to many distro's glibc releases while the later has not. So, I guess it's up to you as to whether or not to take #706 which I now realize is really a workaround for a glibc bug in Fedora 26, which is already patched upstream.