summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGenCXX/blocks.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-11-10 09:22:44 +0000
committerJohn McCall <rjmccall@apple.com>2011-11-10 09:22:44 +0000
commite63abb5d2bb4bb6eb0b81e44ce4aea9e78826e0b (patch)
treeac21130db3fff20d3723f6769d89b88aa371ec9d /clang/test/CodeGenCXX/blocks.cpp
parent1c7047375a180ff80abb414e2075b1d5a240bb77 (diff)
downloadbcm5719-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.cpp50
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
+}
OpenPOWER on IntegriCloud