1// RUN: %clang_cc1 -std=c++11 -S -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: @_ZL25globalInitList1__initlist = internal global [3 x i32] [i32 1, i32 2, i32 3]
51// CHECK: @globalInitList1 = global %{{[^ ]+}} { i32* getelementptr inbounds ([3 x i32]* @_ZL25globalInitList1__initlist, i32 0, i32 0), i{{32|64}} 3 }
52std::initializer_list<int> globalInitList1 = {1, 2, 3};
53
54// CHECK: @_ZL25globalInitList2__initlist = internal global [2 x %{{[^ ]*}}] zeroinitializer
55// CHECK: @globalInitList2 = global %{{[^ ]+}} { %[[WITHARG:[^ *]+]]* getelementptr inbounds ([2 x
56// CHECK: appending global
57// CHECK: define internal void
58// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 0
59// CHECK: call void @_ZN8witharg1C1ERK10destroyme1(%[[WITHARG]]* getelementptr inbounds ([2 x %[[WITHARG]]]* @_ZL25globalInitList2__initlist, i{{32|64}} 0, i{{32|64}} 1
60// CHECK: __cxa_atexit
61// CHECK: call void @_ZN10destroyme1D1Ev
62// CHECK: call void @_ZN10destroyme1D1Ev
63std::initializer_list<witharg1> globalInitList2 = {
64  witharg1(destroyme1()), witharg1(destroyme1())
65};
66
67void fn1(int i) {
68  // CHECK: define void @_Z3fn1i
69  // temporary array
70  // CHECK: [[array:%[^ ]+]] = alloca [3 x i32]
71  // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0
72  // CHECK-NEXT: store i32 1, i32*
73  // CHECK-NEXT: getelementptr
74  // CHECK-NEXT: store
75  // CHECK-NEXT: getelementptr
76  // CHECK-NEXT: load
77  // CHECK-NEXT: store
78  // init the list
79  // CHECK-NEXT: getelementptr
80  // CHECK-NEXT: getelementptr inbounds [3 x i32]*
81  // CHECK-NEXT: store i32*
82  // CHECK-NEXT: getelementptr
83  // CHECK-NEXT: store i{{32|64}} 3
84  std::initializer_list<int> intlist{1, 2, i};
85}
86
87void fn2() {
88  // CHECK: define void @_Z3fn2v
89  void target(std::initializer_list<destroyme1>);
90  // objects should be destroyed before dm2, after call returns
91  // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E
92  target({ destroyme1(), destroyme1() });
93  // CHECK: call void @_ZN10destroyme1D1Ev
94  destroyme2 dm2;
95  // CHECK: call void @_ZN10destroyme2D1Ev
96}
97
98void fn3() {
99  // CHECK: define void @_Z3fn3v
100  // objects should be destroyed after dm2
101  auto list = { destroyme1(), destroyme1() };
102  destroyme2 dm2;
103  // CHECK: call void @_ZN10destroyme2D1Ev
104  // CHECK: call void @_ZN10destroyme1D1Ev
105}
106
107void fn4() {
108  // CHECK: define void @_Z3fn4v
109  void target(std::initializer_list<witharg1>);
110  // objects should be destroyed before dm2, after call returns
111  // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
112  // CHECK: call void @_Z6targetSt16initializer_listI8witharg1E
113  target({ witharg1(destroyme1()), witharg1(destroyme1()) });
114  // CHECK: call void @_ZN8witharg1D1Ev
115  // CHECK: call void @_ZN10destroyme1D1Ev
116  destroyme2 dm2;
117  // CHECK: call void @_ZN10destroyme2D1Ev
118}
119
120void fn5() {
121  // CHECK: define void @_Z3fn5v
122  // temps should be destroyed before dm2
123  // objects should be destroyed after dm2
124  // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
125  auto list = { witharg1(destroyme1()), witharg1(destroyme1()) };
126  // CHECK: call void @_ZN10destroyme1D1Ev
127  destroyme2 dm2;
128  // CHECK: call void @_ZN10destroyme2D1Ev
129  // CHECK: call void @_ZN8witharg1D1Ev
130}
131
132void fn6() {
133  // CHECK: define void @_Z3fn6v
134  void target(const wantslist1&);
135  // objects should be destroyed before dm2, after call returns
136  // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
137  // CHECK: call void @_Z6targetRK10wantslist1
138  target({ destroyme1(), destroyme1() });
139  // CHECK: call void @_ZN10wantslist1D1Ev
140  // CHECK: call void @_ZN10destroyme1D1Ev
141  destroyme2 dm2;
142  // CHECK: call void @_ZN10destroyme2D1Ev
143}
144
145void fn7() {
146  // CHECK: define void @_Z3fn7v
147  // temps should be destroyed before dm2
148  // object should be destroyed after dm2
149  // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
150  wantslist1 wl = { destroyme1(), destroyme1() };
151  // CHECK: call void @_ZN10destroyme1D1Ev
152  destroyme2 dm2;
153  // CHECK: call void @_ZN10destroyme2D1Ev
154  // CHECK: call void @_ZN10wantslist1D1Ev
155}
156
157void fn8() {
158  // CHECK: define void @_Z3fn8v
159  void target(std::initializer_list<std::initializer_list<destroyme1>>);
160  // objects should be destroyed before dm2, after call returns
161  // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE
162  std::initializer_list<destroyme1> inner;
163  target({ inner, { destroyme1() } });
164  // CHECK: call void @_ZN10destroyme1D1Ev
165  // Only one destroy loop, since only one inner init list is directly inited.
166  // CHECK-NOT: call void @_ZN10destroyme1D1Ev
167  destroyme2 dm2;
168  // CHECK: call void @_ZN10destroyme2D1Ev
169}
170
171void fn9() {
172  // CHECK: define void @_Z3fn9v
173  // objects should be destroyed after dm2
174  std::initializer_list<destroyme1> inner;
175  std::initializer_list<std::initializer_list<destroyme1>> list =
176      { inner, { destroyme1() } };
177  destroyme2 dm2;
178  // CHECK: call void @_ZN10destroyme2D1Ev
179  // CHECK: call void @_ZN10destroyme1D1Ev
180  // Only one destroy loop, since only one inner init list is directly inited.
181  // CHECK-NOT: call void @_ZN10destroyme1D1Ev
182  // CHECK: ret void
183}
184
185struct haslist1 {
186  std::initializer_list<int> il;
187  haslist1();
188};
189
190// CHECK: define void @_ZN8haslist1C2Ev
191haslist1::haslist1()
192// CHECK: alloca [3 x i32]
193// CHECK: store i32 1
194// CHECK: store i32 2
195// CHECK: store i32 3
196// CHECK: store i{{32|64}} 3
197  : il{1, 2, 3}
198{
199  destroyme2 dm2;
200}
201
202struct haslist2 {
203  std::initializer_list<destroyme1> il;
204  haslist2();
205};
206
207// CHECK: define void @_ZN8haslist2C2Ev
208haslist2::haslist2()
209  : il{destroyme1(), destroyme1()}
210{
211  destroyme2 dm2;
212  // CHECK: call void @_ZN10destroyme2D1Ev
213  // CHECK: call void @_ZN10destroyme1D1Ev
214}
215
216void fn10() {
217  // CHECK: define void @_Z4fn10v
218  // CHECK: alloca [3 x i32]
219  // CHECK: call noalias i8* @_Znw{{[jm]}}
220  // CHECK: store i32 1
221  // CHECK: store i32 2
222  // CHECK: store i32 3
223  // CHECK: store i32*
224  // CHECK: store i{{32|64}} 3
225  (void) new std::initializer_list<int> {1, 2, 3};
226}
227
228void fn11() {
229  // CHECK: define void @_Z4fn11v
230  (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()};
231  // CHECK: call void @_ZN10destroyme1D1Ev
232  destroyme2 dm2;
233  // CHECK: call void @_ZN10destroyme2D1Ev
234}
235
236namespace PR12178 {
237  struct string {
238    string(int);
239    ~string();
240  };
241
242  struct pair {
243    string a;
244    int b;
245  };
246
247  struct map {
248    map(std::initializer_list<pair>);
249  };
250
251  map m{ {1, 2}, {3, 4} };
252}
253