assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
// These types work out because ConvertType(id) == i8*.
- CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
+ EmitInitOfCatchParam(CGF, Caught, CatchParam);
}
CGF.EmitStmt(CatchStmt->getCatchBody());
llvm::Value *Tmp =
CGF.Builder.CreateBitCast(Caught,
CGF.ConvertType(CatchParam->getType()));
- CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
+ EmitInitOfCatchParam(CGF, Tmp, CatchParam);
CGF.EmitStmt(CatchStmt->getCatchBody());
llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);
CGF.EmitAutoVarDecl(*CatchParam);
-
- Address CatchParamAddr = CGF.GetAddrOfLocalVar(CatchParam);
-
- switch (CatchParam->getType().getQualifiers().getObjCLifetime()) {
- case Qualifiers::OCL_Strong:
- CastExn = CGF.EmitARCRetainNonBlock(CastExn);
- // fallthrough
-
- case Qualifiers::OCL_None:
- case Qualifiers::OCL_ExplicitNone:
- case Qualifiers::OCL_Autoreleasing:
- CGF.Builder.CreateStore(CastExn, CatchParamAddr);
- break;
-
- case Qualifiers::OCL_Weak:
- CGF.EmitARCInitWeak(CatchParamAddr, CastExn);
- break;
- }
+ EmitInitOfCatchParam(CGF, CastExn, CatchParam);
}
CGF.ObjCEHValueStack.push_back(Exn);
CGF.EmitBlock(Cont.getBlock());
}
+void CGObjCRuntime::EmitInitOfCatchParam(CodeGenFunction &CGF,
+ llvm::Value *exn,
+ const VarDecl *paramDecl) {
+
+ Address paramAddr = CGF.GetAddrOfLocalVar(paramDecl);
+
+ switch (paramDecl->getType().getQualifiers().getObjCLifetime()) {
+ case Qualifiers::OCL_Strong:
+ exn = CGF.EmitARCRetainNonBlock(exn);
+ // fallthrough
+
+ case Qualifiers::OCL_None:
+ case Qualifiers::OCL_ExplicitNone:
+ case Qualifiers::OCL_Autoreleasing:
+ CGF.Builder.CreateStore(exn, paramAddr);
+ return;
+
+ case Qualifiers::OCL_Weak:
+ CGF.EmitARCInitWeak(paramAddr, exn);
+ return;
+ }
+ llvm_unreachable("invalid ownership qualifier");
+}
+
namespace {
struct CallSyncExit final : EHScopeStack::Cleanup {
llvm::Value *SyncExitFn;
llvm::Constant *beginCatchFn,
llvm::Constant *endCatchFn,
llvm::Constant *exceptionRethrowFn);
+
+ void EmitInitOfCatchParam(CodeGenFunction &CGF, llvm::Value *exn,
+ const VarDecl *paramDecl);
+
/// Emits an \@synchronize() statement, using the \p syncEnterFn and
/// \p syncExitFn arguments as the functions called to lock and unlock
/// the object. This function can be called by subclasses that use
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s
-// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s -check-prefix=GLOBALS
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-apple-darwin10 -emit-llvm -fblocks -fobjc-arc -fobjc-exceptions -fobjc-runtime=macosx-fragile-10.10 -o - %s | FileCheck %s -check-prefix=GLOBALS
@class Opaque;
void testBlockLayoutWeak(__weak id x) {
useBlock(^{ (void) x; });
}
+
+// CHECK-LABEL: define void @testCatch()
+// CHECK: [[X:%.*]] = alloca [[A:%.*]]*, align 4
+// CHECK: [[Y:%.*]] = alloca i8*, align 4
+// CHECK: call void @objc_exception_try_enter
+// CHECK: br i1
+// CHECK: call void @checkpoint(i32 0)
+// CHECK: call void @objc_exception_try_exit
+// CHECK: br label
+// CHECK: call void @checkpoint(i32 3)
+// CHECK: [[EXN:%.*]] = call i8* @objc_exception_extract
+// CHECK: call i32 @objc_exception_match(
+// CHECK: br i1
+// CHECK: [[T0:%.*]] = bitcast i8* [[EXN]] to [[A]]*
+// CHECK: [[T1:%.*]] = bitcast [[A]]* [[T0]] to i8*
+// CHECK: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK: [[T3:%.*]] = bitcast i8* [[T2]] to [[A]]*
+// CHECK: store [[A]]* [[T3]], [[A]]** [[X]]
+// CHECK: call void @checkpoint(i32 1)
+// CHECK: [[T0:%.*]] = bitcast [[A]]** [[X]] to i8**
+// CHECK: call void @objc_storeStrong(i8** [[T0]], i8* null)
+// CHECK: br label
+// CHECK: [[T0:%.*]] = call i8* @objc_retain(i8* [[EXN]])
+// CHECK: store i8* [[T0]], i8** [[Y]]
+// CHECK: call void @checkpoint(i32 2)
+// CHECK: call void @objc_storeStrong(i8** [[Y]], i8* null)
+extern void checkpoint(int n);
+void testCatch() {
+ @try {
+ checkpoint(0);
+ } @catch (A *x) {
+ checkpoint(1);
+ } @catch (id y) {
+ checkpoint(2);
+ }
+ checkpoint(3);
+}