From fecc66c1671f4d33f3f62702ea42a5e69c8ad26b Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 3 Apr 2026 09:06:44 -0700 Subject: [PATCH 1/6] drop support for gcc-11 --- .github/workflows/ci.cpu.yml | 6 +++--- README.md | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.cpu.yml b/.github/workflows/ci.cpu.yml index ddaf68d41..3cdf73fec 100644 --- a/.github/workflows/ci.cpu.yml +++ b/.github/workflows/ci.cpu.yml @@ -24,9 +24,9 @@ jobs: - { name: "CPU (clang 16, Debug, TSAN)", build: "Debug", tag: llvm16-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=thread" } - { name: "CPU (clang 16, Release)", build: "Release", tag: llvm16-cuda12.9, cxxstd: "20", cxxflags: "-stdlib=libc++" } - { name: "CPU (clang 16, Release, ASAN)", build: "Release", tag: llvm16-cuda12.9, cxxstd: "20", cxxflags: "-stdlib=libc++ -fsanitize=address -fsanitize-ignorelist=/home/coder/stdexec/sanitizer-ignorelist.txt" } - - { name: "CPU (gcc 11, Debug)", build: "Debug", tag: gcc11-cuda12.9, cxxstd: "20", cxxflags: "", } - - { name: "CPU (gcc 11, Release)", build: "Release", tag: gcc11-cuda12.9, cxxstd: "20", cxxflags: "", } - - { name: "CPU (gcc 11, Release, ASAN)", build: "Release", tag: gcc11-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=address" } + - { name: "CPU (gcc 12, Debug)", build: "Debug", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "", } + - { name: "CPU (gcc 12, Release)", build: "Release", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "", } + - { name: "CPU (gcc 12, Release, ASAN)", build: "Release", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=address" } - { name: "CPU (gcc 12, Release, TSAN)", build: "Release", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=thread" } - { name: "CPU (gcc 13, Debug)", build: "Debug", tag: gcc13-cuda12.9, cxxstd: "20", cxxflags: "", } - { name: "CPU (gcc 14, Debug)", build: "Debug", tag: gcc14-cuda12.9, cxxstd: "20", cxxflags: "", } diff --git a/README.md b/README.md index dadaef2fe..7d747efb9 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ below](#nvhpc-sdk) for more details). `stdexec` requires compiling with C++20 (`-std=c++20`) but otherwise does not have any dependencies and only requires a sufficiently new compiler: -- gcc 11+ +- gcc 12+ - clang 16+ - MSVC 14.43+ - XCode 16+ From 11ac3579bb8b7c028a3aa5b286002cb5f0646117 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 3 Apr 2026 11:03:05 -0700 Subject: [PATCH 2/6] do not run sanitizers on relacy tests --- CMakeLists.txt | 1 + test/CMakeLists.txt | 8 +++++--- test/exec/CMakeLists.txt | 2 +- test/exec/asio/CMakeLists.txt | 2 +- test/exec/taskflow/CMakeLists.txt | 2 +- test/exec/tbb/CMakeLists.txt | 2 +- test/nvexec/CMakeLists.txt | 2 +- test/rrd/CMakeLists.txt | 18 ++++++++++++++++++ 8 files changed, 29 insertions(+), 8 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 19a6bb16f..c50e092a5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -109,6 +109,7 @@ set(BUILD_TESTING ${STDEXEC_BUILD_TESTS}) if (STDEXEC_BUILD_TESTS) # CTest automatically calls enable_testing() if BUILD_TESTING is ON # https://cmake.org/cmake/help/latest/module/CTest.html#module:CTest + list(APPEND CMAKE_CTEST_ARGUMENTS "--output-on-failure") include(CTest) endif() diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 3566d85eb..00d285dab 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -133,10 +133,12 @@ include(${Catch2_SOURCE_DIR}/contrib/Catch.cmake) # For testing that builds fail as expected include(${icm_SOURCE_DIR}/icm_build_failure_testing.cmake) -catch_discover_tests(test.stdexec) -catch_discover_tests(test.scratch) +catch_discover_tests(test.stdexec PROPERTIES TIMEOUT 30) + +catch_discover_tests(test.scratch PROPERTIES TIMEOUT 30) + if(STDEXEC_BUILD_SYSTEM_CONTEXT AND NOT STDEXEC_ENABLE_CUDA) - catch_discover_tests(test.system_context_replaceability) + catch_discover_tests(test.system_context_replaceability PROPERTIES TIMEOUT 30) endif() add_subdirectory(exec) diff --git a/test/exec/CMakeLists.txt b/test/exec/CMakeLists.txt index b7245dc78..3424dd3df 100644 --- a/test/exec/CMakeLists.txt +++ b/test/exec/CMakeLists.txt @@ -77,7 +77,7 @@ target_link_libraries(test.exec common_test_settings) # Discover the Catch2 test built by the application -catch_discover_tests(test.exec) +catch_discover_tests(test.exec PROPERTIES TIMEOUT 30) if(STDEXEC_ENABLE_ASIO) add_subdirectory(asio) diff --git a/test/exec/asio/CMakeLists.txt b/test/exec/asio/CMakeLists.txt index f7d11a0e0..cd6b4b620 100644 --- a/test/exec/asio/CMakeLists.txt +++ b/test/exec/asio/CMakeLists.txt @@ -31,4 +31,4 @@ target_link_libraries(test.asioexec PRIVATE common_test_settings) -catch_discover_tests(test.asioexec) +catch_discover_tests(test.asioexec PROPERTIES TIMEOUT 30) diff --git a/test/exec/taskflow/CMakeLists.txt b/test/exec/taskflow/CMakeLists.txt index 6727d2a90..565804e2f 100644 --- a/test/exec/taskflow/CMakeLists.txt +++ b/test/exec/taskflow/CMakeLists.txt @@ -29,4 +29,4 @@ target_link_libraries(test.taskflowexec PRIVATE common_test_settings) -catch_discover_tests(test.taskflowexec) +catch_discover_tests(test.taskflowexec PROPERTIES TIMEOUT 30) diff --git a/test/exec/tbb/CMakeLists.txt b/test/exec/tbb/CMakeLists.txt index f0aba9347..ac53a32f7 100644 --- a/test/exec/tbb/CMakeLists.txt +++ b/test/exec/tbb/CMakeLists.txt @@ -29,4 +29,4 @@ target_link_libraries(test.tbbexec PRIVATE common_test_settings) -catch_discover_tests(test.tbbexec) +catch_discover_tests(test.tbbexec PROPERTIES TIMEOUT 30) diff --git a/test/nvexec/CMakeLists.txt b/test/nvexec/CMakeLists.txt index 445fd9314..f178ebdba 100644 --- a/test/nvexec/CMakeLists.txt +++ b/test/nvexec/CMakeLists.txt @@ -61,4 +61,4 @@ target_link_libraries(test.nvexec # target_compile_options(test.nvexec PRIVATE "-ftemplate-backtrace-limit=9999") # endif() -catch_discover_tests(test.nvexec) +catch_discover_tests(test.nvexec PROPERTIES TIMEOUT 30) diff --git a/test/rrd/CMakeLists.txt b/test/rrd/CMakeLists.txt index 0622fd33f..e27280b7f 100644 --- a/test/rrd/CMakeLists.txt +++ b/test/rrd/CMakeLists.txt @@ -1,5 +1,22 @@ include(FetchContent) +# Relacy has its own runtime checks and does not compose with compiler sanitizers. +# Strip any -fsanitize* flags in this directory so Relacy-linked targets run cleanly. +function(_stdexec_strip_sanitize_flags out_var in_value) + separate_arguments(_flags UNIX_COMMAND "${in_value}") + list(FILTER _flags EXCLUDE REGEX "^-fsanitize") + string(JOIN " " _joined ${_flags}) + set(${out_var} "${_joined}" PARENT_SCOPE) +endfunction() + +foreach(_cfg "" "_DEBUG" "_RELEASE" "_RELWITHDEBINFO" "_MINSIZEREL") + set(_var "CMAKE_CXX_FLAGS${_cfg}") + if(DEFINED ${_var} AND NOT "${${_var}}" STREQUAL "") + _stdexec_strip_sanitize_flags(_stripped "${${_var}}") + set(${_var} "${_stripped}") + endif() +endforeach() + FetchContent_Declare( relacy GIT_REPOSITORY https://github.com/dvyukov/relacy @@ -29,6 +46,7 @@ function(add_relacy_test target_name) CXX_EXTENSIONS OFF) add_test(NAME relacy-${target_name} COMMAND ${target_name}) + set_tests_properties(relacy-${target_name} PROPERTIES TIMEOUT 120) endfunction() set(relacy_tests From 510ece75b065ae8beb5f52d784ff046b8dd3ee91 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 3 Apr 2026 11:22:35 -0700 Subject: [PATCH 3/6] test gcc-14 release ASAN instead of gcc-12 --- .github/workflows/ci.cpu.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.cpu.yml b/.github/workflows/ci.cpu.yml index 3cdf73fec..24b3f9e9d 100644 --- a/.github/workflows/ci.cpu.yml +++ b/.github/workflows/ci.cpu.yml @@ -26,12 +26,14 @@ jobs: - { name: "CPU (clang 16, Release, ASAN)", build: "Release", tag: llvm16-cuda12.9, cxxstd: "20", cxxflags: "-stdlib=libc++ -fsanitize=address -fsanitize-ignorelist=/home/coder/stdexec/sanitizer-ignorelist.txt" } - { name: "CPU (gcc 12, Debug)", build: "Debug", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "", } - { name: "CPU (gcc 12, Release)", build: "Release", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "", } - - { name: "CPU (gcc 12, Release, ASAN)", build: "Release", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=address" } + # With the following config, 2 tests mysteriously time out, but only in CI and not locally. + # - { name: "CPU (gcc 12, Release, ASAN)", build: "Release", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=address" } - { name: "CPU (gcc 12, Release, TSAN)", build: "Release", tag: gcc12-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=thread" } - { name: "CPU (gcc 13, Debug)", build: "Debug", tag: gcc13-cuda12.9, cxxstd: "20", cxxflags: "", } - { name: "CPU (gcc 14, Debug)", build: "Debug", tag: gcc14-cuda12.9, cxxstd: "20", cxxflags: "", } - { name: "CPU (gcc 14, Debug, ASAN)", build: "Debug", tag: gcc14-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=address" } - { name: "CPU (gcc 14, Debug, TSAN)", build: "Debug", tag: gcc14-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=thread" } + - { name: "CPU (gcc 14, Release, ASAN)", build: "Release", tag: gcc14-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=address" } - { name: "CPU (gcc 14, Release, LEAK)", build: "Release", tag: gcc14-cuda12.9, cxxstd: "20", cxxflags: "-fsanitize=leak", } - { name: "CPU (gcc 14, Release, c++23)", build: "Release", tag: gcc14-cuda12.9, cxxstd: "23", cxxflags: "", } container: From 524da12a82608262a80e495604bd0cbd69dbc486 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 3 Apr 2026 11:50:09 -0700 Subject: [PATCH 4/6] turn off -Wmaybe-uninitialized for tests when compiling with gcc --- test/CMakeLists.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 00d285dab..4862e2a92 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -88,7 +88,9 @@ set_target_properties(common_test_settings PROPERTIES target_include_directories(common_test_settings INTERFACE "${CMAKE_CURRENT_LIST_DIR}") target_compile_definitions(common_test_settings INTERFACE STDEXEC_NAMESPACE=std::execution) target_compile_options(common_test_settings INTERFACE - $<$:/wd4714>) # function marked as __forceinline not inlined + $<$:/wd4714> # function marked as __forceinline not inlined + $<$:-Wno-maybe-uninitialized> # warnings being emitted from stdlib headers, why? + ) target_link_libraries(common_test_settings INTERFACE $) # target_compile_definitions( # common_test_settings INTERFACE From 32546c3afaab711800541686e5ef8ae597ea6ac6 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 3 Apr 2026 18:49:38 -0700 Subject: [PATCH 5/6] avoid symmetric transfer on GCC --- examples/CMakeLists.txt | 2 ++ include/stdexec/__detail/__as_awaitable.hpp | 16 ++++++++-------- include/stdexec/__detail/__task.hpp | 6 ++++++ test/stdexec/types/test_task.cpp | 5 ----- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 60db139d8..591f68d77 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -32,6 +32,8 @@ function(def_example example) PRIVATE STDEXEC::stdexec stdexec_executable_flags $) + target_compile_options(${target} INTERFACE + $<$:-Wno-maybe-uninitialized>) # warnings being emitted from stdlib headers, why? endfunction() set(stdexec_examples diff --git a/include/stdexec/__detail/__as_awaitable.hpp b/include/stdexec/__detail/__as_awaitable.hpp index bc274a501..d5d07d7ae 100644 --- a/include/stdexec/__detail/__as_awaitable.hpp +++ b/include/stdexec/__detail/__as_awaitable.hpp @@ -33,7 +33,6 @@ #include // for std::identity #include #include -#include STDEXEC_PRAGMA_PUSH() STDEXEC_PRAGMA_IGNORE_GNU("-Wmissing-braces") @@ -307,8 +306,7 @@ namespace STDEXEC } constexpr auto - await_suspend([[maybe_unused]] __std::coroutine_handle<_Promise> __hcoro) noexcept // - -> __std::coroutine_handle<> + await_suspend([[maybe_unused]] __std::coroutine_handle<_Promise> __hcoro) noexcept -> bool { STDEXEC_ASSERT(this->__continuation_ == __hcoro); @@ -330,14 +328,14 @@ namespace STDEXEC // The operation completed inline with set_value or set_error, so we can just // resume the current coroutine. await_resume will either return the value or // throw as appropriate. - return __hcoro; + return false; } else { // If __ready_ was still false when executing the CAS, then the operation did not // complete inline. The continuation will be resumed when the operation // completes, so we return a noop_coroutine to suspend the current coroutine. - return __std::noop_coroutine(); + return true; } } @@ -363,7 +361,7 @@ namespace STDEXEC {} auto await_suspend([[maybe_unused]] __std::coroutine_handle<_Promise> __hcoro) - -> __std::coroutine_handle<> + -> STDEXEC_PP_IF(STDEXEC_GCC(), bool, __std::coroutine_handle<>) { STDEXEC_ASSERT(this->__continuation_ == __hcoro); { @@ -379,14 +377,16 @@ namespace STDEXEC // unhandled_stopped() on the promise to propagate the stop signal. That will // result in the coroutine being torn down, so beware. We then resume the // returned coroutine handle (which may be a noop_coroutine). - return __hcoro.promise().unhandled_stopped(); + return STDEXEC_PP_IF(STDEXEC_GCC(), + (__hcoro.promise().unhandled_stopped().resume(), true), + __hcoro.promise().unhandled_stopped()); } else { // The operation completed with set_value or set_error, so we can just resume // the current coroutine. await_resume will either return the value or throw as // appropriate. - return __hcoro; + return STDEXEC_PP_IF(STDEXEC_GCC(), false, __hcoro); } } diff --git a/include/stdexec/__detail/__task.hpp b/include/stdexec/__detail/__task.hpp index a5a5f666c..c2f1f84db 100644 --- a/include/stdexec/__detail/__task.hpp +++ b/include/stdexec/__detail/__task.hpp @@ -252,11 +252,17 @@ namespace STDEXEC return __attrs{}; } +#if !STDEXEC_GCC() + // This transforms a task into an __awaiter that can perform symmetric transfer when + // co_awaited. It is disabled on GCC due to + // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94794, which causes unbounded stack + // growth. template constexpr auto as_awaitable(_ParentPromise& __parent) && noexcept { return __awaiter<_ParentPromise>(static_cast(*this), __parent); } +#endif private: using __on_stopped_t = __forward_stop_request; diff --git a/test/stdexec/types/test_task.cpp b/test/stdexec/types/test_task.cpp index c84b1840e..49bb83b00 100644 --- a/test/stdexec/types/test_task.cpp +++ b/test/stdexec/types/test_task.cpp @@ -244,9 +244,6 @@ namespace CHECK(i == 42); } -# if !STDEXEC_GCC() || (STDEXEC_GCC_VERSION >= 13'00 && defined(__OPTIMIZE__)) - // This test is disabled on GCC due to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94794 - auto sync() -> ex::task { co_return 42; @@ -281,8 +278,6 @@ namespace CHECK(i == 84'000'042); } -# endif - // FUTURE TODO: add support so that `co_await sndr` can return a reference. // auto test_task_awaits_just_ref_sender() -> ex::task { // int value = 42; From 4a663e49cfe6702c9e89ffaee05e3cca9b02cc88 Mon Sep 17 00:00:00 2001 From: Eric Niebler Date: Fri, 3 Apr 2026 18:51:19 -0700 Subject: [PATCH 6/6] format --- include/stdexec/__detail/__task.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/stdexec/__detail/__task.hpp b/include/stdexec/__detail/__task.hpp index c2f1f84db..69a1001e2 100644 --- a/include/stdexec/__detail/__task.hpp +++ b/include/stdexec/__detail/__task.hpp @@ -252,7 +252,7 @@ namespace STDEXEC return __attrs{}; } -#if !STDEXEC_GCC() +# if !STDEXEC_GCC() // This transforms a task into an __awaiter that can perform symmetric transfer when // co_awaited. It is disabled on GCC due to // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94794, which causes unbounded stack @@ -262,7 +262,7 @@ namespace STDEXEC { return __awaiter<_ParentPromise>(static_cast(*this), __parent); } -#endif +# endif private: using __on_stopped_t = __forward_stop_request;