Skip to content

Commit fe7fdca

Browse files
committed
[MLIR] Fix parseFunctionLikeOp() to fail parsing empty regions
- Change parseOptionalRegion to return an OptionalParseResult. - Change parseFunctionLikeOp() to fail parsing if the function body was parsed but was empty. - See https://llvm.discourse.group/t/funcop-parsing-bug/2164 Differential Revision: https://reviews.llvm.org/D91886
1 parent 2452334 commit fe7fdca

File tree

10 files changed

+51
-29
lines changed

10 files changed

+51
-29
lines changed

flang/include/flang/Optimizer/Dialect/FIROps.td

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2856,7 +2856,8 @@ def fir_DispatchTableOp : fir_Op<"dispatch_table",
28562856

28572857
// Parse the optional table body.
28582858
mlir::Region *body = result.addRegion();
2859-
if (parser.parseOptionalRegion(*body, llvm::None, llvm::None))
2859+
OptionalParseResult parseResult = parser.parseOptionalRegion(*body);
2860+
if (parseResult.hasValue() && failed(*parseResult))
28602861
return mlir::failure();
28612862

28622863
ensureTerminator(*body, parser.getBuilder(), result.location);

mlir/include/mlir/IR/OpImplementation.h

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -646,23 +646,23 @@ class OpAsmParser {
646646
// Region Parsing
647647
//===--------------------------------------------------------------------===//
648648

649-
/// Parses a region. Any parsed blocks are appended to "region" and must be
649+
/// Parses a region. Any parsed blocks are appended to 'region' and must be
650650
/// moved to the op regions after the op is created. The first block of the
651-
/// region takes "arguments" of types "argTypes". If "enableNameShadowing" is
651+
/// region takes 'arguments' of types 'argTypes'. If 'enableNameShadowing' is
652652
/// set to true, the argument names are allowed to shadow the names of other
653-
/// existing SSA values defined above the region scope. "enableNameShadowing"
653+
/// existing SSA values defined above the region scope. 'enableNameShadowing'
654654
/// can only be set to true for regions attached to operations that are
655-
/// "IsolatedFromAbove".
655+
/// 'IsolatedFromAbove.
656656
virtual ParseResult parseRegion(Region &region,
657657
ArrayRef<OperandType> arguments = {},
658658
ArrayRef<Type> argTypes = {},
659659
bool enableNameShadowing = false) = 0;
660660

661661
/// Parses a region if present.
662-
virtual ParseResult parseOptionalRegion(Region &region,
663-
ArrayRef<OperandType> arguments = {},
664-
ArrayRef<Type> argTypes = {},
665-
bool enableNameShadowing = false) = 0;
662+
virtual OptionalParseResult
663+
parseOptionalRegion(Region &region, ArrayRef<OperandType> arguments = {},
664+
ArrayRef<Type> argTypes = {},
665+
bool enableNameShadowing = false) = 0;
666666

667667
/// Parses a region if present. If the region is present, a new region is
668668
/// allocated and placed in `region`. If no region is present or on failure,

mlir/lib/Dialect/LLVMIR/IR/LLVMDialect.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,9 +1187,12 @@ static ParseResult parseGlobalOp(OpAsmParser &parser, OperationState &result) {
11871187
return parser.emitError(parser.getNameLoc(),
11881188
"type can only be omitted for string globals");
11891189
}
1190-
} else if (parser.parseOptionalRegion(initRegion, /*arguments=*/{},
1191-
/*argTypes=*/{})) {
1192-
return failure();
1190+
} else {
1191+
OptionalParseResult parseResult =
1192+
parser.parseOptionalRegion(initRegion, /*arguments=*/{},
1193+
/*argTypes=*/{});
1194+
if (parseResult.hasValue() && failed(*parseResult))
1195+
return failure();
11931196
}
11941197

11951198
result.addAttribute("type", TypeAttr::get(types[0]));
@@ -1398,8 +1401,9 @@ static ParseResult parseLLVMFuncOp(OpAsmParser &parser,
13981401
resultAttrs);
13991402

14001403
auto *body = result.addRegion();
1401-
return parser.parseOptionalRegion(
1404+
OptionalParseResult parseResult = parser.parseOptionalRegion(
14021405
*body, entryArgs, entryArgs.empty() ? ArrayRef<Type>() : argTypes);
1406+
return failure(parseResult.hasValue() && failed(*parseResult));
14031407
}
14041408

14051409
// Print the LLVMFuncOp. Collects argument and result types and passes them to

