diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGCXX.cpp | 13 | ||||
-rw-r--r-- | lib/CodeGen/CGClass.cpp | 35 |
2 files changed, 35 insertions, 13 deletions
diff --git a/lib/CodeGen/CGCXX.cpp b/lib/CodeGen/CGCXX.cpp index 4390f3a3e3..f6fc202eaa 100644 --- a/lib/CodeGen/CGCXX.cpp +++ b/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/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 4172948b60..785b9e129a 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/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()); |