]> granicus.if.org Git - clang/commitdiff
Ensure we run cleanups for CXXTemporaries on the exceptional edge. WIP.
authorMike Stump <mrs@apple.com>
Thu, 17 Dec 2009 06:08:47 +0000 (06:08 +0000)
committerMike Stump <mrs@apple.com>
Thu, 17 Dec 2009 06:08:47 +0000 (06:08 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91588 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGException.cpp
lib/CodeGen/CGTemporaries.cpp

index c66bb46bd8c5687f8db82b85a053469481916082..debebf20ae6b3175dd759927d6eeb01ea45320c7 100644 (file)
@@ -150,17 +150,37 @@ static void CopyObject(CodeGenFunction &CGF, const Expr *E,
     } else if (CXXConstructorDecl *CopyCtor
                = RD->getCopyConstructor(CGF.getContext(), 0)) {
       llvm::BasicBlock *PrevLandingPad = CGF.getInvokeDest();
+      llvm::Value *CondPtr = 0;
       if (CGF.Exceptions) {
         CodeGenFunction::EHCleanupBlock Cleanup(CGF);
         llvm::Constant *FreeExceptionFn = getFreeExceptionFn(CGF);
         
+        llvm::BasicBlock *CondBlock = CGF.createBasicBlock("cond.free");
+        llvm::BasicBlock *Cont = CGF.createBasicBlock("cont");
+        CondPtr = CGF.CreateTempAlloca(llvm::Type::getInt1Ty(CGF.getLLVMContext()),
+                                       "doEHfree");
+
+        CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CondPtr),
+                                 CondBlock, Cont);
+        CGF.EmitBlock(CondBlock);
+
         // Load the exception pointer.
         llvm::Value *ExceptionPtr = CGF.Builder.CreateLoad(ExceptionPtrPtr);
         CGF.Builder.CreateCall(FreeExceptionFn, ExceptionPtr);
+
+        CGF.EmitBlock(Cont);
       }
 
+      if (CondPtr)
+        CGF.Builder.CreateStore(llvm::ConstantInt::getTrue(CGF.getLLVMContext()),
+                                CondPtr);
+
       llvm::Value *Src = CGF.EmitLValue(E).getAddress();
-      CGF.setInvokeDest(PrevLandingPad);
+        
+      //CGF.setInvokeDest(PrevLandingPad);
+      if (CondPtr)
+        CGF.Builder.CreateStore(llvm::ConstantInt::getFalse(CGF.getLLVMContext()),
+                                CondPtr);
 
       llvm::BasicBlock *TerminateHandler = CGF.getTerminateHandler();
       PrevLandingPad = CGF.getInvokeDest();
index 884c21230adaa22a44db72e01ad427cd81c5dcaf..8e214b46760e4bf136b17769369f4625151e8f86 100644 (file)
@@ -41,6 +41,33 @@ void CodeGenFunction::PushCXXTemporary(const CXXTemporary *Temporary,
                                                  CondPtr));
 
   PushCleanupBlock(DtorBlock);
+
+  if (Exceptions) {
+    const CXXLiveTemporaryInfo& Info = LiveTemporaries.back();
+    llvm::BasicBlock *CondEnd = 0;
+    
+    EHCleanupBlock Cleanup(*this);
+
+    // If this is a conditional temporary, we need to check the condition
+    // boolean and only call the destructor if it's true.
+    if (Info.CondPtr) {
+      llvm::BasicBlock *CondBlock = createBasicBlock("cond.dtor.call");
+      CondEnd = createBasicBlock("cond.dtor.end");
+
+      llvm::Value *Cond = Builder.CreateLoad(Info.CondPtr);
+      Builder.CreateCondBr(Cond, CondBlock, CondEnd);
+      EmitBlock(CondBlock);
+    }
+
+    EmitCXXDestructorCall(Info.Temporary->getDestructor(),
+                          Dtor_Complete, Info.ThisPtr);
+
+    if (CondEnd) {
+      // Reset the condition. to false.
+      Builder.CreateStore(llvm::ConstantInt::getFalse(VMContext), Info.CondPtr);
+      EmitBlock(CondEnd);
+    }
+  }
 }
 
 void CodeGenFunction::PopCXXTemporary() {