https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84414
Bug ID: 84414 Summary: miscompile due to assuming that object returned by value cannot alias its own member pointer values Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: richard-gccbugzilla at metafoo dot co.uk CC: timshen at gcc dot gnu.org Target Milestone: --- GCC (all versions) miscompiles this code: struct A { A *children; long long arr[100]; A() : children() {} A(int) : children(this) {} }; __attribute__((noinline)) A Foo() { return A(0); } A x[3] = {}; void Bar(int n) { A a = Foo(); for (int i = 0; i < n; i++) { a.children[i].children = x; } } int main() { Bar(3); return x[0].children || !x[1].children || !x[2].children; } A correct compilation must return 0 from main, but GCC at -O2 returns 1. The reason is that it fails to reload 'a.children' on each iteration of the loop in 'Bar', reasoning (incorrectly) that the store to 'a.children[i].children' cannot alias 'a.children' because 'a' has not escaped. The above code has defined behavior in C++17, where the 'guaranteed copy elision' rules mean that the 'this' pointer inside the A::A(int) constructor points to the 'a' object inside 'Bar'. But since GCC chooses to perform copy elision on this code in all language modes (and always has done so), and the fact that it performed copy-elision is observable, this is not a C++17-specific bug. (The same miscompile can also be observed via NRVO.)