diff options
| author | John McCall <rjmccall@apple.com> | 2012-09-25 06:56:03 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2012-09-25 06:56:03 +0000 |
| commit | b0433eeb2e536e21a62030fd2f17d94ad2a1d2f5 (patch) | |
| tree | 3b0fba774252c9e3043a44518153aa21b131efcd /clang/test/CodeGenObjC | |
| parent | 446ff28df1242fcd11ce1df18af9c944afdcbdd3 (diff) | |
| download | bcm5719-llvm-b0433eeb2e536e21a62030fd2f17d94ad2a1d2f5.tar.gz bcm5719-llvm-b0433eeb2e536e21a62030fd2f17d94ad2a1d2f5.zip | |
During jump-scope checking, build an ExprWithCleanups immediately
into the enclosing scope; this is a more accurate model but is
(I believe) unnecessary in my test case due to other flaws.
However, one of those flaws is now intentional: blocks which
appear in return statements can be trivially observed to not
extend in lifetime past the return, and so we can allow a jump
past them. Do the necessary magic in IR-generation to make
this work.
llvm-svn: 164589
Diffstat (limited to 'clang/test/CodeGenObjC')
| -rw-r--r-- | clang/test/CodeGenObjC/arc-blocks.m | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/clang/test/CodeGenObjC/arc-blocks.m b/clang/test/CodeGenObjC/arc-blocks.m index 2326bce2be2..cbdb49418b2 100644 --- a/clang/test/CodeGenObjC/arc-blocks.m +++ b/clang/test/CodeGenObjC/arc-blocks.m @@ -532,3 +532,60 @@ void test16() { // CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 // CHECK-NEXT: store void ()* null, void ()** [[BLKVAR]], align 8 } + +// rdar://12151005 +// +// This is an intentional exception to our conservative jump-scope +// checking for full-expressions containing block literals with +// non-trivial cleanups: if the block literal appears in the operand +// of a return statement, there's no need to extend its lifetime. +id (^test17(id self, int which))(void) { + switch (which) { + case 1: return ^{ return self; }; + case 0: return ^{ return self; }; + } + return (void*) 0; +} +// CHECK: define i8* ()* @test17( +// CHECK: [[RET:%.*]] = alloca i8* ()*, align +// CHECK-NEXT: [[SELF:%.*]] = alloca i8*, +// CHECK: [[B0:%.*]] = alloca [[BLOCK:<.*>]], align +// CHECK: [[B1:%.*]] = alloca [[BLOCK]], align +// CHECK: [[T0:%.*]] = call i8* @objc_retain(i8* +// CHECK-NEXT: store i8* [[T0]], i8** [[SELF]], align +// CHECK-NOT: objc_retain +// CHECK-NOT: objc_release +// CHECK: [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]]* [[B0]], i32 0, i32 5 +// CHECK-NOT: objc_retain +// CHECK-NOT: objc_release +// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK]]* [[B0]], i32 0, i32 5 +// CHECK-NEXT: [[T1:%.*]] = load i8** [[SELF]], align +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: store i8* [[T2]], i8** [[T0]], +// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B0]] to i8* ()* +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()* +// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]] +// CHECK-NEXT: [[T0:%.*]] = load i8** [[DESTROY]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) +// CHECK-NEXT: store i32 +// CHECK-NEXT: br label +// CHECK-NOT: objc_retain +// CHECK-NOT: objc_release +// CHECK: [[DESTROY:%.*]] = getelementptr inbounds [[BLOCK]]* [[B1]], i32 0, i32 5 +// CHECK-NOT: objc_retain +// CHECK-NOT: objc_release +// CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK]]* [[B1]], i32 0, i32 5 +// CHECK-NEXT: [[T1:%.*]] = load i8** [[SELF]], align +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]]) +// CHECK-NEXT: store i8* [[T2]], i8** [[T0]], +// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK]]* [[B1]] to i8* ()* +// CHECK-NEXT: [[T1:%.*]] = bitcast i8* ()* [[T0]] to i8* +// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retainBlock(i8* [[T1]]) +// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to i8* ()* +// CHECK-NEXT: store i8* ()* [[T3]], i8* ()** [[RET]] +// CHECK-NEXT: [[T0:%.*]] = load i8** [[DESTROY]] +// CHECK-NEXT: call void @objc_release(i8* [[T0]]) +// CHECK-NEXT: store i32 +// CHECK-NEXT: br label |

