e5ad2abfb5ed21d2d14cf1d492ca041ee3a6ec59
[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
19 declare void @g()
20
21 ;T1: define void @f() {
22 ;T1:   entry:
23 ;T1:     catchret from undef to label %next
24 ;T1:     ; CHECK1: CatchReturnInst needs to be provided a CatchPad
25 ;T1:   next:
26 ;T1:     unreachable
27 ;T1: }
28
29 ;T2: define void @f() {
30 ;T2:   entry:
31 ;T2:     %x = cleanuppad within none []
32 ;T2:     ; catchret's first operand's operator must be catchpad
33 ;T2:     catchret from %x to label %entry
34 ;T2:     ; CHECK2: CatchReturnInst needs to be provided a CatchPad
35 ;T2: }
36
37 ;T3: define void @f() {
38 ;T3:   entry:
39 ;T3:     cleanupret from undef unwind label %next
40 ;T3:     ; CHECK3: CleanupReturnInst needs to be provided a CleanupPad
41 ;T3:   next:
42 ;T3:     unreachable
43 ;T3: }
44
45 ;T4: define void @f() {
46 ;T4:   entry:
47 ;T4:     %cs = catchswitch within none [label %next] unwind to caller
48 ;T4:   next:
49 ;T4:     %x = catchpad within %cs []
50 ;T4:     ; cleanupret first operand's operator must be cleanuppad
51 ;T4:     cleanupret from %x unwind to caller
52 ;T4:     ; CHECK4: CleanupReturnInst needs to be provided a CleanupPad
53 ;T4: }
54
55 ;T5: define void @f() personality void ()* @g {
56 ;T5:   entry:
57 ;T5:     ret void
58 ;T5:   switch:
59 ;T5:     %cs = catchswitch within none [label %catch] unwind to caller
60 ;T5:   catch:
61 ;T5:     catchpad within %cs []
62 ;T5:     unreachable
63 ;T5:   bogus:
64 ;T5:     cleanuppad within %cs []
65 ;T5:     ; CHECK5: CleanupPadInst has an invalid parent
66 ;T5:     unreachable
67 ;T5: }
68
69 ;T6: define void @f() personality void ()* @g {
70 ;T6:   entry:
71 ;T6:     ret void
72 ;T6:   switch1:
73 ;T6:     %cs1 = catchswitch within none [label %catch1] unwind label %catch2
74 ;T6:     ; CHECK6: Block containg CatchPadInst must be jumped to only by its catchswitch
75 ;T6:   catch1:
76 ;T6:     catchpad within %cs1 []
77 ;T6:     unreachable
78 ;T6:   switch2:
79 ;T6:     %cs2 = catchswitch within none [label %catch2] unwind to caller
80 ;T6:   catch2:
81 ;T6:     catchpad within %cs2 []
82 ;T6:     unreachable
83 ;T6: }
84
85 ;T7: define void @f() personality void ()* @g {
86 ;T7:   entry:
87 ;T7:     ret void
88 ;T7:   switch1:
89 ;T7:     %cs1 = catchswitch within none [label %catch1] unwind to caller
90 ;T7:   catch1:
91 ;T7:     catchpad within %cs1 []
92 ;T7:     unreachable
93 ;T7:   switch2:
94 ;T7:     %cs2 = catchswitch within %cs1 [label %catch2] unwind to caller
95 ;T7:     ; CHECK7: CatchSwitchInst has an invalid parent
96 ;T7:   catch2:
97 ;T7:     catchpad within %cs2 []
98 ;T7:     unreachable
99 ;T7: }
100
101 ;T8: define void @f() personality void ()* @g {
102 ;T8:   entry:
103 ;T8:     ret void
104 ;T8:   switch1:
105 ;T8:     %cs1 = catchswitch within none [ label %switch1 ] unwind to caller
106 ;T8:     ; CHECK8: CatchSwitchInst handlers must be catchpads
107 ;T8: }
108
109 ;T9: define void @f() personality void ()* @g {
110 ;T9:   entry:
111 ;T9:     ret void
112 ;T9:   cleanup:
113 ;T9:     %cp = cleanuppad within none []
114 ;T9:     invoke void @g() [ "funclet"(token %cp) ]
115 ;T9:       to label %exit unwind label %cleanup
116 ;T9:       ; CHECK9: EH pad cannot handle exceptions raised within it
117 ;T9:       ; CHECK9-NEXT: %cp = cleanuppad within none []
118 ;T9:       ; CHECK9-NEXT: invoke void @g() [ "funclet"(token %cp) ]
119 ;T9:   exit:
120 ;T9:     ret void
121 ;T9: }
122
123 ;T10: define void @f() personality void ()* @g {
124 ;T10:   entry:
125 ;T10:     ret void
126 ;T10:   cleanup1:
127 ;T10:     %cp1 = cleanuppad within none []
128 ;T10:     unreachable
129 ;T10:   switch:
130 ;T10:     %cs = catchswitch within %cp1 [label %catch] unwind to caller
131 ;T10:   catch:
132 ;T10:     %catchp1 = catchpad within %cs [i32 1]
133 ;T10:     unreachable
134 ;T10:   cleanup2:
135 ;T10:     %cp2 = cleanuppad within %catchp1 []
136 ;T10:     unreachable
137 ;T10:   cleanup3:
138 ;T10:     %cp3 = cleanuppad within %cp2 []
139 ;T10:     cleanupret from %cp3 unwind label %switch
140 ;T10:       ; CHECK10: EH pad cannot handle exceptions raised within it
141 ;T10:       ; CHECK10-NEXT: %cs = catchswitch within %cp1 [label %catch] unwind to caller
142 ;T10:       ; CHECK10-NEXT: cleanupret from %cp3 unwind label %switch
143 ;T10: }
144
145 ;T11: define void @f() personality void ()* @g {
146 ;T11:   entry:
147 ;T11:     ret void
148 ;T11:   cleanup1:
149 ;T11:     %cp1 = cleanuppad within none []
150 ;T11:     unreachable
151 ;T11:   cleanup2:
152 ;T11:     %cp2 = cleanuppad within %cp1 []
153 ;T11:     unreachable
154 ;T11:   switch:
155 ;T11:     %cs = catchswitch within none [label %catch] unwind label %cleanup2
156 ;T11:     ; CHECK11: A single unwind edge may only enter one EH pad
157 ;T11:     ; CHECK11-NEXT: %cs = catchswitch within none [label %catch] unwind label %cleanup2
158 ;T11:   catch:
159 ;T11:     catchpad within %cs [i32 1]
160 ;T11:     unreachable
161 ;T11: }
162
163 ;T12: define void @f() personality void ()* @g {
164 ;T12:   entry:
165 ;T12:     ret void
166 ;T12:   cleanup:
167 ;T12:     %cp = cleanuppad within none []
168 ;T12:     cleanupret from %cp unwind label %switch
169 ;T12:     ; CHECK12: A cleanupret must exit its cleanup
170 ;T12:     ; CHECK12-NEXT: cleanupret from %cp unwind label %switch
171 ;T12:   switch:
172 ;T12:     %cs = catchswitch within %cp [label %catch] unwind to caller
173 ;T12:   catch:
174 ;T12:     catchpad within %cs [i32 1]
175 ;T12:     unreachable
176 ;T12: }
177
178 ;T13: define void @f() personality void ()* @g {
179 ;T13:   entry:
180 ;T13:     ret void
181 ;T13:   switch:
182 ;T13:     %cs = catchswitch within none [label %catch] unwind label %switch
183 ;T13:     ; CHECK13: EH pad cannot handle exceptions raised within it
184 ;T13:     ; CHECK13-NEXT:  %cs = catchswitch within none [label %catch] unwind label %switch
185 ;T13:   catch:
186 ;T13:     catchpad within %cs [i32 0]
187 ;T13:     unreachable
188 ;T13: }
189
190 ;T14: define void @f() personality void ()* @g {
191 ;T14:   entry:
192 ;T14:     ret void
193 ;T14:   cleanup:
194 ;T14:     %cp = cleanuppad within none []
195 ;T14:     unreachable
196 ;T14:   left:
197 ;T14:     cleanupret from %cp unwind label %switch
198 ;T14:   right:
199 ;T14:     cleanupret from %cp unwind to caller
200 ;T14:     ; CHECK14: Unwind edges out of a funclet pad must have the same unwind dest
201 ;T14:     ; CHECK14-NEXT: %cp = cleanuppad within none []
202 ;T14:     ; CHECK14-NEXT: cleanupret from %cp unwind label %switch
203 ;T14:     ; CHECK14-NEXT: cleanupret from %cp unwind to caller
204 ;T14:   switch:
205 ;T14:     %cs = catchswitch within none [label %catch] unwind to caller
206 ;T14:   catch:
207 ;T14:     catchpad within %cs [i32 1]
208 ;T14:     unreachable
209 ;T14: }
210
211 ;T15: define void @f() personality void ()* @g {
212 ;T15:   entry:
213 ;T15:     ret void
214 ;T15:   switch:
215 ;T15:     %cs = catchswitch within none [label %catch] unwind to caller
216 ;T15:   catch:
217 ;T15:     %catch.pad = catchpad within %cs [i32 1]
218 ;T15:     invoke void @g() [ "funclet"(token %catch.pad) ]
219 ;T15:       to label %unreachable unwind label %target1
220 ;T15:   unreachable:
221 ;T15:     unreachable
222 ;T15:   target1:
223 ;T15:     cleanuppad within none []
224 ;T15:     unreachable
225 ;T15:   target2:
226 ;T15:     cleanuppad within none []
227 ;T15:     unreachable
228 ;T15:   nested.1:
229 ;T15:     %nested.pad.1 = cleanuppad within %catch.pad []
230 ;T15:     unreachable
231 ;T15:   nested.2:
232 ;T15:     %nested.pad.2 = cleanuppad within %nested.pad.1 []
233 ;T15:     cleanupret from %nested.pad.2 unwind label %target2
234 ;T15:     ; CHECK15: Unwind edges out of a funclet pad must have the same unwind dest
235 ;T15:     ; CHECK15-NEXT: %catch.pad = catchpad within %cs [i32 1]
236 ;T15:     ; CHECK15-NEXT: cleanupret from %nested.pad.2 unwind label %target2
237 ;T15:     ; CHECK15-NEXT: invoke void @g() [ "funclet"(token %catch.pad) ]
238 ;T15:     ; CHECK15-NEXT:   to label %unreachable unwind label %target1
239 ;T15: }
240
241 ;T16: define void @f() personality void ()* @g {
242 ;T16:   entry:
243 ;T16:     ret void
244 ;T16:   switch:
245 ;T16:     %cs = catchswitch within none [label %catch] unwind to caller
246 ;T16:   catch:
247 ;T16:     %catch.pad = catchpad within %cs [i32 1]
248 ;T16:     invoke void @g() [ "funclet"(token %catch.pad) ]
249 ;T16:       to label %unreachable unwind label %target1
250 ;T16:     ; CHECK16: Unwind edges out of a catch must have the same unwind dest as the parent catchswitch
251 ;T16:     ; CHECK16-NEXT:   %catch.pad = catchpad within %cs [i32 1]
252 ;T16:     ; CHECK16-NEXT:  invoke void @g() [ "funclet"(token %catch.pad) ]
253 ;T16:     ; CHECK16-NEXT:          to label %unreachable unwind label %target1
254 ;T16:     ; CHECK16-NEXT:  %cs = catchswitch within none [label %catch] unwind to caller
255 ;T16:   unreachable:
256 ;T16:     unreachable
257 ;T16:   target1:
258 ;T16:     cleanuppad within none []
259 ;T16:     unreachable
260 ;T16: }
261
262 ;T17: define void @f() personality void ()* @g {
263 ;T17:   entry:
264 ;T17:     ret void
265 ;T17:   switch:
266 ;T17:     %cs = catchswitch within none [label %catch] unwind label %target1
267 ;T17:   catch:
268 ;T17:     %catch.pad = catchpad within %cs [i32 1]
269 ;T17:     invoke void @g() [ "funclet"(token %catch.pad) ]
270 ;T17:       to label %unreachable unwind label %target2
271 ;T17:     ; CHECK17: Unwind edges out of a catch must have the same unwind dest as the parent catchswitch
272 ;T17:     ; CHECK17-NEXT:  %catch.pad = catchpad within %cs [i32 1]
273 ;T17:     ; CHECK17-NEXT:  invoke void @g() [ "funclet"(token %catch.pad) ]
274 ;T17:     ; CHECK17-NEXT:          to label %unreachable unwind label %target2
275 ;T17:     ; CHECK17-NEXT:  %cs = catchswitch within none [label %catch] unwind label %target1
276 ;T17:   unreachable:
277 ;T17:     unreachable
278 ;T17:   target1:
279 ;T17:     cleanuppad within none []
280 ;T17:     unreachable
281 ;T17:   target2:
282 ;T17:     cleanuppad within none []
283 ;T17:     unreachable
284 ;T17: }