Skip to content

Commit 405c2b1

Browse files
committed
Devirtualize destructor of final class.
Summary: Take advantage of the final keyword to devirtualize destructor calls. Fix https://bugs.llvm.org/show_bug.cgi?id=21368 Reviewers: rsmith Reviewed By: rsmith Subscribers: davidxl, Prazek, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D63161 llvm-svn: 364100
1 parent 22e3dc6 commit 405c2b1

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

clang/lib/CodeGen/CGExprCXX.cpp

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1865,9 +1865,33 @@ static void EmitObjectDelete(CodeGenFunction &CGF,
18651865
Dtor = RD->getDestructor();
18661866

18671867
if (Dtor->isVirtual()) {
1868-
CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType,
1869-
Dtor);
1870-
return;
1868+
bool UseVirtualCall = true;
1869+
const Expr *Base = DE->getArgument();
1870+
if (auto *DevirtualizedDtor =
1871+
dyn_cast_or_null<const CXXDestructorDecl>(
1872+
Dtor->getDevirtualizedMethod(
1873+
Base, CGF.CGM.getLangOpts().AppleKext))) {
1874+
UseVirtualCall = false;
1875+
const CXXRecordDecl *DevirtualizedClass =
1876+
DevirtualizedDtor->getParent();
1877+
if (declaresSameEntity(getCXXRecord(Base), DevirtualizedClass)) {
1878+
// Devirtualized to the class of the base type (the type of the
1879+
// whole expression).
1880+
Dtor = DevirtualizedDtor;
1881+
} else {
1882+
// Devirtualized to some other type. Would need to cast the this
1883+
// pointer to that type but we don't have support for that yet, so
1884+
// do a virtual call. FIXME: handle the case where it is
1885+
// devirtualized to the derived type (the type of the inner
1886+
// expression) as in EmitCXXMemberOrOperatorMemberCallExpr.
1887+
UseVirtualCall = true;
1888+
}
1889+
}
1890+
if (UseVirtualCall) {
1891+
CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType,
1892+
Dtor);
1893+
return;
1894+
}
18711895
}
18721896
}
18731897
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s
2+
3+
namespace Test1 {
4+
struct A { virtual ~A() {} };
5+
struct B final : A {};
6+
struct C : A { virtual ~C() final {} };
7+
struct D { virtual ~D() final = 0; };
8+
// CHECK-LABEL: define void @_ZN5Test13fooEPNS_1BE
9+
void foo(B *b) {
10+
// CHECK: call void @_ZN5Test11BD1Ev
11+
delete b;
12+
}
13+
// CHECK-LABEL: define void @_ZN5Test14foo2EPNS_1CE
14+
void foo2(C *c) {
15+
// CHECK: call void @_ZN5Test11CD1Ev
16+
delete c;
17+
}
18+
// CHECK-LABEL: define void @_ZN5Test14evilEPNS_1DE
19+
void evil(D *p) {
20+
// CHECK-NOT: call void @_ZN5Test11DD1Ev
21+
delete p;
22+
}
23+
}

0 commit comments

Comments
 (0)