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@+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 +}