]> granicus.if.org Git - clang/commitdiff
Adjust a fixup's starting branch if it's being resolved because
authorJohn McCall <rjmccall@apple.com>
Sat, 18 Sep 2010 02:24:39 +0000 (02:24 +0000)
committerJohn McCall <rjmccall@apple.com>
Sat, 18 Sep 2010 02:24:39 +0000 (02:24 +0000)
it reached the outermost scope and it hasn't yet been forwarded
to a cleanup.  Fixed PR8175.

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

lib/CodeGen/CodeGenFunction.cpp
lib/CodeGen/CodeGenFunction.h

index aae8ecf66703377d32e0f1a2bd322d1ccd661e13..c2016e83863e66134f4e0ad06414124172239421 100644 (file)
 using namespace clang;
 using namespace CodeGen;
 
+static void ResolveAllBranchFixups(CodeGenFunction &CGF,
+                                   llvm::SwitchInst *Switch,
+                                   llvm::BasicBlock *CleanupEntry);
+
 CodeGenFunction::CodeGenFunction(CodeGenModule &cgm)
   : BlockFunction(cgm, *this, Builder), CGM(cgm),
     Target(CGM.getContext().Target),
@@ -1075,8 +1079,10 @@ void CodeGenFunction::PopCleanupBlock(bool FallthroughIsBranchThrough) {
                           Scope.getBranchAfterBlock(I));
         }
 
+        // If there aren't any enclosing cleanups, we can resolve all
+        // the fixups now.
         if (HasFixups && !HasEnclosingCleanups)
-          ResolveAllBranchFixups(Switch);
+          ResolveAllBranchFixups(*this, Switch, NormalEntry);
       } else {
         // We should always have a branch-through destination in this case.
         assert(BranchThroughDest);
@@ -1325,21 +1331,38 @@ void CodeGenFunction::EmitBranchThroughEHCleanup(UnwindDest Dest) {
 /// All the branch fixups on the EH stack have propagated out past the
 /// outermost normal cleanup; resolve them all by adding cases to the
 /// given switch instruction.
-void CodeGenFunction::ResolveAllBranchFixups(llvm::SwitchInst *Switch) {
+static void ResolveAllBranchFixups(CodeGenFunction &CGF,
+                                   llvm::SwitchInst *Switch,
+                                   llvm::BasicBlock *CleanupEntry) {
   llvm::SmallPtrSet<llvm::BasicBlock*, 4> CasesAdded;
 
-  for (unsigned I = 0, E = EHStack.getNumBranchFixups(); I != E; ++I) {
+  for (unsigned I = 0, E = CGF.EHStack.getNumBranchFixups(); I != E; ++I) {
     // Skip this fixup if its destination isn't set or if we've
     // already treated it.
-    BranchFixup &Fixup = EHStack.getBranchFixup(I);
+    BranchFixup &Fixup = CGF.EHStack.getBranchFixup(I);
     if (Fixup.Destination == 0) continue;
     if (!CasesAdded.insert(Fixup.Destination)) continue;
 
-    Switch->addCase(Builder.getInt32(Fixup.DestinationIndex),
+    // If there isn't an OptimisticBranchBlock, then InitialBranch is
+    // still pointing directly to its destination; forward it to the
+    // appropriate cleanup entry.  This is required in the specific
+    // case of
+    //   { std::string s; goto lbl; }
+    //   lbl:
+    // i.e. where there's an unresolved fixup inside a single cleanup
+    // entry which we're currently popping.
+    if (Fixup.OptimisticBranchBlock == 0) {
+      new llvm::StoreInst(CGF.Builder.getInt32(Fixup.DestinationIndex),
+                          CGF.getNormalCleanupDestSlot(),
+                          Fixup.InitialBranch);
+      Fixup.InitialBranch->setSuccessor(0, CleanupEntry);
+    }
+
+    Switch->addCase(CGF.Builder.getInt32(Fixup.DestinationIndex),
                     Fixup.Destination);
   }
 
-  EHStack.clearFixups();
+  CGF.EHStack.clearFixups();
 }
 
 void CodeGenFunction::ResolveBranchFixups(llvm::BasicBlock *Block) {
index 4a5beb4baa15cb6c875d5a392f3d682380871b1a..d2fa57a9edc350d0f785dcc0fdcb23baf70bfb91 100644 (file)
@@ -414,7 +414,7 @@ public:
   void popNullFixups();
 
   /// Clears the branch-fixups list.  This should only be called by
-  /// CodeGenFunction::ResolveAllBranchFixups.
+  /// ResolveAllBranchFixups.
   void clearFixups() { BranchFixups.clear(); }
 
   /// Gets the next EH destination index.
@@ -625,7 +625,6 @@ public:
   /// the cleanup blocks that have been added.
   void PopCleanupBlocks(EHScopeStack::stable_iterator OldCleanupStackSize);
 
-  void ResolveAllBranchFixups(llvm::SwitchInst *Switch);
   void ResolveBranchFixups(llvm::BasicBlock *Target);
 
   /// The given basic block lies in the current EH scope, but may be a