https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95615
--- Comment #3 from Iain Sandoe <iains at gcc dot gnu.org> --- Actually, I don't think the example goes far enough. ISTM, [on exception in the places noted] that non-trivial DTORs for frame copies of parms should be run after the GRO and promise DTOR but before the frame is freed. Do you agree? (if so I have a patch for this now) So, I think the modified example below should print: Y () Y (const Y&) operator new() Y (const Y&) promise_type() get_return_object() task() ~task() ~promise_type() ~Y () operator delete ~Y () caught X ~Y () ======= but *both* [master] GCC and clang print: Y () Y (const Y&) operator new() Y (const Y&) promise_type() task() ~Y () ~task() ~Y () ======= #if __has_include(<coroutine>) #include <coroutine> #else #include <experimental/coroutine> namespace std { using namespace std::experimental; } #endif #include <cstdio> struct X {}; int Y_live = 0; struct Y { Y () { std::puts("Y ()"); Y_live++; } Y (const Y&) { std::puts("Y (const Y&)"); Y_live++; } ~Y () { std::puts("~Y ()"); Y_live--; } }; struct task { struct promise_type { void* operator new(size_t sz) { std::puts("operator new()"); return ::operator new(sz); } void operator delete(void* p, size_t sz) { std::puts("operator delete"); return ::operator delete(p, sz); } promise_type() { std::puts("promise_type()"); // throw X{}; } ~promise_type() { std::puts("~promise_type()"); } struct awaiter { bool await_ready() { //throw X{}; return false; } void await_suspend(std::coroutine_handle<>) { //throw X{}; } void await_resume() { //throw X{}; } }; awaiter initial_suspend() { // throw X{}; return {}; } task get_return_object() { // throw X{}; return task{}; } std::suspend_never final_suspend() noexcept { return {}; } void return_void() noexcept {} void unhandled_exception() noexcept { std::puts("unhandled_exception()"); } }; task() { std::puts("task()"); } ~task() { std::puts("~task()"); } task(task&&) { std::puts("task(task&&)"); } }; task f(Y Val) { co_return; } int main() { Y Val; try { auto a = f(Val); } catch (X) { std::puts("caught X"); } } ====