1 | // RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -std=c++11 -emit-llvm -o - | FileCheck %s |
2 | |
3 | template <class T> void takeItByValue(T); |
4 | void takeABlock(void (^)()); |
5 | |
6 | // rdar://problem/11022704 |
7 | namespace test_int { |
8 | void test() { |
9 | const int x = 100; |
10 | takeABlock(^{ takeItByValue(x); }); |
11 | // CHECK: call void @_Z13takeItByValueIiEvT_(i32 100) |
12 | } |
13 | } |
14 | |
15 | namespace test_int_ref { |
16 | void test() { |
17 | const int y = 200; |
18 | const int &x = y; |
19 | takeABlock(^{ takeItByValue(x); }); |
20 | |
21 | // TODO: there's no good reason that this isn't foldable. |
22 | // CHECK: call void @_Z13takeItByValueIiEvT_(i32 {{%.*}}) |
23 | } |
24 | } |
25 | |
26 | namespace test_float { |
27 | void test() { |
28 | const float x = 1; |
29 | takeABlock(^{ takeItByValue(x); }); |
30 | // CHECK: call void @_Z13takeItByValueIfEvT_(float 1.0 |
31 | } |
32 | } |
33 | |
34 | namespace test_float_ref { |
35 | void test() { |
36 | const float y = 100; |
37 | const float &x = y; |
38 | takeABlock(^{ takeItByValue(x); }); |
39 | |
40 | // TODO: there's no good reason that this isn't foldable. |
41 | // CHECK: call void @_Z13takeItByValueIfEvT_(float {{%.*}}) |
42 | } |
43 | } |
44 | |
45 | namespace test_complex_int { |
46 | void test() { |
47 | constexpr _Complex int x = 500; |
48 | takeABlock(^{ takeItByValue(x); }); |
49 | // CHECK: store { i32, i32 } { i32 500, i32 0 }, |
50 | |
51 | // CHECK: store i32 500, |
52 | // CHECK-NEXT: store i32 0, |
53 | // CHECK-NEXT: [[COERCE:%.*]] = bitcast |
54 | // CHECK-NEXT: [[CVAL:%.*]] = load i64, i64* [[COERCE]] |
55 | // CHECK-NEXT: call void @_Z13takeItByValueICiEvT_(i64 [[CVAL]]) |
56 | } |
57 | } |
58 | |
59 | namespace test_complex_int_ref { |
60 | void test() { |
61 | const _Complex int y = 100; |
62 | const _Complex int &x = y; |
63 | takeABlock(^{ takeItByValue(x); }); |
64 | // CHECK: call void @_Z13takeItByValueICiEvT_(i64 |
65 | } |
66 | } |
67 | |
68 | namespace test_complex_int_ref_mutable { |
69 | _Complex int y = 100; |
70 | void test() { |
71 | const _Complex int &x = y; |
72 | takeABlock(^{ takeItByValue(x); }); |
73 | // CHECK: [[R:%.*]] = load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_ZN28test_complex_int_ref_mutable1yE, i32 0, i32 0) |
74 | // CHECK-NEXT: [[I:%.*]] = load i32, i32* getelementptr inbounds ({ i32, i32 }, { i32, i32 }* @_ZN28test_complex_int_ref_mutable1yE, i32 0, i32 1) |
75 | // CHECK-NEXT: [[RSLOT:%.*]] = getelementptr inbounds { i32, i32 }, { i32, i32 }* [[CSLOT:%.*]], i32 0, i32 0 |
76 | // CHECK-NEXT: [[ISLOT:%.*]] = getelementptr inbounds { i32, i32 }, { i32, i32 }* [[CSLOT]], i32 0, i32 1 |
77 | // CHECK-NEXT: store i32 [[R]], i32* [[RSLOT]] |
78 | // CHECK-NEXT: store i32 [[I]], i32* [[ISLOT]] |
79 | // CHECK-NEXT: [[COERCE:%.*]] = bitcast { i32, i32 }* [[CSLOT]] to i64* |
80 | // CHECK-NEXT: [[CVAL:%.*]] = load i64, i64* [[COERCE]], |
81 | // CHECK-NEXT: call void @_Z13takeItByValueICiEvT_(i64 [[CVAL]]) |
82 | } |
83 | } |
84 | |
85 | // rdar://13295759 |
86 | namespace test_block_in_lambda { |
87 | void takeBlock(void (^block)()); |
88 | |
89 | // The captured variable has to be non-POD so that we have a copy expression. |
90 | struct A { |
91 | void *p; |
92 | A(const A &); |
93 | ~A(); |
94 | void use() const; |
95 | }; |
96 | |
97 | void test(A a) { |
98 | auto lambda = [a]() { |
99 | takeBlock(^{ a.use(); }); |
100 | }; |
101 | lambda(); // make sure we emit the invocation function |
102 | } |
103 | // CHECK-LABEL: define internal void @"_ZZN20test_block_in_lambda4testENS_1AEENK3$_0clEv"( |
104 | // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], align 8 |
105 | // CHECK: [[THIS:%.*]] = load [[LAMBDA_T:%.*]]*, [[LAMBDA_T:%.*]]** |
106 | // CHECK: [[TO_DESTROY:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 |
107 | // CHECK: [[T0:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 |
108 | // CHECK-NEXT: [[T1:%.*]] = getelementptr inbounds [[LAMBDA_T]], [[LAMBDA_T]]* [[THIS]], i32 0, i32 0 |
109 | // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AC1ERKS0_({{.*}}* [[T0]], {{.*}}* dereferenceable({{[0-9]+}}) [[T1]]) |
110 | // CHECK-NEXT: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* |
111 | // CHECK-NEXT: call void @_ZN20test_block_in_lambda9takeBlockEU13block_pointerFvvE(void ()* [[T0]]) |
112 | // CHECK-NEXT: call void @_ZN20test_block_in_lambda1AD1Ev({{.*}}* [[TO_DESTROY]]) |
113 | // CHECK-NEXT: ret void |
114 | } |
115 | |