blob: 68754f436ae3ff27adf8dd52f6609bc24a0b12ce [file] [log] [blame]
Sebastian Redl32cf1f22012-02-17 08:42:25 +00001// 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
35void fn1(int i) {
36 // CHECK: define void @_Z3fn1i
37 // temporary array
38 // CHECK: [[array:%[^ ]+]] = alloca [3 x i32]
39 // CHECK: getelementptr inbounds [3 x i32]* [[array]], i{{32|64}} 0
40 // CHECK-NEXT: store i32 1, i32*
41 // CHECK-NEXT: getelementptr
42 // CHECK-NEXT: store
43 // CHECK-NEXT: getelementptr
44 // CHECK-NEXT: load
45 // CHECK-NEXT: store
46 // init the list
47 // CHECK-NEXT: getelementptr
48 // CHECK-NEXT: getelementptr inbounds [3 x i32]*
49 // CHECK-NEXT: store i32*
50 // CHECK-NEXT: getelementptr
51 // CHECK-NEXT: store i{{32|64}} 3
52 std::initializer_list<int> intlist{1, 2, i};
53}
54
55struct destroyme1 {
56 ~destroyme1();
57};
58struct destroyme2 {
59 ~destroyme2();
60};
Sebastian Redl25e640a2012-02-19 12:27:51 +000061struct witharg1 {
62 witharg1(const destroyme1&);
63 ~witharg1();
64};
Sebastian Redlbac5cf42012-02-19 12:27:56 +000065struct wantslist1 {
66 wantslist1(std::initializer_list<destroyme1>);
67 ~wantslist1();
68};
Sebastian Redl32cf1f22012-02-17 08:42:25 +000069
70void fn2() {
71 // CHECK: define void @_Z3fn2v
72 void target(std::initializer_list<destroyme1>);
73 // objects should be destroyed before dm2, after call returns
Sebastian Redl25e640a2012-02-19 12:27:51 +000074 // CHECK: call void @_Z6targetSt16initializer_listI10destroyme1E
Sebastian Redl32cf1f22012-02-17 08:42:25 +000075 target({ destroyme1(), destroyme1() });
76 // CHECK: call void @_ZN10destroyme1D1Ev
77 destroyme2 dm2;
78 // CHECK: call void @_ZN10destroyme2D1Ev
79}
80
81void fn3() {
82 // CHECK: define void @_Z3fn3v
83 // objects should be destroyed after dm2
84 auto list = { destroyme1(), destroyme1() };
85 destroyme2 dm2;
86 // CHECK: call void @_ZN10destroyme2D1Ev
87 // CHECK: call void @_ZN10destroyme1D1Ev
88}
Sebastian Redl25e640a2012-02-19 12:27:51 +000089
90void fn4() {
91 // CHECK: define void @_Z3fn4v
92 void target(std::initializer_list<witharg1>);
93 // objects should be destroyed before dm2, after call returns
94 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
95 // CHECK: call void @_Z6targetSt16initializer_listI8witharg1E
96 target({ witharg1(destroyme1()), witharg1(destroyme1()) });
97 // CHECK: call void @_ZN8witharg1D1Ev
98 // CHECK: call void @_ZN10destroyme1D1Ev
99 destroyme2 dm2;
100 // CHECK: call void @_ZN10destroyme2D1Ev
101}
102
103void fn5() {
104 // CHECK: define void @_Z3fn5v
105 // temps should be destroyed before dm2
106 // objects should be destroyed after dm2
107 // CHECK: call void @_ZN8witharg1C1ERK10destroyme1
108 auto list = { witharg1(destroyme1()), witharg1(destroyme1()) };
109 // CHECK: call void @_ZN10destroyme1D1Ev
110 destroyme2 dm2;
111 // CHECK: call void @_ZN10destroyme2D1Ev
112 // CHECK: call void @_ZN8witharg1D1Ev
113}
Sebastian Redlbac5cf42012-02-19 12:27:56 +0000114
115void fn6() {
116 // CHECK: define void @_Z3fn6v
117 void target(const wantslist1&);
118 // objects should be destroyed before dm2, after call returns
119 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
120 // CHECK: call void @_Z6targetRK10wantslist1
121 target({ destroyme1(), destroyme1() });
122 // CHECK: call void @_ZN10wantslist1D1Ev
123 // CHECK: call void @_ZN10destroyme1D1Ev
124 destroyme2 dm2;
125 // CHECK: call void @_ZN10destroyme2D1Ev
126}
127
128void fn7() {
129 // CHECK: define void @_Z3fn7v
130 // temps should be destroyed before dm2
131 // object should be destroyed after dm2
132 // CHECK: call void @_ZN10wantslist1C1ESt16initializer_listI10destroyme1E
133 wantslist1 wl = { destroyme1(), destroyme1() };
134 // CHECK: call void @_ZN10destroyme1D1Ev
135 destroyme2 dm2;
136 // CHECK: call void @_ZN10destroyme2D1Ev
137 // CHECK: call void @_ZN10wantslist1D1Ev
138}
Sebastian Redlaf130fd2012-02-19 12:28:02 +0000139
140void fn8() {
141 // CHECK: define void @_Z3fn8v
142 void target(std::initializer_list<std::initializer_list<destroyme1>>);
143 // objects should be destroyed before dm2, after call returns
144 // CHECK: call void @_Z6targetSt16initializer_listIS_I10destroyme1EE
145 std::initializer_list<destroyme1> inner;
146 target({ inner, { destroyme1() } });
147 // CHECK: call void @_ZN10destroyme1D1Ev
148 // Only one destroy loop, since only one inner init list is directly inited.
149 // CHECK-NOT: call void @_ZN10destroyme1D1Ev
150 destroyme2 dm2;
151 // CHECK: call void @_ZN10destroyme2D1Ev
152}
153
154void fn9() {
155 // CHECK: define void @_Z3fn9v
156 // objects should be destroyed after dm2
157 std::initializer_list<destroyme1> inner;
158 std::initializer_list<std::initializer_list<destroyme1>> list =
159 { inner, { destroyme1() } };
160 destroyme2 dm2;
161 // CHECK: call void @_ZN10destroyme2D1Ev
162 // CHECK: call void @_ZN10destroyme1D1Ev
163 // Only one destroy loop, since only one inner init list is directly inited.
164 // CHECK-NOT: call void @_ZN10destroyme1D1Ev
165 // CHECK: ret void
166}
Sebastian Redl924db712012-02-19 15:41:54 +0000167
168struct haslist1 {
169 std::initializer_list<int> il;
170 haslist1();
171};
172
173// CHECK: define void @_ZN8haslist1C2Ev
174haslist1::haslist1()
175// CHECK: alloca [3 x i32]
176// CHECK: store i32 1
177// CHECK: store i32 2
178// CHECK: store i32 3
179// CHECK: store i{{32|64}} 3
180 : il{1, 2, 3}
181{
182 destroyme2 dm2;
183}
184
185struct haslist2 {
186 std::initializer_list<destroyme1> il;
187 haslist2();
188};
189
190// CHECK: define void @_ZN8haslist2C2Ev
191haslist2::haslist2()
192 : il{destroyme1(), destroyme1()}
193{
194 destroyme2 dm2;
195 // CHECK: call void @_ZN10destroyme2D1Ev
196 // CHECK: call void @_ZN10destroyme1D1Ev
197}
Sebastian Redl972edf02012-02-19 16:03:09 +0000198
199void fn10() {
200 // CHECK: define void @_Z4fn10v
201 // CHECK: alloca [3 x i32]
Benjamin Kramer4b45d7f2012-02-19 16:20:58 +0000202 // CHECK: call noalias i8* @_Znw{{[jm]}}
Sebastian Redl972edf02012-02-19 16:03:09 +0000203 // CHECK: store i32 1
204 // CHECK: store i32 2
205 // CHECK: store i32 3
206 // CHECK: store i32*
207 // CHECK: store i{{32|64}} 3
208 (void) new std::initializer_list<int> {1, 2, 3};
209}
210
211void fn11() {
212 // CHECK: define void @_Z4fn11v
213 (void) new std::initializer_list<destroyme1> {destroyme1(), destroyme1()};
214 // CHECK: call void @_ZN10destroyme1D1Ev
215 destroyme2 dm2;
216 // CHECK: call void @_ZN10destroyme2D1Ev
217}