diff options
| author | John McCall <rjmccall@apple.com> | 2011-09-10 01:16:55 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2011-09-10 01:16:55 +0000 |
| commit | cd78e805e9c0d1a1b7ccbb67773aa51589c040f7 (patch) | |
| tree | 0d46a178933812aaad4d14ba3d3449b2397061fb /clang/test | |
| parent | a51d74fc35aafa7c609e950cfc6e39146a8280cb (diff) | |
| download | bcm5719-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.m | 37 |
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 +} |

