blob: d683493a83d812fc4ed3168703c5d0cc993d4060 [file] [log] [blame]
David Blaikie1b76fbc2012-09-10 23:06:08 +00001// RUN: %clang_cc1 -std=c++11 -S -triple x86_64-none-linux-gnu -emit-llvm -o - %s | FileCheck %s
Sebastian Redl32cf1f22012-02-17 08:42:25 +00002
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
Sebastian Redl19b1a6e2012-02-25 20:51:20 +000035struct 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
Richard Smith04e51762013-04-14 23:01:42 +000054namespace 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
Sebastian Redl19b1a6e2012-02-25 20:51:20 +000060// 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
69std::initializer_list<witharg1> globalInitList2 = {
70 witharg1(destroyme1()), witharg1(destroyme1())
71};
72
Sebastian Redl32cf1f22012-02-17 08:42:25 +000073void 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
Sebastian Redl32cf1f22012-02-17 08:42:25 +000093void fn2() {
94 // CHECK: define void @_Z3fn2v
95 void target(std::initializer_list<destroyme1>);
96 // objects should be destroyed before dm2, after call returns
Sebastian Redl25e640a2012-02-19 12:27:51 +000097 // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E
Sebastian Redl32cf1f22012-02-17 08:42:25 +000098 target({ destroyme1(), destroyme1() });
99 // CHECK: call void @_ZN10destroyme1D1Ev
100 destroyme2 dm2;
101 // CHECK: call void @_ZN10destroyme2D1Ev
102}
103
104void 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}
Sebastian Redl25e640a2012-02-19 12:27:51 +0000112
113void 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
126void 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}
Sebastian Redlbac5cf42012-02-19 12:27:56 +0000137
138void 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
151void 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}
Sebastian Redlaf130fd2012-02-19 12:28:02 +0000162
163void 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
177void 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}
Sebastian Redl924db712012-02-19 15:41:54 +0000190
191struct haslist1 {
192 std::initializer_list<int> il;
193 haslist1();
194};
195
196// CHECK: define void @_ZN8haslist1C2Ev
197haslist1::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
208struct haslist2 {
209 std::initializer_list<destroyme1> il;
210 haslist2();
211};
212
213// CHECK: define void @_ZN8haslist2C2Ev
214haslist2::haslist2()
215 : il{destroyme1(), destroyme1()}
216{
217 destroyme2 dm2;
218 // CHECK: call void @_ZN10destroyme2D1Ev
219 // CHECK: call void @_ZN10destroyme1D1Ev
220}
Sebastian Redl972edf02012-02-19 16:03:09 +0000221
222void fn10() {
223 // CHECK: define void @_Z4fn10v
224 // CHECK: alloca [3 x i32]
Benjamin Kramer4b45d7f2012-02-19 16:20:58 +0000225 // CHECK: call noalias i8* @_Znw{{[jm]}}
Sebastian Redl972edf02012-02-19 16:03:09 +0000226 // 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
234void 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}
Sebastian Redl28357452012-03-05 19:35:43 +0000241
242namespace 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}
Douglas Gregor29a11f42013-04-06 00:46:20 +0000259
260namespace 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}