Skip to content

Corrade with BUILD_TESTS=ON compilation error: call to non-‘constexpr’ function #136

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
cmey opened this issue May 26, 2022 · 5 comments

Comments

@cmey
Copy link

cmey commented May 26, 2022

Hi!

cmake -DBUILD_TESTS=ON ../
cmake --build .

fails with:

/home/cmey/Code/cpp/wonderland_repos/corrade/src/Corrade/Utility/Assert.h:242:6: error: call to non-‘constexpr’ function ‘Corrade::Utility::Test::{anonymous}::divide(int, int)::<lambda()>’
  239 |     static_cast<void>((condition) ? 0 : ([&]() {                            \
      |                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  240 |         Corrade::Utility::Error{Corrade::Utility::Error::defaultOutput()} << message; \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  241 |         std::abort();                                                       \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  242 |     }(), 0))
      |     ~^~

/home/cmey/Code/cpp/wonderland_repos/corrade/src/Corrade/Utility/Assert.h:239:42: note: ‘Corrade::Utility::Test::{anonymous}::divide(int, int)::<lambda()>’ is not usable as a ‘constexpr’ function because:
  239 |     static_cast<void>((condition) ? 0 : ([&]() {                            \

/home/cmey/Code/cpp/wonderland_repos/corrade/src/Corrade/Utility/Assert.h:239:42: note: lambdas are implicitly ‘constexpr’ only in C++17 and later
  239 |     static_cast<void>((condition) ? 0 : ([&]() {                            \

This is with g++ version: g++ (Ubuntu 11.2.0-19ubuntu1) 11.2.0
on Corrade branch master git # ba75f71, no local change.

Note: the build finishes correctly without BUILD_TESTS=ON.

@cmey
Copy link
Author

cmey commented May 26, 2022

And with clang++:

Ubuntu clang version 14.0.0-1ubuntu1
Target: x86_64-pc-linux-gnu
Thread model: posix

another constexpr-related error:

[ 63%] Building CXX object src/Corrade/Utility/Test/CMakeFiles/UtilityDebugAssertDisabledTest.dir/AssertDisabledTest.cpp.o
/home/cmey/Code/cpp/wonderland_repos/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:136:23: error: constexpr variable 'three' must be initialized by a constant expression
        constexpr int three = divide(15, 0);
                      ^       ~~~~~~~~~~~~~
/home/cmey/Code/cpp/wonderland_repos/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:123:12: note: non-literal type '(lambda at /home/cmey/Code/cpp/wonderland_repos/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:123:12)' cannot be used in a constant expression
    return TESTED_CONSTEXPR_ASSERT(b, "b can't be zero"), a/(b + 5);

@mosra
Copy link
Owner

mosra commented May 26, 2022

Heh... unpossible. This has worked for ages on all compilers back to Clang 3.8, GCC 4.8 and MSVC 2015.

Both the GCC and the Clang error is about the same thing, a lambda that gets called if an expression fails. Which is a valid technique explained in this post from 2017. I don't know where the GCC error originates from, but I suspect it would be from AssertDisabledTest.cpp as well, since that's where this macro is mainly tested?

Like with #135, I have a suspicion there's something seriously broken with the toolchain you use 😅

@cmey
Copy link
Author

cmey commented May 26, 2022

The compilation error is reproducible in a clean Docker environment (docker run -it ubuntu:22.04) using clang-11, clang-12, clang-13, clang-14, and gcc-11 (haven't tried more) and also reproducible in archlinux docker image (docker run -it archlinux) using gcc:

[root@0e7cc222fbdc build]# cmake -DBUILD_TESTS=ON ../
-- The CXX compiler identification is GNU 12.1.0

[root@0e7cc222fbdc build]# cmake --build . --parallel
In file included from /tmp/corrade/src/Corrade/Containers/Pointer.h:37,
                 from /tmp/corrade/src/Corrade/TestSuite/Tester.h:35,
                 from /tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:35:
/tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp: In member function ‘void Corrade::Utility::Test::{anonymous}::AssertDisabledTest::constexprTest()’:
/tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:136:37:   in ‘constexpr’ expansion of ‘Corrade::Utility::Test::{anonymous}::divide(15, 0)’
/tmp/corrade/src/Corrade/Utility/Assert.h:242:6: error: call to non-‘constexpr’ function ‘Corrade::Utility::Test::{anonymous}::divide(int, int)::<lambda()>’
  239 |     static_cast<void>((condition) ? 0 : ([&]() {                            \
      |                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  240 |         Corrade::Utility::Error{Corrade::Utility::Error::defaultOutput()} << message; \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  241 |         std::abort();                                                       \
      |         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  242 |     }(), 0))
      |     ~^~
/tmp/corrade/src/Corrade/Utility/DebugAssert.h:86:5: note: in expansion of macro ‘CORRADE_CONSTEXPR_ASSERT’
   86 |     CORRADE_CONSTEXPR_ASSERT(condition, message)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~
/tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:41:33: note: in expansion of macro ‘CORRADE_CONSTEXPR_DEBUG_ASSERT’
   41 | #define TESTED_CONSTEXPR_ASSERT CORRADE_CONSTEXPR_DEBUG_ASSERT
      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:123:12: note: in expansion of macro ‘TESTED_CONSTEXPR_ASSERT’
  123 |     return TESTED_CONSTEXPR_ASSERT(b, "b can't be zero"), a/(b + 5);
      |            ^~~~~~~~~~~~~~~~~~~~~~~
/tmp/corrade/src/Corrade/Utility/Assert.h:239:42: note: ‘Corrade::Utility::Test::{anonymous}::divide(int, int)::<lambda()>’ is not usable as a ‘constexpr’ function because:
  239 |     static_cast<void>((condition) ? 0 : ([&]() {                            \
      |                                          ^
/tmp/corrade/src/Corrade/Utility/DebugAssert.h:86:5: note: in expansion of macro ‘CORRADE_CONSTEXPR_ASSERT’
   86 |     CORRADE_CONSTEXPR_ASSERT(condition, message)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~
/tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:41:33: note: in expansion of macro ‘CORRADE_CONSTEXPR_DEBUG_ASSERT’
   41 | #define TESTED_CONSTEXPR_ASSERT CORRADE_CONSTEXPR_DEBUG_ASSERT
      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:123:12: note: in expansion of macro ‘TESTED_CONSTEXPR_ASSERT’
  123 |     return TESTED_CONSTEXPR_ASSERT(b, "b can't be zero"), a/(b + 5);
      |            ^~~~~~~~~~~~~~~~~~~~~~~
/tmp/corrade/src/Corrade/Utility/Assert.h:239:42: note: lambdas are implicitly ‘constexpr’ only in C++17 and later
  239 |     static_cast<void>((condition) ? 0 : ([&]() {                            \
      |                                          ^
/tmp/corrade/src/Corrade/Utility/DebugAssert.h:86:5: note: in expansion of macro ‘CORRADE_CONSTEXPR_ASSERT’
   86 |     CORRADE_CONSTEXPR_ASSERT(condition, message)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~
/tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:41:33: note: in expansion of macro ‘CORRADE_CONSTEXPR_DEBUG_ASSERT’
   41 | #define TESTED_CONSTEXPR_ASSERT CORRADE_CONSTEXPR_DEBUG_ASSERT
      |                                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/tmp/corrade/src/Corrade/Utility/Test/AssertDisabledTest.cpp:123:12: note: in expansion of macro ‘TESTED_CONSTEXPR_ASSERT’
  123 |     return TESTED_CONSTEXPR_ASSERT(b, "b can't be zero"), a/(b + 5);
      |            ^~~~~~~~~~~~~~~~~~~~~~~

@mosra
Copy link
Owner

mosra commented May 27, 2022

Wait, I'm stupid. Sorry, realized the actual reason just now.

Yes, it fails even for me. The key was that CMAKE_BUILD_TYPE is unset by default, and ... tests for the CORRADE_DEBUG_ASSERT() macro don't handle that case properly, expecting either NDEBUG or CORRADE_IS_DEBUG_BUILD being set, and there's neither if CMAKE_BUILD_TYPE is empty. The AssertDisabledTest then passes a failing statement to the assert macro to test it's indeed not doing anything, which in turn means that a constexpr variable is not initialized by a constexpr statement (as that's how the assert failure manifests at compile time).

TL;DR: if you build with -DCMAKE_BUILD_TYPE=Release or Debug, it'll go through. Working on a proper fix now, apologies for assuming it's your toolchain being cursed and not my code being stupid.

@mosra mosra added this to the 2022.0a milestone May 27, 2022
@mosra
Copy link
Owner

mosra commented May 27, 2022

Should be fixed with 1fea951, sorry again :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

2 participants