[cfe-commits] r92117 - /cfe/trunk/lib/CodeGen/CGObjCGNU.cpp

David Chisnall csdavec at swan.ac.uk
Wed Dec 23 18:26:35 PST 2009


Author: theraven
Date: Wed Dec 23 20:26:34 2009
New Revision: 92117

URL: http://llvm.org/viewvc/llvm-project?rev=92117&view=rev
Log:
Fix for bug 5691.

This fixes throwing exceptions inside @catch blocks nested inside outer @try blocks and also fixes jumping from an inner @finally to an outer @finally (via any relevant @catch blocks).

The code exhibiting this bug was based on code from CGObjCMac.  I believe that this bug may still be present on the Mac runtimes, although the test case in the bug contains a few GNUisms and won't compile without some minor tweaks with Apple's libobjc.


Modified:
    cfe/trunk/lib/CodeGen/CGObjCGNU.cpp

Modified: cfe/trunk/lib/CodeGen/CGObjCGNU.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGObjCGNU.cpp?rev=92117&r1=92116&r2=92117&view=diff

==============================================================================
--- cfe/trunk/lib/CodeGen/CGObjCGNU.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGObjCGNU.cpp Wed Dec 23 20:26:34 2009
@@ -1607,7 +1607,7 @@
   Params.push_back(PtrTy);
   llvm::Value *RethrowFn =
     CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
-          Params, false), "_Unwind_Resume_or_Rethrow");
+          Params, false), "objc_exception_throw");
 
   bool isTry = isa<ObjCAtTryStmt>(S);
   llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
@@ -1618,7 +1618,7 @@
   llvm::BasicBlock *FinallyRethrow = CGF.createBasicBlock("finally.throw");
   llvm::BasicBlock *FinallyEnd = CGF.createBasicBlock("finally.end");
 
-  // GNU runtime does not currently support @synchronized()
+  // @synchronized()
   if (!isTry) {
     std::vector<const llvm::Type*> Args(1, IdTy);
     llvm::FunctionType *FTy =
@@ -1770,7 +1770,13 @@
   ESelArgs.clear();
   ESelArgs.push_back(Exc);
   ESelArgs.push_back(Personality);
-  ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0));
+  // If there is a @catch or @finally clause in outside of this one then we
+  // need to make sure that we catch and rethrow it.  
+  if (PrevLandingPad) {
+    ESelArgs.push_back(NULLPtr);
+  } else {
+    ESelArgs.push_back(llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 0));
+  }
   CGF.Builder.CreateCall(llvm_eh_selector, ESelArgs.begin(), ESelArgs.end(),
       "selector");
   CGF.Builder.CreateCall(llvm_eh_typeid_for,
@@ -1811,11 +1817,23 @@
   CGF.EmitBranch(FinallyEnd);
 
   CGF.EmitBlock(FinallyRethrow);
-  CGF.Builder.CreateCall(RethrowFn, CGF.Builder.CreateLoad(RethrowPtr));
-  CGF.Builder.CreateUnreachable();
 
-  CGF.EmitBlock(FinallyEnd);
+  llvm::Value *ExceptionObject = CGF.Builder.CreateLoad(RethrowPtr);
+  llvm::BasicBlock *UnwindBB = CGF.getInvokeDest();
+  if (!UnwindBB) {
+    CGF.Builder.CreateCall(RethrowFn, ExceptionObject);
+    // Exception always thrown, next instruction is never reached.
+    CGF.Builder.CreateUnreachable();
+  } else {
+    // If there is a @catch block outside this scope, we invoke instead of
+    // calling because we may return to this function.  This is very slow, but
+    // some people still do it.  It would be nice to add an optimised path for
+    // this.
+    CGF.Builder.CreateInvoke(RethrowFn, UnwindBB, UnwindBB, &ExceptionObject,
+        &ExceptionObject+1);
+  }
 
+  CGF.EmitBlock(FinallyEnd);
 }
 
 void CGObjCGNU::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,





More information about the cfe-commits mailing list