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