[Bug c++/95598] New: [coroutines] Destructor for object returned from get_return_object() never called
lewissbaker.opensource at gmail dot com
gcc-bugzilla@gcc.gnu.org
Tue Jun 9 04:48:35 GMT 2020
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95598
Bug ID: 95598
Summary: [coroutines] Destructor for object returned from
get_return_object() never called
Product: gcc
Version: 10.1.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: lewissbaker.opensource at gmail dot com
Target Milestone: ---
Compile the following code with GCC trunk with flags -std=c++2a -fcoroutines
See https://godbolt.org/z/zTjjGm
----
#include <coroutine>
#include <cstdio>
using namespace std;
struct generator {
struct promise_type {
generator get_return_object() {
return
generator{coroutine_handle<promise_type>::from_promise(*this)};
}
void return_void() {}
void unhandled_exception() {}
suspend_always initial_suspend() { return {}; }
suspend_always final_suspend() { return {}; }
};
generator(coroutine_handle<promise_type> coro) {
std::printf("generator() @ %p\n", this);
}
generator(generator&& g) noexcept {
std::printf("generator(move from %p) @ %p\n", &g, this);
}
~generator() {
std::printf("~generator() @ %p\n", this);
}
};
generator f() {
co_return;
}
int main() {
generator g = f();
}
----
The expected output of this program is following (assuming copy-elision has
occurred - this is what Clang outputs):
```
generator() @ <address-A>
~generator() @ <address-A>
```
Or if copy elision has not occurred, at least the number of
constructor/destructor calls should be balanced:
```
generator() @ <address-A>
generator(move from <address-A>) @ <address-B>
~generator() @ <address-A>
~generator() @ <address-B>
```
However, the observed output is:
```
generator() @ <address-A>
generator(move from <address-A>) @ <address-B>
~generator() @ <address-B>
```
ie. the destructor of the generator constructed at <address-A> is never called.
In this case the object constructed at <address-A> is the object returned from
promise.get_return_object() and the object constructed at <address-B> is the
object returned from the coroutine ramp function f().
It seems that the coroutine ramp function is failing to call the destructor of
the object returned from promise.get_return_object() when the coroutine ramp
function returns.
Normally, this omission of the call to the destructor would not be observed as
the return-value is moved and the destructor of a moved-from object has no
effect, but that is not always the case.
More information about the Gcc-bugs
mailing list