[Mlir-commits] [mlir] [mlir][scf] Fix crash in ForOp verifier when body block has no arguments (PR #183946)
Mehdi Amini
llvmlistbot at llvm.org
Sun Mar 1 02:32:18 PST 2026
https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/183946
>From 72a8a82927181ddf9197d3b917558684eea2aa68 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Sat, 28 Feb 2026 12:11:12 -0800
Subject: [PATCH] [mlir][scf] Fix crash in ForOp verifier when body block has
no arguments
A malformed `scf.for` whose body block contains no arguments caused
`getRegionIterArgs()` to crash via an out-of-bounds `drop_front(1)` call.
This happened because `verifyLoopLikeOpInterface` (a `verifyRegionTrait`)
invokes `getRegionIterArgs()` during `verifyRegionInvariants`, which runs
before `verifyRegions()` has a chance to report a proper diagnostic.
Fix by adding an explicit check in `ForOp::verify()` (which runs in
`verifyInvariants`, before any region trait verifiers execute) that ensures
the body block has at least as many arguments as there are induction
variables. This prevents the crash and produces a clear error message.
Fixes #159737
---
mlir/lib/Dialect/SCF/IR/SCF.cpp | 16 ++++++++++++++++
mlir/test/Dialect/SCF/invalid.mlir | 15 +++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/mlir/lib/Dialect/SCF/IR/SCF.cpp b/mlir/lib/Dialect/SCF/IR/SCF.cpp
index c46a0577c4b96..76467154e869f 100644
--- a/mlir/lib/Dialect/SCF/IR/SCF.cpp
+++ b/mlir/lib/Dialect/SCF/IR/SCF.cpp
@@ -348,6 +348,16 @@ void ForOp::build(OpBuilder &builder, OperationState &result, Value lb,
}
LogicalResult ForOp::verify() {
+ // Check that the body block has at least the induction variable argument.
+ // This must be checked before verifyRegions() and before any region trait
+ // verifiers (e.g. LoopLikeOpInterface) that call getRegionIterArgs(), to
+ // avoid crashing with an out-of-bounds drop_front on an empty arg list.
+ if (getBody()->getNumArguments() < getNumInductionVars())
+ return emitOpError("expected body to have at least ")
+ << getNumInductionVars()
+ << " argument(s) for the induction variable, but got "
+ << getBody()->getNumArguments();
+
// Check that the number of init args and op results is the same.
if (getInitArgs().size() != getNumResults())
return emitOpError(
@@ -357,6 +367,12 @@ LogicalResult ForOp::verify() {
}
LogicalResult ForOp::verifyRegions() {
+ // Check that the body block has at least the induction variable argument.
+ if (getBody()->getNumArguments() < getNumInductionVars())
+ return emitOpError("expected body to have at least ")
+ << getNumInductionVars() << " argument(s) for the induction "
+ << "variable, but got " << getBody()->getNumArguments();
+
// Check that the body defines as single block argument for the induction
// variable.
if (getInductionVar().getType() != getLowerBound().getType())
diff --git a/mlir/test/Dialect/SCF/invalid.mlir b/mlir/test/Dialect/SCF/invalid.mlir
index 985e347fbf5ee..e7031b29adf69 100644
--- a/mlir/test/Dialect/SCF/invalid.mlir
+++ b/mlir/test/Dialect/SCF/invalid.mlir
@@ -835,3 +835,18 @@ func.func @invalid_reference(%a: index) {
}
return
}
+
+// -----
+
+// Regression test for https://github.com/llvm/llvm-project/issues/159737
+// A scf.for whose body block has no arguments used to crash in
+// getRegionIterArgs() via verifyLoopLikeOpInterface instead of producing a
+// proper diagnostic.
+func.func @for_missing_induction_var(%arg0: index, %arg1: index) {
+ %c1 = arith.constant 1 : index
+ // expected-error at +1 {{expected body to have at least 1 argument(s) for the induction variable, but got 0}}
+ "scf.for"(%arg0, %arg1, %c1) ({
+ "scf.yield"() : () -> ()
+ }) : (index, index, index) -> ()
+ return
+}
More information about the Mlir-commits
mailing list