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 constructed
1 move constructed
1 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 constructed
0 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
As Oliv mentioned, it appears this is just a bug with GCC's experimental coroutine support. A ticket has been raised here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With