summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-09-10 01:16:55 +0000
committerJohn McCall <rjmccall@apple.com>2011-09-10 01:16:55 +0000
commitcd78e805e9c0d1a1b7ccbb67773aa51589c040f7 (patch)
tree0d46a178933812aaad4d14ba3d3449b2397061fb /clang/test
parenta51d74fc35aafa7c609e950cfc6e39146a8280cb (diff)
downloadbcm5719-llvm-cd78e805e9c0d1a1b7ccbb67773aa51589c040f7.tar.gz
bcm5719-llvm-cd78e805e9c0d1a1b7ccbb67773aa51589c040f7.zip
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
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGenObjC/arc.m37
1 files changed, 37 insertions, 0 deletions
diff --git a/clang/test/CodeGenObjC/arc.m b/clang/test/CodeGenObjC/arc.m
index 154918bb5b5..7982fd6ebc7 100644
--- a/clang/test/CodeGenObjC/arc.m
+++ b/clang/test/CodeGenObjC/arc.m
@@ -1855,3 +1855,40 @@ void test62(void) {
// 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
+}
OpenPOWER on IntegriCloud