1 | // RUN: %clang_cc1 %s -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s |
2 | |
3 | // CHECK: %[[STRUCT_BLOCK_DESCRIPTOR:.*]] = type { i64, i64 } |
4 | // CHECK: @[[BLOCK_DESCRIPTOR22:.*]] = internal constant { i64, i64, i8*, i8*, i8*, i8* } { i64 0, i64 36, i8* bitcast (void (i8*, i8*)* @__copy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE to i8*), i8* bitcast (void (i8*)* @__destroy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE to i8*), i8* getelementptr inbounds ([6 x i8], [6 x i8]* @{{.*}}, i32 0, i32 0), i8* null }, align 8 |
5 | |
6 | namespace test0 { |
7 | // CHECK-LABEL: define void @_ZN5test04testEi( |
8 | // CHECK: define internal void @___ZN5test04testEi_block_invoke{{.*}}( |
9 | // CHECK: define internal void @___ZN5test04testEi_block_invoke_2{{.*}}( |
10 | void test(int x) { |
11 | ^{ ^{ (void) x; }; }; |
12 | } |
13 | } |
14 | |
15 | extern void (^out)(); |
16 | |
17 | namespace test1 { |
18 | // Capturing const objects doesn't require a local block. |
19 | // CHECK-LABEL: define void @_ZN5test15test1Ev() |
20 | // CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out |
21 | void test1() { |
22 | const int NumHorsemen = 4; |
23 | out = ^{ (void) NumHorsemen; }; |
24 | } |
25 | |
26 | // That applies to structs too... |
27 | // CHECK-LABEL: define void @_ZN5test15test2Ev() |
28 | // CHECK: store void ()* bitcast ({{.*}} @__block_literal_global{{.*}} to void ()*), void ()** @out |
29 | struct loc { double x, y; }; |
30 | void test2() { |
31 | const loc target = { 5, 6 }; |
32 | out = ^{ (void) target; }; |
33 | } |
34 | |
35 | // ...unless they have mutable fields... |
36 | // CHECK-LABEL: define void @_ZN5test15test3Ev() |
37 | // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], |
38 | // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* |
39 | // CHECK: store void ()* [[T0]], void ()** @out |
40 | struct mut { mutable int x; }; |
41 | void test3() { |
42 | const mut obj = { 5 }; |
43 | out = ^{ (void) obj; }; |
44 | } |
45 | |
46 | // ...or non-trivial destructors... |
47 | // CHECK-LABEL: define void @_ZN5test15test4Ev() |
48 | // CHECK: [[OBJ:%.*]] = alloca |
49 | // CHECK: [[BLOCK:%.*]] = alloca [[BLOCK_T:<{.*}>]], |
50 | // CHECK: [[T0:%.*]] = bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* |
51 | // CHECK: store void ()* [[T0]], void ()** @out |
52 | struct scope { int x; ~scope(); }; |
53 | void test4() { |
54 | const scope obj = { 5 }; |
55 | out = ^{ (void) obj; }; |
56 | } |
57 | |
58 | // ...or non-trivial copy constructors, but it's not clear how to do |
59 | // that and still have a constant initializer in '03. |
60 | } |
61 | |
62 | namespace test2 { |
63 | struct A { |
64 | A(); |
65 | A(const A &); |
66 | ~A(); |
67 | }; |
68 | |
69 | struct B { |
70 | B(); |
71 | B(const B &); |
72 | ~B(); |
73 | }; |
74 | |
75 | // CHECK-LABEL: define void @_ZN5test24testEv() |
76 | void test() { |
77 | __block A a; |
78 | __block B b; |
79 | ^{ (void)a; (void)b; }; |
80 | } |
81 | |
82 | // CHECK-LABEL: define internal void @__Block_byref_object_copy |
83 | // CHECK: call void @_ZN5test21AC1ERKS0_( |
84 | |
85 | // CHECK-LABEL: define internal void @__Block_byref_object_dispose |
86 | // CHECK: call void @_ZN5test21AD1Ev( |
87 | |
88 | // CHECK-LABEL: define internal void @__Block_byref_object_copy |
89 | // CHECK: call void @_ZN5test21BC1ERKS0_( |
90 | |
91 | // CHECK-LABEL: define internal void @__Block_byref_object_dispose |
92 | // CHECK: call void @_ZN5test21BD1Ev( |
93 | } |
94 | |
95 | // rdar://problem/9334739 |
96 | // Make sure we mark destructors for parameters captured in blocks. |
97 | namespace test3 { |
98 | struct A { |
99 | A(const A&); |
100 | ~A(); |
101 | }; |
102 | |
103 | struct B : A { |
104 | }; |
105 | |
106 | void test(B b) { |
107 | extern void consume(void(^)()); |
108 | consume(^{ (void) b; }); |
109 | } |
110 | } |
111 | |
112 | // rdar://problem/9971485 |
113 | namespace test4 { |
114 | struct A { |
115 | A(); |
116 | ~A(); |
117 | }; |
118 | |
119 | void foo(A a); |
120 | |
121 | void test() { |
122 | extern void consume(void(^)()); |
123 | consume(^{ return foo(A()); }); |
124 | } |
125 | // CHECK-LABEL: define void @_ZN5test44testEv() |
126 | // CHECK-LABEL: define internal void @___ZN5test44testEv_block_invoke |
127 | // CHECK: [[TMP:%.*]] = alloca [[A:%.*]], align 1 |
128 | // CHECK-NEXT: store i8* [[BLOCKDESC:%.*]], i8** {{.*}}, align 8 |
129 | // CHECK-NEXT: bitcast i8* [[BLOCKDESC]] to <{ i8*, i32, i32, i8*, %[[STRUCT_BLOCK_DESCRIPTOR]]* }>* |
130 | // CHECK: call void @_ZN5test41AC1Ev([[A]]* [[TMP]]) |
131 | // CHECK-NEXT: call void @_ZN5test43fooENS_1AE([[A]]* [[TMP]]) |
132 | // CHECK-NEXT: call void @_ZN5test41AD1Ev([[A]]* [[TMP]]) |
133 | // CHECK-NEXT: ret void |
134 | } |
135 | |
136 | namespace test5 { |
137 | struct A { |
138 | unsigned afield; |
139 | A(); |
140 | A(const A&); |
141 | ~A(); |
142 | void foo() const; |
143 | }; |
144 | |
145 | void doWithBlock(void(^)()); |
146 | |
147 | void test(bool cond) { |
148 | A x; |
149 | void (^b)() = (cond ? ^{ x.foo(); } : (void(^)()) 0); |
150 | doWithBlock(b); |
151 | } |
152 | |
153 | // CHECK-LABEL: define void @_ZN5test54testEb( |
154 | // CHECK: [[COND:%.*]] = alloca i8 |
155 | // CHECK-NEXT: [[X:%.*]] = alloca [[A:%.*]], align 4 |
156 | // CHECK-NEXT: [[B:%.*]] = alloca void ()*, align 8 |
157 | // CHECK-NEXT: [[BLOCK:%.*]] = alloca [[BLOCK_T:.*]], align 8 |
158 | // CHECK-NEXT: [[CLEANUP_ACTIVE:%.*]] = alloca i1 |
159 | // CHECK-NEXT: [[T0:%.*]] = zext i1 |
160 | // CHECK-NEXT: store i8 [[T0]], i8* [[COND]], align 1 |
161 | // CHECK-NEXT: call void @_ZN5test51AC1Ev([[A]]* [[X]]) |
162 | // CHECK-NEXT: [[CLEANUP_ADDR:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 |
163 | // CHECK-NEXT: [[T0:%.*]] = load i8, i8* [[COND]], align 1 |
164 | // CHECK-NEXT: [[T1:%.*]] = trunc i8 [[T0]] to i1 |
165 | // CHECK-NEXT: store i1 false, i1* [[CLEANUP_ACTIVE]] |
166 | // CHECK-NEXT: br i1 [[T1]], |
167 | |
168 | // CHECK-NOT: br |
169 | // CHECK: [[CAPTURE:%.*]] = getelementptr inbounds [[BLOCK_T]], [[BLOCK_T]]* [[BLOCK]], i32 0, i32 5 |
170 | // CHECK-NEXT: call void @_ZN5test51AC1ERKS0_([[A]]* [[CAPTURE]], [[A]]* dereferenceable({{[0-9]+}}) [[X]]) |
171 | // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]] |
172 | // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()* |
173 | // CHECK-NEXT: br label |
174 | // CHECK: br label |
175 | // CHECK: phi |
176 | // CHECK-NEXT: store |
177 | // CHECK-NEXT: load |
178 | // CHECK-NEXT: call void @_ZN5test511doWithBlockEU13block_pointerFvvE( |
179 | // CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_ACTIVE]] |
180 | // CHECK-NEXT: br i1 [[T0]] |
181 | // CHECK: call void @_ZN5test51AD1Ev([[A]]* [[CLEANUP_ADDR]]) |
182 | // CHECK-NEXT: br label |
183 | // CHECK: call void @_ZN5test51AD1Ev([[A]]* [[X]]) |
184 | // CHECK-NEXT: ret void |
185 | } |
186 | |
187 | namespace test6 { |
188 | struct A { |
189 | A(); |
190 | ~A(); |
191 | }; |
192 | |
193 | void foo(const A &, void (^)()); |
194 | void bar(); |
195 | |
196 | void test() { |
197 | // Make sure that the temporary cleanup isn't somehow captured |
198 | // within the block. |
199 | foo(A(), ^{ bar(); }); |
200 | bar(); |
201 | } |
202 | |
203 | // CHECK-LABEL: define void @_ZN5test64testEv() |
204 | // CHECK: [[TEMP:%.*]] = alloca [[A:%.*]], align 1 |
205 | // CHECK-NEXT: call void @_ZN5test61AC1Ev([[A]]* [[TEMP]]) |
206 | // CHECK-NEXT: call void @_ZN5test63fooERKNS_1AEU13block_pointerFvvE( |
207 | // CHECK-NEXT: call void @_ZN5test61AD1Ev([[A]]* [[TEMP]]) |
208 | // CHECK-NEXT: call void @_ZN5test63barEv() |
209 | // CHECK-NEXT: ret void |
210 | } |
211 | |
212 | namespace test7 { |
213 | int f() { |
214 | static int n; |
215 | int *const p = &n; |
216 | return ^{ return *p; }(); |
217 | } |
218 | } |
219 | |
220 | namespace test8 { |
221 | // <rdar://problem/10832617>: failure to capture this after skipping rebuild |
222 | // of the 'this' pointer. |
223 | struct X { |
224 | int x; |
225 | |
226 | template<typename T> |
227 | int foo() { |
228 | return ^ { return x; }(); |
229 | } |
230 | }; |
231 | |
232 | template int X::foo<int>(); |
233 | } |
234 | |
235 | // rdar://13459289 |
236 | namespace test9 { |
237 | struct B { |
238 | void *p; |
239 | B(); |
240 | B(const B&); |
241 | ~B(); |
242 | }; |
243 | |
244 | void use_block(void (^)()); |
245 | void use_block_2(void (^)(), const B &a); |
246 | |
247 | // Ensuring that creating a non-trivial capture copy expression |
248 | // doesn't end up stealing the block registration for the block we |
249 | // just parsed. That block must have captures or else it won't |
250 | // force registration. Must occur within a block for some reason. |
251 | void test() { |
252 | B x; |
253 | use_block(^{ |
254 | int y; |
255 | use_block_2(^{ (void)y; }, x); |
256 | }); |
257 | } |
258 | } |
259 | |
260 | namespace test10 { |
261 | // Check that 'v' is included in the copy helper function name to indicate |
262 | // the constructor taking a volatile parameter is called to copy the captured |
263 | // object. |
264 | |
265 | // CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_8_32c16_ZTSVN6test101BE( |
266 | // CHECK: call void @_ZN6test101BC1ERVKS0_( |
267 | // CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_8_32c16_ZTSVN6test101BE( |
268 | // CHECK: call void @_ZN6test101BD1Ev( |
269 | |
270 | struct B { |
271 | int a; |
272 | B(); |
273 | B(const B &); |
274 | B(const volatile B &); |
275 | ~B(); |
276 | }; |
277 | |
278 | void test() { |
279 | volatile B x; |
280 | ^{ (void)x; }; |
281 | } |
282 | } |
283 | |
284 | // Copy/dispose helper functions and block descriptors of blocks that capture |
285 | // objects that are non-external and non-trivial have internal linkage. |
286 | |
287 | // CHECK-LABEL: define internal void @_ZN12_GLOBAL__N_14testEv( |
288 | // CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESCRIPTOR22]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %{{.*}}, align 8 |
289 | |
290 | // CHECK-LABEL: define internal void @__copy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE( |
291 | // CHECK-LABEL: define internal void @__destroy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE( |
292 | |
293 | namespace { |
294 | struct B { |
295 | int a; |
296 | B(); |
297 | B(const B &); |
298 | ~B(); |
299 | }; |
300 | |
301 | void test() { |
302 | B x; |
303 | ^{ (void)x; }; |
304 | } |
305 | } |
306 | |
307 | void callTest() { |
308 | test(); |
309 | } |
310 | |