-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[mlir][IR] Improve error message when parsing incorrect type #134984
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[mlir][IR] Improve error message when parsing incorrect type #134984
Conversation
@llvm/pr-subscribers-mlir-vector @llvm/pr-subscribers-mlir-tensor Author: Matthias Springer (matthias-springer) ChangesImprove error messages when parsing an incorrect type. Before:
After:
This error message is produced when a certain operand/result type is expected according to an op's TableGen definition, but a different type is parsed. Type constraints (which may have nice error messages) are checked after parsing a type. If an incorrect type is parsed, we never get to the point of printing type constraint error messages. This may discourage users from specifying C++ classes with type constraints. (Explicitly specifying C++ classes is beneficial because the auto-generated C++ code will have richer type information.) See #134981 for an example where specifying additional type information with type constraints (e.g., Note: In order to generate a better error message, the parser must retrieve a type's name from the C++ class. TableGen-generated type classes always have a Full diff: https://github.com/llvm/llvm-project/pull/134984.diff 8 Files Affected:
diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h
index 25c7d15eb8ed5..6efad01dec4cc 100644
--- a/mlir/include/mlir/IR/OpImplementation.h
+++ b/mlir/include/mlir/IR/OpImplementation.h
@@ -21,6 +21,19 @@
#include "llvm/Support/SMLoc.h"
#include <optional>
+namespace {
+// reference https://stackoverflow.com/a/16000226
+template <typename T, typename = void>
+struct HasStaticName : std::false_type {};
+
+template <typename T>
+struct HasStaticName<T,
+ typename std::enable_if<
+ std::is_same<::llvm::StringLiteral,
+ std::decay_t<decltype(T::name)>>::value,
+ void>::type> : std::true_type {};
+} // namespace
+
namespace mlir {
class AsmParsedResourceEntry;
class AsmResourceBuilder;
@@ -1238,8 +1251,13 @@ class AsmParser {
// Check for the right kind of type.
result = llvm::dyn_cast<TypeT>(type);
- if (!result)
- return emitError(loc, "invalid kind of type specified");
+ if (!result) {
+ InFlightDiagnostic diag =
+ emitError(loc, "invalid kind of type specified");
+ if constexpr (HasStaticName<TypeT>::value)
+ diag << ": expected " << TypeT::name << ", but found " << type;
+ return diag;
+ }
return success();
}
@@ -1270,8 +1288,13 @@ class AsmParser {
// Check for the right kind of Type.
result = llvm::dyn_cast<TypeT>(type);
- if (!result)
- return emitError(loc, "invalid kind of Type specified");
+ if (!result) {
+ InFlightDiagnostic diag =
+ emitError(loc, "invalid kind of type specified");
+ if constexpr (HasStaticName<TypeT>::value)
+ diag << ": expected " << TypeT::name << ", but found " << type;
+ return diag;
+ }
return success();
}
@@ -1307,8 +1330,13 @@ class AsmParser {
// Check for the right kind of type.
result = llvm::dyn_cast<TypeType>(type);
- if (!result)
- return emitError(loc, "invalid kind of type specified");
+ if (!result) {
+ InFlightDiagnostic diag =
+ emitError(loc, "invalid kind of type specified");
+ if constexpr (HasStaticName<TypeType>::value)
+ diag << ": expected " << TypeType::name << ", but found " << type;
+ return diag;
+ }
return success();
}
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index 5b4e3f92f6d53..b16bab8e5e1ab 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -281,7 +281,7 @@ func.func @test_assign_type_mismatch(%arg1: f32) {
func.func @test_assign_to_array(%arg1: !emitc.array<4xi32>) {
%v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4xi32>
- // expected-error @+1 {{invalid kind of Type specified}}
+ // expected-error @+1 {{invalid kind of type specified: expected emitc.lvalue, but found '!emitc.array<4xi32>}}
emitc.assign %arg1 : !emitc.array<4xi32> to %v : !emitc.array<4xi32>
return
}
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index a7ca109df9382..db55088d812e6 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -121,7 +121,7 @@ func.func @gep_missing_result_type(%pos : i64, %base : !llvm.ptr) {
// -----
func.func @gep_non_function_type(%pos : i64, %base : !llvm.ptr) {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.function, but found '!llvm.ptr'}}
llvm.getelementptr %base[%pos] : !llvm.ptr
}
diff --git a/mlir/test/Dialect/SparseTensor/invalid.mlir b/mlir/test/Dialect/SparseTensor/invalid.mlir
index 908d2d8aa83f7..4c37fc6882bab 100644
--- a/mlir/test/Dialect/SparseTensor/invalid.mlir
+++ b/mlir/test/Dialect/SparseTensor/invalid.mlir
@@ -347,7 +347,7 @@ func.func @sparse_wrong_arity_compression(%arg0: memref<?xf64>,
// -----
func.func @sparse_convert_unranked(%arg0: tensor<*xf32>) -> tensor<10xf32> {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xf32>'}}
%0 = sparse_tensor.convert %arg0 : tensor<*xf32> to tensor<10xf32>
return %0 : tensor<10xf32>
}
diff --git a/mlir/test/Dialect/Tensor/invalid.mlir b/mlir/test/Dialect/Tensor/invalid.mlir
index eeb3967337806..e3923bbfd7340 100644
--- a/mlir/test/Dialect/Tensor/invalid.mlir
+++ b/mlir/test/Dialect/Tensor/invalid.mlir
@@ -81,7 +81,7 @@ func.func @insert_too_many_indices(%arg0: f32, %arg1: tensor<?xf32>) {
// -----
func.func @tensor.from_elements_wrong_result_type() {
- // expected-error@+2 {{'tensor.from_elements' invalid kind of type specified}}
+ // expected-error@+2 {{'tensor.from_elements' invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xi32>}}
%c0 = arith.constant 0 : i32
%0 = tensor.from_elements %c0 : tensor<*xi32>
return
@@ -459,7 +459,7 @@ func.func @pad_yield_type(%arg0: tensor<?x4xi32>, %arg1: i8) -> tensor<?x9xi32>
// -----
func.func @invalid_splat(%v : f32) {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.tensor, but found 'memref<8xf32>'}}
tensor.splat %v : memref<8xf32>
return
}
diff --git a/mlir/test/Dialect/Vector/invalid.mlir b/mlir/test/Dialect/Vector/invalid.mlir
index ea6d0021391fb..ef87030bf0752 100644
--- a/mlir/test/Dialect/Vector/invalid.mlir
+++ b/mlir/test/Dialect/Vector/invalid.mlir
@@ -1,7 +1,7 @@
// RUN: mlir-opt %s -split-input-file -verify-diagnostics
func.func @broadcast_to_scalar(%arg0: f32) -> f32 {
- // expected-error@+1 {{custom op 'vector.broadcast' invalid kind of type specified}}
+ // expected-error@+1 {{custom op 'vector.broadcast' invalid kind of type specified: expected builtin.vector, but found 'f32'}}
%0 = vector.broadcast %arg0 : f32 to f32
}
@@ -144,7 +144,7 @@ func.func @extract_element(%arg0: vector<4x4xf32>) {
// -----
func.func @extract_vector_type(%arg0: index) {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.vector, but found 'index'}}
%1 = vector.extract %arg0[] : index from index
}
@@ -1174,7 +1174,7 @@ func.func @shape_cast_scalability_flag_is_dropped(%arg0 : vector<2x[15]x[2]xf32>
// -----
func.func @bitcast_not_vector(%arg0 : vector<5x1x3x2xf32>) {
- // expected-error@+1 {{'vector.bitcast' invalid kind of type specified}}
+ // expected-error@+1 {{'vector.bitcast' invalid kind of type specified: expected builtin.vector, but found 'f32'}}
%0 = vector.bitcast %arg0 : vector<5x1x3x2xf32> to f32
}
@@ -1628,7 +1628,7 @@ func.func @scan_unsupported_kind(%arg0: vector<2x3xf32>, %arg1: vector<3xf32>) -
// -----
func.func @invalid_splat(%v : f32) {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.vector, but found 'memref<8xf32>'}}
vector.splat %v : memref<8xf32>
return
}
diff --git a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
index 4500175cd22b2..7bb64542accdf 100644
--- a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
@@ -246,7 +246,7 @@ llvm.func @matrix_transpose_intr_wrong_type(%matrix : f32) -> vector<48xf32> {
// -----
llvm.func @active_lane_intr_wrong_type(%base : i64, %n : vector<7xi64>) -> vector<7xi1> {
- // expected-error @below{{invalid kind of type specified}}
+ // expected-error @below{{invalid kind of type specified: expected builtin.integer, but found 'vector<7xi64>'}}
%0 = llvm.intr.get.active.lane.mask %base, %n : i64, vector<7xi64> to vector<7xi1>
llvm.return %0 : vector<7xi1>
}
diff --git a/mlir/test/mlir-tblgen/attr-or-type-format.mlir b/mlir/test/mlir-tblgen/attr-or-type-format.mlir
index 6b61deff1b69f..75aca36ae531b 100644
--- a/mlir/test/mlir-tblgen/attr-or-type-format.mlir
+++ b/mlir/test/mlir-tblgen/attr-or-type-format.mlir
@@ -129,7 +129,7 @@ func.func private @test_verifier_fails() -> () attributes {
// -----
func.func private @test_attr_with_type_failed_to_parse_type() -> () attributes {
- // expected-error@+2 {{invalid kind of type specified}}
+ // expected-error@+2 {{invalid kind of type specified: expected builtin.integer, but found 'vector<4xi32>}}
// expected-error@+1 {{failed to parse TestAttrWithTypeParam parameter 'int_type'}}
attr = #test.attr_with_type<vector<4xi32>, vector<4xi32>>
}
|
@llvm/pr-subscribers-mlir-emitc Author: Matthias Springer (matthias-springer) ChangesImprove error messages when parsing an incorrect type. Before:
After:
This error message is produced when a certain operand/result type is expected according to an op's TableGen definition, but a different type is parsed. Type constraints (which may have nice error messages) are checked after parsing a type. If an incorrect type is parsed, we never get to the point of printing type constraint error messages. This may discourage users from specifying C++ classes with type constraints. (Explicitly specifying C++ classes is beneficial because the auto-generated C++ code will have richer type information.) See #134981 for an example where specifying additional type information with type constraints (e.g., Note: In order to generate a better error message, the parser must retrieve a type's name from the C++ class. TableGen-generated type classes always have a Full diff: https://github.com/llvm/llvm-project/pull/134984.diff 8 Files Affected:
diff --git a/mlir/include/mlir/IR/OpImplementation.h b/mlir/include/mlir/IR/OpImplementation.h
index 25c7d15eb8ed5..6efad01dec4cc 100644
--- a/mlir/include/mlir/IR/OpImplementation.h
+++ b/mlir/include/mlir/IR/OpImplementation.h
@@ -21,6 +21,19 @@
#include "llvm/Support/SMLoc.h"
#include <optional>
+namespace {
+// reference https://stackoverflow.com/a/16000226
+template <typename T, typename = void>
+struct HasStaticName : std::false_type {};
+
+template <typename T>
+struct HasStaticName<T,
+ typename std::enable_if<
+ std::is_same<::llvm::StringLiteral,
+ std::decay_t<decltype(T::name)>>::value,
+ void>::type> : std::true_type {};
+} // namespace
+
namespace mlir {
class AsmParsedResourceEntry;
class AsmResourceBuilder;
@@ -1238,8 +1251,13 @@ class AsmParser {
// Check for the right kind of type.
result = llvm::dyn_cast<TypeT>(type);
- if (!result)
- return emitError(loc, "invalid kind of type specified");
+ if (!result) {
+ InFlightDiagnostic diag =
+ emitError(loc, "invalid kind of type specified");
+ if constexpr (HasStaticName<TypeT>::value)
+ diag << ": expected " << TypeT::name << ", but found " << type;
+ return diag;
+ }
return success();
}
@@ -1270,8 +1288,13 @@ class AsmParser {
// Check for the right kind of Type.
result = llvm::dyn_cast<TypeT>(type);
- if (!result)
- return emitError(loc, "invalid kind of Type specified");
+ if (!result) {
+ InFlightDiagnostic diag =
+ emitError(loc, "invalid kind of type specified");
+ if constexpr (HasStaticName<TypeT>::value)
+ diag << ": expected " << TypeT::name << ", but found " << type;
+ return diag;
+ }
return success();
}
@@ -1307,8 +1330,13 @@ class AsmParser {
// Check for the right kind of type.
result = llvm::dyn_cast<TypeType>(type);
- if (!result)
- return emitError(loc, "invalid kind of type specified");
+ if (!result) {
+ InFlightDiagnostic diag =
+ emitError(loc, "invalid kind of type specified");
+ if constexpr (HasStaticName<TypeType>::value)
+ diag << ": expected " << TypeType::name << ", but found " << type;
+ return diag;
+ }
return success();
}
diff --git a/mlir/test/Dialect/EmitC/invalid_ops.mlir b/mlir/test/Dialect/EmitC/invalid_ops.mlir
index 5b4e3f92f6d53..b16bab8e5e1ab 100644
--- a/mlir/test/Dialect/EmitC/invalid_ops.mlir
+++ b/mlir/test/Dialect/EmitC/invalid_ops.mlir
@@ -281,7 +281,7 @@ func.func @test_assign_type_mismatch(%arg1: f32) {
func.func @test_assign_to_array(%arg1: !emitc.array<4xi32>) {
%v = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4xi32>
- // expected-error @+1 {{invalid kind of Type specified}}
+ // expected-error @+1 {{invalid kind of type specified: expected emitc.lvalue, but found '!emitc.array<4xi32>}}
emitc.assign %arg1 : !emitc.array<4xi32> to %v : !emitc.array<4xi32>
return
}
diff --git a/mlir/test/Dialect/LLVMIR/invalid.mlir b/mlir/test/Dialect/LLVMIR/invalid.mlir
index a7ca109df9382..db55088d812e6 100644
--- a/mlir/test/Dialect/LLVMIR/invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/invalid.mlir
@@ -121,7 +121,7 @@ func.func @gep_missing_result_type(%pos : i64, %base : !llvm.ptr) {
// -----
func.func @gep_non_function_type(%pos : i64, %base : !llvm.ptr) {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.function, but found '!llvm.ptr'}}
llvm.getelementptr %base[%pos] : !llvm.ptr
}
diff --git a/mlir/test/Dialect/SparseTensor/invalid.mlir b/mlir/test/Dialect/SparseTensor/invalid.mlir
index 908d2d8aa83f7..4c37fc6882bab 100644
--- a/mlir/test/Dialect/SparseTensor/invalid.mlir
+++ b/mlir/test/Dialect/SparseTensor/invalid.mlir
@@ -347,7 +347,7 @@ func.func @sparse_wrong_arity_compression(%arg0: memref<?xf64>,
// -----
func.func @sparse_convert_unranked(%arg0: tensor<*xf32>) -> tensor<10xf32> {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xf32>'}}
%0 = sparse_tensor.convert %arg0 : tensor<*xf32> to tensor<10xf32>
return %0 : tensor<10xf32>
}
diff --git a/mlir/test/Dialect/Tensor/invalid.mlir b/mlir/test/Dialect/Tensor/invalid.mlir
index eeb3967337806..e3923bbfd7340 100644
--- a/mlir/test/Dialect/Tensor/invalid.mlir
+++ b/mlir/test/Dialect/Tensor/invalid.mlir
@@ -81,7 +81,7 @@ func.func @insert_too_many_indices(%arg0: f32, %arg1: tensor<?xf32>) {
// -----
func.func @tensor.from_elements_wrong_result_type() {
- // expected-error@+2 {{'tensor.from_elements' invalid kind of type specified}}
+ // expected-error@+2 {{'tensor.from_elements' invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xi32>}}
%c0 = arith.constant 0 : i32
%0 = tensor.from_elements %c0 : tensor<*xi32>
return
@@ -459,7 +459,7 @@ func.func @pad_yield_type(%arg0: tensor<?x4xi32>, %arg1: i8) -> tensor<?x9xi32>
// -----
func.func @invalid_splat(%v : f32) {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.tensor, but found 'memref<8xf32>'}}
tensor.splat %v : memref<8xf32>
return
}
diff --git a/mlir/test/Dialect/Vector/invalid.mlir b/mlir/test/Dialect/Vector/invalid.mlir
index ea6d0021391fb..ef87030bf0752 100644
--- a/mlir/test/Dialect/Vector/invalid.mlir
+++ b/mlir/test/Dialect/Vector/invalid.mlir
@@ -1,7 +1,7 @@
// RUN: mlir-opt %s -split-input-file -verify-diagnostics
func.func @broadcast_to_scalar(%arg0: f32) -> f32 {
- // expected-error@+1 {{custom op 'vector.broadcast' invalid kind of type specified}}
+ // expected-error@+1 {{custom op 'vector.broadcast' invalid kind of type specified: expected builtin.vector, but found 'f32'}}
%0 = vector.broadcast %arg0 : f32 to f32
}
@@ -144,7 +144,7 @@ func.func @extract_element(%arg0: vector<4x4xf32>) {
// -----
func.func @extract_vector_type(%arg0: index) {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.vector, but found 'index'}}
%1 = vector.extract %arg0[] : index from index
}
@@ -1174,7 +1174,7 @@ func.func @shape_cast_scalability_flag_is_dropped(%arg0 : vector<2x[15]x[2]xf32>
// -----
func.func @bitcast_not_vector(%arg0 : vector<5x1x3x2xf32>) {
- // expected-error@+1 {{'vector.bitcast' invalid kind of type specified}}
+ // expected-error@+1 {{'vector.bitcast' invalid kind of type specified: expected builtin.vector, but found 'f32'}}
%0 = vector.bitcast %arg0 : vector<5x1x3x2xf32> to f32
}
@@ -1628,7 +1628,7 @@ func.func @scan_unsupported_kind(%arg0: vector<2x3xf32>, %arg1: vector<3xf32>) -
// -----
func.func @invalid_splat(%v : f32) {
- // expected-error@+1 {{invalid kind of type specified}}
+ // expected-error@+1 {{invalid kind of type specified: expected builtin.vector, but found 'memref<8xf32>'}}
vector.splat %v : memref<8xf32>
return
}
diff --git a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
index 4500175cd22b2..7bb64542accdf 100644
--- a/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
+++ b/mlir/test/Target/LLVMIR/llvmir-invalid.mlir
@@ -246,7 +246,7 @@ llvm.func @matrix_transpose_intr_wrong_type(%matrix : f32) -> vector<48xf32> {
// -----
llvm.func @active_lane_intr_wrong_type(%base : i64, %n : vector<7xi64>) -> vector<7xi1> {
- // expected-error @below{{invalid kind of type specified}}
+ // expected-error @below{{invalid kind of type specified: expected builtin.integer, but found 'vector<7xi64>'}}
%0 = llvm.intr.get.active.lane.mask %base, %n : i64, vector<7xi64> to vector<7xi1>
llvm.return %0 : vector<7xi1>
}
diff --git a/mlir/test/mlir-tblgen/attr-or-type-format.mlir b/mlir/test/mlir-tblgen/attr-or-type-format.mlir
index 6b61deff1b69f..75aca36ae531b 100644
--- a/mlir/test/mlir-tblgen/attr-or-type-format.mlir
+++ b/mlir/test/mlir-tblgen/attr-or-type-format.mlir
@@ -129,7 +129,7 @@ func.func private @test_verifier_fails() -> () attributes {
// -----
func.func private @test_attr_with_type_failed_to_parse_type() -> () attributes {
- // expected-error@+2 {{invalid kind of type specified}}
+ // expected-error@+2 {{invalid kind of type specified: expected builtin.integer, but found 'vector<4xi32>}}
// expected-error@+1 {{failed to parse TestAttrWithTypeParam parameter 'int_type'}}
attr = #test.attr_with_type<vector<4xi32>, vector<4xi32>>
}
|
struct HasStaticName : std::false_type {}; | ||
|
||
template <typename T> | ||
struct HasStaticName<T, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an alternative to this, can we enforce that each type has a getTypeName
method? Similar to how each operation class must have a getOperationName
method?
edit: That won't be sufficient because type interfaces don't have this method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like a great change!
…4984) Improve error messages when parsing an incorrect type. Before: ``` invalid kind of type specified ``` After: ``` invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xi32>' ``` This error message is produced when a certain operand/result type is expected according to an op's TableGen definition, but a different type is parsed. Type constraints (which may have nice error messages) are checked after parsing a type. If an incorrect type is parsed, we never get to the point of printing type constraint error messages. This may discourage users from specifying C++ classes with type constraints. (Explicitly specifying C++ classes is beneficial because the auto-generated C++ code will have richer type information; explicit casts are unnecessary, etc.) See llvm#134981 for an example where specifying additional type information with type constraints (e.g., `LLVM_AnyVector`) lead to worse error messages. Note: In order to generate a better error message, the parser must retrieve a type's name from the C++ class. TableGen-generated type classes always have a `name` field, but hand-written C++ type classes may not. The `HasStaticName` template was copied from `DialectImplementation.h` (`HasStaticDialectName`).
…4984) Improve error messages when parsing an incorrect type. Before: ``` invalid kind of type specified ``` After: ``` invalid kind of type specified: expected builtin.tensor, but found 'tensor<*xi32>' ``` This error message is produced when a certain operand/result type is expected according to an op's TableGen definition, but a different type is parsed. Type constraints (which may have nice error messages) are checked after parsing a type. If an incorrect type is parsed, we never get to the point of printing type constraint error messages. This may discourage users from specifying C++ classes with type constraints. (Explicitly specifying C++ classes is beneficial because the auto-generated C++ code will have richer type information; explicit casts are unnecessary, etc.) See llvm#134981 for an example where specifying additional type information with type constraints (e.g., `LLVM_AnyVector`) lead to worse error messages. Note: In order to generate a better error message, the parser must retrieve a type's name from the C++ class. TableGen-generated type classes always have a `name` field, but hand-written C++ type classes may not. The `HasStaticName` template was copied from `DialectImplementation.h` (`HasStaticDialectName`).
Improve error messages when parsing an incorrect type.
Before:
After:
This error message is produced when a certain operand/result type is expected according to an op's TableGen definition, but a different type is parsed. Type constraints (which may have nice error messages) are checked after parsing a type. If an incorrect type is parsed, we never get to the point of printing type constraint error messages. This may discourage users from specifying C++ classes with type constraints. (Explicitly specifying C++ classes is beneficial because the auto-generated C++ code will have richer type information; explicit casts are unnecessary, etc.) See #134981 for an example where specifying additional type information with type constraints (e.g.,
LLVM_AnyVector
) lead to worse error messages.Note: In order to generate a better error message, the parser must retrieve a type's name from the C++ class. TableGen-generated type classes always have a
name
field, but hand-written C++ type classes may not. TheHasStaticName
template was copied fromDialectImplementation.h
(HasStaticDialectName
).