When converting a block pointer to an Objective-C pointer type, extend
the lifetime of the block by copying it to the heap, or else we'll get
a dangling reference because the code working with the non-block-typed
object will not know it needs to copy.
There is some danger here, e.g. with assigning a block literal to an
unsafe variable, but, well, it's an unsafe variable.
llvm-svn: 139451
diff --git a/clang/test/CodeGenObjC/arc.m b/clang/test/CodeGenObjC/arc.m
index 154918b..7982fd6 100644
--- a/clang/test/CodeGenObjC/arc.m
+++ b/clang/test/CodeGenObjC/arc.m
@@ -1855,3 +1855,40 @@
// CHECK: call i8* @objc_getProperty
// CHECK: call void @objc_setProperty
+// rdar://problem/10088932
+void test64_helper(id);
+void test64a(void) {
+ int x;
+ test64_helper(^{ (void) x; });
+
+ // CHECK: define void @test64a()
+ // CHECK: [[X:%.*]] = alloca i32, align 4
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
+ // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
+ // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
+ // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
+ // CHECK-NEXT: call void @test64_helper(i8* [[T4]])
+ // CHECK-NEXT: [[T5:%.*]] = bitcast void ()* [[T3]] to i8*
+ // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: ret void
+}
+void test64b(void) {
+ int x;
+ id b = ^{ (void) x; };
+
+ // CHECK: define void @test64b()
+ // CHECK: [[X:%.*]] = alloca i32, align 4
+ // CHECK-NEXT: [[B:%.*]] = alloca i8*, align 8
+ // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8
+ // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
+ // CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+ // CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]])
+ // CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
+ // CHECK-NEXT: [[T4:%.*]] = bitcast void ()* [[T3]] to i8*
+ // CHECK-NEXT: store i8* [[T4]], i8** [[B]], align 8
+ // CHECK-NEXT: [[T5:%.*]] = load i8** [[B]]
+ // CHECK-NEXT: call void @objc_release(i8* [[T5]])
+ // CHECK-NEXT: ret void
+}