llvm/test/Verifier/invalid-eh.ll
David Majnemer d724de3510 [Verifier] Don't abort on invalid cleanuprets
Code in visitEHPadPredecessors assume a little too much about the
validity of a cleanupret with an invalid cleanuppad operand.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@262364 91177308-0d34-0410-b5e6-96231b3b80d8
2016-03-01 18:59:50 +00:00

457 lines
17 KiB
LLVM

; 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: }