diff options
author | John McCall <rjmccall@apple.com> | 2010-09-18 02:24:39 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2010-09-18 02:24:39 +0000 |
commit | f09d96f76d6c87c3527285e867ebfa7606e49556 (patch) | |
tree | f5ddfe4085bf825d6dffa47e64145e69a7b36216 /clang/lib/CodeGen/CodeGenFunction.cpp | |
parent | 6ba7815115c9f29f652a21d1e348f7b6099cf6cb (diff) | |
download | bcm5719-llvm-f09d96f76d6c87c3527285e867ebfa7606e49556.tar.gz bcm5719-llvm-f09d96f76d6c87c3527285e867ebfa7606e49556.zip |
Adjust a fixup's starting branch if it's being resolved because
it reached the outermost scope and it hasn't yet been forwarded
to a cleanup. Fixed PR8175.
llvm-svn: 114259
Diffstat (limited to 'clang/lib/CodeGen/CodeGenFunction.cpp')
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 35 |
1 files changed, 29 insertions, 6 deletions
diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index aae8ecf6670..c2016e83863 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -28,6 +28,10 @@ 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) { |