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>
This commit is contained in:
Ben Clayton 2020-11-24 15:15:36 +00:00 committed by Commit Bot service account
parent c489875ff0
commit 1e87fe5517
4 changed files with 46 additions and 4 deletions

View File

@ -83,13 +83,15 @@ class List {
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 @@ class List {
private:
std::vector<Diagnostic> entries_;
bool contains_errors_ = false;
size_t error_count_ = 0;
};
} // namespace diag

View File

@ -238,8 +238,17 @@ bool ParserImpl::Parse() {
// 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());

View File

@ -233,6 +233,15 @@ class ParserImpl {
/// @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 @@ class ParserImpl {
int silence_errors_ = 0;
std::unordered_map<std::string, ast::type::Type*> registered_constructs_;
ast::Module module_;
size_t max_errors_ = 25;
};
} // namespace wgsl

View File

@ -28,6 +28,7 @@ class ParserImplErrorTest : public ParserImplTest {};
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 @@ TEST_F(ParserImplErrorTest, LoopMissingRBrace) {
" ^\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"