summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/IR/Verifier.cpp15
-rw-r--r--llvm/test/Verifier/invalid-eh.ll50
2 files changed, 59 insertions, 6 deletions
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index f02879eeb5b..8367a2702eb 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -3119,8 +3119,6 @@ void Verifier::visitLandingPadInst(LandingPadInst &LPI) {
}
void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
- visitEHPadPredecessors(CPI);
-
BasicBlock *BB = CPI.getParent();
Function *F = BB->getParent();
@@ -3136,6 +3134,7 @@ void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
Assert(BB->getFirstNonPHI() == &CPI,
"CatchPadInst not the first non-PHI instruction in the block.", &CPI);
+ visitEHPadPredecessors(CPI);
visitFuncletPadInst(CPI);
}
@@ -3148,8 +3147,6 @@ void Verifier::visitCatchReturnInst(CatchReturnInst &CatchReturn) {
}
void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
- visitEHPadPredecessors(CPI);
-
BasicBlock *BB = CPI.getParent();
Function *F = BB->getParent();
@@ -3166,6 +3163,7 @@ void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
Assert(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),
"CleanupPadInst has an invalid parent.", &CPI);
+ visitEHPadPredecessors(CPI);
visitFuncletPadInst(CPI);
}
@@ -3173,8 +3171,12 @@ void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) {
User *FirstUser = nullptr;
Value *FirstUnwindPad = nullptr;
SmallVector<FuncletPadInst *, 8> Worklist({&FPI});
+ std::set<FuncletPadInst *> Seen;
+
while (!Worklist.empty()) {
FuncletPadInst *CurrentPad = Worklist.pop_back_val();
+ Assert(Seen.insert(CurrentPad).second,
+ "FuncletPadInst must not be nested within itself", CurrentPad);
Value *UnresolvedAncestorPad = nullptr;
for (User *U : CurrentPad->users()) {
BasicBlock *UnwindDest;
@@ -3210,6 +3212,8 @@ void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) {
bool ExitsFPI;
if (UnwindDest) {
UnwindPad = UnwindDest->getFirstNonPHI();
+ if (!cast<Instruction>(UnwindPad)->isEHPad())
+ continue;
Value *UnwindParent = getParentPad(UnwindPad);
// Ignore unwind edges that don't exit CurrentPad.
if (UnwindParent == CurrentPad)
@@ -3323,8 +3327,6 @@ void Verifier::visitFuncletPadInst(FuncletPadInst &FPI) {
}
void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) {
- visitEHPadPredecessors(CatchSwitch);
-
BasicBlock *BB = CatchSwitch.getParent();
Function *F = BB->getParent();
@@ -3362,6 +3364,7 @@ void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) {
"CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler);
}
+ visitEHPadPredecessors(CatchSwitch);
visitTerminatorInst(CatchSwitch);
}
diff --git a/llvm/test/Verifier/invalid-eh.ll b/llvm/test/Verifier/invalid-eh.ll
index 0f27198af53..f94e3a6d1cb 100644
--- a/llvm/test/Verifier/invalid-eh.ll
+++ b/llvm/test/Verifier/invalid-eh.ll
@@ -19,6 +19,9 @@
; 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
declare void @g()
@@ -370,3 +373,50 @@ declare void @g()
;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: }
OpenPOWER on IntegriCloud