https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128085
Bug ID: 128085
Summary: [11/12/13/14/15/16/17 Regression] wrong code at -O2
destroying an object with an anonymous-namespace
virtual base; -fno-ipa-modref avoids it
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: ipa
Assignee: unassigned at gcc dot gnu.org
Reporter: yqtian668 at gmail dot com
Target Milestone: ---
Target: x86_64-pc-linux-gnu
Created attachment 65921
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65921&action=edit
Preprocessed placement-new testcase; SIGSEGV at -O2
## Reproducer
The attached bug1-test2.ii was verified to reproduce.
The source is:
```cpp
#include <cstdio>
#include <new>
static unsigned checksum, trace;
namespace {
struct A;
unsigned call(A& r);
struct A {
unsigned x = 2662398282u;
virtual ~A() { trace = trace * 31 + 512; }
virtual unsigned f() { return x * 103 + 50; }
};
struct B : virtual A {
~B() { trace = trace * 31 + 513; checksum = checksum * 31 + call(*this); }
};
unsigned call(A& r) { return r.f(); }
}
int main() {
{
alignas(B) unsigned char buf[sizeof(B)];
A* p = new (buf) B;
p->~A();
}
printf("%08x %08x\n", checksum, trace);
}
```
## Command and result
```
g++ -std=c++14 -Wall -Wextra -D_GLIBCXX_ASSERTIONS -O2 bug1-test2.cpp -o test
./test
```
Expected: exit 0 and output `d9344cf8 0000401f`.
Actual on the trunk compiler below: SIGSEGV. Compilation succeeds without
diagnostics.
The preprocessed attachment also produces SIGSEGV with:
```
g++ -std=c++14 -O2 bug1-test2.ii -o test
./test
```
Adding either `-fno-tree-dse` or `-fno-ipa-modref` produces the expected
output.
Adding `-fno-devirtualize` still produces SIGSEGV.
Replacing `-O2` with `-O0 -fsanitize=undefined,address` produces the expected
output without sanitizer diagnostics. These checks were rerun on 2026-10-22.
`A` has a virtual destructor. The unqualified explicit destructor call through
`A*` invokes the destructor for `B`. During `B::~B`, the final overrider of `f`
is `A::f`; its field has already been initialized. Arithmetic is unsigned.
## Regression evidence
The previously recorded release sweep found 4.9.4, 5.5.0, 6.5.0, 7.5.0, 8.5.0,
9.5.0 and 10.5.0 working; 11.5.0, 12.5.0, 13.5.0, 14.4.0, 15.3.0 and 16.2.0
failing.
The release sweep was not repeated during this report preparation.
Bisection using this placement-new testcase identified
r11-3308-gd119f34c952f87, "New modref/ipa_modref optimization passes"
(2020-09-20). The recorded parent 2fe5b7d1f66 passes; d119f34c952 fails.
This identifies the change that exposes the failure, not necessarily the source
location of the underlying defect.
## Additional evidence / suspected mechanism
The related `bug1-test3.cpp` reproduces on this trunk with
`-O2 -fno-early-inlining`, but passes at plain `-O2` (both rerun).
The related testcase is:
```cpp
static unsigned trace;
namespace {
struct A { unsigned x = 1; virtual ~A() { trace = trace * 31 + 1; } };
struct B : virtual A { ~B() { trace = trace * 31 + 2; } };
struct C : B { ~C() { trace = trace * 31 + 3; } };
}
int main() { A* p = new C; delete p; return trace == 0; }
```
Earlier inspection of a larger form of that testcase showed vptr stores
removed,
while a subsequent virtual thunk still loaded a vptr for pointer adjustment.
The flag sensitivity suggests an interaction between DSE and IPA modref;
the precise defect in the memory-access analysis is not established.
PR120098 appears different: the recorded tests fail on versions containing its
fix, and disabling devirtualization does not avoid this failure.
## Compiler details
Verified on 2026-10-22 using GCC trunk revision 8cc6e7178c2e,
17.0.0 20261021 (experimental), target x86_64-pc-linux-gnu.
```
Using built-in specs.
COLLECT_GCC=/opt/gcc/bin/g++
COLLECT_LTO_WRAPPER=/opt/gcc/libexec/gcc/x86_64-pc-linux-gnu/17.0.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /src/configure --prefix=/opt/gcc --enable-languages=c,c++
--disable-multilib --disable-bootstrap --enable-checking=yes
Thread model: posix
Supported LTO compression algorithms: zlib
gcc version 17.0.0 20261021 (experimental) (GCC)
```