resolver: Remove error codes

We've decided that these will be omitted for now.

Move the check-spec-examples script into the tools/src directory, and update the go modules.
Add a bash script to build and run this.

Change-Id: I852f8ddb1b9b987410a2a49cf6d14e54c3cf3f0e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56381
Auto-Submit: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
Ben Clayton 2021-06-29 14:42:19 +00:00 committed by Tint LUCI CQ
parent 91622e3853
commit 5a88ec8822
13 changed files with 153 additions and 150 deletions

View File

@ -42,8 +42,7 @@ TEST_F(ResolverCallValidationTest, Recursive_Invalid) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0004: recursion is not permitted. 'main' attempted " "12:34 error: recursion is not permitted. 'main' attempted to call "
"to call "
"itself."); "itself.");
} }
@ -70,8 +69,7 @@ TEST_F(ResolverCallValidationTest, Undeclared_Invalid) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(), "12:34 error: unable to find called function: func");
"12:34 error: v-0006: unable to find called function: func");
} }
TEST_F(ResolverCallValidationTest, TooFewArgs) { TEST_F(ResolverCallValidationTest, TooFewArgs) {

View File

@ -45,8 +45,8 @@ TEST_F(ResolverControlBlockValidationTest,
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0025: switch statement selector expression must be " "12:34 error: switch statement selector expression must be of a "
"of a scalar integer type"); "scalar integer type");
} }
TEST_F(ResolverControlBlockValidationTest, SwitchWithoutDefault_Fail) { TEST_F(ResolverControlBlockValidationTest, SwitchWithoutDefault_Fail) {
@ -106,8 +106,7 @@ TEST_F(ResolverControlBlockValidationTest, SwitchWithTwoDefault_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
"12:34 error v-0008: switch statement must have exactly one default " "12:34 error: switch statement must have exactly one default clause");
"clause");
} }
TEST_F(ResolverControlBlockValidationTest, UnreachableCode_continue) { TEST_F(ResolverControlBlockValidationTest, UnreachableCode_continue) {
@ -164,8 +163,8 @@ TEST_F(ResolverControlBlockValidationTest,
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0026: the case selector values must have the same " "12:34 error: the case selector values must have the same type as "
"type as the selector expression."); "the selector expression.");
} }
TEST_F(ResolverControlBlockValidationTest, TEST_F(ResolverControlBlockValidationTest,
@ -193,8 +192,8 @@ TEST_F(ResolverControlBlockValidationTest,
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0026: the case selector values must have the same " "12:34 error: the case selector values must have the same type as "
"type as the selector expression."); "the selector expression.");
} }
TEST_F(ResolverControlBlockValidationTest, TEST_F(ResolverControlBlockValidationTest,
@ -228,8 +227,8 @@ TEST_F(ResolverControlBlockValidationTest,
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0027: a literal value must not appear more than " "12:34 error: a literal value must not appear more than once in "
"once in the case selectors for a switch statement: '2u'"); "the case selectors for a switch statement: '2u'");
} }
TEST_F(ResolverControlBlockValidationTest, TEST_F(ResolverControlBlockValidationTest,
@ -264,10 +263,9 @@ TEST_F(ResolverControlBlockValidationTest,
WrapInFunction(block); WrapInFunction(block);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: a literal value must not appear more than once in "
"12:34 error v-0027: a literal value must not appear more than once in " "the case selectors for a switch statement: '10'");
"the case selectors for a switch statement: '10'");
} }
TEST_F(ResolverControlBlockValidationTest, TEST_F(ResolverControlBlockValidationTest,
@ -288,10 +286,9 @@ TEST_F(ResolverControlBlockValidationTest,
WrapInFunction(block); WrapInFunction(block);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: a fallthrough statement must not appear as the last "
"12:34 error v-0028: a fallthrough statement must not appear as the " "statement in last clause of a switch");
"last statement in last clause of a switch");
} }
TEST_F(ResolverControlBlockValidationTest, SwitchCase_Pass) { TEST_F(ResolverControlBlockValidationTest, SwitchCase_Pass) {

View File

@ -42,7 +42,7 @@ TEST_F(ResolverFunctionValidationTest, FunctionNamesMustBeUnique_fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
R"(12:34 error v-0016: duplicate function named 'func' R"(12:34 error: duplicate function named 'func'
note: first function declared here)"); note: first function declared here)");
} }
@ -74,8 +74,8 @@ TEST_F(ResolverFunctionValidationTest,
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-2000: duplicate declaration 'foo'\n56:78 note: " "12:34 error: duplicate declaration 'foo'\n56:78 note: 'foo' first "
"'foo' first declared here:"); "declared here:");
} }
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
@ -91,8 +91,8 @@ TEST_F(ResolverFunctionValidationTest,
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"error v-2000: duplicate declaration 'foo'\n12:34 note: 'foo' " "error: duplicate declaration 'foo'\n12:34 note: 'foo' first "
"first declared here:"); "declared here:");
} }
TEST_F(ResolverFunctionValidationTest, FunctionUsingSameVariableName_Pass) { TEST_F(ResolverFunctionValidationTest, FunctionUsingSameVariableName_Pass) {
@ -163,9 +163,8 @@ TEST_F(ResolverFunctionValidationTest, FunctionEndWithoutReturnStatement_Fail) {
ast::DecorationList{}); ast::DecorationList{});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: non-void function must end with a return statement");
"12:34 error v-0002: non-void function must end with a return statement");
} }
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
@ -186,9 +185,8 @@ TEST_F(ResolverFunctionValidationTest,
ast::StatementList{}, ast::DecorationList{}); ast::StatementList{}, ast::DecorationList{});
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: non-void function must end with a return statement");
"12:34 error v-0002: non-void function must end with a return statement");
} }
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
@ -214,8 +212,8 @@ TEST_F(ResolverFunctionValidationTest,
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-000y: return statement type must match its function " "12:34 error: return statement type must match its function return "
"return type, returned 'i32', expected 'void'"); "type, returned 'i32', expected 'void'");
} }
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
@ -229,8 +227,8 @@ TEST_F(ResolverFunctionValidationTest,
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-000y: return statement type must match its function " "12:34 error: return statement type must match its function return "
"return type, returned 'void', expected 'f32'"); "type, returned 'void', expected 'f32'");
} }
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
@ -256,8 +254,8 @@ TEST_F(ResolverFunctionValidationTest,
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-000y: return statement type must match its function " "12:34 error: return statement type must match its function return "
"return type, returned 'i32', expected 'f32'"); "type, returned 'i32', expected 'f32'");
} }
TEST_F(ResolverFunctionValidationTest, TEST_F(ResolverFunctionValidationTest,
@ -287,8 +285,8 @@ TEST_F(ResolverFunctionValidationTest,
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-000y: return statement type must match its function " "12:34 error: return statement type must match its function return "
"return type, returned 'u32', expected 'myf32'"); "type, returned 'u32', expected 'myf32'");
} }
TEST_F(ResolverFunctionValidationTest, PipelineStage_MustBeUnique_Fail) { TEST_F(ResolverFunctionValidationTest, PipelineStage_MustBeUnique_Fail) {

View File

@ -616,8 +616,7 @@ bool Resolver::ValidateVariableConstructor(const ast::Variable* var,
bool Resolver::GlobalVariable(ast::Variable* var) { bool Resolver::GlobalVariable(ast::Variable* var) {
if (variable_stack_.has(var->symbol())) { if (variable_stack_.has(var->symbol())) {
AddError("v-0011", AddError("redeclared global identifier '" +
"redeclared global identifier '" +
builder_->Symbols().NameFor(var->symbol()) + "'", builder_->Symbols().NameFor(var->symbol()) + "'",
var->source()); var->source());
return false; return false;
@ -630,13 +629,11 @@ bool Resolver::GlobalVariable(ast::Variable* var) {
variable_stack_.set_global(var->symbol(), info); variable_stack_.set_global(var->symbol(), info);
if (!var->is_const() && info->storage_class == ast::StorageClass::kNone) { if (!var->is_const() && info->storage_class == ast::StorageClass::kNone) {
AddError("v-0022", "global variables must have a storage class", AddError("global variables must have a storage class", var->source());
var->source());
return false; return false;
} }
if (var->is_const() && !(info->storage_class == ast::StorageClass::kNone)) { if (var->is_const() && !(info->storage_class == ast::StorageClass::kNone)) {
AddError("v-global01", "global constants shouldn't have a storage class", AddError("global constants shouldn't have a storage class", var->source());
var->source());
return false; return false;
} }
@ -678,8 +675,7 @@ bool Resolver::GlobalVariable(ast::Variable* var) {
bool Resolver::ValidateGlobalVariable(const VariableInfo* info) { bool Resolver::ValidateGlobalVariable(const VariableInfo* info) {
auto duplicate_func = symbol_to_function_.find(info->declaration->symbol()); auto duplicate_func = symbol_to_function_.find(info->declaration->symbol());
if (duplicate_func != symbol_to_function_.end()) { if (duplicate_func != symbol_to_function_.end()) {
AddError("v-2000", AddError("duplicate declaration '" +
"duplicate declaration '" +
builder_->Symbols().NameFor(info->declaration->symbol()) + "'", builder_->Symbols().NameFor(info->declaration->symbol()) + "'",
info->declaration->source()); info->declaration->source());
AddNote("'" + builder_->Symbols().NameFor(info->declaration->symbol()) + AddNote("'" + builder_->Symbols().NameFor(info->declaration->symbol()) +
@ -866,8 +862,7 @@ bool Resolver::ValidateVariable(const VariableInfo* info) {
if (auto* r = storage_type->As<sem::Array>()) { if (auto* r = storage_type->As<sem::Array>()) {
if (r->IsRuntimeSized()) { if (r->IsRuntimeSized()) {
AddError("v-0015", AddError("runtime arrays may only appear as the last member of a struct",
"runtime arrays may only appear as the last member of a struct",
var->source()); var->source());
return false; return false;
} }
@ -1040,8 +1035,7 @@ bool Resolver::ValidateFunction(const ast::Function* func,
const FunctionInfo* info) { const FunctionInfo* info) {
auto func_it = symbol_to_function_.find(func->symbol()); auto func_it = symbol_to_function_.find(func->symbol());
if (func_it != symbol_to_function_.end()) { if (func_it != symbol_to_function_.end()) {
AddError("v-0016", AddError("duplicate function named '" +
"duplicate function named '" +
builder_->Symbols().NameFor(func->symbol()) + "'", builder_->Symbols().NameFor(func->symbol()) + "'",
func->source()); func->source());
AddNote("first function declared here", AddNote("first function declared here",
@ -1053,8 +1047,7 @@ bool Resolver::ValidateFunction(const ast::Function* func,
VariableInfo* var; VariableInfo* var;
if (variable_stack_.get(func->symbol(), &var, &is_global)) { if (variable_stack_.get(func->symbol(), &var, &is_global)) {
if (is_global) { if (is_global) {
AddError("v-2000", AddError("duplicate declaration '" +
"duplicate declaration '" +
builder_->Symbols().NameFor(func->symbol()) + "'", builder_->Symbols().NameFor(func->symbol()) + "'",
func->source()); func->source());
AddNote("'" + builder_->Symbols().NameFor(func->symbol()) + AddNote("'" + builder_->Symbols().NameFor(func->symbol()) +
@ -1099,7 +1092,7 @@ bool Resolver::ValidateFunction(const ast::Function* func,
if (func->body()) { if (func->body()) {
if (!func->get_last_statement() || if (!func->get_last_statement() ||
!func->get_last_statement()->Is<ast::ReturnStatement>()) { !func->get_last_statement()->Is<ast::ReturnStatement>()) {
AddError("v-0002", "non-void function must end with a return statement", AddError("non-void function must end with a return statement",
func->source()); func->source());
return false; return false;
} }
@ -2038,13 +2031,11 @@ bool Resolver::FunctionCall(const ast::CallExpression* call) {
if (callee_func_it == symbol_to_function_.end()) { if (callee_func_it == symbol_to_function_.end()) {
if (current_function_ && if (current_function_ &&
current_function_->declaration->symbol() == ident->symbol()) { current_function_->declaration->symbol() == ident->symbol()) {
AddError("v-0004", AddError("recursion is not permitted. '" + name +
"recursion is not permitted. '" + name +
"' attempted to call itself.", "' attempted to call itself.",
call->source()); call->source());
} else { } else {
AddError("v-0006: unable to find called function: " + name, AddError("unable to find called function: " + name, call->source());
call->source());
} }
return false; return false;
} }
@ -2400,8 +2391,7 @@ bool Resolver::Identifier(ast::IdentifierExpression* expr) {
return false; return false;
} }
AddError("v-0006: identifier must be declared before use: " + name, AddError("identifier must be declared before use: " + name, expr->source());
expr->source());
return false; return false;
} }
@ -2829,9 +2819,7 @@ bool Resolver::VariableDeclStatement(const ast::VariableDeclStatement* stmt) {
bool is_global = false; bool is_global = false;
if (variable_stack_.get(var->symbol(), nullptr, &is_global)) { if (variable_stack_.get(var->symbol(), nullptr, &is_global)) {
const char* error_code = is_global ? "v-0013" : "v-0014"; AddError("redeclared identifier '" +
AddError(error_code,
"redeclared identifier '" +
builder_->Symbols().NameFor(var->symbol()) + "'", builder_->Symbols().NameFor(var->symbol()) + "'",
var->source()); var->source());
return false; return false;
@ -3370,18 +3358,16 @@ bool Resolver::ValidateStructure(const sem::Struct* str) {
if (r->IsRuntimeSized()) { if (r->IsRuntimeSized()) {
if (member != str->Members().back()) { if (member != str->Members().back()) {
AddError( AddError(
"v-0015",
"runtime arrays may only appear as the last member of a struct", "runtime arrays may only appear as the last member of a struct",
member->Declaration()->source()); member->Declaration()->source());
return false; return false;
} }
if (!str->IsBlockDecorated()) { if (!str->IsBlockDecorated()) {
AddError("v-0015", AddError(
"a struct containing a runtime-sized array " "a struct containing a runtime-sized array "
"requires the [[block]] attribute: '" + "requires the [[block]] attribute: '" +
builder_->Symbols().NameFor(str->Declaration()->name()) + builder_->Symbols().NameFor(str->Declaration()->name()) + "'",
"'", member->Declaration()->source());
member->Declaration()->source());
return false; return false;
} }
} }
@ -3568,12 +3554,12 @@ bool Resolver::ValidateReturn(const ast::ReturnStatement* ret) {
: builder_->create<sem::Void>(); : builder_->create<sem::Void>();
if (func_type->UnwrapRef() != ret_type) { if (func_type->UnwrapRef() != ret_type) {
AddError("v-000y", AddError(
"return statement type must match its function " "return statement type must match its function "
"return type, returned '" + "return type, returned '" +
ret_type->FriendlyName(builder_->Symbols()) + "', expected '" + ret_type->FriendlyName(builder_->Symbols()) + "', expected '" +
current_function_->return_type_name + "'", current_function_->return_type_name + "'",
ret->source()); ret->source());
return false; return false;
} }
@ -3598,10 +3584,10 @@ bool Resolver::Return(ast::ReturnStatement* ret) {
bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) { bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
auto* cond_type = TypeOf(s->condition())->UnwrapRef(); auto* cond_type = TypeOf(s->condition())->UnwrapRef();
if (!cond_type->is_integer_scalar()) { if (!cond_type->is_integer_scalar()) {
AddError("v-0025", AddError(
"switch statement selector expression must be of a " "switch statement selector expression must be of a "
"scalar integer type", "scalar integer type",
s->condition()->source()); s->condition()->source());
return false; return false;
} }
@ -3612,8 +3598,7 @@ bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
if (case_stmt->IsDefault()) { if (case_stmt->IsDefault()) {
if (has_default) { if (has_default) {
// More than one default clause // More than one default clause
AddError("v-0008", AddError("switch statement must have exactly one default clause",
"switch statement must have exactly one default clause",
case_stmt->source()); case_stmt->source());
return false; return false;
} }
@ -3622,20 +3607,20 @@ bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
for (auto* selector : case_stmt->selectors()) { for (auto* selector : case_stmt->selectors()) {
if (cond_type != TypeOf(selector)) { if (cond_type != TypeOf(selector)) {
AddError("v-0026", AddError(
"the case selector values must have the same " "the case selector values must have the same "
"type as the selector expression.", "type as the selector expression.",
case_stmt->source()); case_stmt->source());
return false; return false;
} }
auto v = selector->value_as_u32(); auto v = selector->value_as_u32();
if (selector_set.find(v) != selector_set.end()) { if (selector_set.find(v) != selector_set.end()) {
AddError("v-0027", AddError(
"a literal value must not appear more than once in " "a literal value must not appear more than once in "
"the case selectors for a switch statement: '" + "the case selectors for a switch statement: '" +
builder_->str(selector) + "'", builder_->str(selector) + "'",
case_stmt->source()); case_stmt->source());
return false; return false;
} }
selector_set.emplace(v); selector_set.emplace(v);
@ -3652,10 +3637,10 @@ bool Resolver::ValidateSwitch(const ast::SwitchStatement* s) {
auto* last_clause = s->body().back()->As<ast::CaseStatement>(); auto* last_clause = s->body().back()->As<ast::CaseStatement>();
auto* last_stmt = last_clause->body()->last(); auto* last_stmt = last_clause->body()->last();
if (last_stmt && last_stmt->Is<ast::FallthroughStatement>()) { if (last_stmt && last_stmt->Is<ast::FallthroughStatement>()) {
AddError("v-0028", AddError(
"a fallthrough statement must not appear as " "a fallthrough statement must not appear as "
"the last statement in last clause of a switch", "the last statement in last clause of a switch",
last_stmt->source()); last_stmt->source());
return false; return false;
} }
} }
@ -3875,12 +3860,6 @@ void Resolver::Mark(const ast::Node* node) {
<< "Pointer: " << node; << "Pointer: " << node;
} }
void Resolver::AddError(const char* code,
const std::string& msg,
const Source& source) const {
diagnostics_.add_error(diag::System::Resolver, code, msg, source);
}
void Resolver::AddError(const std::string& msg, const Source& source) const { void Resolver::AddError(const std::string& msg, const Source& source) const {
diagnostics_.add_error(diag::System::Resolver, msg, source); diagnostics_.add_error(diag::System::Resolver, msg, source);
} }

View File

@ -411,12 +411,6 @@ class Resolver {
/// @param node the AST node. /// @param node the AST node.
void Mark(const ast::Node* node); void Mark(const ast::Node* node);
/// Adds the given error message to the diagnostics
/// [DEPRECATED] Remove all codes
void AddError(const char* code,
const std::string& msg,
const Source& source) const;
/// Adds the given error message to the diagnostics /// Adds the given error message to the diagnostics
void AddError(const std::string& msg, const Source& source) const; void AddError(const std::string& msg, const Source& source) const;

View File

@ -31,7 +31,7 @@ TEST_F(ResolverStorageClassValidationTest, GlobalVariableNoStorageClass_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0022: global variables must have a storage class"); "12:34 error: global variables must have a storage class");
} }
TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) { TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) {

View File

@ -100,8 +100,7 @@ TEST_F(ResolverTypeValidationTest, GlobalConstantWithStorageClass_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-global01: global constants shouldn't have a storage " "12:34 error: global constants shouldn't have a storage class");
"class");
} }
TEST_F(ResolverTypeValidationTest, GlobalConstNoStorageClass_Pass) { TEST_F(ResolverTypeValidationTest, GlobalConstNoStorageClass_Pass) {
@ -216,10 +215,9 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayInFunction_Fail) {
}); });
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: runtime arrays may only appear as the last member of "
"12:34 error v-0015: runtime arrays may only appear as the last member " "a struct");
"of a struct");
} }
TEST_F(ResolverTypeValidationTest, RuntimeArrayIsLast_Pass) { TEST_F(ResolverTypeValidationTest, RuntimeArrayIsLast_Pass) {
@ -256,8 +254,8 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayIsLastNoBlock_Fail) {
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0015: a struct containing a runtime-sized array " "12:34 error: a struct containing a runtime-sized array requires "
"requires the [[block]] attribute: 'Foo'"); "the [[block]] attribute: 'Foo'");
} }
TEST_F(ResolverTypeValidationTest, RuntimeArrayIsNotLast_Fail) { TEST_F(ResolverTypeValidationTest, RuntimeArrayIsNotLast_Fail) {
@ -279,7 +277,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayIsNotLast_Fail) {
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(12:34 error v-0015: runtime arrays may only appear as the last member of a struct)"); R"(12:34 error: runtime arrays may only appear as the last member of a struct)");
} }
TEST_F(ResolverTypeValidationTest, RuntimeArrayAsGlobalVariable) { TEST_F(ResolverTypeValidationTest, RuntimeArrayAsGlobalVariable) {
@ -289,7 +287,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsGlobalVariable) {
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error v-0015: runtime arrays may only appear as the last member of a struct)"); R"(56:78 error: runtime arrays may only appear as the last member of a struct)");
} }
TEST_F(ResolverTypeValidationTest, RuntimeArrayAsLocalVariable) { TEST_F(ResolverTypeValidationTest, RuntimeArrayAsLocalVariable) {
@ -300,7 +298,7 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsLocalVariable) {
EXPECT_EQ( EXPECT_EQ(
r()->error(), r()->error(),
R"(56:78 error v-0015: runtime arrays may only appear as the last member of a struct)"); R"(56:78 error: runtime arrays may only appear as the last member of a struct)");
} }
TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) { TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
@ -324,10 +322,9 @@ TEST_F(ResolverTypeValidationTest, RuntimeArrayAsParameter_Fail) {
}); });
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: runtime arrays may only appear as the last member of "
"12:34 error v-0015: runtime arrays may only appear as the last member " "a struct");
"of a struct");
} }
TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsNotLast_Fail) { TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsNotLast_Fail) {
@ -349,10 +346,9 @@ TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsNotLast_Fail) {
WrapInFunction(); WrapInFunction();
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ( EXPECT_EQ(r()->error(),
r()->error(), "12:34 error: runtime arrays may only appear as the last member of "
"12:34 error v-0015: runtime arrays may only appear as the last member " "a struct");
"of a struct");
} }
TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsLast_Pass) { TEST_F(ResolverTypeValidationTest, AliasRuntimeArrayIsLast_Pass) {

View File

@ -213,7 +213,7 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariable_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: v-0006: identifier must be declared before use: b"); "12:34 error: identifier must be declared before use: b");
} }
TEST_F(ResolverValidationTest, UsingUndefinedVariableInBlockStatement_Fail) { TEST_F(ResolverValidationTest, UsingUndefinedVariableInBlockStatement_Fail) {
@ -229,7 +229,7 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableInBlockStatement_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: v-0006: identifier must be declared before use: b"); "12:34 error: identifier must be declared before use: b");
} }
TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariableAfter_Fail) { TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariableAfter_Fail) {
@ -251,8 +251,7 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariableAfter_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: v-0006: identifier must be declared before use: " "12:34 error: identifier must be declared before use: global_var");
"global_var");
} }
TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariable_Pass) { TEST_F(ResolverValidationTest, UsingUndefinedVariableGlobalVariable_Pass) {
@ -295,7 +294,7 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableInnerScope_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: v-0006: identifier must be declared before use: a"); "12:34 error: identifier must be declared before use: a");
} }
TEST_F(ResolverValidationTest, UsingUndefinedVariableOuterScope_Pass) { TEST_F(ResolverValidationTest, UsingUndefinedVariableOuterScope_Pass) {
@ -338,7 +337,7 @@ TEST_F(ResolverValidationTest, UsingUndefinedVariableDifferentScope_Fail) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error: v-0006: identifier must be declared before use: a"); "12:34 error: identifier must be declared before use: a");
} }
TEST_F(ResolverValidationTest, StorageClass_FunctionVariableWorkgroupClass) { TEST_F(ResolverValidationTest, StorageClass_FunctionVariableWorkgroupClass) {

View File

@ -124,7 +124,7 @@ TEST_F(ResolverVarLetValidationTest, LocalVarRedeclared) {
WrapInFunction(v1, v2); WrapInFunction(v1, v2);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'v'"); EXPECT_EQ(r()->error(), "12:34 error: redeclared identifier 'v'");
} }
TEST_F(ResolverVarLetValidationTest, LocalLetRedeclared) { TEST_F(ResolverVarLetValidationTest, LocalLetRedeclared) {
@ -135,7 +135,7 @@ TEST_F(ResolverVarLetValidationTest, LocalLetRedeclared) {
WrapInFunction(l1, l2); WrapInFunction(l1, l2);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'l'"); EXPECT_EQ(r()->error(), "12:34 error: redeclared identifier 'l'");
} }
TEST_F(ResolverVarLetValidationTest, GlobalVarRedeclared) { TEST_F(ResolverVarLetValidationTest, GlobalVarRedeclared) {
@ -146,7 +146,7 @@ TEST_F(ResolverVarLetValidationTest, GlobalVarRedeclared) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0011: redeclared global identifier 'v'"); "12:34 error: redeclared global identifier 'v'");
} }
TEST_F(ResolverVarLetValidationTest, GlobalLetRedeclared) { TEST_F(ResolverVarLetValidationTest, GlobalLetRedeclared) {
@ -157,7 +157,7 @@ TEST_F(ResolverVarLetValidationTest, GlobalLetRedeclared) {
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), EXPECT_EQ(r()->error(),
"12:34 error v-0011: redeclared global identifier 'l'"); "12:34 error: redeclared global identifier 'l'");
} }
TEST_F(ResolverVarLetValidationTest, GlobalVarRedeclaredAsLocal) { TEST_F(ResolverVarLetValidationTest, GlobalVarRedeclaredAsLocal) {
@ -173,7 +173,7 @@ TEST_F(ResolverVarLetValidationTest, GlobalVarRedeclaredAsLocal) {
Expr(2.0f))); Expr(2.0f)));
EXPECT_FALSE(r()->Resolve()) << r()->error(); EXPECT_FALSE(r()->Resolve()) << r()->error();
EXPECT_EQ(r()->error(), "12:34 error v-0013: redeclared identifier 'v'"); EXPECT_EQ(r()->error(), "12:34 error: redeclared identifier 'v'");
} }
TEST_F(ResolverVarLetValidationTest, VarRedeclaredInInnerBlock) { TEST_F(ResolverVarLetValidationTest, VarRedeclaredInInnerBlock) {
@ -190,7 +190,7 @@ TEST_F(ResolverVarLetValidationTest, VarRedeclaredInInnerBlock) {
WrapInFunction(outer_body); WrapInFunction(outer_body);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'v'"); EXPECT_EQ(r()->error(), "12:34 error: redeclared identifier 'v'");
} }
TEST_F(ResolverVarLetValidationTest, VarRedeclaredInIfBlock) { TEST_F(ResolverVarLetValidationTest, VarRedeclaredInIfBlock) {
@ -213,7 +213,7 @@ TEST_F(ResolverVarLetValidationTest, VarRedeclaredInIfBlock) {
WrapInFunction(outer_body); WrapInFunction(outer_body);
EXPECT_FALSE(r()->Resolve()); EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error v-0014: redeclared identifier 'v'"); EXPECT_EQ(r()->error(), "12:34 error: redeclared identifier 'v'");
} }
TEST_F(ResolverVarLetValidationTest, InferredPtrStorageAccessMismatch) { TEST_F(ResolverVarLetValidationTest, InferredPtrStorageAccessMismatch) {

33
tools/check-spec-examples Executable file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env bash
# Copyright 2021 The Tint Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -e # Fail on any error.
if [ ! -x "$(which go)" ] ; then
echo "error: go needs to be on \$PATH to use $0"
exit 1
fi
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd )"
ROOT_DIR="$( cd "${SCRIPT_DIR}/.." >/dev/null 2>&1 && pwd )"
BINARY="${SCRIPT_DIR}/bin/check-spec-examples"
# Rebuild the binary.
# Note, go caches build artifacts, so this is quick for repeat calls
pushd "${SCRIPT_DIR}/src/cmd/check-spec-examples" > /dev/null
go build -o "${BINARY}" main.go
popd > /dev/null
"${BINARY}" "$@"

View File

@ -42,7 +42,7 @@ import (
const ( const (
toolName = "check-spec-examples" toolName = "check-spec-examples"
defaultSpecPath = "https://gpuweb.github.io/gpuweb/wgsl.html" defaultSpecPath = "https://gpuweb.github.io/gpuweb/wgsl/"
) )
var ( var (
@ -152,6 +152,10 @@ func run() error {
return err return err
} }
if len(examples) == 0 {
return fmt.Errorf("no examples found")
}
// Create a temporary directory to hold the examples as separate files // Create a temporary directory to hold the examples as separate files
tmpDir, err := ioutil.TempDir("", "wgsl-spec-examples") tmpDir, err := ioutil.TempDir("", "wgsl-spec-examples")
if err != nil { if err != nil {
@ -193,9 +197,8 @@ type example struct {
// tryCompile attempts to compile the example e in the directory wd, using the // tryCompile attempts to compile the example e in the directory wd, using the
// compiler at the given path. If the example is annotated with 'function-scope' // compiler at the given path. If the example is annotated with 'function-scope'
// then the code is wrapped with a basic vertex-stage-entry function. // then the code is wrapped with a basic vertex-stage-entry function.
// If the first compile fails with an error message containing 'error v-0003', // If the first compile fails then a dummy vertex-state-entry function is
// then a dummy vertex-state-entry function is appended to the source, and // appended to the source, and another attempt to compile the shader is made.
// another attempt to compile the shader is made.
func tryCompile(compiler, wd string, e example) error { func tryCompile(compiler, wd string, e example) error {
code := e.code code := e.code
if e.functionScope { if e.functionScope {
@ -209,9 +212,7 @@ func tryCompile(compiler, wd string, e example) error {
return nil return nil
} }
if !addedStubFunction && strings.Contains(err.Error(), "error v-0003") { if !addedStubFunction {
// error v-0003: At least one of vertex, fragment or compute shader
// must be present. Add a stub entry point to satisfy the compiler.
code += "\n[[stage(vertex)]] fn main() {}\n" code += "\n[[stage(vertex)]] fn main() {}\n"
addedStubFunction = true addedStubFunction = true
continue continue

View File

@ -5,4 +5,5 @@ go 1.16
require ( require (
github.com/fatih/color v1.10.0 github.com/fatih/color v1.10.0
github.com/sergi/go-diff v1.2.0 github.com/sergi/go-diff v1.2.0
golang.org/x/net v0.0.0-20210614182718-04defd469f4e
) )

View File

@ -17,9 +17,16 @@ github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNX
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae h1:/WDfKMnPU+m5M4xB+6x4kaepxRw6jWvR5iDRdvjHgy8=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=