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 ; RUN: sed -e s/.T22:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK22 %s 23 ; RUN: sed -e s/.T23:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK23 %s 24 ; RUN: sed -e s/.T24:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK24 %s 25 ; RUN: sed -e s/.T25:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK25 %s 26 ; RUN: sed -e s/.T26:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK26 %s 27 28 declare void @g() 29 30 ;T1: define void @f() { 31 ;T1: entry: 32 ;T1: catchret from undef to label %next 33 ;T1: ; CHECK1: CatchReturnInst needs to be provided a CatchPad 34 ;T1: next: 35 ;T1: unreachable 36 ;T1: } 37 38 ;T2: define void @f() { 39 ;T2: entry: 40 ;T2: %x = cleanuppad within none [] 41 ;T2: ; catchret's first operand's operator must be catchpad 42 ;T2: catchret from %x to label %entry 43 ;T2: ; CHECK2: CatchReturnInst needs to be provided a CatchPad 44 ;T2: } 45 46 ;T3: define void @f() { 47 ;T3: entry: 48 ;T3: cleanupret from undef unwind label %next 49 ;T3: ; CHECK3: CleanupReturnInst needs to be provided a CleanupPad 50 ;T3: next: 51 ;T3: unreachable 52 ;T3: } 53 54 ;T4: define void @f() { 55 ;T4: entry: 56 ;T4: %cs = catchswitch within none [label %next] unwind to caller 57 ;T4: next: 58 ;T4: %x = catchpad within %cs [] 59 ;T4: ; cleanupret first operand's operator must be cleanuppad 60 ;T4: cleanupret from %x unwind to caller 61 ;T4: ; CHECK4: CleanupReturnInst needs to be provided a CleanupPad 62 ;T4: } 63 64 ;T5: define void @f() personality void ()* @g { 65 ;T5: entry: 66 ;T5: ret void 67 ;T5: switch: 68 ;T5: %cs = catchswitch within none [label %catch] unwind to caller 69 ;T5: catch: 70 ;T5: catchpad within %cs [] 71 ;T5: unreachable 72 ;T5: bogus: 73 ;T5: cleanuppad within %cs [] 74 ;T5: ; CHECK5: CleanupPadInst has an invalid parent 75 ;T5: unreachable 76 ;T5: } 77 78 ;T6: define void @f() personality void ()* @g { 79 ;T6: entry: 80 ;T6: ret void 81 ;T6: switch1: 82 ;T6: %cs1 = catchswitch within none [label %catch1] unwind label %catch2 83 ;T6: ; CHECK6: Block containg CatchPadInst must be jumped to only by its catchswitch 84 ;T6: catch1: 85 ;T6: catchpad within %cs1 [] 86 ;T6: unreachable 87 ;T6: switch2: 88 ;T6: %cs2 = catchswitch within none [label %catch2] unwind to caller 89 ;T6: catch2: 90 ;T6: catchpad within %cs2 [] 91 ;T6: unreachable 92 ;T6: } 93 94 ;T7: define void @f() personality void ()* @g { 95 ;T7: entry: 96 ;T7: ret void 97 ;T7: switch1: 98 ;T7: %cs1 = catchswitch within none [label %catch1] unwind to caller 99 ;T7: catch1: 100 ;T7: catchpad within %cs1 [] 101 ;T7: unreachable 102 ;T7: switch2: 103 ;T7: %cs2 = catchswitch within %cs1 [label %catch2] unwind to caller 104 ;T7: ; CHECK7: CatchSwitchInst has an invalid parent 105 ;T7: catch2: 106 ;T7: catchpad within %cs2 [] 107 ;T7: unreachable 108 ;T7: } 109 110 ;T8: define void @f() personality void ()* @g { 111 ;T8: entry: 112 ;T8: ret void 113 ;T8: switch1: 114 ;T8: %cs1 = catchswitch within none [ label %switch1 ] unwind to caller 115 ;T8: ; CHECK8: CatchSwitchInst handlers must be catchpads 116 ;T8: } 117 118 ;T9: define void @f() personality void ()* @g { 119 ;T9: entry: 120 ;T9: ret void 121 ;T9: cleanup: 122 ;T9: %cp = cleanuppad within none [] 123 ;T9: invoke void @g() [ "funclet"(token %cp) ] 124 ;T9: to label %exit unwind label %cleanup 125 ;T9: ; CHECK9: EH pad cannot handle exceptions raised within it 126 ;T9: ; CHECK9-NEXT: %cp = cleanuppad within none [] 127 ;T9: ; CHECK9-NEXT: invoke void @g() [ "funclet"(token %cp) ] 128 ;T9: exit: 129 ;T9: ret void 130 ;T9: } 131 132 ;T10: define void @f() personality void ()* @g { 133 ;T10: entry: 134 ;T10: ret void 135 ;T10: cleanup1: 136 ;T10: %cp1 = cleanuppad within none [] 137 ;T10: unreachable 138 ;T10: switch: 139 ;T10: %cs = catchswitch within %cp1 [label %catch] unwind to caller 140 ;T10: catch: 141 ;T10: %catchp1 = catchpad within %cs [i32 1] 142 ;T10: unreachable 143 ;T10: cleanup2: 144 ;T10: %cp2 = cleanuppad within %catchp1 [] 145 ;T10: unreachable 146 ;T10: cleanup3: 147 ;T10: %cp3 = cleanuppad within %cp2 [] 148 ;T10: cleanupret from %cp3 unwind label %switch 149 ;T10: ; CHECK10: EH pad cannot handle exceptions raised within it 150 ;T10: ; CHECK10-NEXT: %cs = catchswitch within %cp1 [label %catch] unwind to caller 151 ;T10: ; CHECK10-NEXT: cleanupret from %cp3 unwind label %switch 152 ;T10: } 153 154 ;T11: define void @f() personality void ()* @g { 155 ;T11: entry: 156 ;T11: ret void 157 ;T11: cleanup1: 158 ;T11: %cp1 = cleanuppad within none [] 159 ;T11: unreachable 160 ;T11: cleanup2: 161 ;T11: %cp2 = cleanuppad within %cp1 [] 162 ;T11: unreachable 163 ;T11: switch: 164 ;T11: %cs = catchswitch within none [label %catch] unwind label %cleanup2 165 ;T11: ; CHECK11: A single unwind edge may only enter one EH pad 166 ;T11: ; CHECK11-NEXT: %cs = catchswitch within none [label %catch] unwind label %cleanup2 167 ;T11: catch: 168 ;T11: catchpad within %cs [i32 1] 169 ;T11: unreachable 170 ;T11: } 171 172 ;T12: define void @f() personality void ()* @g { 173 ;T12: entry: 174 ;T12: ret void 175 ;T12: cleanup: 176 ;T12: %cp = cleanuppad within none [] 177 ;T12: cleanupret from %cp unwind label %switch 178 ;T12: ; CHECK12: A cleanupret must exit its cleanup 179 ;T12: ; CHECK12-NEXT: cleanupret from %cp unwind label %switch 180 ;T12: switch: 181 ;T12: %cs = catchswitch within %cp [label %catch] unwind to caller 182 ;T12: catch: 183 ;T12: catchpad within %cs [i32 1] 184 ;T12: unreachable 185 ;T12: } 186 187 ;T13: define void @f() personality void ()* @g { 188 ;T13: entry: 189 ;T13: ret void 190 ;T13: switch: 191 ;T13: %cs = catchswitch within none [label %catch] unwind label %switch 192 ;T13: ; CHECK13: EH pad cannot handle exceptions raised within it 193 ;T13: ; CHECK13-NEXT: %cs = catchswitch within none [label %catch] unwind label %switch 194 ;T13: catch: 195 ;T13: catchpad within %cs [i32 0] 196 ;T13: unreachable 197 ;T13: } 198 199 ;T14: define void @f() personality void ()* @g { 200 ;T14: entry: 201 ;T14: ret void 202 ;T14: cleanup: 203 ;T14: %cp = cleanuppad within none [] 204 ;T14: unreachable 205 ;T14: left: 206 ;T14: cleanupret from %cp unwind label %switch 207 ;T14: right: 208 ;T14: cleanupret from %cp unwind to caller 209 ;T14: ; CHECK14: Unwind edges out of a funclet pad must have the same unwind dest 210 ;T14: ; CHECK14-NEXT: %cp = cleanuppad within none [] 211 ;T14: ; CHECK14-NEXT: cleanupret from %cp unwind label %switch 212 ;T14: ; CHECK14-NEXT: cleanupret from %cp unwind to caller 213 ;T14: switch: 214 ;T14: %cs = catchswitch within none [label %catch] unwind to caller 215 ;T14: catch: 216 ;T14: catchpad within %cs [i32 1] 217 ;T14: unreachable 218 ;T14: } 219 220 ;T15: define void @f() personality void ()* @g { 221 ;T15: entry: 222 ;T15: ret void 223 ;T15: switch: 224 ;T15: %cs = catchswitch within none [label %catch] unwind to caller 225 ;T15: catch: 226 ;T15: %catch.pad = catchpad within %cs [i32 1] 227 ;T15: invoke void @g() [ "funclet"(token %catch.pad) ] 228 ;T15: to label %unreachable unwind label %target1 229 ;T15: unreachable: 230 ;T15: unreachable 231 ;T15: target1: 232 ;T15: cleanuppad within none [] 233 ;T15: unreachable 234 ;T15: target2: 235 ;T15: cleanuppad within none [] 236 ;T15: unreachable 237 ;T15: nested.1: 238 ;T15: %nested.pad.1 = cleanuppad within %catch.pad [] 239 ;T15: unreachable 240 ;T15: nested.2: 241 ;T15: %nested.pad.2 = cleanuppad within %nested.pad.1 [] 242 ;T15: cleanupret from %nested.pad.2 unwind label %target2 243 ;T15: ; CHECK15: Unwind edges out of a funclet pad must have the same unwind dest 244 ;T15: ; CHECK15-NEXT: %catch.pad = catchpad within %cs [i32 1] 245 ;T15: ; CHECK15-NEXT: cleanupret from %nested.pad.2 unwind label %target2 246 ;T15: ; CHECK15-NEXT: invoke void @g() [ "funclet"(token %catch.pad) ] 247 ;T15: ; CHECK15-NEXT: to label %unreachable unwind label %target1 248 ;T15: } 249 250 ;T16: define void @f() personality void ()* @g { 251 ;T16: entry: 252 ;T16: ret void 253 ;T16: switch: 254 ;T16: %cs = catchswitch within none [label %catch] unwind to caller 255 ;T16: catch: 256 ;T16: %catch.pad = catchpad within %cs [i32 1] 257 ;T16: invoke void @g() [ "funclet"(token %catch.pad) ] 258 ;T16: to label %unreachable unwind label %target1 259 ;T16: ; CHECK16: Unwind edges out of a catch must have the same unwind dest as the parent catchswitch 260 ;T16: ; CHECK16-NEXT: %catch.pad = catchpad within %cs [i32 1] 261 ;T16: ; CHECK16-NEXT: invoke void @g() [ "funclet"(token %catch.pad) ] 262 ;T16: ; CHECK16-NEXT: to label %unreachable unwind label %target1 263 ;T16: ; CHECK16-NEXT: %cs = catchswitch within none [label %catch] unwind to caller 264 ;T16: unreachable: 265 ;T16: unreachable 266 ;T16: target1: 267 ;T16: cleanuppad within none [] 268 ;T16: unreachable 269 ;T16: } 270 271 ;T17: define void @f() personality void ()* @g { 272 ;T17: entry: 273 ;T17: ret void 274 ;T17: switch: 275 ;T17: %cs = catchswitch within none [label %catch] unwind label %target1 276 ;T17: catch: 277 ;T17: %catch.pad = catchpad within %cs [i32 1] 278 ;T17: invoke void @g() [ "funclet"(token %catch.pad) ] 279 ;T17: to label %unreachable unwind label %target2 280 ;T17: ; CHECK17: Unwind edges out of a catch must have the same unwind dest as the parent catchswitch 281 ;T17: ; CHECK17-NEXT: %catch.pad = catchpad within %cs [i32 1] 282 ;T17: ; CHECK17-NEXT: invoke void @g() [ "funclet"(token %catch.pad) ] 283 ;T17: ; CHECK17-NEXT: to label %unreachable unwind label %target2 284 ;T17: ; CHECK17-NEXT: %cs = catchswitch within none [label %catch] unwind label %target1 285 ;T17: unreachable: 286 ;T17: unreachable 287 ;T17: target1: 288 ;T17: cleanuppad within none [] 289 ;T17: unreachable 290 ;T17: target2: 291 ;T17: cleanuppad within none [] 292 ;T17: unreachable 293 ;T17: } 294 295 ;T18: define void @f() personality void ()* @g { 296 ;T18: entry: 297 ;T18: invoke void @g() 298 ;T18: to label %invoke.cont unwind label %left 299 ;T18: invoke.cont: 300 ;T18: invoke void @g() 301 ;T18: to label %unreachable unwind label %right 302 ;T18: left: 303 ;T18: %cp.left = cleanuppad within none [] 304 ;T18: invoke void @g() [ "funclet"(token %cp.left) ] 305 ;T18: to label %unreachable unwind label %right 306 ;T18: right: 307 ;T18: %cp.right = cleanuppad within none [] 308 ;T18: invoke void @g() [ "funclet"(token %cp.right) ] 309 ;T18: to label %unreachable unwind label %left 310 ;T18: ; CHECK18: EH pads can't handle each other's exceptions 311 ;T18: ; CHECK18-NEXT: %cp.left = cleanuppad within none [] 312 ;T18: ; CHECK18-NEXT: invoke void @g() [ "funclet"(token %cp.left) ] 313 ;T18: ; CHECK18-NEXT: to label %unreachable unwind label %right 314 ;T18: ; CHECK18-NEXT: %cp.right = cleanuppad within none [] 315 ;T18: ; CHECK18-NEXT: invoke void @g() [ "funclet"(token %cp.right) ] 316 ;T18: ; CHECK18-NEXT: to label %unreachable unwind label %left 317 ;T18: unreachable: 318 ;T18: unreachable 319 ;T18: } 320 321 ;T19: define void @f() personality void ()* @g { 322 ;T19: entry: 323 ;T19: ret void 324 ;T19: red: 325 ;T19: %redpad = cleanuppad within none [] 326 ;T19: unreachable 327 ;T19: red.inner: 328 ;T19: %innerpad = cleanuppad within %redpad [] 329 ;T19: invoke void @g() [ "funclet"(token %innerpad) ] 330 ;T19: to label %unreachable unwind label %green 331 ;T19: green: 332 ;T19: %greenswitch = catchswitch within none [label %catch] unwind label %blue 333 ;T19: catch: 334 ;T19: catchpad within %greenswitch [i32 42] 335 ;T19: unreachable 336 ;T19: blue: 337 ;T19: %bluepad = cleanuppad within none [] 338 ;T19: cleanupret from %bluepad unwind label %red 339 ;T19: ; CHECK19: EH pads can't handle each other's exceptions 340 ;T19: ; CHECK19-NEXT: %redpad = cleanuppad within none [] 341 ;T19: ; CHECK19-NEXT: invoke void @g() [ "funclet"(token %innerpad) ] 342 ;T19: ; CHECK19-NEXT: to label %unreachable unwind label %green 343 ;T19: ; CHECK19-NEXT: %greenswitch = catchswitch within none [label %catch] unwind label %blue 344 ;T19: ; CHECK19-NEXT: %bluepad = cleanuppad within none [] 345 ;T19: ; CHECK19-NEXT: cleanupret from %bluepad unwind label %red 346 ;T19: unreachable: 347 ;T19: unreachable 348 ;T19: } 349 350 ;T20: define void @f() personality void ()* @g { 351 ;T20: entry: 352 ;T20: ret void 353 ;T20: switch: 354 ;T20: %cs = catchswitch within none [label %catch] unwind label %catch 355 ;T20: ; CHECK20: Catchswitch cannot unwind to one of its catchpads 356 ;T20: ; CHECK20-NEXT: %cs = catchswitch within none [label %catch] unwind label %catch 357 ;T20: ; CHECK20-NEXT: %cp = catchpad within %cs [i32 4] 358 ;T20: catch: 359 ;T20: %cp = catchpad within %cs [i32 4] 360 ;T20: unreachable 361 ;T20: } 362 363 ;T21: define void @f() personality void ()* @g { 364 ;T21: entry: 365 ;T21: ret void 366 ;T21: switch: 367 ;T21: %cs = catchswitch within none [label %catch1] unwind label %catch2 368 ;T21: ; CHECK21: Catchswitch cannot unwind to one of its catchpads 369 ;T21: ; CHECK21-NEXT: %cs = catchswitch within none [label %catch1] unwind label %catch2 370 ;T21: ; CHECK21-NEXT: %cp2 = catchpad within %cs [i32 2] 371 ;T21: catch1: 372 ;T21: %cp1 = catchpad within %cs [i32 1] 373 ;T21: unreachable 374 ;T21: catch2: 375 ;T21: %cp2 = catchpad within %cs [i32 2] 376 ;T21: unreachable 377 ;T21: } 378 379 ;T22: define void @f() personality void ()* @g { 380 ;T22: invoke void @g() 381 ;T22: to label %merge unwind label %cleanup 382 ;T22: 383 ;T22: cleanup: 384 ;T22: %outer = cleanuppad within none [] 385 ;T22: invoke void @g() [ "funclet"(token %outer) ] 386 ;T22: to label %merge unwind label %merge 387 ;T22: ; CHECK22: The unwind destination does not have an exception handling instruction! 388 ;T22: ; CHECK22: invoke void @g() [ "funclet"(token %outer) ] 389 ;T22: ; CHECK22: to label %merge unwind label %merge 390 ;T22: 391 ;T22: merge: 392 ;T22: unreachable 393 ;T22: } 394 395 ;T23: define void @f() personality void ()* @g { 396 ;T23: invoke void @g() 397 ;T23: to label %exit unwind label %pad 398 ;T23: 399 ;T23: pad: 400 ;T23: %outer = catchpad within %outer [] 401 ;T23: ; CHECK23: CatchPadInst needs to be directly nested in a CatchSwitchInst. 402 ;T23: ; CHECK23: %outer = catchpad within %outer [] 403 ;T23: unreachable 404 ;T23: 405 ;T23: exit: 406 ;T23: unreachable 407 ;T23: } 408 409 ;T24: define void @f() personality void ()* @g { 410 ;T24: invoke void @g() 411 ;T24: to label %exit unwind label %pad 412 ;T24: ; CHECK24: A single unwind edge may only enter one EH pad 413 ;T24: ; CHECK24: invoke void @g() 414 ;T24: ; CHECK24: to label %exit unwind label %pad 415 ;T24: 416 ;T24: pad: 417 ;T24: %outer = cleanuppad within %outer [] 418 ;T24: ; CHECK24: FuncletPadInst must not be nested within itself 419 ;T24: ; CHECK24: %outer = cleanuppad within %outer [] 420 ;T24: unreachable 421 ;T24: 422 ;T24: exit: 423 ;T24: unreachable 424 ;T24: } 425 426 ;T25: define void @f() personality void ()* @g { 427 ;T25: entry: 428 ;T25: unreachable 429 ;T25: 430 ;T25: catch.dispatch: 431 ;T25: %cs = catchswitch within %cp2 [label %catch] unwind label %ehcleanup 432 ;T25: ; CHECK25: EH pad jumps through a cycle of pads 433 ;T25: ; CHECK25: %cs = catchswitch within %cp2 [label %catch] unwind label %ehcleanup 434 ;T25: 435 ;T25: catch: 436 ;T25: %cp2 = catchpad within %cs [i8* null, i32 64, i8* null] 437 ;T25: unreachable 438 ;T25: 439 ;T25: ehcleanup: 440 ;T25: %cp3 = cleanuppad within none [] 441 ;T25: cleanupret from %cp3 unwind to caller 442 ;T25: } 443 444 ;T26: define void @f() personality void ()* @g { 445 ;T26: entry: 446 ;T26: ret void 447 ;T26: 448 ;T26: ehcleanup: 449 ;T26: cleanuppad within none [] 450 ;T26: cleanupret from none unwind label %ehcleanup 451 ;T26: ; CHECK26: A cleanupret must exit its cleanup 452 ;T26: ; CHECK26: cleanupret from none unwind label %ehcleanup 453 ;T26: ; CHECK26: CleanupReturnInst needs to be provided a CleanupPad 454 ;T26: ; CHECK26: cleanupret from none unwind label %ehcleanup 455 ;T26: ; CHECK26: token none 456 ;T26: } 457