Devirtualize virtual call hierarchy if just base dtor exists

Martin Liška mliska@suse.cz
Wed Oct 22 16:16:00 GMT 2014


On 10/22/2014 05:30 PM, Jonathan Wakely wrote:
> On 22 October 2014 16:15, Martin Liška wrote:
>> Hello.
>>
>> I've been playing with following example:
>>
>> #include <stdlib.h>
>>
>> class Base
>> {
>> public:
>>    virtual ~Base() {}
>> };
>>
>> class Derived: public Base
>> {
>> };
>>
>> #define N 1000
>>
>> int main()
>> {
>>    Base **b = (Base **)malloc (sizeof(Base *) * N);
>>    for (unsigned i = 0; i < N; i++)
>>      b[i] = new Derived();
>>
>>    for (unsigned i = 0; i < N; i++)
>>      delete b[i];
>>
>>    return 0;
>> }
>>
>> Where I would like to somehow give an advice to devirtualize machinery. My
>> motivation is to inline destruction in 'delete b[i]'.
>> 'final' keyword does not solve my problem:
>>
>> a.c:9:7: error: virtual function ‘virtual Derived::~Derived()’
>>   class Derived: public Base
>>         ^
>> a.c:6:11: error: overriding final function ‘virtual Base::~Base()’
>>     virtual ~Base() final {}
>
> Virtual destructors are special, derived classes *must* override them,
> so you can't make it final in the base class.
>
>> If I enclose my classes to anonymous namespace:
>>
>> Procesing function int main()/172
>>    Targets of polymorphic call of type 0:struct Base token 2
>>      Contained in type:struct Base at offset 0
>>      This is a complete list. (derived types included)
>>         virtual {anonymous}::Base::~Base()/164 virtual
>> {anonymous}::Derived::~Derived()/183
>>
>> More than one likely target
>
> Presumably because the dynamic type of *b[i] could be Base or Derived,
> and the compiler can't know until it checks it. Does it make any
> difference if you make Base an abstract class? In that case the
> compiler should know that the dynamic type of *b[i] cannot be Base, so
> must be a Derived.


Looks that addition of an abstract method to Base class really helps:

   for (unsigned i = 0; i < N; i++)
     delete b[i];
   4006a0:	48 8b 3b             	mov    (%rbx),%rdi
   4006a3:	48 85 ff             	test   %rdi,%rdi
   4006a6:	74 05                	je     4006ad <main+0x4d>
public:
   virtual ~Base() {}
   virtual void Foo() = 0;
};

class Derived final: public Base
   4006a8:	e8 83 ff ff ff       	callq  400630 <_ZdlPv@plt>
   4006ad:	48 83 c3 08          	add    $0x8,%rbx

Thank you,
Martin

>
>> My question is how can one help compiler if he knows that a class hierarchy
>> is complete and there's no destructor except the virtual for base class?



More information about the Gcc mailing list