https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128086
Bug ID: 128086
Summary: [5/6/7/8/9/10/11/12/13/14/15/16/17 Regression] virtual
call in constructor with virtual bases folded to
__builtin_unreachable at -O2
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 65922
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65922&action=edit
Preprocessed std::max-free testcase; SIGILL at -O2
## Reproducer
The attached bug2.ii was verified to reproduce.
This version avoids the original testcase's dependence on constexpr std::max.
```cpp
#include <new>
static unsigned checksum = 0, trace = 0;
static void mix(unsigned v) { checksum = checksum * 31u + v; }
struct A {
unsigned x = 2844702273u;
virtual unsigned f() { return x * 148u + 470u; }
};
struct B : virtual A {
unsigned y = 1771222491u;
unsigned f() override { return y * 30u + 429u; }
};
struct C : virtual A, virtual B {
C() {
mix(static_cast<C&>(*this).f());
}
};
int main() {
{
alignas(A) alignas(B) alignas(C) unsigned char buf[sizeof(C) > sizeof(B) ?
(sizeof(C) > sizeof(A) ? sizeof(C) : sizeof(A)) : (sizeof(B) > sizeof(A) ?
sizeof(B) : sizeof(A))];
A* p = new (buf) C; (void)p;
}
}
```
## Command and result
```
g++ -std=c++14 -Wall -Wextra -D_GLIBCXX_ASSERTIONS -O2 bug2.cpp -o test
./test
```
Expected: normal termination, exit 0.
Actual on the trunk compiler below: SIGILL.
The only compile warning is the unused static variable `trace`, retained from
reduction. The preprocessed attachment also produces SIGILL with:
```
g++ -std=c++14 -O2 bug2.ii -o test
./test
```
Adding `-fno-devirtualize` restores exit 0. Adding `-fno-tree-dse` or
`-fno-ipa-modref` does not prevent SIGILL. Replacing `-O2` with
`-O0 -fsanitize=undefined,address` gives exit 0 without sanitizer diagnostics.
These checks were rerun on 2026-10-22, including the original std::max variant.
With `-fopt-info-optimized`, GCC reports:
```
bug2.cpp:17:5: optimized: resolving virtual function address reference to
function NULL
bug2.cpp:14:8: optimized: folding virtual function call to
__builtin_unreachable
```
`C` shares a virtual `A` base with `B`. In the body of `C::C`, the bases have
been constructed and `B::f` is the final overrider. The virtual call therefore
has a valid target. Storage is a suitably aligned unsigned-char array; the
object is constructed by placement new. This is not placement new over an
existing named object of class type.
## Regression evidence
The previously recorded release sweep found 4.9.4 working and 5.5.0, 6.5.0,
7.5.0, 8.5.0, 9.5.0, 10.5.0, 11.5.0, 12.5.0, 13.5.0, 14.4.0, 15.3.0 and 16.2.0
failing. Earlier versions generally segfault; 16.2.0 and this trunk trap.
The release sweep was not repeated during this report preparation.
Bisection of the std::max-free variant identified
r5-3634-g6f8091fc3ed9d3, "ipa_polymorphic_call_context: turn into class; add
ctors"
(Jan Hubicka, 2014-09-20). The recorded parent 8e1ba78f1b8 passes;
6f8091fc3ed fails.
Bisection of the original std::max version instead encounters the libstdc++
constexpr min/max change (PR60271), so the std::max-free variant is preferable
for reproducing across old compiler versions.
## Trigger sensitivity and related reports
Earlier reduction attempts using a local `C c`, `new C`, or a buffer declared
with only `alignas(C)` and `sizeof(C)` did not reproduce on trunk. A fixed
64-byte buffer also passed. These observations suggest sensitivity to the
storage declaration, but do not establish the precise faulty type inference.
PR93153 / PR45734 concern placement new over named class objects; this testcase
uses an unsigned-char array. PR120098 concerns anonymous-namespace types;
this testcase has external linkage. The underlying cause remains to be
confirmed.
## 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)
```