]> granicus.if.org Git - clang/commitdiff
Convert the EH cleanups for base and member destructors in a constructor into
authorJohn McCall <rjmccall@apple.com>
Wed, 21 Jul 2010 01:23:41 +0000 (01:23 +0000)
committerJohn McCall <rjmccall@apple.com>
Wed, 21 Jul 2010 01:23:41 +0000 (01:23 +0000)
lazy cleanups.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@108978 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGClass.cpp
test/CodeGenCXX/destructors.cpp

index 799dd644a2e03b9e30942251d5d44a0873b6cda5..bc42ecb3f56565d8f54ccb3f6116f24ecb246490 100644 (file)
@@ -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<CallBaseDtor>(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<CXXRecordDecl>(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<CallMemberDtor>(EHCleanup, Field,
+                                                  RD->getDestructor());
   }
 }
 
index 8efaf01f3c608f7d6b643afb7b101164031291dc..185854a34ed88031cea85f04f05b0a5fdad69a47 100644 (file)
@@ -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(