https://gcc.gnu.org/bugzilla/show_bug.cgi?id=116506
Bug ID: 116506 Summary: [15 Regression] Destructors of temporary awaitables are executed too early Product: gcc Version: 15.0 Status: UNCONFIRMED Keywords: c++-coroutines Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: daklishch at gmail dot com CC: iains at gcc dot gnu.org Target Milestone: --- After r15-3146-g47dbd69b1, destructors of temporary awaitables are executed too early (before suspending) if promise type has an await_transform. For example, the following snippet executes __builtin_trap if compiled with the current trunk but doesn't do so if compiled with GCC 14.2.1 or Clang 18.1.8. ``` $ cat ../test.cpp #include <coroutine> bool g_too_early = true; std::coroutine_handle<> g_handle; struct Awaiter { Awaiter() {} ~Awaiter() { if (g_too_early) { __builtin_trap(); } } bool await_ready() { return false; } void await_suspend(std::coroutine_handle<> handle) { g_handle = handle; } void await_resume() {} }; struct SuspendNever { bool await_ready() noexcept { return true; } void await_suspend(std::coroutine_handle<>) noexcept {} void await_resume() noexcept {} }; struct Coroutine { struct promise_type { Coroutine get_return_object() { return {}; } SuspendNever initial_suspend() { return {}; } SuspendNever final_suspend() noexcept { return {}; } void return_void() {} Awaiter&& await_transform(Awaiter&& u) { return static_cast<Awaiter&&>(u); } }; }; Coroutine foo() { co_await Awaiter{}; } int main() { foo(); g_too_early = false; g_handle.destroy(); } $ ~/gcc-15-trunk/bin/g++ ../test.cpp -o ../test.elf -std=c++20 -fno-exceptions && ../test.elf zsh: illegal hardware instruction (core dumped) ../test.elf $ g++ ../test.cpp -o ../test.elf -std=c++20 -fno-exceptions && ../test.elf $ clang++ ../test.cpp -o ../test.elf -std=c++20 -fno-exceptions -Wno-coroutine-missing-unhandled-exception && ../test.elf ``` CE link: https://godbolt.org/z/G7s35e4q8