1 // RUN: %clang_cc1 -no-opaque-pointers %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{{.*}}(
test(int x)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
test1()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; };
test2()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; };
test3()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(); };
test4()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()
test()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
test(B b)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
test()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]]* noundef [[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
test(bool cond)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: [[COND_CLEANUP_SAVE:%.*]] = alloca [[A]]*, align 8
160 // CHECK-NEXT: [[T0:%.*]] = zext i1
161 // CHECK-NEXT: store i8 [[T0]], i8* [[COND]], align 1
162 // CHECK-NEXT: call void @_ZN5test51AC1Ev([[A]]* {{[^,]*}} [[X]])
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]]* noundef nonnull align {{[0-9]+}} dereferenceable({{[0-9]+}}) [[X]])
171 // CHECK-NEXT: store i1 true, i1* [[CLEANUP_ACTIVE]]
172 // CHECK-NEXT: store [[A]]* [[CAPTURE]], [[A]]** [[COND_CLEANUP_SAVE]], align 8
173 // CHECK-NEXT: bitcast [[BLOCK_T]]* [[BLOCK]] to void ()*
174 // CHECK-NEXT: br label
175 // CHECK: br label
176 // CHECK: phi
177 // CHECK-NEXT: store
178 // CHECK-NEXT: load
179 // CHECK-NEXT: call void @_ZN5test511doWithBlockEU13block_pointerFvvE(
180 // CHECK-NEXT: [[T0:%.*]] = load i1, i1* [[CLEANUP_ACTIVE]]
181 // CHECK-NEXT: br i1 [[T0]]
182 // CHECK: [[T3:%.*]] = load [[A]]*, [[A]]** [[COND_CLEANUP_SAVE]], align 8
183 // CHECK-NEXT: call void @_ZN5test51AD1Ev([[A]]* {{[^,]*}} [[T3]])
184 // CHECK-NEXT: br label
185 // CHECK: call void @_ZN5test51AD1Ev([[A]]* {{[^,]*}} [[X]])
186 // CHECK-NEXT: ret void
187 }
188
189 namespace test6 {
190 struct A {
191 A();
192 ~A();
193 };
194
195 void foo(const A &, void (^)());
196 void bar();
197
test()198 void test() {
199 // Make sure that the temporary cleanup isn't somehow captured
200 // within the block.
201 foo(A(), ^{ bar(); });
202 bar();
203 }
204
205 // CHECK-LABEL: define{{.*}} void @_ZN5test64testEv()
206 // CHECK: [[TEMP:%.*]] = alloca [[A:%.*]], align 1
207 // CHECK-NEXT: call void @_ZN5test61AC1Ev([[A]]* {{[^,]*}} [[TEMP]])
208 // CHECK-NEXT: call void @_ZN5test63fooERKNS_1AEU13block_pointerFvvE(
209 // CHECK-NEXT: call void @_ZN5test61AD1Ev([[A]]* {{[^,]*}} [[TEMP]])
210 // CHECK-NEXT: call void @_ZN5test63barEv()
211 // CHECK-NEXT: ret void
212 }
213
214 namespace test7 {
f()215 int f() {
216 static int n;
217 int *const p = &n;
218 return ^{ return *p; }();
219 }
220 }
221
222 namespace test8 {
223 // <rdar://problem/10832617>: failure to capture this after skipping rebuild
224 // of the 'this' pointer.
225 struct X {
226 int x;
227
228 template<typename T>
footest8::X229 int foo() {
230 return ^ { return x; }();
231 }
232 };
233
234 template int X::foo<int>();
235 }
236
237 // rdar://13459289
238 namespace test9 {
239 struct B {
240 void *p;
241 B();
242 B(const B&);
243 ~B();
244 };
245
246 void use_block(void (^)());
247 void use_block_2(void (^)(), const B &a);
248
249 // Ensuring that creating a non-trivial capture copy expression
250 // doesn't end up stealing the block registration for the block we
251 // just parsed. That block must have captures or else it won't
252 // force registration. Must occur within a block for some reason.
test()253 void test() {
254 B x;
255 use_block(^{
256 int y;
257 use_block_2(^{ (void)y; }, x);
258 });
259 }
260 }
261
262 namespace test10 {
263 // Check that 'v' is included in the copy helper function name to indicate
264 // the constructor taking a volatile parameter is called to copy the captured
265 // object.
266
267 // CHECK-LABEL: define linkonce_odr hidden void @__copy_helper_block_8_32c16_ZTSVN6test101BE(
268 // CHECK: call void @_ZN6test101BC1ERVKS0_(
269 // CHECK-LABEL: define linkonce_odr hidden void @__destroy_helper_block_8_32c16_ZTSVN6test101BE(
270 // CHECK: call void @_ZN6test101BD1Ev(
271
272 struct B {
273 int a;
274 B();
275 B(const B &);
276 B(const volatile B &);
277 ~B();
278 };
279
test()280 void test() {
281 volatile B x;
282 ^{ (void)x; };
283 }
284 }
285
286 // Copy/dispose helper functions and block descriptors of blocks that capture
287 // objects that are non-external and non-trivial have internal linkage.
288
289 // CHECK-LABEL: define internal void @_ZN12_GLOBAL__N_14testEv(
290 // CHECK: store %[[STRUCT_BLOCK_DESCRIPTOR]]* bitcast ({ i64, i64, i8*, i8*, i8*, i8* }* @[[BLOCK_DESCRIPTOR22]] to %[[STRUCT_BLOCK_DESCRIPTOR]]*), %[[STRUCT_BLOCK_DESCRIPTOR]]** %{{.*}}, align 8
291
292 // CHECK-LABEL: define internal void @__copy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE(
293 // CHECK-LABEL: define internal void @__destroy_helper_block_8_32c22_ZTSN12_GLOBAL__N_11BE(
294
295 namespace {
296 struct B {
297 int a;
298 B();
299 B(const B &);
300 ~B();
301 };
302
test()303 void test() {
304 B x;
305 ^{ (void)x; };
306 }
307 }
308
callTest()309 void callTest() {
310 test();
311 }
312