reader/wgsl: Abort after raising too many errors
Change-Id: I641ee8c2e34e059a02742d06c24f96acecb39cd3
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/33720
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: David Neto <dneto@google.com>
Auto-Submit: Ben Clayton <bclayton@google.com>
diff --git a/src/diagnostic/diagnostic.h b/src/diagnostic/diagnostic.h
index 21ce75b..6fea75f 100644
--- a/src/diagnostic/diagnostic.h
+++ b/src/diagnostic/diagnostic.h
@@ -83,13 +83,15 @@
void add(Diagnostic&& diag) {
entries_.emplace_back(std::move(diag));
if (diag.severity >= Severity::Error) {
- contains_errors_ = true;
+ error_count_++;
}
}
/// @returns true iff the diagnostic list contains errors diagnostics (or of
/// higher severity).
- bool contains_errors() const { return contains_errors_; }
+ bool contains_errors() const { return error_count_ > 0; }
+ /// @returns the number of error diagnostics (or of higher severity).
+ size_t error_count() const { return error_count_; }
/// @returns the number of entries in the list.
size_t count() const { return entries_.size(); }
/// @returns the first diagnostic in the list.
@@ -99,7 +101,7 @@
private:
std::vector<Diagnostic> entries_;
- bool contains_errors_ = false;
+ size_t error_count_ = 0;
};
} // namespace diag
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc
index 8e5c0cf..6aab589 100644
--- a/src/reader/wgsl/parser_impl.cc
+++ b/src/reader/wgsl/parser_impl.cc
@@ -238,8 +238,17 @@
// translation_unit
// : global_decl* EOF
void ParserImpl::translation_unit() {
- while (!peek().IsEof() && synchronized_) {
+ while (synchronized_) {
+ auto p = peek();
+ if (p.IsEof()) {
+ break;
+ }
expect_global_decl();
+ if (diags_.error_count() >= max_errors_) {
+ add_error(Source{{}, p.source().file},
+ "stopping after " + std::to_string(max_errors_) + " errors");
+ break;
+ }
}
assert(module_.IsValid());
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h
index 9b6a841..e533847 100644
--- a/src/reader/wgsl/parser_impl.h
+++ b/src/reader/wgsl/parser_impl.h
@@ -233,6 +233,15 @@
/// @returns true if the parse was successful, false otherwise.
bool Parse();
+ /// set_max_diagnostics sets the maximum number of reported errors before
+ /// aborting parsing.
+ /// @param limit the new maximum number of errors
+ void set_max_errors(size_t limit) { max_errors_ = limit; }
+
+ /// @return the number of maximum number of reported errors before aborting
+ /// parsing.
+ size_t get_max_errors() const { return max_errors_; }
+
/// @returns true if an error was encountered.
bool has_error() const { return diags_.contains_errors(); }
@@ -779,6 +788,7 @@
int silence_errors_ = 0;
std::unordered_map<std::string, ast::type::Type*> registered_constructs_;
ast::Module module_;
+ size_t max_errors_ = 25;
};
} // namespace wgsl
diff --git a/src/reader/wgsl/parser_impl_error_msg_test.cc b/src/reader/wgsl/parser_impl_error_msg_test.cc
index 8a53335..d43d60f 100644
--- a/src/reader/wgsl/parser_impl_error_msg_test.cc
+++ b/src/reader/wgsl/parser_impl_error_msg_test.cc
@@ -28,6 +28,7 @@
std::string source = SOURCE; \
std::string expected = EXPECTED; \
auto p = parser(source); \
+ p->set_max_errors(5); \
EXPECT_EQ(false, p->Parse()); \
EXPECT_EQ(true, p->diagnostics().contains_errors()); \
EXPECT_EQ(expected, diag::Formatter().format(p->diagnostics())); \
@@ -1168,6 +1169,26 @@
" ^\n");
}
+TEST_F(ParserImplErrorTest, MaxErrorsReached) {
+ EXPECT("x; x; x; x; x; x; x; x;",
+ "test.wgsl:1:1 error: unexpected token\n"
+ "x; x; x; x; x; x; x; x;\n"
+ "^\n\n"
+ "test.wgsl:1:4 error: unexpected token\n"
+ "x; x; x; x; x; x; x; x;\n"
+ " ^\n\n"
+ "test.wgsl:1:7 error: unexpected token\n"
+ "x; x; x; x; x; x; x; x;\n"
+ " ^\n\n"
+ "test.wgsl:1:10 error: unexpected token\n"
+ "x; x; x; x; x; x; x; x;\n"
+ " ^\n\n"
+ "test.wgsl:1:13 error: unexpected token\n"
+ "x; x; x; x; x; x; x; x;\n"
+ " ^\n\n"
+ "test.wgsl error: stopping after 5 errors");
+}
+
TEST_F(ParserImplErrorTest, MemberExprMissingIdentifier) {
EXPECT("fn f() -> void { x = a.; }",
"test.wgsl:1:24 error: expected identifier for member accessor\n"