From 5c8f9ec8936c6cda9abc6b2b74296b033fa4c478 Mon Sep 17 00:00:00 2001 From: Lauri Vasama Date: Sat, 2 May 2026 17:44:46 +0300 Subject: [PATCH] Work around GCC co_await bugs in test macros Related GCC issues: * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101027 * https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116775 Related Catch2 issues: * https://github.com/catchorg/Catch2/issues/2591 * https://github.com/catchorg/Catch2/issues/2925 --- .../internal/catch_compiler_capabilities.hpp | 29 ------------------- src/catch2/internal/catch_run_context.cpp | 2 ++ src/catch2/internal/catch_test_macro_impl.hpp | 10 +++++-- tests/SelfTest/UsageTests/Misc.tests.cpp | 2 +- 4 files changed, 10 insertions(+), 33 deletions(-) diff --git a/src/catch2/internal/catch_compiler_capabilities.hpp b/src/catch2/internal/catch_compiler_capabilities.hpp index 2bbee6bc61..8871d7b6c6 100644 --- a/src/catch2/internal/catch_compiler_capabilities.hpp +++ b/src/catch2/internal/catch_compiler_capabilities.hpp @@ -130,26 +130,6 @@ #endif // __clang__ -// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug -// which results in calls to destructors being emitted for each temporary, -// without a matching initialization. In practice, this can result in something -// like `std::string::~string` being called on an uninitialized value. -// -// For example, this code will likely segfault under IBM XL: -// ``` -// REQUIRE(std::string("12") + "34" == "1234") -// ``` -// -// Similarly, NVHPC's implementation of `__builtin_constant_p` has a bug which -// results in calls to the immediately evaluated lambda expressions to be -// reported as unevaluated lambdas. -// https://developer.nvidia.com/nvidia_bug/3321845. -// -// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented. -#if defined( __ibmxl__ ) || defined( __CUDACC__ ) || defined( __NVCOMPILER ) -# define CATCH_INTERNAL_CONFIG_NO_USE_BUILTIN_CONSTANT_P -#endif - //////////////////////////////////////////////////////////////////////////////// @@ -390,15 +370,6 @@ #define CATCH_CONFIG_USE_BUILTIN_CONSTANT_P #endif -#if defined( CATCH_CONFIG_USE_BUILTIN_CONSTANT_P ) && \ - !defined( CATCH_CONFIG_NO_USE_BUILTIN_CONSTANT_P ) -# define CATCH_INTERNAL_IGNORE_BUT_WARN( ... ) \ - (void)__builtin_constant_p( __VA_ARGS__ ) /* NOLINT(cppcoreguidelines-pro-type-vararg, \ - hicpp-vararg) */ -#else -# define CATCH_INTERNAL_IGNORE_BUT_WARN( ... ) -#endif - // Even if we do not think the compiler has that warning, we still have // to provide a macro that can be used by the code. #if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION) diff --git a/src/catch2/internal/catch_run_context.cpp b/src/catch2/internal/catch_run_context.cpp index a435170f41..4c33eb5cf8 100644 --- a/src/catch2/internal/catch_run_context.cpp +++ b/src/catch2/internal/catch_run_context.cpp @@ -328,6 +328,8 @@ namespace Catch { bool lastAssertionPassed() { return Detail::g_lastAssertionPassed; } + volatile bool volatileFalse = false; + } // namespace Detail RunContext::RunContext(IConfig const* _config, IEventListenerPtr&& reporter) diff --git a/src/catch2/internal/catch_test_macro_impl.hpp b/src/catch2/internal/catch_test_macro_impl.hpp index f38ec6066c..5a043cea92 100644 --- a/src/catch2/internal/catch_test_macro_impl.hpp +++ b/src/catch2/internal/catch_test_macro_impl.hpp @@ -18,6 +18,10 @@ namespace Catch { namespace Detail { // Defined in catch_run_context.cpp, where the thread-local data lives. bool lastAssertionPassed(); + + // A technically non-constant false. Prevents the compiler from warning + // about or eliminating constant branch conditions. + extern volatile bool volatileFalse; } } @@ -48,7 +52,8 @@ namespace Catch { #define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \ do { /* NOLINT(bugprone-infinite-loop) */ \ /* The expression should not be evaluated, but warnings should hopefully be checked */ \ - CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \ + if(::Catch::Detail::volatileFalse) \ + (void)(__VA_ARGS__); \ Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \ INTERNAL_CATCH_TRY { \ CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \ @@ -57,8 +62,7 @@ namespace Catch { CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \ } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \ catchAssertionHandler.complete(); \ - } while( (void)0, (false) && static_cast( !!(__VA_ARGS__) ) ) // the expression here is never evaluated at runtime but it forces the compiler to give it a look - // The double negation silences MSVC's C4800 warning, the static_cast forces short-circuit evaluation if the type has overloaded &&. + } while(false) /////////////////////////////////////////////////////////////////////////////// #define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \ diff --git a/tests/SelfTest/UsageTests/Misc.tests.cpp b/tests/SelfTest/UsageTests/Misc.tests.cpp index dec51ab8a7..58c4e7a8c2 100644 --- a/tests/SelfTest/UsageTests/Misc.tests.cpp +++ b/tests/SelfTest/UsageTests/Misc.tests.cpp @@ -384,7 +384,7 @@ TEMPLATE_PRODUCT_TEST_CASE("A Template product test case", "[template][product]" } TEMPLATE_PRODUCT_TEST_CASE_SIG("A Template product test case with array signature", "[template][product][nttp]", ((typename T, size_t S), T, S), (std::array, Bar), ((int, 9), (float, 42))) { - TestType x; + TestType x{}; REQUIRE(x.size() > 0); }