https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98419
Bug ID: 98419
Summary: wrong code when destructor of local variable modifies
returned object
Product: gcc
Version: 10.2.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: leni536 at gmail dot com
Target Milestone: ---
Version:
g++ (Compiler-Explorer-Build) 10.2.0
Command line options:
-std=c++17 -O2 -pedantic-errors
```
struct A {
int i;
A(int ** iptrptr): i(1) {
*iptrptr = &i;
}
};
struct B {
int* iptr;
B(): iptr(0) {}
~B() {
*iptr = 2;
}
};
A foo() {
B b;
return A(&b.iptr);
}
```
Observed behavior:
foo() returns an object with its `i` member having the value 1.
https://godbolt.org/z/Yhcjo9
Expected behavior:
foo() to return an object with its `i` member having the value 2.
The destruction of `b` is sequenced before the initialization of the returned
object. The constructor of A sets the int* contained in `b` to point within the
returned object (there is no temporary created with type A, C++17's mandatory
copy elision is assumed here). ~B() then sets the `i` member of the returned
object to 2.
Other observations:
With command line options `-std=c++17 -O0 -pedantic-errors -fsanitize=address`
~B() tramples the stack:
https://godbolt.org/z/M5ETa9
When A has a user-defined copy-constructor or destructor then I get the
expected behavior:
https://godbolt.org/z/osqbfz
https://godbolt.org/z/ozzPaf
Presumably when the returned type is trivially copyable then the copy isn't
elided, with the assumption that it's not observable. In C++17 the copy elision
is mandatory, and it is observable even for trivially copyable types, as shown
in this example.