Consider the following simple coroutine, which tracks its construction and destruction:
#include <coroutine>#include <iostream>struct simple { static inline int x = 0; int id = 0; simple() : id{ x++ } { std::cout << id << " constructed\n"; } simple(simple&&) : id{ x++ } { std::cout << id << " move constructed\n"; } ~simple() { std::cout << id << " destructed\n"; } struct promise_type { simple get_return_object() { return {}; } void return_void() {} void unhandled_exception() { std::terminate(); } auto initial_suspend() noexcept { return std::suspend_never{}; } auto final_suspend() noexcept { return std::suspend_never{}; } };};simple f() { co_return; }int main() { f();}
When compiling with GCC 10.1, the output is:
0 constructed1 move constructed1 destructed
—notably, id 0
is never destructed. This is true even with GCC trunk.
Is there something I've done wrong here, some hidden UB or the like? Or is GCC at fault here?
As a comparison, I tried using Clang's experimental coroutine support, and got
0 constructed0 destructed
which is closer to what I was expecting. I also get this "correct" output even in GCC if I comment out the move constructor in the coroutine object.
Live example: https://godbolt.org/z/UQVURi