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

Reply via email to