[Mlir-commits] [mlir] 48fb79e - Improve error message when declarativeAssembly contains invalid literals
Mehdi Amini
llvmlistbot at llvm.org
Fri Dec 3 16:27:42 PST 2021
Author: Mehdi Amini
Date: 2021-12-04T00:27:32Z
New Revision: 48fb79effb65cb786e8c7264d86af77154bf53c8
URL: https://github.com/llvm/llvm-project/commit/48fb79effb65cb786e8c7264d86af77154bf53c8
DIFF: https://github.com/llvm/llvm-project/commit/48fb79effb65cb786e8c7264d86af77154bf53c8.diff
LOG: Improve error message when declarativeAssembly contains invalid literals
Differential Revision: https://reviews.llvm.org/D115085
Added:
Modified:
mlir/test/mlir-tblgen/op-format-spec.td
mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
mlir/tools/mlir-tblgen/FormatGen.cpp
mlir/tools/mlir-tblgen/FormatGen.h
mlir/tools/mlir-tblgen/OpFormatGen.cpp
Removed:
################################################################################
diff --git a/mlir/test/mlir-tblgen/op-format-spec.td b/mlir/test/mlir-tblgen/op-format-spec.td
index e4d0f9e3b21f8..5b79efc704ec5 100644
--- a/mlir/test/mlir-tblgen/op-format-spec.td
+++ b/mlir/test/mlir-tblgen/op-format-spec.td
@@ -320,13 +320,22 @@ def DirectiveTypeZOperandInvalidI : TestFormat_Op<[{
//===----------------------------------------------------------------------===//
// Test all of the valid literals.
-// CHECK: error: expected valid literal
+// CHECK: error: expected valid literal but got 'a:': keywords should contain only alphanum, '_', '$', or '.' characters
def LiteralInvalidA : TestFormat_Op<[{
+ `a:`
+}]>;
+// CHECK: error: expected valid literal but got '1': single character literal must be a letter or one of '_:,=<>()[]{}?+*'
+def LiteralInvalidB : TestFormat_Op<[{
`1`
}]>;
+// CHECK: error: expected valid literal but got ':abc': valid keyword starts with a letter or '_'
+def LiteralInvalidC : TestFormat_Op<[{
+ `:abc`
+}]>;
+
// CHECK: error: unexpected end of file in literal
// CHECK: error: expected directive, literal, variable, or optional group
-def LiteralInvalidB : TestFormat_Op<[{
+def LiteralInvalidD : TestFormat_Op<[{
`
}]>;
// CHECK-NOT: error
diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
index 3c6035b7baf5b..01ae08e57be9e 100644
--- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp
@@ -606,8 +606,11 @@ FormatParser::parseLiteral(ParserContext ctx) {
/// Get the literal spelling without the surrounding "`".
auto value = curToken.getSpelling().drop_front().drop_back();
- if (!isValidLiteral(value))
- return emitError("literal '" + value + "' is not valid");
+ if (!isValidLiteral(value, [&](Twine diag) {
+ (void)emitError("expected valid literal but got '" + value +
+ "': " + diag);
+ }))
+ return failure();
consumeToken();
return {std::make_unique<LiteralElement>(value)};
diff --git a/mlir/tools/mlir-tblgen/FormatGen.cpp b/mlir/tools/mlir-tblgen/FormatGen.cpp
index fa6c0603ac7e1..b4bad2aef0c3c 100644
--- a/mlir/tools/mlir-tblgen/FormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/FormatGen.cpp
@@ -189,30 +189,50 @@ bool mlir::tblgen::shouldEmitSpaceBefore(StringRef value,
return !StringRef("<>(){}[],").contains(value.front());
}
-bool mlir::tblgen::canFormatStringAsKeyword(StringRef value) {
- if (!isalpha(value.front()) && value.front() != '_')
+bool mlir::tblgen::canFormatStringAsKeyword(
+ StringRef value, function_ref<void(Twine)> emitError) {
+ if (!isalpha(value.front()) && value.front() != '_') {
+ if (emitError)
+ emitError("valid keyword starts with a letter or '_'");
return false;
- return llvm::all_of(value.drop_front(), [](char c) {
- return isalnum(c) || c == '_' || c == '$' || c == '.';
- });
+ }
+ if (!llvm::all_of(value.drop_front(), [](char c) {
+ return isalnum(c) || c == '_' || c == '$' || c == '.';
+ })) {
+ if (emitError)
+ emitError(
+ "keywords should contain only alphanum, '_', '$', or '.' characters");
+ return false;
+ }
+ return true;
}
-bool mlir::tblgen::isValidLiteral(StringRef value) {
- if (value.empty())
+bool mlir::tblgen::isValidLiteral(StringRef value,
+ function_ref<void(Twine)> emitError) {
+ if (value.empty()) {
+ if (emitError)
+ emitError("literal can't be empty");
return false;
+ }
char front = value.front();
// If there is only one character, this must either be punctuation or a
// single character bare identifier.
- if (value.size() == 1)
- return isalpha(front) || StringRef("_:,=<>()[]{}?+*").contains(front);
-
+ if (value.size() == 1) {
+ StringRef bare = "_:,=<>()[]{}?+*";
+ if (isalpha(front) || bare.contains(front))
+ return true;
+ if (emitError)
+ emitError("single character literal must be a letter or one of '" + bare +
+ "'");
+ return false;
+ }
// Check the punctuation that are larger than a single character.
if (value == "->")
return true;
// Otherwise, this must be an identifier.
- return canFormatStringAsKeyword(value);
+ return canFormatStringAsKeyword(value, emitError);
}
//===----------------------------------------------------------------------===//
diff --git a/mlir/tools/mlir-tblgen/FormatGen.h b/mlir/tools/mlir-tblgen/FormatGen.h
index f061d1ed5c678..3a434765b29ec 100644
--- a/mlir/tools/mlir-tblgen/FormatGen.h
+++ b/mlir/tools/mlir-tblgen/FormatGen.h
@@ -147,10 +147,13 @@ class FormatLexer {
bool shouldEmitSpaceBefore(StringRef value, bool lastWasPunctuation);
/// Returns true if the given string can be formatted as a keyword.
-bool canFormatStringAsKeyword(StringRef value);
+bool canFormatStringAsKeyword(StringRef value,
+ function_ref<void(Twine)> emitError = nullptr);
/// Returns true if the given string is valid format literal element.
-bool isValidLiteral(StringRef value);
+/// If `emitError` is provided, it is invoked with the reason for the failure.
+bool isValidLiteral(StringRef value,
+ function_ref<void(Twine)> emitError = nullptr);
/// Whether a failure in parsing the assembly format should be a fatal error.
extern llvm::cl::opt<bool> formatErrorIsFatal;
diff --git a/mlir/tools/mlir-tblgen/OpFormatGen.cpp b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
index dfe671c9b7a93..0827146da180f 100644
--- a/mlir/tools/mlir-tblgen/OpFormatGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpFormatGen.cpp
@@ -2724,9 +2724,12 @@ LogicalResult FormatParser::parseLiteral(std::unique_ptr<Element> &element,
}
// Check that the parsed literal is valid.
- if (!isValidLiteral(value))
- return emitError(literalTok.getLoc(), "expected valid literal");
-
+ if (!isValidLiteral(value, [&](Twine diag) {
+ (void)emitError(literalTok.getLoc(),
+ "expected valid literal but got '" + value +
+ "': " + diag);
+ }))
+ return failure();
element = std::make_unique<LiteralElement>(value);
return ::mlir::success();
}
More information about the Mlir-commits
mailing list