]> granicus.if.org Git - clang/commitdiff
When initializing a catch variable in ARC, be sure to emit retains
authorJohn McCall <rjmccall@apple.com>
Tue, 17 Jan 2012 20:16:56 +0000 (20:16 +0000)
committerJohn McCall <rjmccall@apple.com>
Tue, 17 Jan 2012 20:16:56 +0000 (20:16 +0000)
or whatever else is required for the initialization instead of
assuming it can be done with a simple store.

Fixes PR11732.

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

lib/CodeGen/CGException.cpp
lib/CodeGen/CGObjCRuntime.cpp
test/CodeGenObjC/arc-exceptions.m [new file with mode: 0644]
test/CodeGenObjCXX/arc-exceptions.mm [new file with mode: 0644]

index 15d8d42fa2c71a7d47f5c573c0e14efcd2399f89..7600c48bdbccd61e97d6868dbbc26b34252e3719 100644 (file)
@@ -984,8 +984,23 @@ static void InitCatchParam(CodeGenFunction &CGF,
     if (CatchType->hasPointerRepresentation()) {
       llvm::Value *CastExn =
         CGF.Builder.CreateBitCast(AdjustedExn, LLVMCatchTy, "exn.casted");
-      CGF.Builder.CreateStore(CastExn, ParamAddr);
-      return;
+
+      switch (CatchType.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, ParamAddr);
+        return;
+
+      case Qualifiers::OCL_Weak:
+        CGF.EmitARCInitWeak(ParamAddr, CastExn);
+        return;
+      }
+      llvm_unreachable("bad ownership qualifier!");
     }
 
     // Otherwise, it returns a pointer into the exception object.
index 7cedf400ae61bd0631b1a9e7b10de9113046628b..30be4008c0825792fa56d6f31b443436b4ae36d6 100644 (file)
@@ -246,7 +246,24 @@ void CGObjCRuntime::EmitTryCatchStmt(CodeGenFunction &CGF,
       llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);
 
       CGF.EmitAutoVarDecl(*CatchParam);
-      CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam));
+
+      llvm::Value *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;
+      }
     }
 
     CGF.ObjCEHValueStack.push_back(Exn);
diff --git a/test/CodeGenObjC/arc-exceptions.m b/test/CodeGenObjC/arc-exceptions.m
new file mode 100644 (file)
index 0000000..5ef5aba
--- /dev/null
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fobjc-runtime-has-weak -o - %s | FileCheck %s
+
+@class Ety;
+
+// These first two tests are all PR11732 / rdar://problem/10667070.
+
+void test0_helper(void);
+void test0(void) {
+  @try {
+    test0_helper();
+  } @catch (Ety *e) {
+  }
+}
+// CHECK: define void @test0()
+// CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
+// CHECK-NEXT: invoke void @test0_helper()
+// CHECK:      [[T0:%.*]] = call i8* @objc_begin_catch(
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind
+// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
+// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
+// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind
+// CHECK-NEXT: call void @objc_end_catch() nounwind
+
+void test1_helper(void);
+void test1(void) {
+  @try {
+    test1_helper();
+  } @catch (__weak Ety *e) {
+  }
+}
+// CHECK: define void @test1()
+// CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
+// CHECK-NEXT: invoke void @test1_helper()
+// CHECK:      [[T0:%.*]] = call i8* @objc_begin_catch(
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
+// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind
+// CHECK-NEXT: call void @objc_end_catch() nounwind
diff --git a/test/CodeGenObjCXX/arc-exceptions.mm b/test/CodeGenObjCXX/arc-exceptions.mm
new file mode 100644 (file)
index 0000000..b1fa8ca
--- /dev/null
@@ -0,0 +1,85 @@
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -fobjc-arc -fexceptions -fobjc-exceptions -fcxx-exceptions -fobjc-runtime-has-weak -o - %s | FileCheck %s
+
+@class Ety;
+
+// These first four tests are all PR11732 / rdar://problem/10667070.
+
+void test0_helper(void);
+void test0(void) {
+  @try {
+    test0_helper();
+  } @catch (Ety *e) {
+  }
+}
+// CHECK: define void @_Z5test0v()
+// CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
+// CHECK-NEXT: invoke void @_Z12test0_helperv()
+// CHECK:      [[T0:%.*]] = call i8* @objc_begin_catch(
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind
+// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
+// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
+// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind
+// CHECK-NEXT: call void @objc_end_catch() nounwind
+
+void test1_helper(void);
+void test1(void) {
+  @try {
+    test1_helper();
+  } @catch (__weak Ety *e) {
+  }
+}
+// CHECK: define void @_Z5test1v()
+// CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
+// CHECK-NEXT: invoke void @_Z12test1_helperv()
+// CHECK:      [[T0:%.*]] = call i8* @objc_begin_catch(
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
+// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind
+// CHECK-NEXT: call void @objc_end_catch() nounwind
+
+void test2_helper(void);
+void test2(void) {
+  try {
+    test2_helper();
+  } catch (Ety *e) {
+  }
+}
+// CHECK: define void @_Z5test2v()
+// CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
+// CHECK-NEXT: invoke void @_Z12test2_helperv()
+// CHECK:      [[T0:%.*]] = call i8* @__cxa_begin_catch(
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
+// CHECK-NEXT: [[T3:%.*]] = call i8* @objc_retain(i8* [[T2]]) nounwind
+// CHECK-NEXT: [[T4:%.*]] = bitcast i8* [[T3]] to [[ETY]]*
+// CHECK-NEXT: store [[ETY]]* [[T4]], [[ETY]]** [[E]]
+// CHECK-NEXT: [[T0:%.*]] = load [[ETY]]** [[E]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast [[ETY]]* [[T0]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T1]]) nounwind
+// CHECK-NEXT: call void @__cxa_end_catch() nounwind
+
+void test3_helper(void);
+void test3(void) {
+  try {
+    test3_helper();
+  } catch (Ety * __weak e) {
+  }
+}
+// CHECK: define void @_Z5test3v()
+// CHECK:      [[E:%.*]] = alloca [[ETY:%.*]]*, align 8
+// CHECK-NEXT: invoke void @_Z12test3_helperv()
+// CHECK:      [[T0:%.*]] = call i8* @__cxa_begin_catch(
+// CHECK-NEXT: [[T1:%.*]] = bitcast i8* [[T0]] to [[ETY]]*
+// CHECK-NEXT: [[T2:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: [[T3:%.*]] = bitcast [[ETY]]* [[T1]] to i8*
+// CHECK-NEXT: call i8* @objc_initWeak(i8** [[T2]], i8* [[T3]]) nounwind
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[ETY]]** [[E]] to i8**
+// CHECK-NEXT: call void @objc_destroyWeak(i8** [[T0]]) nounwind
+// CHECK-NEXT: call void @__cxa_end_catch() nounwind