r286534 - PR30937: don't devirtualize if we find that the callee is a pure virtual
Mehdi Amini via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 10 18:12:21 PST 2016
Thinking again, the method “can” be implemented I think. Forget it…
—
Mehdi
> On Nov 10, 2016, at 6:11 PM, Mehdi Amini <mehdi.amini at apple.com> wrote:
>
> Could we emit llvm.unreachable in this case?
>
> —
> Mehdi
>
>> On Nov 10, 2016, at 5:01 PM, Richard Smith via cfe-commits <cfe-commits at lists.llvm.org> wrote:
>>
>> Author: rsmith
>> Date: Thu Nov 10 19:01:31 2016
>> New Revision: 286534
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=286534&view=rev
>> Log:
>> PR30937: don't devirtualize if we find that the callee is a pure virtual
>> function. In that case, there is no requirement that the callee is actually
>> defined, and the code may in fact be valid and have defined behavior if the
>> virtual call is unreachable.
>>
>> Modified:
>> cfe/trunk/lib/CodeGen/CGClass.cpp
>> cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
>>
>> Modified: cfe/trunk/lib/CodeGen/CGClass.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGClass.cpp?rev=286534&r1=286533&r2=286534&view=diff
>> ==============================================================================
>> --- cfe/trunk/lib/CodeGen/CGClass.cpp (original)
>> +++ cfe/trunk/lib/CodeGen/CGClass.cpp Thu Nov 10 19:01:31 2016
>> @@ -2851,9 +2851,9 @@ CodeGenFunction::CanDevirtualizeMemberFu
>> return false;
>>
>> // If the member function is marked 'final', we know that it can't be
>> - // overridden and can therefore devirtualize it.
>> + // overridden and can therefore devirtualize it unless it's pure virtual.
>> if (MD->hasAttr<FinalAttr>())
>> - return true;
>> + return !MD->isPure();
>>
>> // If the base expression (after skipping derived-to-base conversions) is a
>> // class prvalue, then we can devirtualize.
>> @@ -2861,31 +2861,28 @@ CodeGenFunction::CanDevirtualizeMemberFu
>> if (Base->isRValue() && Base->getType()->isRecordType())
>> return true;
>>
>> - // If the most derived class is marked final, we know that no subclass can
>> - // override this member function and so we can devirtualize it. For example:
>> - //
>> - // struct A { virtual void f(); }
>> - // struct B final : A { };
>> - //
>> - // void f(B *b) {
>> - // b->f();
>> - // }
>> - //
>> - if (const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType()) {
>> - if (BestDynamicDecl->hasAttr<FinalAttr>())
>> - return true;
>> -
>> - // There may be a method corresponding to MD in a derived class. If that
>> - // method is marked final, we can devirtualize it.
>> - const CXXMethodDecl *DevirtualizedMethod =
>> - MD->getCorrespondingMethodInClass(BestDynamicDecl);
>> - if (DevirtualizedMethod->hasAttr<FinalAttr>())
>> - return true;
>> - }
>> + // If we don't even know what we would call, we can't devirtualize.
>> + const CXXRecordDecl *BestDynamicDecl = Base->getBestDynamicClassType();
>> + if (!BestDynamicDecl)
>> + return false;
>> +
>> + // There may be a method corresponding to MD in a derived class.
>> + const CXXMethodDecl *DevirtualizedMethod =
>> + MD->getCorrespondingMethodInClass(BestDynamicDecl);
>> +
>> + // If that method is pure virtual, we can't devirtualize. If this code is
>> + // reached, the result would be UB, not a direct call to the derived class
>> + // function, and we can't assume the derived class function is defined.
>> + if (DevirtualizedMethod->isPure())
>> + return false;
>> +
>> + // If that method is marked final, we can devirtualize it.
>> + if (DevirtualizedMethod->hasAttr<FinalAttr>())
>> + return true;
>>
>> // Similarly, if the class itself is marked 'final' it can't be overridden
>> // and we can therefore devirtualize the member function call.
>> - if (MD->getParent()->hasAttr<FinalAttr>())
>> + if (BestDynamicDecl->hasAttr<FinalAttr>())
>> return true;
>>
>> if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Base)) {
>>
>> Modified: cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp
>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp?rev=286534&r1=286533&r2=286534&view=diff
>> ==============================================================================
>> --- cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp (original)
>> +++ cfe/trunk/test/CodeGenCXX/devirtualize-virtual-function-calls.cpp Thu Nov 10 19:01:31 2016
>> @@ -161,3 +161,37 @@ namespace test4 {
>> p->fish.eat();
>> }
>> }
>> +
>> +// Do not devirtualize to pure virtual function calls.
>> +namespace test5 {
>> + struct X {
>> + virtual void f() = 0;
>> + };
>> + struct Y {};
>> + // CHECK-LABEL: define {{.*}} @_ZN5test51f
>> + void f(Y &y, X Y::*p) {
>> + // CHECK-NOT: call {{.*}} @_ZN5test51X1fEv
>> + // CHECK: call void %
>> + (y.*p).f();
>> + };
>> +
>> + struct Z final {
>> + virtual void f() = 0;
>> + };
>> + // CHECK-LABEL: define {{.*}} @_ZN5test51g
>> + void g(Z &z) {
>> + // CHECK-NOT: call {{.*}} @_ZN5test51Z1fEv
>> + // CHECK: call void %
>> + z.f();
>> + }
>> +
>> + struct Q {
>> + virtual void f() final = 0;
>> + };
>> + // CHECK-LABEL: define {{.*}} @_ZN5test51h
>> + void h(Q &q) {
>> + // CHECK-NOT: call {{.*}} @_ZN5test51Q1fEv
>> + // CHECK: call void %
>> + q.f();
>> + }
>> +}
>>
>>
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
More information about the cfe-commits
mailing list