https://gcc.gnu.org/bugzilla/show_bug.cgi?id=128354
Bug ID: 128354
Summary: ICE in symtab_node::get_alias_target after
devirtualizing an explicit destructor call at -O1
Product: gcc
Version: 17.0
Status: UNCONFIRMED
Keywords: ice-on-valid-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
At -O1, GCC aborts during the GIMPLE dse pass while compiling a valid explicit
virtual destructor call. FRE resolves the call to the complete-object
destructor of the allocated derived class; a later IPA mod-ref query crashes
while following that destructor's implicit alias.
Reproducer:
struct A;
void g(A &);
struct A {
virtual ~A() {}
virtual void f();
};
struct B : A {
~B() { h(); }
void h() { g(*this); }
};
int main() {
A *p = new B;
p->~A();
p = new A;
p->~A();
}
Command:
g++ -O1 -c testcase.cpp
Compiler:
g++ (GCC) 17.0.0 20261101 (experimental)
GCC commit cf6e20578339f81bb1a029dedd2d3248337aabba
Target: x86_64-pc-linux-gnu
Actual behavior:
GCC terminates with an internal compiler error during the GIMPLE dse pass. The
first useful frames are:
internal compiler error: Segmentation fault
symtab_node::get_alias_target()
symtab_node::ultimate_alias_target_1(availability*, symtab_node*)
cgraph_node::ultimate_alias_target(availability*, symtab_node*)
get_modref_function_summary(cgraph_node*)
dse_optimize_call
-O1 -fno-tree-dse reaches the same failure through cddce. The testcase compiles
with -O0, -O2, -O3, -Os, -O1 -fno-tree-fre, or -O1 -fno-inline. GCC 8.5
compiles it; GCC 9.5 through 16.2 and current trunk terminate with an internal
compiler error.
Expected behavior:
GCC should compile the valid C++ translation unit without an internal compiler
error. With definitions of A::f and g supplied in another translation unit, the
program also runs without a diagnostic under ASan and UBSan at -O0; Clang trunk
compiles and runs the same program.
Technical details:
After FRE, the first destructor call in main becomes a direct reference to
B::~B()'s complete-object destructor, _ZN1BD1Ev. The callgraph records
_ZN1BD1Ev as a cpp_implicit_alias of the base-object destructor _ZN1BD2Ev. The
crash occurs when get_modref_function_summary follows the callee through
get_alias_target; the dump suggests that the alias node no longer has its
expected alias reference at that point.
Removing the second new A and p->~A() pair, or calling g(*this) directly from
B::~B() instead of through B::h(), avoids the failure.