[WinEH] Fix catchpad pred verification
[oota-llvm.git] / test / Verifier / invalid-eh.ll
1 ; RUN: sed -e s/.T1:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s
2 ; RUN: sed -e s/.T2:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s
3 ; RUN: sed -e s/.T3:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s
4 ; RUN: sed -e s/.T4:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s
5 ; RUN: sed -e s/.T5:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK5 %s
6 ; RUN: sed -e s/.T6:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK6 %s
7 ; RUN: sed -e s/.T7:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK7 %s
8 ; RUN: sed -e s/.T8:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK8 %s
9 ; RUN: sed -e s/.T9:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK9 %s
10 ; RUN: sed -e s/.T10:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK10 %s
11 ; RUN: sed -e s/.T11:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK11 %s
12 ; RUN: sed -e s/.T12:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK12 %s
13 ; RUN: sed -e s/.T13:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK13 %s
14 ; RUN: sed -e s/.T14:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK14 %s
15 ; RUN: sed -e s/.T15:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK15 %s
16 ; RUN: sed -e s/.T16:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK16 %s
17 ; RUN: sed -e s/.T17:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK17 %s
18 ; RUN: sed -e s/.T18:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK18 %s
19 ; RUN: sed -e s/.T19:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK19 %s
20 ; RUN: sed -e s/.T20:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK20 %s
21 ; RUN: sed -e s/.T21:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK21 %s
22
23 declare void @g()
24
25 ;T1: define void @f() {
26 ;T1:   entry:
27 ;T1:     catchret from undef to label %next
28 ;T1:     ; CHECK1: CatchReturnInst needs to be provided a CatchPad
29 ;T1:   next:
30 ;T1:     unreachable
31 ;T1: }
32
33 ;T2: define void @f() {
34 ;T2:   entry:
35 ;T2:     %x = cleanuppad within none []
36 ;T2:     ; catchret's first operand's operator must be catchpad
37 ;T2:     catchret from %x to label %entry
38 ;T2:     ; CHECK2: CatchReturnInst needs to be provided a CatchPad
39 ;T2: }
40
41 ;T3: define void @f() {
42 ;T3:   entry:
43 ;T3:     cleanupret from undef unwind label %next
44 ;T3:     ; CHECK3: CleanupReturnInst needs to be provided a CleanupPad
45 ;T3:   next:
46 ;T3:     unreachable
47 ;T3: }
48
49 ;T4: define void @f() {
50 ;T4:   entry:
51 ;T4:     %cs = catchswitch within none [label %next] unwind to caller
52 ;T4:   next:
53 ;T4:     %x = catchpad within %cs []
54 ;T4:     ; cleanupret first operand's operator must be cleanuppad
55 ;T4:     cleanupret from %x unwind to caller
56 ;T4:     ; CHECK4: CleanupReturnInst needs to be provided a CleanupPad
57 ;T4: }
58
59 ;T5: define void @f() personality void ()* @g {
60 ;T5:   entry:
61 ;T5:     ret void
62 ;T5:   switch:
63 ;T5:     %cs = catchswitch within none [label %catch] unwind to caller
64 ;T5:   catch:
65 ;T5:     catchpad within %cs []
66 ;T5:     unreachable
67 ;T5:   bogus:
68 ;T5:     cleanuppad within %cs []
69 ;T5:     ; CHECK5: CleanupPadInst has an invalid parent
70 ;T5:     unreachable
71 ;T5: }
72
73 ;T6: define void @f() personality void ()* @g {
74 ;T6:   entry:
75 ;T6:     ret void
76 ;T6:   switch1:
77 ;T6:     %cs1 = catchswitch within none [label %catch1] unwind label %catch2
78 ;T6:     ; CHECK6: Block containg CatchPadInst must be jumped to only by its catchswitch
79 ;T6:   catch1:
80 ;T6:     catchpad within %cs1 []
81 ;T6:     unreachable
82 ;T6:   switch2:
83 ;T6:     %cs2 = catchswitch within none [label %catch2] unwind to caller
84 ;T6:   catch2:
85 ;T6:     catchpad within %cs2 []
86 ;T6:     unreachable
87 ;T6: }
88
89 ;T7: define void @f() personality void ()* @g {
90 ;T7:   entry:
91 ;T7:     ret void
92 ;T7:   switch1:
93 ;T7:     %cs1 = catchswitch within none [label %catch1] unwind to caller
94 ;T7:   catch1:
95 ;T7:     catchpad within %cs1 []
96 ;T7:     unreachable
97 ;T7:   switch2:
98 ;T7:     %cs2 = catchswitch within %cs1 [label %catch2] unwind to caller
99 ;T7:     ; CHECK7: CatchSwitchInst has an invalid parent
100 ;T7:   catch2:
101 ;T7:     catchpad within %cs2 []
102 ;T7:     unreachable
103 ;T7: }
104
105 ;T8: define void @f() personality void ()* @g {
106 ;T8:   entry:
107 ;T8:     ret void
108 ;T8:   switch1:
109 ;T8:     %cs1 = catchswitch within none [ label %switch1 ] unwind to caller
110 ;T8:     ; CHECK8: CatchSwitchInst handlers must be catchpads
111 ;T8: }
112
113 ;T9: define void @f() personality void ()* @g {
114 ;T9:   entry:
115 ;T9:     ret void
116 ;T9:   cleanup:
117 ;T9:     %cp = cleanuppad within none []
118 ;T9:     invoke void @g() [ "funclet"(token %cp) ]
119 ;T9:       to label %exit unwind label %cleanup
120 ;T9:       ; CHECK9: EH pad cannot handle exceptions raised within it
121 ;T9:       ; CHECK9-NEXT: %cp = cleanuppad within none []
122 ;T9:       ; CHECK9-NEXT: invoke void @g() [ "funclet"(token %cp) ]
123 ;T9:   exit:
124 ;T9:     ret void
125 ;T9: }
126
127 ;T10: define void @f() personality void ()* @g {
128 ;T10:   entry:
129 ;T10:     ret void
130 ;T10:   cleanup1:
131 ;T10:     %cp1 = cleanuppad within none []
132 ;T10:     unreachable
133 ;T10:   switch:
134 ;T10:     %cs = catchswitch within %cp1 [label %catch] unwind to caller
135 ;T10:   catch:
136 ;T10:     %catchp1 = catchpad within %cs [i32 1]
137 ;T10:     unreachable
138 ;T10:   cleanup2:
139 ;T10:     %cp2 = cleanuppad within %catchp1 []
140 ;T10:     unreachable
141 ;T10:   cleanup3:
142 ;T10:     %cp3 = cleanuppad within %cp2 []
143 ;T10:     cleanupret from %cp3 unwind label %switch
144 ;T10:       ; CHECK10: EH pad cannot handle exceptions raised within it
145 ;T10:       ; CHECK10-NEXT: %cs = catchswitch within %cp1 [label %catch] unwind to caller
146 ;T10:       ; CHECK10-NEXT: cleanupret from %cp3 unwind label %switch
147 ;T10: }
148
149 ;T11: define void @f() personality void ()* @g {
150 ;T11:   entry:
151 ;T11:     ret void
152 ;T11:   cleanup1:
153 ;T11:     %cp1 = cleanuppad within none []
154 ;T11:     unreachable
155 ;T11:   cleanup2:
156 ;T11:     %cp2 = cleanuppad within %cp1 []
157 ;T11:     unreachable
158 ;T11:   switch:
159 ;T11:     %cs = catchswitch within none [label %catch] unwind label %cleanup2
160 ;T11:     ; CHECK11: A single unwind edge may only enter one EH pad
161 ;T11:     ; CHECK11-NEXT: %cs = catchswitch within none [label %catch] unwind label %cleanup2
162 ;T11:   catch:
163 ;T11:     catchpad within %cs [i32 1]
164 ;T11:     unreachable
165 ;T11: }
166
167 ;T12: define void @f() personality void ()* @g {
168 ;T12:   entry:
169 ;T12:     ret void
170 ;T12:   cleanup:
171 ;T12:     %cp = cleanuppad within none []
172 ;T12:     cleanupret from %cp unwind label %switch
173 ;T12:     ; CHECK12: A cleanupret must exit its cleanup
174 ;T12:     ; CHECK12-NEXT: cleanupret from %cp unwind label %switch
175 ;T12:   switch:
176 ;T12:     %cs = catchswitch within %cp [label %catch] unwind to caller
177 ;T12:   catch:
178 ;T12:     catchpad within %cs [i32 1]
179 ;T12:     unreachable
180 ;T12: }
181
182 ;T13: define void @f() personality void ()* @g {
183 ;T13:   entry:
184 ;T13:     ret void
185 ;T13:   switch:
186 ;T13:     %cs = catchswitch within none [label %catch] unwind label %switch
187 ;T13:     ; CHECK13: EH pad cannot handle exceptions raised within it
188 ;T13:     ; CHECK13-NEXT:  %cs = catchswitch within none [label %catch] unwind label %switch
189 ;T13:   catch:
190 ;T13:     catchpad within %cs [i32 0]
191 ;T13:     unreachable
192 ;T13: }
193
194 ;T14: define void @f() personality void ()* @g {
195 ;T14:   entry:
196 ;T14:     ret void
197 ;T14:   cleanup:
198 ;T14:     %cp = cleanuppad within none []
199 ;T14:     unreachable
200 ;T14:   left:
201 ;T14:     cleanupret from %cp unwind label %switch
202 ;T14:   right:
203 ;T14:     cleanupret from %cp unwind to caller
204 ;T14:     ; CHECK14: Unwind edges out of a funclet pad must have the same unwind dest
205 ;T14:     ; CHECK14-NEXT: %cp = cleanuppad within none []
206 ;T14:     ; CHECK14-NEXT: cleanupret from %cp unwind label %switch
207 ;T14:     ; CHECK14-NEXT: cleanupret from %cp unwind to caller
208 ;T14:   switch:
209 ;T14:     %cs = catchswitch within none [label %catch] unwind to caller
210 ;T14:   catch:
211 ;T14:     catchpad within %cs [i32 1]
212 ;T14:     unreachable
213 ;T14: }
214
215 ;T15: define void @f() personality void ()* @g {
216 ;T15:   entry:
217 ;T15:     ret void
218 ;T15:   switch:
219 ;T15:     %cs = catchswitch within none [label %catch] unwind to caller
220 ;T15:   catch:
221 ;T15:     %catch.pad = catchpad within %cs [i32 1]
222 ;T15:     invoke void @g() [ "funclet"(token %catch.pad) ]
223 ;T15:       to label %unreachable unwind label %target1
224 ;T15:   unreachable:
225 ;T15:     unreachable
226 ;T15:   target1:
227 ;T15:     cleanuppad within none []
228 ;T15:     unreachable
229 ;T15:   target2:
230 ;T15:     cleanuppad within none []
231 ;T15:     unreachable
232 ;T15:   nested.1:
233 ;T15:     %nested.pad.1 = cleanuppad within %catch.pad []
234 ;T15:     unreachable
235 ;T15:   nested.2:
236 ;T15:     %nested.pad.2 = cleanuppad within %nested.pad.1 []
237 ;T15:     cleanupret from %nested.pad.2 unwind label %target2
238 ;T15:     ; CHECK15: Unwind edges out of a funclet pad must have the same unwind dest
239 ;T15:     ; CHECK15-NEXT: %catch.pad = catchpad within %cs [i32 1]
240 ;T15:     ; CHECK15-NEXT: cleanupret from %nested.pad.2 unwind label %target2
241 ;T15:     ; CHECK15-NEXT: invoke void @g() [ "funclet"(token %catch.pad) ]
242 ;T15:     ; CHECK15-NEXT:   to label %unreachable unwind label %target1
243 ;T15: }
244
245 ;T16: define void @f() personality void ()* @g {
246 ;T16:   entry:
247 ;T16:     ret void
248 ;T16:   switch:
249 ;T16:     %cs = catchswitch within none [label %catch] unwind to caller
250 ;T16:   catch:
251 ;T16:     %catch.pad = catchpad within %cs [i32 1]
252 ;T16:     invoke void @g() [ "funclet"(token %catch.pad) ]
253 ;T16:       to label %unreachable unwind label %target1
254 ;T16:     ; CHECK16: Unwind edges out of a catch must have the same unwind dest as the parent catchswitch
255 ;T16:     ; CHECK16-NEXT:   %catch.pad = catchpad within %cs [i32 1]
256 ;T16:     ; CHECK16-NEXT:  invoke void @g() [ "funclet"(token %catch.pad) ]
257 ;T16:     ; CHECK16-NEXT:          to label %unreachable unwind label %target1
258 ;T16:     ; CHECK16-NEXT:  %cs = catchswitch within none [label %catch] unwind to caller
259 ;T16:   unreachable:
260 ;T16:     unreachable
261 ;T16:   target1:
262 ;T16:     cleanuppad within none []
263 ;T16:     unreachable
264 ;T16: }
265
266 ;T17: define void @f() personality void ()* @g {
267 ;T17:   entry:
268 ;T17:     ret void
269 ;T17:   switch:
270 ;T17:     %cs = catchswitch within none [label %catch] unwind label %target1
271 ;T17:   catch:
272 ;T17:     %catch.pad = catchpad within %cs [i32 1]
273 ;T17:     invoke void @g() [ "funclet"(token %catch.pad) ]
274 ;T17:       to label %unreachable unwind label %target2
275 ;T17:     ; CHECK17: Unwind edges out of a catch must have the same unwind dest as the parent catchswitch
276 ;T17:     ; CHECK17-NEXT:  %catch.pad = catchpad within %cs [i32 1]
277 ;T17:     ; CHECK17-NEXT:  invoke void @g() [ "funclet"(token %catch.pad) ]
278 ;T17:     ; CHECK17-NEXT:          to label %unreachable unwind label %target2
279 ;T17:     ; CHECK17-NEXT:  %cs = catchswitch within none [label %catch] unwind label %target1
280 ;T17:   unreachable:
281 ;T17:     unreachable
282 ;T17:   target1:
283 ;T17:     cleanuppad within none []
284 ;T17:     unreachable
285 ;T17:   target2:
286 ;T17:     cleanuppad within none []
287 ;T17:     unreachable
288 ;T17: }
289
290 ;T18: define void @f() personality void ()* @g {
291 ;T18:   entry:
292 ;T18:     invoke void @g()
293 ;T18:       to label %invoke.cont unwind label %left
294 ;T18:   invoke.cont:
295 ;T18:     invoke void @g()
296 ;T18:       to label %unreachable unwind label %right
297 ;T18:   left:
298 ;T18:     %cp.left = cleanuppad within none []
299 ;T18:     invoke void @g() [ "funclet"(token %cp.left) ]
300 ;T18:       to label %unreachable unwind label %right
301 ;T18:   right:
302 ;T18:     %cp.right = cleanuppad within none []
303 ;T18:     invoke void @g() [ "funclet"(token %cp.right) ]
304 ;T18:       to label %unreachable unwind label %left
305 ;T18:     ; CHECK18: EH pads can't handle each other's exceptions
306 ;T18:     ; CHECK18-NEXT: %cp.left = cleanuppad within none []
307 ;T18:     ; CHECK18-NEXT:  invoke void @g() [ "funclet"(token %cp.left) ]
308 ;T18:     ; CHECK18-NEXT:          to label %unreachable unwind label %right
309 ;T18:     ; CHECK18-NEXT:  %cp.right = cleanuppad within none []
310 ;T18:     ; CHECK18-NEXT:  invoke void @g() [ "funclet"(token %cp.right) ]
311 ;T18:     ; CHECK18-NEXT:          to label %unreachable unwind label %left
312 ;T18:   unreachable:
313 ;T18:     unreachable
314 ;T18: }
315
316 ;T19: define void @f() personality void ()* @g {
317 ;T19:   entry:
318 ;T19:     ret void
319 ;T19:   red:
320 ;T19:     %redpad = cleanuppad within none []
321 ;T19:     unreachable
322 ;T19:   red.inner:
323 ;T19:     %innerpad = cleanuppad within %redpad []
324 ;T19:     invoke void @g() [ "funclet"(token %innerpad) ]
325 ;T19:       to label %unreachable unwind label %green
326 ;T19:   green:
327 ;T19:     %greenswitch = catchswitch within none [label %catch] unwind label %blue
328 ;T19:   catch:
329 ;T19:     catchpad within %greenswitch [i32 42]
330 ;T19:     unreachable
331 ;T19:   blue:
332 ;T19:     %bluepad = cleanuppad within none []
333 ;T19:     cleanupret from %bluepad unwind label %red
334 ;T19:     ; CHECK19: EH pads can't handle each other's exceptions
335 ;T19:     ; CHECK19-NEXT: %redpad = cleanuppad within none []
336 ;T19:     ; CHECK19-NEXT: invoke void @g() [ "funclet"(token %innerpad) ]
337 ;T19:     ; CHECK19-NEXT:         to label %unreachable unwind label %green
338 ;T19:     ; CHECK19-NEXT: %greenswitch = catchswitch within none [label %catch] unwind label %blue
339 ;T19:     ; CHECK19-NEXT: %bluepad = cleanuppad within none []
340 ;T19:     ; CHECK19-NEXT: cleanupret from %bluepad unwind label %red
341 ;T19:   unreachable:
342 ;T19:     unreachable
343 ;T19: }
344
345 ;T20: define void @f() personality void ()* @g {
346 ;T20:   entry:
347 ;T20:     ret void
348 ;T20:   switch:
349 ;T20:     %cs = catchswitch within none [label %catch] unwind label %catch
350 ;T20:     ; CHECK20: Catchswitch cannot unwind to one of its catchpads
351 ;T20:     ; CHECK20-NEXT: %cs = catchswitch within none [label %catch] unwind label %catch
352 ;T20:     ; CHECK20-NEXT: %cp = catchpad within %cs [i32 4]
353 ;T20:   catch:
354 ;T20:     %cp = catchpad within %cs [i32 4]
355 ;T20:     unreachable
356 ;T20: }
357
358 ;T21: define void @f() personality void ()* @g {
359 ;T21:   entry:
360 ;T21:     ret void
361 ;T21:   switch:
362 ;T21:     %cs = catchswitch within none [label %catch1] unwind label %catch2
363 ;T21:     ; CHECK21: Catchswitch cannot unwind to one of its catchpads
364 ;T21:     ; CHECK21-NEXT: %cs = catchswitch within none [label %catch1] unwind label %catch2
365 ;T21:     ; CHECK21-NEXT: %cp2 = catchpad within %cs [i32 2]
366 ;T21:   catch1:
367 ;T21:     %cp1 = catchpad within %cs [i32 1]
368 ;T21:     unreachable
369 ;T21:   catch2:
370 ;T21:     %cp2 = catchpad within %cs [i32 2]
371 ;T21:     unreachable
372 ;T21: }