mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-19 07:46:49 +00:00
[mlir][Parser] Fix crash when resolving invalid operands with missing location (#128163)
When `resolveOperands` reports an error and no valid `SMLoc` was provided, report the error at the beginning of the op instead of crashing. ``` Assert `Ptr >= BufStart && Ptr <= Buffer->getBufferEnd()' in llvm/lib/Support/SourceMgr.cpp:llvm::SourceMgr::SrcBuffer::getLineNumberSpecialized failed ``` E.g., this is currently the case when parsing the following op with a type but without any operands: ``` let assemblyFormat = "$str (`,` $args^)? attr-dict (`:` type($args)^)?"; ``` Reported error (with this PR): ``` within split at mlir/test/IR/invalid-ops.mlir:122 offset :4:1: error: custom op 'test.variadic_args_types_split' number of operands and types do not match: got 0 operands and 1 types test.variadic_args_types_split "hello_world" : i32 ^ ``` In the ODS-generated C++, the `SMLoc` is populated when parsing the optional group containing `$args`. However, this group is missing in the test case. There are likely additional hand-written parsers that suffer from the same problem. Note: I tried emitting a second `SMLoc` for the optional type group in the `OpFormatGen.cpp`, but this adds quite a bit of complexity in the code base for little improvement in user experience.
This commit is contained in:
parent
25e12726f7
commit
8a3222d8da
@ -1603,10 +1603,12 @@ public:
|
||||
SmallVectorImpl<Value> &result) {
|
||||
size_t operandSize = llvm::range_size(operands);
|
||||
size_t typeSize = llvm::range_size(types);
|
||||
if (operandSize != typeSize)
|
||||
return emitError(loc)
|
||||
if (operandSize != typeSize) {
|
||||
// If no location was provided, report errors at the beginning of the op.
|
||||
return emitError(loc.isValid() ? loc : getNameLoc())
|
||||
<< "number of operands and types do not match: got " << operandSize
|
||||
<< " operands and " << typeSize << " types";
|
||||
}
|
||||
|
||||
for (auto [operand, type] : llvm::zip_equal(operands, types))
|
||||
if (resolveOperand(operand, type, result))
|
||||
|
@ -118,3 +118,8 @@ func.func @invalid_splat(%v : f32) { // expected-note {{prior use here}}
|
||||
|
||||
// expected-error@+1 {{expected ':' after block name}}
|
||||
"g"()({^a:^b })
|
||||
|
||||
// -----
|
||||
|
||||
// expected-error@+1 {{number of operands and types do not match: got 0 operands and 1 types}}
|
||||
test.variadic_args_types_split "hello_world" : i32
|
||||
|
@ -767,4 +767,9 @@ def FormatInferTypeVariadicOperandsOp
|
||||
}];
|
||||
}
|
||||
|
||||
def VariadicArgsTypesSplit : TEST_Op<"variadic_args_types_split"> {
|
||||
let arguments = (ins StrAttr:$str, Variadic<AnyType>:$args);
|
||||
let assemblyFormat = "$str (`,` $args^)? attr-dict (`:` type($args)^)?";
|
||||
}
|
||||
|
||||
#endif // TEST_OPS_SYNTAX
|
||||
|
Loading…
x
Reference in New Issue
Block a user