1 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s
2 void *f();
3
g()4 template <typename T> T* g() {
5 if (T* t = f())
6 return t;
7
8 return 0;
9 }
10
h()11 void h() {
12 void *a = g<void>();
13 }
14
15 struct X {
16 X();
17 X(const X&);
18 ~X();
19 operator bool();
20 };
21
22 struct Y {
23 Y();
24 ~Y();
25 };
26
27 X getX();
28
29 // CHECK-LABEL: define void @_Z11if_destructi(
if_destruct(int z)30 void if_destruct(int z) {
31 // Verify that the condition variable is destroyed at the end of the
32 // "if" statement.
33 // CHECK: call void @_ZN1XC1Ev
34 // CHECK: call zeroext i1 @_ZN1XcvbEv
35 if (X x = X()) {
36 // CHECK: store i32 18
37 z = 18;
38 }
39 // CHECK: call void @_ZN1XD1Ev
40 // CHECK: store i32 17
41 z = 17;
42
43 // CHECK: call void @_ZN1XC1Ev
44 if (X x = X())
45 Y y;
46 // CHECK: br
47 // CHECK: call void @_ZN1YC1Ev
48 // CHECK: call void @_ZN1YD1Ev
49 // CHECK: br
50 // CHECK: call void @_ZN1XD1Ev
51
52 // CHECK: call void @_Z4getXv
53 // CHECK: call zeroext i1 @_ZN1XcvbEv
54 // CHECK: call void @_ZN1XD1Ev
55 // CHECK: br
56 if (getX()) { }
57
58 // CHECK: ret
59 }
60
61 struct ConvertibleToInt {
62 ConvertibleToInt();
63 ~ConvertibleToInt();
64 operator int();
65 };
66
67 ConvertibleToInt getConvToInt();
68
switch_destruct(int z)69 void switch_destruct(int z) {
70 // CHECK: call void @_ZN16ConvertibleToIntC1Ev
71 switch (ConvertibleToInt conv = ConvertibleToInt()) {
72 case 0:
73 break;
74
75 default:
76 // CHECK: store i32 19
77 z = 19;
78 break;
79 }
80 // CHECK: call void @_ZN16ConvertibleToIntD1Ev
81 // CHECK: store i32 20
82 z = 20;
83
84 // CHECK: call void @_Z12getConvToIntv
85 // CHECK: call i32 @_ZN16ConvertibleToIntcviEv
86 // CHECK: call void @_ZN16ConvertibleToIntD1Ev
87 switch(getConvToInt()) {
88 case 0:
89 break;
90 }
91 // CHECK: store i32 27
92 z = 27;
93 // CHECK: ret
94 }
95
96 int foo();
97
98 // CHECK-LABEL: define void @_Z14while_destructi
while_destruct(int z)99 void while_destruct(int z) {
100 // CHECK: [[Z:%.*]] = alloca i32
101 // CHECK: [[CLEANUPDEST:%.*]] = alloca i32
102 while (X x = X()) {
103 // CHECK: call void @_ZN1XC1Ev
104 // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN1XcvbEv
105 // CHECK-NEXT: br i1 [[COND]]
106
107 // Loop-exit staging block.
108 // CHECK: store i32 3, i32* [[CLEANUPDEST]]
109 // CHECK-NEXT: br
110
111 // While body.
112 // CHECK: store i32 21, i32* [[Z]]
113 // CHECK: store i32 0, i32* [[CLEANUPDEST]]
114 // CHECK-NEXT: br
115 z = 21;
116
117 // Cleanup.
118 // CHECK: call void @_ZN1XD1Ev
119 // CHECK-NEXT: [[DEST:%.*]] = load i32, i32* [[CLEANUPDEST]]
120 // CHECK-NEXT: switch i32 [[DEST]]
121 }
122
123 // CHECK: store i32 22, i32* [[Z]]
124 z = 22;
125
126 // CHECK: call void @_Z4getXv
127 // CHECK-NEXT: call zeroext i1 @_ZN1XcvbEv
128 // CHECK-NEXT: call void @_ZN1XD1Ev
129 // CHECK-NEXT: br
130 while(getX()) { }
131
132 // CHECK: store i32 25, i32* [[Z]]
133 z = 25;
134
135 // CHECK: ret
136 }
137
138 // CHECK-LABEL: define void @_Z12for_destructi(
for_destruct(int z)139 void for_destruct(int z) {
140 // CHECK: [[Z:%.*]] = alloca i32
141 // CHECK: [[CLEANUPDEST:%.*]] = alloca i32
142 // CHECK: [[I:%.*]] = alloca i32
143 // CHECK: call void @_ZN1YC1Ev
144 // CHECK-NEXT: br
145 // -> %for.cond
146
147 for(Y y = Y(); X x = X(); ++z) {
148 // %for.cond: The loop condition.
149 // CHECK: call void @_ZN1XC1Ev
150 // CHECK-NEXT: [[COND:%.*]] = call zeroext i1 @_ZN1XcvbEv(
151 // CHECK-NEXT: br i1 [[COND]]
152 // -> %for.body, %for.cond.cleanup
153
154 // %for.cond.cleanup: Exit cleanup staging.
155 // CHECK: store i32 2, i32* [[CLEANUPDEST]]
156 // CHECK-NEXT: br
157 // -> %cleanup
158
159 // %for.body:
160 // CHECK: store i32 23, i32* [[Z]]
161 // CHECK-NEXT: br
162 // -> %for.inc
163 z = 23;
164
165 // %for.inc:
166 // CHECK: [[TMP:%.*]] = load i32, i32* [[Z]]
167 // CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP]], 1
168 // CHECK-NEXT: store i32 [[INC]], i32* [[Z]]
169 // CHECK-NEXT: store i32 0, i32* [[CLEANUPDEST]]
170 // CHECK-NEXT: br
171 // -> %cleanup
172
173 // %cleanup: Destroys X.
174 // CHECK: call void @_ZN1XD1Ev
175 // CHECK-NEXT: [[YDESTTMP:%.*]] = load i32, i32* [[CLEANUPDEST]]
176 // CHECK-NEXT: switch i32 [[YDESTTMP]]
177 // 0 -> %cleanup.cont, default -> %cleanup1
178
179 // %cleanup.cont: (eliminable)
180 // CHECK: br
181 // -> %for.cond
182
183 // %cleanup1: Destroys Y.
184 // CHECK: call void @_ZN1YD1Ev(
185 // CHECK-NEXT: br
186 // -> %for.end
187 }
188
189 // %for.end:
190 // CHECK: store i32 24
191 z = 24;
192
193 // CHECK-NEXT: store i32 0, i32* [[I]]
194 // CHECK-NEXT: br
195 // -> %for.cond6
196
197 // %for.cond6:
198 // CHECK: call void @_Z4getXv
199 // CHECK-NEXT: call zeroext i1 @_ZN1XcvbEv
200 // CHECK-NEXT: call void @_ZN1XD1Ev
201 // CHECK-NEXT: br
202 // -> %for.body10, %for.end16
203
204 // %for.body10:
205 // CHECK: br
206 // -> %for.inc11
207
208 // %for.inc11:
209 // CHECK: call void @_Z4getXv
210 // CHECK-NEXT: load i32, i32* [[I]]
211 // CHECK-NEXT: add
212 // CHECK-NEXT: store
213 // CHECK-NEXT: call void @_ZN1XD1Ev
214 // CHECK-NEXT: br
215 // -> %for.cond6
216 int i = 0;
217 for(; getX(); getX(), ++i) { }
218
219 // %for.end16
220 // CHECK: store i32 26
221 z = 26;
222
223 // CHECK-NEXT: ret void
224 }
225
do_destruct(int z)226 void do_destruct(int z) {
227 // CHECK-LABEL: define void @_Z11do_destruct
228 do {
229 // CHECK: store i32 77
230 z = 77;
231 // CHECK: call void @_Z4getXv
232 // CHECK: call zeroext i1 @_ZN1XcvbEv
233 // CHECK: call void @_ZN1XD1Ev
234 // CHECK: br
235 } while (getX());
236 // CHECK: store i32 99
237 z = 99;
238 // CHECK: ret
239 }
240
241 int f(X);
242
243 template<typename T>
instantiated(T x)244 int instantiated(T x) {
245 int result;
246
247 // CHECK: call void @_ZN1XC1ERKS_
248 // CHECK: call i32 @_Z1f1X
249 // CHECK: call void @_ZN1XD1Ev
250 // CHECK: br
251 // CHECK: store i32 2
252 // CHECK: br
253 // CHECK: store i32 3
254 if (f(x)) { result = 2; } else { result = 3; }
255
256 // CHECK: call void @_ZN1XC1ERKS_
257 // CHECK: call i32 @_Z1f1X
258 // CHECK: call void @_ZN1XD1Ev
259 // CHECK: br
260 // CHECK: store i32 4
261 // CHECK: br
262 while (f(x)) { result = 4; }
263
264 // CHECK: call void @_ZN1XC1ERKS_
265 // CHECK: call i32 @_Z1f1X
266 // CHECK: call void @_ZN1XD1Ev
267 // CHECK: br
268 // CHECK: store i32 6
269 // CHECK: br
270 // CHECK: call void @_ZN1XC1ERKS_
271 // CHECK: call i32 @_Z1f1X
272 // CHECK: store i32 5
273 // CHECK: call void @_ZN1XD1Ev
274 // CHECK: br
275 for (; f(x); f(x), result = 5) {
276 result = 6;
277 }
278
279 // CHECK: call void @_ZN1XC1ERKS_
280 // CHECK: call i32 @_Z1f1X
281 // CHECK: call void @_ZN1XD1Ev
282 // CHECK: switch i32
283 // CHECK: store i32 7
284 // CHECK: store i32 8
285 switch (f(x)) {
286 case 0:
287 result = 7;
288 break;
289
290 case 1:
291 result = 8;
292 }
293
294 // CHECK: store i32 9
295 // CHECK: br
296 // CHECK: call void @_ZN1XC1ERKS_
297 // CHECK: call i32 @_Z1f1X
298 // CHECK: call void @_ZN1XD1Ev
299 // CHECK: br
300 do {
301 result = 9;
302 } while (f(x));
303
304 // CHECK: store i32 10
305 // CHECK: call void @_ZN1XC1ERKS_
306 // CHECK: call zeroext i1 @_ZN1XcvbEv
307 // CHECK: call void @_ZN1XD1Ev
308 // CHECK: br
309 do {
310 result = 10;
311 } while (X(x));
312
313 // CHECK: ret i32
314 return result;
315 }
316
317 template int instantiated(X);
318