1 | // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -emit-llvm -o - %s | FileCheck %s |
2 | void *f(); |
3 | |
4 | template <typename T> T* g() { |
5 | if (T* t = f()) |
6 | return t; |
7 | |
8 | return 0; |
9 | } |
10 | |
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( |
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 | |
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 |
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( |
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 | |
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> |
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 | |