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.

Reply via email to