}
void Verifier::visitCatchPadInst(CatchPadInst &CPI) {
- visitEHPadPredecessors(CPI);
-
BasicBlock *BB = CPI.getParent();
Function *F = BB->getParent();
Assert(BB->getFirstNonPHI() == &CPI,
"CatchPadInst not the first non-PHI instruction in the block.", &CPI);
+ visitEHPadPredecessors(CPI);
visitFuncletPadInst(CPI);
}
}
void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
- visitEHPadPredecessors(CPI);
-
BasicBlock *BB = CPI.getParent();
Function *F = BB->getParent();
Assert(isa<ConstantTokenNone>(ParentPad) || isa<FuncletPadInst>(ParentPad),
"CleanupPadInst has an invalid parent.", &CPI);
+ visitEHPadPredecessors(CPI);
visitFuncletPadInst(CPI);
}
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;
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)
}
void Verifier::visitCatchSwitchInst(CatchSwitchInst &CatchSwitch) {
- visitEHPadPredecessors(CatchSwitch);
-
BasicBlock *BB = CatchSwitch.getParent();
Function *F = BB->getParent();
"CatchSwitchInst handlers must be catchpads", &CatchSwitch, Handler);
}
+ visitEHPadPredecessors(CatchSwitch);
visitTerminatorInst(CatchSwitch);
}
; 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()
;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: }