[clang] Devirtualization for classes with destructors marked as 'final'

A class with a destructor marked final cannot be derived from, so it should afford the same devirtualization opportunities as marking the entire class final.

Patch by logan-5 (Logan Smith)
Reviewed by rsmith

Differential Revision: https://reviews.llvm.org/D66621

llvm-svn: 370597
This commit is contained in:
David Bolvansky 2019-08-31 18:52:44 +00:00
parent 8caa16ec13
commit 20b2708c18
2 changed files with 21 additions and 3 deletions

View File

@ -2067,10 +2067,15 @@ CXXMethodDecl *CXXMethodDecl::getDevirtualizedMethod(const Expr *Base,
if (DevirtualizedMethod->hasAttr<FinalAttr>())
return DevirtualizedMethod;
// Similarly, if the class itself is marked 'final' it can't be overridden
// and we can therefore devirtualize the member function call.
// Similarly, if the class itself or its destructor is marked 'final',
// the class can't be derived from and we can therefore devirtualize the
// member function call.
if (BestDynamicDecl->hasAttr<FinalAttr>())
return DevirtualizedMethod;
if (const auto *dtor = BestDynamicDecl->getDestructor()) {
if (dtor->hasAttr<FinalAttr>())
return DevirtualizedMethod;
}
if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl()))

View File

@ -24,11 +24,24 @@ namespace Test2 {
}
}
namespace Test3 {
namespace Test2a {
struct A {
virtual ~A() final {}
virtual int f();
};
// CHECK-LABEL: define i32 @_ZN6Test2a1fEPNS_1AE
int f(A *a) {
// CHECK: call i32 @_ZN6Test2a1A1fEv
return a->f();
}
}
namespace Test3 {
struct A {
virtual int f(); };
struct B final : A { };
// CHECK-LABEL: define i32 @_ZN5Test31fEPNS_1BE