From ffb945ffb5d29b80fd93649c3572b6d87abce3fc Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Sat, 14 May 2011 23:26:09 +0000 Subject: 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131368 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/CGClass.cpp | 35 ++++++++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) (limited to 'lib/CodeGen/CGClass.cpp') 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(); + if (!RT) + continue; + + CXXRecordDecl *FieldClassDecl = cast(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(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(Body)->getTryBlock()); -- cgit v1.2.3-18-g5258