https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107044
Feng Xue <fxue at os dot amperecomputing.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |fxue at os dot amperecomputing.com --- Comment #3 from Feng Xue <fxue at os dot amperecomputing.com> --- Get another simple case triggering the same ICE. class A { public: virtual ~A(); virtual int f() = 0; }; class B : public A { public: virtual ~B(); virtual int f(); }; void foo(B *b) { A *a = b; delete a; } I had an analysis on this. Currently, gcc does not emit vtable symbol (no varpool_node) for a polymorphic class, if its key virtual method is just a declaration, has not function body defined. But, specially for non-lto compilation, this would result in an incomplete type inheritance graph by build_type_inheritance_graph(), which traverses symtab nodes to do that. It might be a potential issue for devirtualization, which is now exposed by dump_possible_polymorphic_call_targets(). For this case, neither "A" and "B" has its vtable symbol emitted. Thus, the relation that "B" is derived class of "A" is not recorded by build_type_inheritance_graph(). When handling "delete a" in fre pass, dump_possible_polymorphic_call_targets() calls two rounds of possible_polymorphic_call_targets(), one is for non-speculative devirt, which is based on odr_type of "A", the result would be empty, and the other is for speculative devirt, which is based on odr_type of "B", the result target is destructor of "B". This triggers the ICE, because we expect the latter should be subset of the former. If we change the case to: class A { public: virtual int f() = 0; }; class B : public A { public: virtual int f(); }; void foo(B *b) { A *a = b; a->f(); } The non-speculative target set is expected to be "{__cxa_pure_virtual(), B::f()}", but we only get "{ __cxa_pure_virtual() }", which is also incorrect, though it satisfies "gcc_assert (symtab->state < IPA_SSA || targets.length () <= len), and no ICE happens. Probably we could fix the issues in two ways: o. For simplicity, remove the assertion in dump_possible_polymorphic_call_targets(). o. Always emit vtable for polymorphic class declaration in front-end, but I'm not sure if current implementation has other correctness-related consideration on it.