mlir/lib/Dialect/SPIRV/SPIRVOps.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1754,8 +1754,9 @@ static ParseResult parseFuncOp(OpAsmParser &parser, OperationState &state) {
17541754

17551755
// Parse the optional function body.
17561756
auto *body = state.addRegion();
1757-
return parser.parseOptionalRegion(
1757+
OptionalParseResult result = parser.parseOptionalRegion(
17581758
*body, entryArgs, entryArgs.empty() ? ArrayRef<Type>() : argTypes);
1759+
return failure(result.hasValue() && failed(*result));
17591760
}
17601761

17611762
static void print(spirv::FuncOp fnOp, OpAsmPrinter &printer) {

mlir/lib/IR/FunctionImplementation.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,21 @@ mlir::impl::parseFunctionLikeOp(OpAsmParser &parser, OperationState &result,
204204
assert(resultAttrs.size() == resultTypes.size());
205205
addArgAndResultAttrs(builder, result, argAttrs, resultAttrs);
206206

207-
// Parse the optional function body.
207+
// Parse the optional function body. The printer will not print the body if
208+
// its empty, so disallow parsing of empty body in the parser.
208209
auto *body = result.addRegion();
209-
return parser.parseOptionalRegion(
210-
*body, entryArgs, entryArgs.empty() ? ArrayRef<Type>() : argTypes);
210+
llvm::SMLoc loc = parser.getCurrentLocation();
211+
OptionalParseResult parseResult = parser.parseOptionalRegion(
212+
*body, entryArgs, entryArgs.empty() ? ArrayRef<Type>() : argTypes,
213+
/*enableNameShadowing=*/false);
214+
if (parseResult.hasValue()) {
215+
if (failed(*parseResult))
216+
return failure();
217+
// Function body was parsed, make sure its not empty.
218+
if (body->empty())
219+
return parser.emitError(loc, "expected non-empty function body");
220+
}
221+
return success();
211222
}
212223

213224
// Print a function result list.

mlir/lib/Parser/Parser.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1433,12 +1433,12 @@ class CustomOpAsmParser : public OpAsmParser {
14331433
}
14341434

14351435
/// Parses a region if present.
1436-
ParseResult parseOptionalRegion(Region &region,
1437-
ArrayRef<OperandType> arguments,
1438-
ArrayRef<Type> argTypes,
1439-
bool enableNameShadowing) override {
1436+
OptionalParseResult parseOptionalRegion(Region &region,
1437+
ArrayRef<OperandType> arguments,
1438+
ArrayRef<Type> argTypes,
1439+
bool enableNameShadowing) override {
14401440
if (parser.getToken().isNot(Token::l_brace))
1441-
return success();
1441+
return llvm::None;
14421442
return parseRegion(region, arguments, argTypes, enableNameShadowing);
14431443
}
14441444

mlir/test/Dialect/SCF/canonicalize.mlir

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ func @nested_unused(%cond1: i1, %cond2: i1) -> (index) {
8686

8787
// -----
8888

89-
func private @side_effect() {}
89+
func private @side_effect()
9090
func @all_unused(%cond: i1) {
9191
%c0 = constant 0 : index
9292
%c1 = constant 1 : index

mlir/test/IR/invalid.mlir

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,3 +1572,7 @@ func @invalid_region_dominance_with_dominance_free_regions() {
15721572
}
15731573
return
15741574
}
1575+
1576+
// -----
1577+
1578+
func @foo() {} // expected-error {{expected non-empty function body}}

mlir/test/IR/traits.mlir

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -344,12 +344,10 @@ func @failedSingleBlockImplicitTerminator_missing_terminator() {
344344

345345
// Test that operation with the SymbolTable Trait define a new symbol scope.
346346
"test.symbol_scope"() ({
347-
func private @foo() {
348-
}
347+
func private @foo()
349348
"test.finish" () : () -> ()
350349
}) : () -> ()
351-
func private @foo() {
352-
}
350+
func private @foo()
353351

354352
// -----
355353

mlir/tools/mlir-tblgen/OpFormatGen.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -652,8 +652,11 @@ const char *regionListEnsureTerminatorParserCode = R"(
652652
///
653653
/// {0}: The name of the region.
654654
const char *optionalRegionParserCode = R"(
655-
if (parser.parseOptionalRegion(*{0}Region))
656-
return ::mlir::failure();
655+
{
656+
auto parseResult = parser.parseOptionalRegion(*{0}Region);
657+
if (parseResult.hasValue() && failed(*parseResult))
658+
return ::mlir::failure();
659+
}
657660
)";
658661

659662
/// The code snippet used to generate a parser call for a region.

0 commit comments

Comments
 (0)