diff options
Diffstat (limited to 'lib/CodeGen')
-rw-r--r-- | lib/CodeGen/CGException.cpp | 10 | ||||
-rw-r--r-- | lib/CodeGen/CGObjCMac.cpp | 21 |
2 files changed, 26 insertions, 5 deletions
diff --git a/lib/CodeGen/CGException.cpp b/lib/CodeGen/CGException.cpp index 99105e165f..746f68daee 100644 --- a/lib/CodeGen/CGException.cpp +++ b/lib/CodeGen/CGException.cpp @@ -1326,6 +1326,12 @@ namespace { CGF.EHStack.pushCleanup<CallEndCatchForFinally>(NormalAndEHCleanup, ForEHVar, EndCatchFn); + // Save the current cleanup destination in case there are + // cleanups in the finally block. + llvm::Value *SavedCleanupDest = + CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot(), + "cleanup.dest.saved"); + // Emit the finally block. CGF.EmitStmt(Body); @@ -1349,6 +1355,10 @@ namespace { CGF.Builder.CreateUnreachable(); CGF.EmitBlock(ContBB); + + // Restore the cleanup destination. + CGF.Builder.CreateStore(SavedCleanupDest, + CGF.getNormalCleanupDestSlot()); } // Leave the end-catch cleanup. As an optimization, pretend that diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp index 3a80330a2f..47e303fb1e 100644 --- a/lib/CodeGen/CGObjCMac.cpp +++ b/lib/CodeGen/CGObjCMac.cpp @@ -2674,11 +2674,22 @@ namespace { if (isa<ObjCAtTryStmt>(S)) { if (const ObjCAtFinallyStmt* FinallyStmt = - cast<ObjCAtTryStmt>(S).getFinallyStmt()) + cast<ObjCAtTryStmt>(S).getFinallyStmt()) { + // Save the current cleanup destination in case there's + // control flow inside the finally statement. + llvm::Value *CurCleanupDest = + CGF.Builder.CreateLoad(CGF.getNormalCleanupDestSlot()); + CGF.EmitStmt(FinallyStmt->getFinallyBody()); - // Currently, the end of the cleanup must always exist. - CGF.EnsureInsertPoint(); + if (CGF.HaveInsertPoint()) { + CGF.Builder.CreateStore(CurCleanupDest, + CGF.getNormalCleanupDestSlot()); + } else { + // Currently, the end of the cleanup must always exist. + CGF.EnsureInsertPoint(); + } + } } else { // Emit objc_sync_exit(expr); as finally's sole statement for // @synchronized. @@ -3030,8 +3041,8 @@ void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try"); llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler"); llvm::Value *DidCatch = - CGF.Builder.CreateIsNull(SetJmpResult, "did_catch_exception"); - CGF.Builder.CreateCondBr(DidCatch, TryBlock, TryHandler); + CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception"); + CGF.Builder.CreateCondBr(DidCatch, TryHandler, TryBlock); // Emit the protected block. CGF.EmitBlock(TryBlock); |