diff options
| author | John McCall <rjmccall@apple.com> | 2011-11-10 09:22:44 +0000 |
|---|---|---|
| committer | John McCall <rjmccall@apple.com> | 2011-11-10 09:22:44 +0000 |
| commit | e63abb5d2bb4bb6eb0b81e44ce4aea9e78826e0b (patch) | |
| tree | ac21130db3fff20d3723f6769d89b88aa371ec9d /clang/test/CodeGenCXX/blocks.cpp | |
| parent | 1c7047375a180ff80abb414e2075b1d5a240bb77 (diff) | |
| download | bcm5719-llvm-e63abb5d2bb4bb6eb0b81e44ce4aea9e78826e0b.tar.gz bcm5719-llvm-e63abb5d2bb4bb6eb0b81e44ce4aea9e78826e0b.zip | |
Fix a subtle bug with cleanups: when activating
a previously-inactive cleanup, not only do we need a
flag variable, but we should also force the cleanup to
query the flag variable. However, we only need to do
this when we're activating in a context that's
conditionally executed; otherwise, we may safely
assume that the cleanup is dominated by the activation
point.
llvm-svn: 144271
Diffstat (limited to 'clang/test/CodeGenCXX/blocks.cpp')
| -rw-r--r-- | clang/test/CodeGenCXX/blocks.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/blocks.cpp b/clang/test/CodeGenCXX/blocks.cpp index cc56525e1d5..e3160a03940 100644 --- a/clang/test/CodeGenCXX/blocks.cpp +++ b/clang/test/CodeGenCXX/blocks.cpp @@ -128,3 +128,53 @@ namespace test4 { // CHECK-NEXT: ret void } +namespace test5 { + struct A { + unsigned afield; + A(); + A(const A&); + ~A(); + void foo() const; + }; + + void doWithBlock(void(^)()); + + void test(bool cond) { + A x; + void (^b)() = (cond ? ^{ x.foo(); } : (void(^)()) 0); + doWithBlock(b); + } + + // CHECK: define void @_ZN5test54testEb( + // CHECK: [[COND:%.*]] = alloca i8 + // CHECK-NEXT: [[X:%.*]] = alloca [[A:%.*]], align 4 + // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8 + // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8 + // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1 + // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] + // CHECK-NEXT: [[T0:%.*]] = zext i1 + // CHECK-NEXT: store i8 [[T0]], i8* [[COND]], align 1 + // CHECK-NEXT: call void @_ZN5test51AC1Ev([[A]]* [[X]]) + // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 + // CHECK-NEXT: [[T0:%.*]] = load i8* [[COND]], align 1 + // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1 + // CHECK-NEXT: br i1 [[T1]], + + // CHECK-NOT: br + // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 + // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* [[X]]) + // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]] + // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* + // CHECK-NEXT: br label + // CHECK: br label + // CHECK: phi + // CHECK-NEXT: store + // CHECK-NEXT: load + // CHECK-NEXT: call void @_ZN5test511doWithBlockEU13block_pointerFvvE( + // CHECK-NEXT: [[T0:%.*]] = load i1* [[CLEANUP_ACTIVE]] + // CHECK-NEXT: br i1 [[T0]] + // CHECK: call void @_ZN5test51AD1Ev([[A]]* [[CLEANUP_ADDR]]) + // CHECK-NEXT: br label + // CHECK: call void @_ZN5test51AD1Ev([[A]]* [[X]]) + // CHECK-NEXT: ret void +} |

