cxx0x-initializer-stdinitializerlist.cpp revision 211c8ddb5b500ed84833751363d0cfe1115f4dd3
1// RUN: %clang_cc1 -std=c++11 -S -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: @_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
54namespace 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
69std::initializer_list<witharg1> globalInitList2 = {
70  witharg1(destroyme1()), witharg1(destroyme1())
71};
72
73void 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
93void 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
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}
112
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}
137
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}
162
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}
190
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}
221
222void 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
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}
241
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}
259
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}
278
279namespace dtors {
280  struct S {
281    S();
282    ~S();
283  };
284  void f() {
285    std::initializer_list<S>{ S(), S() };
286  }
287  void g() {
288    auto x = std::initializer_list<S>{ S(), S() };
289  }
290}
291