| ; UNSUPPORTED: system-windows |
| |
| ; RUN: sed -e s/.T1:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK1 %s |
| ; RUN: sed -e s/.T2:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK2 %s |
| ; RUN: sed -e s/.T3:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s |
| ; RUN: sed -e s/.T4:// %s | not llvm-as -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s |
| ; RUN: sed -e s/.T5:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK5 %s |
| ; RUN: sed -e s/.T6:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK6 %s |
| ; RUN: sed -e s/.T7:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK7 %s |
| ; RUN: sed -e s/.T8:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK8 %s |
| ; RUN: sed -e s/.T9:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK9 %s |
| ; RUN: sed -e s/.T10:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK10 %s |
| ; RUN: sed -e s/.T11:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK11 %s |
| ; RUN: sed -e s/.T12:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK12 %s |
| ; RUN: sed -e s/.T13:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK13 %s |
| ; RUN: sed -e s/.T14:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK14 %s |
| ; RUN: sed -e s/.T15:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK15 %s |
| ; RUN: sed -e s/.T16:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK16 %s |
| ; RUN: sed -e s/.T17:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK17 %s |
| ; RUN: sed -e s/.T18:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK18 %s |
| ; RUN: sed -e s/.T19:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK19 %s |
| ; RUN: sed -e s/.T20:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK20 %s |
| ; RUN: sed -e s/.T21:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK21 %s |
| ; RUN: sed -e s/.T22:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK22 %s |
| ; RUN: sed -e s/.T23:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK23 %s |
| ; RUN: sed -e s/.T24:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK24 %s |
| ; RUN: sed -e s/.T25:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK25 %s |
| ; RUN: sed -e s/.T26:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK26 %s |
| |
| declare void @g() |
| |
| ;T1: define void @f() { |
| ;T1: entry: |
| ;T1: catchret from undef to label %next |
| ;T1: ; CHECK1: CatchReturnInst needs to be provided a CatchPad |
| ;T1: next: |
| ;T1: unreachable |
| ;T1: } |
| |
| ;T2: define void @f() { |
| ;T2: entry: |
| ;T2: %x = cleanuppad within none [] |
| ;T2: ; catchret's first operand's operator must be catchpad |
| ;T2: catchret from %x to label %entry |
| ;T2: ; CHECK2: CatchReturnInst needs to be provided a CatchPad |
| ;T2: } |
| |
| ;T3: define void @f() { |
| ;T3: entry: |
| ;T3: cleanupret from undef unwind label %next |
| ;T3: ; CHECK3: CleanupReturnInst needs to be provided a CleanupPad |
| ;T3: next: |
| ;T3: unreachable |
| ;T3: } |
| |
| ;T4: define void @f() { |
| ;T4: entry: |
| ;T4: %cs = catchswitch within none [label %next] unwind to caller |
| ;T4: next: |
| ;T4: %x = catchpad within %cs [] |
| ;T4: ; cleanupret first operand's operator must be cleanuppad |
| ;T4: cleanupret from %x unwind to caller |
| ;T4: ; CHECK4: CleanupReturnInst needs to be provided a CleanupPad |
| ;T4: } |
| |
| ;T5: define void @f() personality void ()* @g { |
| ;T5: entry: |
| ;T5: ret void |
| ;T5: switch: |
| ;T5: %cs = catchswitch within none [label %catch] unwind to caller |
| ;T5: catch: |
| ;T5: catchpad within %cs [] |
| ;T5: unreachable |
| ;T5: bogus: |
| ;T5: cleanuppad within %cs [] |
| ;T5: ; CHECK5: CleanupPadInst has an invalid parent |
| ;T5: unreachable |
| ;T5: } |
| |
| ;T6: define void @f() personality void ()* @g { |
| ;T6: entry: |
| ;T6: ret void |
| ;T6: switch1: |
| ;T6: %cs1 = catchswitch within none [label %catch1] unwind label %catch2 |
| ;T6: ; CHECK6: Block containg CatchPadInst must be jumped to only by its catchswitch |
| ;T6: catch1: |
| ;T6: catchpad within %cs1 [] |
| ;T6: unreachable |
| ;T6: switch2: |
| ;T6: %cs2 = catchswitch within none [label %catch2] unwind to caller |
| ;T6: catch2: |
| ;T6: catchpad within %cs2 [] |
| ;T6: unreachable |
| ;T6: } |
| |
| ;T7: define void @f() personality void ()* @g { |
| ;T7: entry: |
| ;T7: ret void |
| ;T7: switch1: |
| ;T7: %cs1 = catchswitch within none [label %catch1] unwind to caller |
| ;T7: catch1: |
| ;T7: catchpad within %cs1 [] |
| ;T7: unreachable |
| ;T7: switch2: |
| ;T7: %cs2 = catchswitch within %cs1 [label %catch2] unwind to caller |
| ;T7: ; CHECK7: CatchSwitchInst has an invalid parent |
| ;T7: catch2: |
| ;T7: catchpad within %cs2 [] |
| ;T7: unreachable |
| ;T7: } |
| |
| ;T8: define void @f() personality void ()* @g { |
| ;T8: entry: |
| ;T8: ret void |
| ;T8: switch1: |
| ;T8: %cs1 = catchswitch within none [ label %switch1 ] unwind to caller |
| ;T8: ; CHECK8: CatchSwitchInst handlers must be catchpads |
| ;T8: } |
| |
| ;T9: define void @f() personality void ()* @g { |
| ;T9: entry: |
| ;T9: ret void |
| ;T9: cleanup: |
| ;T9: %cp = cleanuppad within none [] |
| ;T9: invoke void @g() [ "funclet"(token %cp) ] |
| ;T9: to label %exit unwind label %cleanup |
| ;T9: ; CHECK9: EH pad cannot handle exceptions raised within it |
| ;T9: ; CHECK9-NEXT: %cp = cleanuppad within none [] |
| ;T9: ; CHECK9-NEXT: invoke void @g() [ "funclet"(token %cp) ] |
| ;T9: exit: |
| ;T9: ret void |
| ;T9: } |
| |
| ;T10: define void @f() personality void ()* @g { |
| ;T10: entry: |
| ;T10: ret void |
| ;T10: cleanup1: |
| ;T10: %cp1 = cleanuppad within none [] |
| ;T10: unreachable |
| ;T10: switch: |
| ;T10: %cs = catchswitch within %cp1 [label %catch] unwind to caller |
| ;T10: catch: |
| ;T10: %catchp1 = catchpad within %cs [i32 1] |
| ;T10: unreachable |
| ;T10: cleanup2: |
| ;T10: %cp2 = cleanuppad within %catchp1 [] |
| ;T10: unreachable |
| ;T10: cleanup3: |
| ;T10: %cp3 = cleanuppad within %cp2 [] |
| ;T10: cleanupret from %cp3 unwind label %switch |
| ;T10: ; CHECK10: EH pad cannot handle exceptions raised within it |
| ;T10: ; CHECK10-NEXT: %cs = catchswitch within %cp1 [label %catch] unwind to caller |
| ;T10: ; CHECK10-NEXT: cleanupret from %cp3 unwind label %switch |
| ;T10: } |
| |
| ;T11: define void @f() personality void ()* @g { |
| ;T11: entry: |
| ;T11: ret void |
| ;T11: cleanup1: |
| ;T11: %cp1 = cleanuppad within none [] |
| ;T11: unreachable |
| ;T11: cleanup2: |
| ;T11: %cp2 = cleanuppad within %cp1 [] |
| ;T11: unreachable |
| ;T11: switch: |
| ;T11: %cs = catchswitch within none [label %catch] unwind label %cleanup2 |
| ;T11: ; CHECK11: A single unwind edge may only enter one EH pad |
| ;T11: ; CHECK11-NEXT: %cs = catchswitch within none [label %catch] unwind label %cleanup2 |
| ;T11: catch: |
| ;T11: catchpad within %cs [i32 1] |
| ;T11: unreachable |
| ;T11: } |
| |
| ;T12: define void @f() personality void ()* @g { |
| ;T12: entry: |
| ;T12: ret void |
| ;T12: cleanup: |
| ;T12: %cp = cleanuppad within none [] |
| ;T12: cleanupret from %cp unwind label %switch |
| ;T12: ; CHECK12: A cleanupret must exit its cleanup |
| ;T12: ; CHECK12-NEXT: cleanupret from %cp unwind label %switch |
| ;T12: switch: |
| ;T12: %cs = catchswitch within %cp [label %catch] unwind to caller |
| ;T12: catch: |
| ;T12: catchpad within %cs [i32 1] |
| ;T12: unreachable |
| ;T12: } |
| |
| ;T13: define void @f() personality void ()* @g { |
| ;T13: entry: |
| ;T13: ret void |
| ;T13: switch: |
| ;T13: %cs = catchswitch within none [label %catch] unwind label %switch |
| ;T13: ; CHECK13: EH pad cannot handle exceptions raised within it |
| ;T13: ; CHECK13-NEXT: %cs = catchswitch within none [label %catch] unwind label %switch |
| ;T13: catch: |
| ;T13: catchpad within %cs [i32 0] |
| ;T13: unreachable |
| ;T13: } |
| |
| ;T14: define void @f() personality void ()* @g { |
| ;T14: entry: |
| ;T14: ret void |
| ;T14: cleanup: |
| ;T14: %cp = cleanuppad within none [] |
| ;T14: unreachable |
| ;T14: left: |
| ;T14: cleanupret from %cp unwind label %switch |
| ;T14: right: |
| ;T14: cleanupret from %cp unwind to caller |
| ;T14: ; CHECK14: Unwind edges out of a funclet pad must have the same unwind dest |
| ;T14: ; CHECK14-NEXT: %cp = cleanuppad within none [] |
| ;T14: ; CHECK14-NEXT: cleanupret from %cp unwind label %switch |
| ;T14: ; CHECK14-NEXT: cleanupret from %cp unwind to caller |
| ;T14: switch: |
| ;T14: %cs = catchswitch within none [label %catch] unwind to caller |
| ;T14: catch: |
| ;T14: catchpad within %cs [i32 1] |
| ;T14: unreachable |
| ;T14: } |
| |
| ;T15: define void @f() personality void ()* @g { |
| ;T15: entry: |
| ;T15: ret void |
| ;T15: switch: |
| ;T15: %cs = catchswitch within none [label %catch] unwind to caller |
| ;T15: catch: |
| ;T15: %catch.pad = catchpad within %cs [i32 1] |
| ;T15: invoke void @g() [ "funclet"(token %catch.pad) ] |
| ;T15: to label %unreachable unwind label %target1 |
| ;T15: unreachable: |
| ;T15: unreachable |
| ;T15: target1: |
| ;T15: cleanuppad within none [] |
| ;T15: unreachable |
| ;T15: target2: |
| ;T15: cleanuppad within none [] |
| ;T15: unreachable |
| ;T15: nested.1: |
| ;T15: %nested.pad.1 = cleanuppad within %catch.pad [] |
| ;T15: unreachable |
| ;T15: nested.2: |
| ;T15: %nested.pad.2 = cleanuppad within %nested.pad.1 [] |
| ;T15: cleanupret from %nested.pad.2 unwind label %target2 |
| ;T15: ; CHECK15: Unwind edges out of a funclet pad must have the same unwind dest |
| ;T15: ; CHECK15-NEXT: %catch.pad = catchpad within %cs [i32 1] |
| ;T15: ; CHECK15-NEXT: cleanupret from %nested.pad.2 unwind label %target2 |
| ;T15: ; CHECK15-NEXT: invoke void @g() [ "funclet"(token %catch.pad) ] |
| ;T15: ; CHECK15-NEXT: to label %unreachable unwind label %target1 |
| ;T15: } |
| |
| ;T16: define void @f() personality void ()* @g { |
| ;T16: entry: |
| ;T16: ret void |
| ;T16: switch: |
| ;T16: %cs = catchswitch within none [label %catch] unwind to caller |
| ;T16: catch: |
| ;T16: %catch.pad = catchpad within %cs [i32 1] |
| ;T16: invoke void @g() [ "funclet"(token %catch.pad) ] |
| ;T16: to label %unreachable unwind label %target1 |
| ;T16: ; CHECK16: Unwind edges out of a catch must have the same unwind dest as the parent catchswitch |
| ;T16: ; CHECK16-NEXT: %catch.pad = catchpad within %cs [i32 1] |
| ;T16: ; CHECK16-NEXT: invoke void @g() [ "funclet"(token %catch.pad) ] |
| ;T16: ; CHECK16-NEXT: to label %unreachable unwind label %target1 |
| ;T16: ; CHECK16-NEXT: %cs = catchswitch within none [label %catch] unwind to caller |
| ;T16: unreachable: |
| ;T16: unreachable |
| ;T16: target1: |
| ;T16: cleanuppad within none [] |
| ;T16: unreachable |
| ;T16: } |
| |
| ;T17: define void @f() personality void ()* @g { |
| ;T17: entry: |
| ;T17: ret void |
| ;T17: switch: |
| ;T17: %cs = catchswitch within none [label %catch] unwind label %target1 |
| ;T17: catch: |
| ;T17: %catch.pad = catchpad within %cs [i32 1] |
| ;T17: invoke void @g() [ "funclet"(token %catch.pad) ] |
| ;T17: to label %unreachable unwind label %target2 |
| ;T17: ; CHECK17: Unwind edges out of a catch must have the same unwind dest as the parent catchswitch |
| ;T17: ; CHECK17-NEXT: %catch.pad = catchpad within %cs [i32 1] |
| ;T17: ; CHECK17-NEXT: invoke void @g() [ "funclet"(token %catch.pad) ] |
| ;T17: ; CHECK17-NEXT: to label %unreachable unwind label %target2 |
| ;T17: ; CHECK17-NEXT: %cs = catchswitch within none [label %catch] unwind label %target1 |
| ;T17: unreachable: |
| ;T17: unreachable |
| ;T17: target1: |
| ;T17: cleanuppad within none [] |
| ;T17: unreachable |
| ;T17: target2: |
| ;T17: cleanuppad within none [] |
| ;T17: unreachable |
| ;T17: } |
| |
| ;T18: define void @f() personality void ()* @g { |
| ;T18: entry: |
| ;T18: invoke void @g() |
| ;T18: to label %invoke.cont unwind label %left |
| ;T18: invoke.cont: |
| ;T18: invoke void @g() |
| ;T18: to label %unreachable unwind label %right |
| ;T18: left: |
| ;T18: %cp.left = cleanuppad within none [] |
| ;T18: invoke void @g() [ "funclet"(token %cp.left) ] |
| ;T18: to label %unreachable unwind label %right |
| ;T18: right: |
| ;T18: %cp.right = cleanuppad within none [] |
| ;T18: invoke void @g() [ "funclet"(token %cp.right) ] |
| ;T18: to label %unreachable unwind label %left |
| ;T18: ; CHECK18: EH pads can't handle each other's exceptions |
| ;T18: ; CHECK18-NEXT: %cp.left = cleanuppad within none [] |
| ;T18: ; CHECK18-NEXT: invoke void @g() [ "funclet"(token %cp.left) ] |
| ;T18: ; CHECK18-NEXT: to label %unreachable unwind label %right |
| ;T18: ; CHECK18-NEXT: %cp.right = cleanuppad within none [] |
| ;T18: ; CHECK18-NEXT: invoke void @g() [ "funclet"(token %cp.right) ] |
| ;T18: ; CHECK18-NEXT: to label %unreachable unwind label %left |
| ;T18: unreachable: |
| ;T18: unreachable |
| ;T18: } |
| |
| ;T19: define void @f() personality void ()* @g { |
| ;T19: entry: |
| ;T19: ret void |
| ;T19: red: |
| ;T19: %redpad = cleanuppad within none [] |
| ;T19: unreachable |
| ;T19: red.inner: |
| ;T19: %innerpad = cleanuppad within %redpad [] |
| ;T19: invoke void @g() [ "funclet"(token %innerpad) ] |
| ;T19: to label %unreachable unwind label %green |
| ;T19: green: |
| ;T19: %greenswitch = catchswitch within none [label %catch] unwind label %blue |
| ;T19: catch: |
| ;T19: catchpad within %greenswitch [i32 42] |
| ;T19: unreachable |
| ;T19: blue: |
| ;T19: %bluepad = cleanuppad within none [] |
| ;T19: cleanupret from %bluepad unwind label %red |
| ;T19: ; CHECK19: EH pads can't handle each other's exceptions |
| ;T19: ; CHECK19-NEXT: %redpad = cleanuppad within none [] |
| ;T19: ; CHECK19-NEXT: invoke void @g() [ "funclet"(token %innerpad) ] |
| ;T19: ; CHECK19-NEXT: to label %unreachable unwind label %green |
| ;T19: ; CHECK19-NEXT: %greenswitch = catchswitch within none [label %catch] unwind label %blue |
| ;T19: ; CHECK19-NEXT: %bluepad = cleanuppad within none [] |
| ;T19: ; CHECK19-NEXT: cleanupret from %bluepad unwind label %red |
| ;T19: unreachable: |
| ;T19: unreachable |
| ;T19: } |
| |
| ;T20: define void @f() personality void ()* @g { |
| ;T20: entry: |
| ;T20: ret void |
| ;T20: switch: |
| ;T20: %cs = catchswitch within none [label %catch] unwind label %catch |
| ;T20: ; CHECK20: Catchswitch cannot unwind to one of its catchpads |
| ;T20: ; CHECK20-NEXT: %cs = catchswitch within none [label %catch] unwind label %catch |
| ;T20: ; CHECK20-NEXT: %cp = catchpad within %cs [i32 4] |
| ;T20: catch: |
| ;T20: %cp = catchpad within %cs [i32 4] |
| ;T20: unreachable |
| ;T20: } |
| |
| ;T21: define void @f() personality void ()* @g { |
| ;T21: entry: |
| ;T21: ret void |
| ;T21: switch: |
| ;T21: %cs = catchswitch within none [label %catch1] unwind label %catch2 |
| ;T21: ; CHECK21: Catchswitch cannot unwind to one of its catchpads |
| ;T21: ; CHECK21-NEXT: %cs = catchswitch within none [label %catch1] unwind label %catch2 |
| ;T21: ; CHECK21-NEXT: %cp2 = catchpad within %cs [i32 2] |
| ;T21: catch1: |
| ;T21: %cp1 = catchpad within %cs [i32 1] |
| ;T21: unreachable |
| ;T21: catch2: |
| ;T21: %cp2 = catchpad within %cs [i32 2] |
| ;T21: unreachable |
| ;T21: } |
| |
| ;T22: define void @f() personality void ()* @g { |
| ;T22: invoke void @g() |
| ;T22: to label %merge unwind label %cleanup |
| ;T22: |
| ;T22: cleanup: |
| ;T22: %outer = cleanuppad within none [] |
| ;T22: invoke void @g() [ "funclet"(token %outer) ] |
| ;T22: to label %merge unwind label %merge |
| ;T22: ; CHECK22: The unwind destination does not have an exception handling instruction! |
| ;T22: ; CHECK22: invoke void @g() [ "funclet"(token %outer) ] |
| ;T22: ; CHECK22: to label %merge unwind label %merge |
| ;T22: |
| ;T22: merge: |
| ;T22: unreachable |
| ;T22: } |
| |
| ;T23: define void @f() personality void ()* @g { |
| ;T23: invoke void @g() |
| ;T23: to label %exit unwind label %pad |
| ;T23: |
| ;T23: pad: |
| ;T23: %outer = catchpad within %outer [] |
| ;T23: ; CHECK23: CatchPadInst needs to be directly nested in a CatchSwitchInst. |
| ;T23: ; CHECK23: %outer = catchpad within %outer [] |
| ;T23: unreachable |
| ;T23: |
| ;T23: exit: |
| ;T23: unreachable |
| ;T23: } |
| |
| ;T24: define void @f() personality void ()* @g { |
| ;T24: invoke void @g() |
| ;T24: to label %exit unwind label %pad |
| ;T24: ; CHECK24: A single unwind edge may only enter one EH pad |
| ;T24: ; CHECK24: invoke void @g() |
| ;T24: ; CHECK24: to label %exit unwind label %pad |
| ;T24: |
| ;T24: pad: |
| ;T24: %outer = cleanuppad within %outer [] |
| ;T24: ; CHECK24: FuncletPadInst must not be nested within itself |
| ;T24: ; CHECK24: %outer = cleanuppad within %outer [] |
| ;T24: unreachable |
| ;T24: |
| ;T24: exit: |
| ;T24: unreachable |
| ;T24: } |
| |
| ;T25: define void @f() personality void ()* @g { |
| ;T25: entry: |
| ;T25: unreachable |
| ;T25: |
| ;T25: catch.dispatch: |
| ;T25: %cs = catchswitch within %cp2 [label %catch] unwind label %ehcleanup |
| ;T25: ; CHECK25: EH pad jumps through a cycle of pads |
| ;T25: ; CHECK25: %cs = catchswitch within %cp2 [label %catch] unwind label %ehcleanup |
| ;T25: |
| ;T25: catch: |
| ;T25: %cp2 = catchpad within %cs [i8* null, i32 64, i8* null] |
| ;T25: unreachable |
| ;T25: |
| ;T25: ehcleanup: |
| ;T25: %cp3 = cleanuppad within none [] |
| ;T25: cleanupret from %cp3 unwind to caller |
| ;T25: } |
| |
| ;T26: define void @f() personality void ()* @g { |
| ;T26: entry: |
| ;T26: ret void |
| ;T26: |
| ;T26: ehcleanup: |
| ;T26: cleanuppad within none [] |
| ;T26: cleanupret from none unwind label %ehcleanup |
| ;T26: ; CHECK26: A cleanupret must exit its cleanup |
| ;T26: ; CHECK26: cleanupret from none unwind label %ehcleanup |
| ;T26: ; CHECK26: CleanupReturnInst needs to be provided a CleanupPad |
| ;T26: ; CHECK26: cleanupret from none unwind label %ehcleanup |
| ;T26: ; CHECK26: token none |
| ;T26: } |