1// RUN: %clang_cc1 -std=c++11 -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
2
3namespace 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
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
27    initializer_list() : __begin_(nullptr), __size_(0) {}
28
29    size_t    size()  const {return __size_;}
30    const _E* begin() const {return __begin_;}
31    const _E* end()   const {return __begin_ + __size_;}
32  };
33}
34
35struct destroyme1 {
36  ~destroyme1();
37};
38struct destroyme2 {
39  ~destroyme2();
40};
41struct witharg1 {
42  witharg1(const destroyme1&);
43  ~witharg1();
44};
45struct 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 }
52std::initializer_list<int> globalInitList1 = {1, 2, 3};
53
54namespace 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-LABEL: 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-LABEL: 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
94std::initializer_list<witharg1> globalInitList2 = {
95  witharg1(destroyme1()), witharg1(destroyme1())
96};
97
98void fn1(int i) {
99  // CHECK-LABEL: 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
118void fn2() {
119  // CHECK-LABEL: 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
129void fn3() {
130  // CHECK-LABEL: 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
138void fn4() {
139  // CHECK-LABEL: 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
151void fn5() {
152  // CHECK-LABEL: 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
163void fn6() {
164  // CHECK-LABEL: 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
176void fn7() {
177  // CHECK-LABEL: 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
188void fn8() {
189  // CHECK-LABEL: 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
202void fn9() {
203  // CHECK-LABEL: 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
216struct haslist1 {
217  std::initializer_list<int> il;
218  haslist1();
219};
220
221// CHECK-LABEL: define void @_ZN8haslist1C2Ev
222haslist1::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
233struct haslist2 {
234  std::initializer_list<destroyme1> il;
235  haslist2();
236};
237
238// CHECK-LABEL: define void @_ZN8haslist2C2Ev
239haslist2::haslist2()
240  : il{destroyme1(), destroyme1()}
241{
242  destroyme2 dm2;
243  // CHECK: call void @_ZN10destroyme2D1Ev
244  // CHECK: call void @_ZN10destroyme1D1Ev
245}
246
247void fn10() {
248  // CHECK-LABEL: 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
259void fn11() {
260  // CHECK-LABEL: 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
267namespace 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
285namespace rdar13325066 {
286  struct X { ~X(); };
287
288  // CHECK-LABEL: define void @_ZN12rdar133250664loopERNS_1XES1_
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
304namespace dtors {
305  struct S {
306    S();
307    ~S();
308  };
309  void z();
310
311  // CHECK-LABEL: define void @_ZN5dtors1fEv(
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-LABEL: define void @_ZN5dtors1gEv(
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-LABEL: define void @_ZN5dtors1hEv(
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
363namespace 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
399namespace 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-LABEL: define void @_ZN6nested1gEv(
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
435namespace DR1070 {
436  struct A {
437    A(std::initializer_list<int>);
438  };
439  struct B {
440    int i;
441    A a;
442  };
443  B b = {1};
444  struct C {
445    std::initializer_list<int> a;
446    B b;
447    std::initializer_list<double> c;
448  };
449  C c = {};
450}
451
452namespace ArrayOfInitList {
453  struct S {
454    S(std::initializer_list<int>);
455  };
456  S x[1] = {};
457}
458