1 // RUN: %clang_cc1 -std=c++11 -S -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
2
3 namespace std {
4 typedef decltype(sizeof(int)) size_t;
5
6 // libc++'s implementation
7 template <class _E>
8 class initializer_list
9 {
10 const _E* __begin_;
11 size_t __size_;
12
initializer_list(const _E * __b,size_t __s)13 initializer_list(const _E* __b, size_t __s)
14 : __begin_(__b),
15 __size_(__s)
16 {}
17
18 public:
19 typedef _E value_type;
20 typedef const _E& reference;
21 typedef const _E& const_reference;
22 typedef size_t size_type;
23
24 typedef const _E* iterator;
25 typedef const _E* const_iterator;
26
initializer_list()27 initializer_list() : __begin_(nullptr), __size_(0) {}
28
size() const29 size_t size() const {return __size_;}
begin() const30 const _E* begin() const {return __begin_;}
end() const31 const _E* end() const {return __begin_ + __size_;}
32 };
33 }
34
35 struct destroyme1 {
36 ~destroyme1();
37 };
38 struct destroyme2 {
39 ~destroyme2();
40 };
41 struct witharg1 {
42 witharg1(const destroyme1&);
43 ~witharg1();
44 };
45 struct wantslist1 {
46 wantslist1(std::initializer_list<destroyme1>);
47 ~wantslist1();
48 };
49
50 // CHECK: @_ZGR15globalInitList1 = private constant [3 x i32] [i32 1, i32 2, i32 3]
51 // CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZGR15globalInitList1, i32 0, i32 0), i{{32|64}} 3 }
52 std::initializer_list<int> globalInitList1 = {1, 2, 3};
53
54 namespace thread_local_global_array {
55 // FIXME: We should be able to constant-evaluate this even though the
56 // initializer is not a constant expression (pointers to thread_local
57 // objects aren't really a problem).
58 //
59 // CHECK: @_ZN25thread_local_global_array1xE = thread_local global
60 // CHECK: @_ZGRN25thread_local_global_array1xE = private thread_local constant [4 x i32] [i32 1, i32 2, i32 3, i32 4]
61 std::initializer_list<int> thread_local x = { 1, 2, 3, 4 };
62 }
63
64 // CHECK: @globalInitList2 = global %{{[^ ]+}} zeroinitializer
65 // CHECK: @_ZGR15globalInitList2 = private global [2 x %[[WITHARG:[^ ]*]]] zeroinitializer
66
67 // CHECK: @_ZN15partly_constant1kE = global i32 0, align 4
68 // CHECK: @_ZN15partly_constant2ilE = global {{.*}} null, align 8
69 // CHECK: @[[PARTLY_CONSTANT_OUTER:_ZGRN15partly_constant2ilE.*]] = private global {{.*}} zeroinitializer, align 8
70 // CHECK: @[[PARTLY_CONSTANT_INNER:_ZGRN15partly_constant2ilE.*]] = private global [3 x {{.*}}] zeroinitializer, align 8
71 // CHECK: @[[PARTLY_CONSTANT_FIRST:_ZGRN15partly_constant2ilE.*]] = private constant [3 x i32] [i32 1, i32 2, i32 3], align 4
72 // CHECK: @[[PARTLY_CONSTANT_SECOND:_ZGRN15partly_constant2ilE.*]] = private global [2 x i32] zeroinitializer, align 4
73 // CHECK: @[[PARTLY_CONSTANT_THIRD:_ZGRN15partly_constant2ilE.*]] = private constant [4 x i32] [i32 5, i32 6, i32 7, i32 8], align 4
74
75 // CHECK: appending global
76
77
78 // thread_local initializer:
79 // CHECK: define internal void
80 // CHECK: store i32* getelementptr inbounds ([4 x i32]* @_ZGRN25thread_local_global_array1xE, i64 0, i64 0),
81 // CHECK: i32** getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 0), align 8
82 // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZN25thread_local_global_array1xE, i32 0, i32 1), align 8
83
84
85 // CHECK: define internal void
86 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 0
87 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i{{32|64}} 0, i{{32|64}} 1
88 // CHECK: __cxa_atexit
89 // CHECK: store %[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZGR15globalInitList2, i64 0, i64 0),
90 // CHECK: %[[WITHARG]]** getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 0), align 8
91 // CHECK: store i64 2, i64* getelementptr inbounds (%{{.*}}* @globalInitList2, i32 0, i32 1), align 8
92 // CHECK: call void @_ZN10destroyme1D1Ev
93 // CHECK: call void @_ZN10destroyme1D1Ev
94 std::initializer_list<witharg1> globalInitList2 = {
95 witharg1(destroyme1()), witharg1(destroyme1())
96 };
97
fn1(int i)98 void fn1(int i) {
99 // CHECK: define void @_Z3fn1i
100 // temporary array
101 // CHECK: [[array:%[^ ]+]] = alloca [3 x i32]
102 // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0
103 // CHECK-NEXT: store i32 1, i32*
104 // CHECK-NEXT: getelementptr
105 // CHECK-NEXT: store
106 // CHECK-NEXT: getelementptr
107 // CHECK-NEXT: load
108 // CHECK-NEXT: store
109 // init the list
110 // CHECK-NEXT: getelementptr
111 // CHECK-NEXT: getelementptr inbounds [3 x i32]*
112 // CHECK-NEXT: store i32*
113 // CHECK-NEXT: getelementptr
114 // CHECK-NEXT: store i{{32|64}} 3
115 std::initializer_list<int> intlist{1, 2, i};
116 }
117
fn2()118 void fn2() {
119 // CHECK: define void @_Z3fn2v
120 void target(std::initializer_list<destroyme1>);
121 // objects should be destroyed before dm2, after call returns
122 // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E
123 target({ destroyme1(), destroyme1() });
124 // CHECK: call void @_ZN10destroyme1D1Ev
125 destroyme2 dm2;
126 // CHECK: call void @_ZN10destroyme2D1Ev
127 }
128
fn3()129 void fn3() {
130 // CHECK: define void @_Z3fn3v
131 // objects should be destroyed after dm2
132 auto list = { destroyme1(), destroyme1() };
133 destroyme2 dm2;
134 // CHECK: call void @_ZN10destroyme2D1Ev
135 // CHECK: call void @_ZN10destroyme1D1Ev
136 }
137
fn4()138 void fn4() {
139 // CHECK: define void @_Z3fn4v
140 void target(std::initializer_list<witharg1>);
141 // objects should be destroyed before dm2, after call returns
142 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
143 // CHECK: call void @_Z6targetSt16initializer_listI8witharg1E
144 target({ witharg1(destroyme1()), witharg1(destroyme1()) });
145 // CHECK: call void @_ZN8witharg1D1Ev
146 // CHECK: call void @_ZN10destroyme1D1Ev
147 destroyme2 dm2;
148 // CHECK: call void @_ZN10destroyme2D1Ev
149 }
150
fn5()151 void fn5() {
152 // CHECK: define void @_Z3fn5v
153 // temps should be destroyed before dm2
154 // objects should be destroyed after dm2
155 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
156 auto list = { witharg1(destroyme1()), witharg1(destroyme1()) };
157 // CHECK: call void @_ZN10destroyme1D1Ev
158 destroyme2 dm2;
159 // CHECK: call void @_ZN10destroyme2D1Ev
160 // CHECK: call void @_ZN8witharg1D1Ev
161 }
162
fn6()163 void fn6() {
164 // CHECK: define void @_Z3fn6v
165 void target(const wantslist1&);
166 // objects should be destroyed before dm2, after call returns
167 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
168 // CHECK: call void @_Z6targetRK10wantslist1
169 target({ destroyme1(), destroyme1() });
170 // CHECK: call void @_ZN10wantslist1D1Ev
171 // CHECK: call void @_ZN10destroyme1D1Ev
172 destroyme2 dm2;
173 // CHECK: call void @_ZN10destroyme2D1Ev
174 }
175
fn7()176 void fn7() {
177 // CHECK: define void @_Z3fn7v
178 // temps should be destroyed before dm2
179 // object should be destroyed after dm2
180 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
181 wantslist1 wl = { destroyme1(), destroyme1() };
182 // CHECK: call void @_ZN10destroyme1D1Ev
183 destroyme2 dm2;
184 // CHECK: call void @_ZN10destroyme2D1Ev
185 // CHECK: call void @_ZN10wantslist1D1Ev
186 }
187
fn8()188 void fn8() {
189 // CHECK: define void @_Z3fn8v
190 void target(std::initializer_list<std::initializer_list<destroyme1>>);
191 // objects should be destroyed before dm2, after call returns
192 // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE
193 std::initializer_list<destroyme1> inner;
194 target({ inner, { destroyme1() } });
195 // CHECK: call void @_ZN10destroyme1D1Ev
196 // Only one destroy loop, since only one inner init list is directly inited.
197 // CHECK-NOT: call void @_ZN10destroyme1D1Ev
198 destroyme2 dm2;
199 // CHECK: call void @_ZN10destroyme2D1Ev
200 }
201
fn9()202 void fn9() {
203 // CHECK: define void @_Z3fn9v
204 // objects should be destroyed after dm2
205 std::initializer_list<destroyme1> inner;
206 std::initializer_list<std::initializer_list<destroyme1>> list =
207 { inner, { destroyme1() } };
208 destroyme2 dm2;
209 // CHECK: call void @_ZN10destroyme2D1Ev
210 // CHECK: call void @_ZN10destroyme1D1Ev
211 // Only one destroy loop, since only one inner init list is directly inited.
212 // CHECK-NOT: call void @_ZN10destroyme1D1Ev
213 // CHECK: ret void
214 }
215
216 struct haslist1 {
217 std::initializer_list<int> il;
218 haslist1();
219 };
220
221 // CHECK: define void @_ZN8haslist1C2Ev
haslist1()222 haslist1::haslist1()
223 // CHECK: alloca [3 x i32]
224 // CHECK: store i32 1
225 // CHECK: store i32 2
226 // CHECK: store i32 3
227 // CHECK: store i{{32|64}} 3
228 : il{1, 2, 3}
229 {
230 destroyme2 dm2;
231 }
232
233 struct haslist2 {
234 std::initializer_list<destroyme1> il;
235 haslist2();
236 };
237
238 // CHECK: define void @_ZN8haslist2C2Ev
haslist2()239 haslist2::haslist2()
240 : il{destroyme1(), destroyme1()}
241 {
242 destroyme2 dm2;
243 // CHECK: call void @_ZN10destroyme2D1Ev
244 // CHECK: call void @_ZN10destroyme1D1Ev
245 }
246
fn10()247 void fn10() {
248 // CHECK: define void @_Z4fn10v
249 // CHECK: alloca [3 x i32]
250 // CHECK: call noalias i8* @_Znw{{[jm]}}
251 // CHECK: store i32 1
252 // CHECK: store i32 2
253 // CHECK: store i32 3
254 // CHECK: store i32*
255 // CHECK: store i{{32|64}} 3
256 (void) new std::initializer_list<int> {1, 2, 3};
257 }
258
fn11()259 void fn11() {
260 // CHECK: define void @_Z4fn11v
261 (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()};
262 // CHECK: call void @_ZN10destroyme1D1Ev
263 destroyme2 dm2;
264 // CHECK: call void @_ZN10destroyme2D1Ev
265 }
266
267 namespace PR12178 {
268 struct string {
269 string(int);
270 ~string();
271 };
272
273 struct pair {
274 string a;
275 int b;
276 };
277
278 struct map {
279 map(std::initializer_list<pair>);
280 };
281
282 map m{ {1, 2}, {3, 4} };
283 }
284
285 namespace rdar13325066 {
286 struct X { ~X(); };
287
288 // CHECK: define void @_ZN12rdar133250664loopERNS_1XES1_
loop(X & x1,X & x2)289 void loop(X &x1, X &x2) {
290 // CHECK: br label
291 // CHECK: br i1
292 // CHECK: br label
293 // CHECK call void @_ZN12rdar133250661XD1Ev
294 // CHECK: br label
295 // CHECK: br label
296 // CHECK: call void @_ZN12rdar133250661XD1Ev
297 // CHECK: br i1
298 // CHECK: br label
299 // CHECK: ret void
300 for (X x : { x1, x2 }) { }
301 }
302 }
303
304 namespace dtors {
305 struct S {
306 S();
307 ~S();
308 };
309 void z();
310
311 // CHECK: define void @_ZN5dtors1fEv(
f()312 void f() {
313 // CHECK: call void @_ZN5dtors1SC1Ev(
314 // CHECK: call void @_ZN5dtors1SC1Ev(
315 std::initializer_list<S>{ S(), S() };
316
317 // Destruction loop for underlying array.
318 // CHECK: br label
319 // CHECK: call void @_ZN5dtors1SD1Ev(
320 // CHECK: br i1
321
322 // CHECK: call void @_ZN5dtors1zEv(
323 z();
324
325 // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
326 }
327
328 // CHECK: define void @_ZN5dtors1gEv(
g()329 void g() {
330 // CHECK: call void @_ZN5dtors1SC1Ev(
331 // CHECK: call void @_ZN5dtors1SC1Ev(
332 auto x = std::initializer_list<S>{ S(), S() };
333
334 // Destruction loop for underlying array.
335 // CHECK: br label
336 // CHECK: call void @_ZN5dtors1SD1Ev(
337 // CHECK: br i1
338
339 // CHECK: call void @_ZN5dtors1zEv(
340 z();
341
342 // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
343 }
344
345 // CHECK: define void @_ZN5dtors1hEv(
h()346 void h() {
347 // CHECK: call void @_ZN5dtors1SC1Ev(
348 // CHECK: call void @_ZN5dtors1SC1Ev(
349 std::initializer_list<S> x = { S(), S() };
350
351 // CHECK-NOT: call void @_ZN5dtors1SD1Ev(
352
353 // CHECK: call void @_ZN5dtors1zEv(
354 z();
355
356 // Destruction loop for underlying array.
357 // CHECK: br label
358 // CHECK: call void @_ZN5dtors1SD1Ev(
359 // CHECK: br i1
360 }
361 }
362
363 namespace partly_constant {
364 int k;
365 std::initializer_list<std::initializer_list<int>> &&il = { { 1, 2, 3 }, { 4, k }, { 5, 6, 7, 8 } };
366 // First init list.
367 // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]],
368 // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_FIRST]], i64 0, i64 0),
369 // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 0)
370 // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0, i32 1)
371 // CHECK-NOT: @[[PARTLY_CONSTANT_FIRST]],
372 //
373 // Second init list array (non-constant).
374 // CHECK: store i32 4, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0)
375 // CHECK: load i32* @_ZN15partly_constant1kE
376 // CHECK: store i32 {{.*}}, i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 1)
377 //
378 // Second init list.
379 // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_SECOND]], i64 0, i64 0),
380 // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 0)
381 // CHECK: store i64 2, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 1, i32 1)
382 //
383 // Third init list.
384 // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
385 // CHECK: store i32* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_THIRD]], i64 0, i64 0),
386 // CHECK: i32** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 2, i32 0)
387 // CHECK: store i64 4, i64* getelementptr inbounds ({{.*}}* @_ZGRN15partly_constant2ilE4, i64 0, i64 2, i32 1)
388 // CHECK-NOT: @[[PARTLY_CONSTANT_THIRD]],
389 //
390 // Outer init list.
391 // CHECK: store {{.*}}* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_INNER]], i64 0, i64 0),
392 // CHECK: {{.*}}** getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 0)
393 // CHECK: store i64 3, i64* getelementptr inbounds ({{.*}}* @[[PARTLY_CONSTANT_OUTER]], i32 0, i32 1)
394 //
395 // 'il' reference.
396 // CHECK: store {{.*}}* @[[PARTLY_CONSTANT_OUTER]], {{.*}}** @_ZN15partly_constant2ilE, align 8
397 }
398
399 namespace nested {
400 struct A { A(); ~A(); };
401 struct B { const A &a; ~B(); };
402 struct C { std::initializer_list<B> b; ~C(); };
403 void f();
404 // CHECK: define void @_ZN6nested1gEv(
g()405 void g() {
406 // CHECK: call void @_ZN6nested1AC1Ev(
407 // CHECK-NOT: call
408 // CHECK: call void @_ZN6nested1AC1Ev(
409 // CHECK-NOT: call
410 const C &c { { { A() }, { A() } } };
411
412 // CHECK: call void @_ZN6nested1fEv(
413 // CHECK-NOT: call
414 f();
415
416 // CHECK: call void @_ZN6nested1CD1Ev(
417 // CHECK-NOT: call
418
419 // Destroy B[2] array.
420 // FIXME: This isn't technically correct: reverse construction order would
421 // destroy the second B then the second A then the first B then the first A.
422 // CHECK: call void @_ZN6nested1BD1Ev(
423 // CHECK-NOT: call
424 // CHECK: br
425
426 // CHECK-NOT: call
427 // CHECK: call void @_ZN6nested1AD1Ev(
428 // CHECK-NOT: call
429 // CHECK: call void @_ZN6nested1AD1Ev(
430 // CHECK-NOT: call
431 // CHECK: }
432 }
433 }
434