I was reading subsection 18.2 Constructors and Destructors of section 18 exception handling in C++17 standard draft where there is an example(page 384). I tried to understand where destruction of object A returned inside the try block happens but couldn't find. So I copied the example, added some prints and see that dtor of that object is never called. What am I missing here? Someone please explain what's happening here.
#include <stdio.h>
struct A {
int a_;
explicit A(int a):a_(a) {
printf("A(%d)'s ctor\n", a_);
}
~A() {
printf("A(%d)'s dtor\n", a_);
}
};
struct Y { ~Y() noexcept(false) {
printf("y's dtor\n");
throw 0; } };
A f() {
try {
A a(23);
Y y;
A b(56);
return A(100); // #1 who destructs this ??
} catch (...) {
printf("handling exception..\n");
}
printf("At line %d now..\n", __LINE__);
return A(200); // #2
}
int main() {
auto ret = f();
printf("f returned A(%d) object\n", ret.a_);
return 0;
}
Above code outputs following:
A(23)'s ctor
A(56)'s ctor
A(100)'s ctor
A(56)'s dtor
y's dtor
A(23)'s dtor
handling exception..
At line 34 now..
A(200)'s ctor
f returned A(200) object
A(200)'s dtor
...Program finished with exit code 0
According to the C++17 standard [except.ctor]/2:
If an exception is thrown during the destruction of temporaries or local variables for a return statement, the destructor for the returned object (if any) is also invoked. The objects are destroyed in the reverse order of the completion of their construction.
Then there is an illustrative example (which you modified slightly) to demonstrate: after the Y
destructor throws, the next thing that happens is that the A(100)
object should be destroyed, so you should see a destruction message.
The posted output indicates a compiler bug. This is very similar to the issue reported as LLVM bug 12286 and gcc bug 33799.
The latter is marked as being fixed in GCC 10 (after initially being reported in 2007!). However, testing with the version 10.0.1 20200418 (experimental)
on Godbolt: even though the test case in the 33799 bug report is fixed, the code in this question remains unfixed. I added a comment to that bug report about this example.