aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenObjC/arc-blocks.m
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
committerDimitry Andric <dim@FreeBSD.org>2013-06-10 20:45:12 +0000
commit6a0372513edbc473b538d2f724efac50405d6fef (patch)
tree8f7776b7310bebaf415ac5b69e46e9f928c37144 /test/CodeGenObjC/arc-blocks.m
parent809500fc2c13c8173a16b052304d983864e4a1e1 (diff)
Vendor import of clang tags/RELEASE_33/final r183502 (effectively, 3.3vendor/clang/clang-release_33-r183502
Notes
Notes: svn path=/vendor/clang/dist/; revision=251609 svn path=/vendor/clang/clang-release_33-r183502/; revision=251610; tag=vendor/clang/clang-release_33-r183502
Diffstat (limited to 'test/CodeGenObjC/arc-blocks.m')
-rw-r--r--test/CodeGenObjC/arc-blocks.m39
1 files changed, 39 insertions, 0 deletions
diff --git a/test/CodeGenObjC/arc-blocks.m b/test/CodeGenObjC/arc-blocks.m
index 3281b2aab864..c9ba2f615347 100644
--- a/test/CodeGenObjC/arc-blocks.m
+++ b/test/CodeGenObjC/arc-blocks.m
@@ -650,5 +650,44 @@ void test18(id x) {
// CHECK-UNOPT-NEXT: ret void
}
+// rdar://13588325
+void test19_sink(void (^)(int));
+void test19(void (^b)(void)) {
+// CHECK: define void @test19(
+// Prologue.
+// CHECK: [[B:%.*]] = alloca void ()*,
+// CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]],
+// CHECK-NEXT: [[T0:%.*]] = bitcast void ()* {{%.*}} to i8*
+// CHECK-NEXT: [[T1:%.*]] = call i8* @objc_retain(i8* [[T0]])
+// CHECK-NEXT: [[T2:%.*]] = bitcast i8* [[T1]] to void ()*
+// CHECK-NEXT: store void ()* [[T2]], void ()** [[B]]
+
+// Block setup. We skip most of this. Note the bare retain.
+// CHECK-NEXT: [[SLOTREL:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK: [[SLOT:%.*]] = getelementptr inbounds [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5
+// CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]],
+// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+// CHECK-NEXT: [[T2:%.*]] = call i8* @objc_retain(i8* [[T1]])
+// CHECK-NEXT: [[T3:%.*]] = bitcast i8* [[T2]] to void ()*
+// CHECK-NEXT: store void ()* [[T3]], void ()** [[SLOT]],
+// Call.
+// CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void (i32)*
+// CHECK-NEXT: call void @test19_sink(void (i32)* [[T0]])
+
+ test19_sink(^(int x) { b(); });
+
+// Block teardown.
+// CHECK-NEXT: [[T0:%.*]] = load void ()** [[SLOTREL]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T1]])
+
+// Local cleanup.
+// CHECK-NEXT: [[T0:%.*]] = load void ()** [[B]]
+// CHECK-NEXT: [[T1:%.*]] = bitcast void ()* [[T0]] to i8*
+// CHECK-NEXT: call void @objc_release(i8* [[T1]])
+
+// CHECK-NEXT: ret void
+}
+
// CHECK: attributes [[NUW]] = { nounwind }
// CHECK-UNOPT: attributes [[NUW]] = { nounwind }