[Mlir-commits] [mlir] [MLIR] Guard optional operand resolution in generated op parsers (PR #180796)
Henrich Lauko
llvmlistbot at llvm.org
Tue Feb 10 09:58:18 PST 2026
https://github.com/xlauko created https://github.com/llvm/llvm-project/pull/180796
Skip resolveOperands for optional operands when they are absent to
avoid out-of-bounds access on the empty types vector.
>From 05bb31f6b9ed3c8b87a250ce5d740da4415aab76 Mon Sep 17 00:00:00 2001
From: xlauko <xlauko at mail.muni.cz>
Date: Tue, 10 Feb 2026 18:56:44 +0100
Subject: [PATCH] [MLIR] Guard optional operand resolution in generated op
parsers
Skip resolveOperands for optional operands when they are absent to
avoid out-of-bounds access on the empty types vector.
---
mlir/test/lib/Dialect/Test/TestOpsSyntax.td | 11 +++++++++++
mlir/test/mlir-tblgen/op-format.mlir | 6 ++++++
mlir/tools/mlir-tblgen/OpFormatGen.cpp | 6 ++++++
3 files changed, 23 insertions(+)
diff --git a/mlir/test/lib/Dialect/Test/TestOpsSyntax.td b/mlir/test/lib/Dialect/Test/TestOpsSyntax.td
index 73de8295380a6..6b10ec6173a50 100644
--- a/mlir/test/lib/Dialect/Test/TestOpsSyntax.td
+++ b/mlir/test/lib/Dialect/Test/TestOpsSyntax.td
@@ -667,6 +667,17 @@ def FormatTypesMatchContextOp : TEST_Op<"format_types_match_context", [
let assemblyFormat = "attr-dict $value `:` type($value)";
}
+def FormatTypesMatchOptionalOp : TEST_Op<"format_types_match_optional", [
+ OptionalTypesMatchWith<"optional type matches result",
+ "result", "optional", "$_self">
+ ]> {
+ let arguments = (ins Optional<AnyType>:$optional);
+ let results = (outs Optional<AnyType>:$result);
+ let assemblyFormat = [{
+ (`(` $optional^ `:` type($result) `)`)? attr-dict
+ }];
+}
+
//===----------------------------------------------------------------------===//
// InferTypeOpInterface type inference in assembly format
//===----------------------------------------------------------------------===//
diff --git a/mlir/test/mlir-tblgen/op-format.mlir b/mlir/test/mlir-tblgen/op-format.mlir
index ac0931f18f042..7ff9091d5500d 100644
--- a/mlir/test/mlir-tblgen/op-format.mlir
+++ b/mlir/test/mlir-tblgen/op-format.mlir
@@ -488,6 +488,12 @@ test.format_infer_variadic_type_from_non_variadic %i64, %i64 : i64
// CHECK: test.format_types_match_context %[[I64]] : i64
%ignored_res6 = test.format_types_match_context %i64 : i64
+// CHECK: test.format_types_match_optional(%[[I64]] : i64)
+%ignored_res7 = test.format_types_match_optional(%i64 : i64)
+
+// CHECK: test.format_types_match_optional
+test.format_types_match_optional
+
//===----------------------------------------------------------------------===//
// InferTypeOpInterface type inference
//===----------------------------------------------------------------------===//
diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
index ccf21d16005af..b834c6f8d3aaf 100644
--- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
@@ -1848,6 +1848,10 @@ void OperationFormat::genParserOperandTypeResolution(
// separately.
for (unsigned i = 0, e = op.getNumOperands(); i != e; ++i) {
NamedTypeConstraint &operand = op.getOperand(i);
+ // Optional operands may not be present; guard resolution to avoid
+ // out-of-bounds access on the (potentially empty) types vector.
+ if (operand.isOptional())
+ body << " if (!" << operand.name << "Operands.empty()) {\n";
body << " if (parser.resolveOperands(" << operand.name << "Operands, ";
// Resolve the type of this operand.
@@ -1856,6 +1860,8 @@ void OperationFormat::genParserOperandTypeResolution(
body << ", " << operand.name
<< "OperandsLoc, result.operands))\n return ::mlir::failure();\n";
+ if (operand.isOptional())
+ body << " }\n";
}
}
More information about the Mlir-commits
mailing list