[llvm] [Verifier] Don't look up the funclet color of an unreachable block (PR #222500)
Timur Baidusenov via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 9 20:46:03 PDT 2026
https://github.com/bai-tim created https://github.com/llvm/llvm-project/pull/222500
Fixes #192015.
>From 2910022c4bb6c0edc8f7d1ae067b8d56149737ff Mon Sep 17 00:00:00 2001
From: Timur Baidusenov <timurbaidusenov at gmail.com>
Date: Tue, 8 Sep 2026 21:58:22 +0300
Subject: [PATCH] [Verifier] Don't look up the funclet color of an unreachable
block
Fixes #192015.
---
llvm/lib/IR/Verifier.cpp | 44 +++++++++++--------
.../Verifier/funclet-unreachable-block.ll | 17 +++++++
2 files changed, 42 insertions(+), 19 deletions(-)
create mode 100644 llvm/test/Verifier/funclet-unreachable-block.ll
diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp
index 20df60ed61da3..b26e3b9f84263 100644
--- a/llvm/lib/IR/Verifier.cpp
+++ b/llvm/lib/IR/Verifier.cpp
@@ -7260,26 +7260,32 @@ void Verifier::visitIntrinsicCall(Intrinsic::ID ID, CallBase &Call) {
if (BlockEHFuncletColors.empty())
BlockEHFuncletColors = colorEHFunclets(*F);
- // Check for catch-/cleanup-pad in first funclet block
- bool InEHFunclet = false;
+ // colorEHFunclets() leaves unreachable blocks colorless. Such a call
+ // is in no funclet and WinEHPrepare will not see it, so there is
+ // nothing to check.
BasicBlock *CallBB = Call.getParent();
- const ColorVector &CV = BlockEHFuncletColors.find(CallBB)->second;
- assert(CV.size() > 0 && "Uncolored block");
- for (BasicBlock *ColorFirstBB : CV)
- if (auto It = ColorFirstBB->getFirstNonPHIIt();
- It != ColorFirstBB->end())
- if (isa_and_nonnull<FuncletPadInst>(&*It))
- InEHFunclet = true;
-
- // Check for funclet operand bundle
- bool HasToken = false;
- for (unsigned I = 0, E = Call.getNumOperandBundles(); I != E; ++I)
- if (Call.getOperandBundleAt(I).getTagID() == LLVMContext::OB_funclet)
- HasToken = true;
-
- // This would cause silent code truncation in WinEHPrepare
- if (InEHFunclet)
- Check(HasToken, "Missing funclet token on intrinsic call", &Call);
+ auto ColorsIt = BlockEHFuncletColors.find(CallBB);
+ if (ColorsIt != BlockEHFuncletColors.end()) {
+ // Check for catch-/cleanup-pad in first funclet block
+ bool InEHFunclet = false;
+ const ColorVector &CV = ColorsIt->second;
+ assert(CV.size() > 0 && "Uncolored block");
+ for (BasicBlock *ColorFirstBB : CV)
+ if (auto It = ColorFirstBB->getFirstNonPHIIt();
+ It != ColorFirstBB->end())
+ if (isa_and_nonnull<FuncletPadInst>(&*It))
+ InEHFunclet = true;
+
+ // Check for funclet operand bundle
+ bool HasToken = false;
+ for (unsigned I = 0, E = Call.getNumOperandBundles(); I != E; ++I)
+ if (Call.getOperandBundleAt(I).getTagID() == LLVMContext::OB_funclet)
+ HasToken = true;
+
+ // This would cause silent code truncation in WinEHPrepare
+ if (InEHFunclet)
+ Check(HasToken, "Missing funclet token on intrinsic call", &Call);
+ }
}
}
diff --git a/llvm/test/Verifier/funclet-unreachable-block.ll b/llvm/test/Verifier/funclet-unreachable-block.ll
new file mode 100644
index 0000000000000..4ecc8902a9a30
--- /dev/null
+++ b/llvm/test/Verifier/funclet-unreachable-block.ll
@@ -0,0 +1,17 @@
+; RUN: llvm-as -disable-output %s
+
+; colorEHFunclets() leaves unreachable blocks colorless, so there is no funclet
+; color to look up for a call in one. The verifier must not crash on that.
+
+declare i32 @__CxxFrameHandler3(...)
+declare ptr @llvm.objc.retain(ptr returned) nounwind
+
+define void @f(ptr %p) personality ptr @__CxxFrameHandler3 {
+entry:
+ ret void
+
+unreachable.funclet: ; No predecessors!
+ %pad = cleanuppad within none []
+ %call = call ptr @llvm.objc.retain(ptr %p) [ "funclet"(token %pad) ]
+ cleanupret from %pad unwind to caller
+}
More information about the llvm-commits
mailing list