summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2011-05-14 23:26:09 +0000
committerAnders Carlsson <andersca@mac.com>2011-05-14 23:26:09 +0000
commit9bd7d16440f97821fe2d036f3118c5c7aae926bb (patch)
treebc635b613f3e4c8459ee8b57904e07d4bec87ee5 /clang/lib
parent1eace078a48af107906ec49f3156a86e282360d3 (diff)
downloadbcm5719-llvm-9bd7d16440f97821fe2d036f3118c5c7aae926bb.tar.gz
bcm5719-llvm-9bd7d16440f97821fe2d036f3118c5c7aae926bb.zip
When emitting the destructor for a class with a vtable, if we can determine
that the destructor body is trivial and that all member variables also have either trivial destructors or trivial destructor bodies, we don't need to initialize the vtable pointers since no virtual member functions will be called on the destructor. Fixes PR9181. llvm-svn: 131368
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Decl.cpp14
-rw-r--r--clang/lib/CodeGen/CGCXX.cpp13
-rw-r--r--clang/lib/CodeGen/CGClass.cpp35
3 files changed, 49 insertions, 13 deletions
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index b57c6ab7d76..d4df017383d 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -1422,6 +1422,20 @@ bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
return false;
}
+bool FunctionDecl::hasTrivialBody() const
+{
+ Stmt *S = getBody();
+ if (!S) {
+ // Since we don't have a body for this function, we don't know if it's
+ // trivial or not.
+ return false;
+ }
+
+ if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
+ return true;
+ return false;
+}
+
bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const {
for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
if (I->IsDeleted || I->Body || I->IsLateTemplateParsed) {
diff --git a/clang/lib/CodeGen/CGCXX.cpp b/clang/lib/CodeGen/CGCXX.cpp
index 4390f3a3e3e..f6fc202eaae 100644
--- a/clang/lib/CodeGen/CGCXX.cpp
+++ b/clang/lib/CodeGen/CGCXX.cpp
@@ -28,17 +28,6 @@
using namespace clang;
using namespace CodeGen;
-/// Determines whether the given function has a trivial body that does
-/// not require any specific codegen.
-static bool HasTrivialBody(const FunctionDecl *FD) {
- Stmt *S = FD->getBody();
- if (!S)
- return true;
- if (isa<CompoundStmt>(S) && cast<CompoundStmt>(S)->body_empty())
- return true;
- return false;
-}
-
/// Try to emit a base destructor as an alias to its primary
/// base-class destructor.
bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
@@ -47,7 +36,7 @@ bool CodeGenModule::TryEmitBaseDestructorAsAlias(const CXXDestructorDecl *D) {
// If the destructor doesn't have a trivial body, we have to emit it
// separately.
- if (!HasTrivialBody(D))
+ if (!D->hasTrivialBody())
return true;
const CXXRecordDecl *Class = D->getParent();
diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp
index 4172948b602..785b9e129a1 100644
--- a/clang/lib/CodeGen/CGClass.cpp
+++ b/clang/lib/CodeGen/CGClass.cpp
@@ -741,6 +741,38 @@ void CodeGenFunction::EmitCtorPrologue(const CXXConstructorDecl *CD,
EmitMemberInitializer(*this, ClassDecl, MemberInitializers[I], CD, Args);
}
+/// CanSkipVTablePointerInitialization - Check whether we need to initialize
+/// any vtable pointers before calling this destructor.
+static bool CanSkipVTablePointerInitialization(ASTContext &Context,
+ const CXXDestructorDecl *Dtor) {
+ if (!Dtor->hasTrivialBody())
+ return false;
+
+ // Check the fields.
+ const CXXRecordDecl *ClassDecl = Dtor->getParent();
+ for (CXXRecordDecl::field_iterator I = ClassDecl->field_begin(),
+ E = ClassDecl->field_end(); I != E; ++I) {
+ const FieldDecl *Field = *I;
+
+ QualType FieldBaseElementType =
+ Context.getBaseElementType(Field->getType());
+
+ const RecordType *RT = FieldBaseElementType->getAs<RecordType>();
+ if (!RT)
+ continue;
+
+ CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
+ if (FieldClassDecl->hasTrivialDestructor())
+ continue;
+ if (FieldClassDecl->getDestructor()->hasTrivialBody())
+ continue;
+
+ return false;
+ }
+
+ return true;
+}
+
/// EmitDestructorBody - Emits the body of the current destructor.
void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
const CXXDestructorDecl *Dtor = cast<CXXDestructorDecl>(CurGD.getDecl());
@@ -792,7 +824,8 @@ void CodeGenFunction::EmitDestructorBody(FunctionArgList &Args) {
EnterDtorCleanups(Dtor, Dtor_Base);
// Initialize the vtable pointers before entering the body.
- InitializeVTablePointers(Dtor->getParent());
+ if (!CanSkipVTablePointerInitialization(getContext(), Dtor))
+ InitializeVTablePointers(Dtor->getParent());
if (isTryBody)
EmitStmt(cast<CXXTryStmt>(Body)->getTryBlock());
OpenPOWER on IntegriCloud