More refactoring around constructor/destructor code generation.
Fix some bugs with function-try-blocks and simplify normal try-block
code generation.

This implementation excludes a deleting destructor's call to
operator delete() from the function-try-block, which I believe
is correct but which I can't find straightforward support for at
a moment's glance.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@96670 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp
index d956c1c..142cb81 100644
--- a/lib/CodeGen/CGException.cpp
+++ b/lib/CodeGen/CGException.cpp
@@ -427,6 +427,26 @@
 }
 
 void CodeGenFunction::EmitCXXTryStmt(const CXXTryStmt &S) {
+  CXXTryStmtInfo Info = EnterCXXTryStmt(S);
+  EmitStmt(S.getTryBlock());
+  ExitCXXTryStmt(S, Info);
+}
+
+CodeGenFunction::CXXTryStmtInfo
+CodeGenFunction::EnterCXXTryStmt(const CXXTryStmt &S) {
+  CXXTryStmtInfo Info;
+  Info.SavedLandingPad = getInvokeDest();
+  Info.HandlerBlock = createBasicBlock("try.handler");
+  Info.FinallyBlock = createBasicBlock("finally");
+
+  PushCleanupBlock(Info.FinallyBlock);
+  setInvokeDest(Info.HandlerBlock);
+
+  return Info;
+}
+
+void CodeGenFunction::ExitCXXTryStmt(const CXXTryStmt &S,
+                                     CXXTryStmtInfo TryInfo) {
   // Pointer to the personality function
   llvm::Constant *Personality =
     CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty
@@ -439,54 +459,12 @@
   llvm::Value *llvm_eh_selector =
     CGM.getIntrinsic(llvm::Intrinsic::eh_selector);
 
-  llvm::BasicBlock *PrevLandingPad = getInvokeDest();
-  llvm::BasicBlock *TryHandler = createBasicBlock("try.handler");
-  llvm::BasicBlock *FinallyBlock = createBasicBlock("finally");
+  llvm::BasicBlock *PrevLandingPad = TryInfo.SavedLandingPad;
+  llvm::BasicBlock *TryHandler = TryInfo.HandlerBlock;
+  llvm::BasicBlock *FinallyBlock = TryInfo.FinallyBlock;
   llvm::BasicBlock *FinallyRethrow = createBasicBlock("finally.throw");
   llvm::BasicBlock *FinallyEnd = createBasicBlock("finally.end");
 
-  // Push an EH context entry, used for handling rethrows.
-  PushCleanupBlock(FinallyBlock);
-
-  // Emit the statements in the try {} block
-  setInvokeDest(TryHandler);
-
-  // FIXME: We should not have to do this here.  The AST should have the member
-  // initializers under the CXXTryStmt's TryBlock.
-  if (OuterTryBlock == &S) {
-    GlobalDecl GD = CurGD;
-    const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl());
-
-    if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
-      size_t OldCleanupStackSize = CleanupEntries.size();
-      EmitCtorPrologue(CD, CurGD.getCtorType());
-      EmitStmt(S.getTryBlock());
-
-      // If any of the member initializers are temporaries bound to references
-      // make sure to emit their destructors.
-      EmitCleanupBlocks(OldCleanupStackSize);
-    } else if (const CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(FD)) {
-      llvm::BasicBlock *DtorEpilogue  = createBasicBlock("dtor.epilogue");
-      PushCleanupBlock(DtorEpilogue);
-
-      InitializeVtablePtrs(DD->getParent());
-      EmitStmt(S.getTryBlock());
-
-      CleanupBlockInfo Info = PopCleanupBlock();
-
-      assert(Info.CleanupBlock == DtorEpilogue && "Block mismatch!");
-      EmitBlock(DtorEpilogue);
-      EmitDtorEpilogue(DD, GD.getDtorType());
-
-      if (Info.SwitchBlock)
-        EmitBlock(Info.SwitchBlock);
-      if (Info.EndBlock)
-        EmitBlock(Info.EndBlock);
-    } else
-      EmitStmt(S.getTryBlock());
-  } else
-    EmitStmt(S.getTryBlock());
-
   // Jump to end if there is no exception
   EmitBranchThroughCleanup(FinallyEnd);