1 // RUN: %clang_cc1 -std=c++11 -S -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 
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 
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: @_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 }
52 std::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
63 std::initializer_list<witharg1> globalInitList2 = {
64   witharg1(destroyme1()), witharg1(destroyme1())
65 };
66 
67 void 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 
87 void 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 
98 void 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 
107 void 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 
120 void 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 
132 void 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 
145 void 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 
157 void 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 
171 void 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 
185 struct haslist1 {
186   std::initializer_list<int> il;
187   haslist1();
188 };
189 
190 // CHECK: define void @_ZN8haslist1C2Ev
191 haslist1::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 
202 struct haslist2 {
203   std::initializer_list<destroyme1> il;
204   haslist2();
205 };
206 
207 // CHECK: define void @_ZN8haslist2C2Ev
208 haslist2::haslist2()
209   : il{destroyme1(), destroyme1()}
210 {
211   destroyme2 dm2;
212   // CHECK: call void @_ZN10destroyme2D1Ev
213   // CHECK: call void @_ZN10destroyme1D1Ev
214 }
215 
216 void 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 
228 void 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 
236 namespace 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