From: John McCall Date: Wed, 21 Jul 2010 01:23:41 +0000 (+0000) Subject: Convert the EH cleanups for base and member destructors in a constructor into X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=182ab5112650d3228291c4dadd64a9f77f5aeb51;p=clang Convert the EH cleanups for base and member destructors in a constructor into lazy cleanups. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108978 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp index 799dd644a2..bc42ecb3f5 100644 --- a/lib/CodeGen/CGClass.cpp +++ b/lib/CodeGen/CGClass.cpp @@ -310,6 +310,22 @@ static llvm::Value *GetVTTParameter(CodeGenFunction &CGF, GlobalDecl GD, return VTT; } +namespace { + struct CallBaseDtor : EHScopeStack::LazyCleanup { + CXXDestructorDecl *Dtor; + bool isBaseVirtual; + llvm::Value *Addr; + + CallBaseDtor(CXXDestructorDecl *DD, bool isVirtual, llvm::Value *Addr) + : Dtor(DD), isBaseVirtual(isVirtual), Addr(Addr) {} + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + // FIXME: Is this OK for C++0x delegating constructors? + CGF.EmitCXXDestructorCall(Dtor, Dtor_Base, isBaseVirtual, Addr); + } + }; +} + static void EmitBaseInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, CXXBaseOrMemberInitializer *BaseInit, @@ -338,13 +354,10 @@ static void EmitBaseInitializer(CodeGenFunction &CGF, CGF.EmitAggExpr(BaseInit->getInit(), V, false, false, true); - if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor()) { - // FIXME: Is this OK for C++0x delegating constructors? - CodeGenFunction::CleanupBlock Cleanup(CGF, EHCleanup); - - CXXDestructorDecl *DD = BaseClassDecl->getDestructor(); - CGF.EmitCXXDestructorCall(DD, Dtor_Base, isBaseVirtual, V); - } + if (CGF.Exceptions && !BaseClassDecl->hasTrivialDestructor()) + CGF.EHStack.pushLazyCleanup(EHCleanup, + BaseClassDecl->getDestructor(), + isBaseVirtual, V); } static void EmitAggMemberInitializer(CodeGenFunction &CGF, @@ -432,6 +445,25 @@ static void EmitAggMemberInitializer(CodeGenFunction &CGF, // Emit the fall-through block. CGF.EmitBlock(AfterFor, true); } + +namespace { + struct CallMemberDtor : EHScopeStack::LazyCleanup { + FieldDecl *Field; + CXXDestructorDecl *Dtor; + + CallMemberDtor(FieldDecl *Field, CXXDestructorDecl *Dtor) + : Field(Field), Dtor(Dtor) {} + + void Emit(CodeGenFunction &CGF, bool IsForEH) { + // FIXME: Is this OK for C++0x delegating constructors? + llvm::Value *ThisPtr = CGF.LoadCXXThis(); + LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0); + + CGF.EmitCXXDestructorCall(Dtor, Dtor_Complete, /*ForVirtualBase=*/false, + LHS.getAddress()); + } + }; +} static void EmitMemberInitializer(CodeGenFunction &CGF, const CXXRecordDecl *ClassDecl, @@ -532,17 +564,9 @@ static void EmitMemberInitializer(CodeGenFunction &CGF, return; CXXRecordDecl *RD = cast(RT->getDecl()); - if (!RD->hasTrivialDestructor()) { - // FIXME: Is this OK for C++0x delegating constructors? - CodeGenFunction::CleanupBlock Cleanup(CGF, EHCleanup); - - llvm::Value *ThisPtr = CGF.LoadCXXThis(); - LValue LHS = CGF.EmitLValueForField(ThisPtr, Field, 0); - - CXXDestructorDecl *DD = RD->getDestructor(); - CGF.EmitCXXDestructorCall(DD, Dtor_Complete, /*ForVirtualBase=*/false, - LHS.getAddress()); - } + if (!RD->hasTrivialDestructor()) + CGF.EHStack.pushLazyCleanup(EHCleanup, Field, + RD->getDestructor()); } } diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index 8efaf01f3c..185854a34e 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -262,11 +262,6 @@ namespace test5 { // Checks from test3: - // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev( - // CHECK: call void @_ZN5test31BD2Ev( - // CHECK: call void @_ZN5test31AD2Ev( - // CHECK: ret void - // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev( // CHECK: invoke void @_ZN5test312_GLOBAL__N_11DD1Ev( // CHECK: call void @_ZdlPv({{.*}}) nounwind @@ -289,6 +284,11 @@ namespace test5 { // CHECK: call void @_ZN5test312_GLOBAL__N_11DD0Ev( // CHECK: ret void + // CHECK: define internal void @_ZN5test312_GLOBAL__N_11CD2Ev( + // CHECK: call void @_ZN5test31BD2Ev( + // CHECK: call void @_ZN5test31AD2Ev( + // CHECK: ret void + // CHECK: declare void @_ZN5test31BD2Ev( // CHECK: declare void @_ZN5test31AD2Ev(