[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