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