[cfe-commits] r159326 - in /cfe/trunk: include/clang/AST/Expr.h lib/AST/Expr.cpp lib/CodeGen/CGExprCXX.cpp test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp

John McCall rjmccall at apple.com
Wed Jun 27 21:56:54 PDT 2012


On Jun 27, 2012, at 9:47 PM, Rafael EspĂ­ndola wrote:
>> Inner (and therefore "this") will indeed have type MostDerivedClassDecl
>> here, but that's not necessarily the type that declares the final override for
>> the method being called:
>> 
>>  struct Primary { virtual ~Primary(); void *member; };
>> 
>>  struct A { virtual void foo(); }; // its own final override
>>  struct final B : Primary, A {}; // most derived
>>  void test(B *b) {
>>    b->foo();
>>  }
>> 
>> My example happens to have us devirtualize to the original method,
>> but that's not necessarily the case;  you can have arbitrary inheritance
>> and overriding between A and the most-derived class, like so:
>> 
>>  struct A { virtual void foo(); };
>>  struct B : A { virtual void foo(); }; // final override
>>  struct final C : Primary, B {}; // most derived
>>  void test(C *c) {
>>    static_cast<A*>(c)->foo();
>>  }
>> 
>> And of course the offset from A to B doesn't have to be zero, either:
>> 
>>  struct A { virtual void foo(); };
>>  struct B : Primary, A { virtual void foo(); }; // final override
>>  struct final C : Primary, B {}; // most derived
>>  void test(C *c) {
>>    static_cast<A*>(d)->foo();
>>  }
>> 
>> Really, you have to do a derived-to-base conversion from the most-derived
>> class to the base actually declaring the method.  Fortunately, that can't
>> actually fail (they can in general, due to ambiguity) because of the
>> well-formedness constraints on final overriders.
> 
> Thanks!
> 
> I think a valid summary is that there are 3 types we have to consider:
> 
> 1 The type of the expression
> 2 The type of the most derived dynamic class we can find
> 3 The type of the class defining the method we want to call
> 
> Computing the this pointer is simple when type 3 is the same as type 1
> or 2. When that is not the case we have to construct a cast, which
> doesn't look trivial to do from CodeGen given that the methods for
> handling CXXCastPath are in sema (should we do part of the
> devirtualization in sema?).
> 
> My current idea is to just drop the optimization when type 3 is not
> equal to type 1 or 2. The attached hackish patch does that. I will try
> to clean it up in the morning, but now I need some sleep :-)

There's actually another problem that I hadn't initially considered, which
is that the final overrider may have a covariant return type requiring
adjustment.

I think we should just drop the optimization for now if the final overrider
is not the method that was type-checked against;  that will still catch
the most important case, which is when someone directly calls a
method on an object of final type but the method happens to be
implemented on a base class.  We can file a bug to revisit the more
aggressive optimization later.

John.



More information about the cfe-commits mailing list