diff --git a/src/validator_impl.cc b/src/validator_impl.cc index 48fd7d26e4..968b2c6b4a 100644 --- a/src/validator_impl.cc +++ b/src/validator_impl.cc @@ -35,13 +35,8 @@ bool ValidatorImpl::Validate(const ast::Module* module) { return false; } function_stack_.push_scope(); - for (const auto& var : module->global_variables()) { - if (variable_stack_.has(var->name())) { - set_error(var->source(), - "v-0011: redeclared global identifier '" + var->name() + "'"); - return false; - } - variable_stack_.set_global(var->name(), var.get()); + if (!ValidateGlobalVariables(module->global_variables())) { + return false; } if (!CheckImports(module)) { return false; @@ -59,6 +54,24 @@ bool ValidatorImpl::Validate(const ast::Module* module) { return true; } +bool ValidatorImpl::ValidateGlobalVariables( + const ast::VariableList& global_vars) { + for (const auto& var : global_vars) { + if (variable_stack_.has(var->name())) { + set_error(var->source(), + "v-0011: redeclared global identifier '" + var->name() + "'"); + return false; + } + if (var->storage_class() == ast::StorageClass::kNone) { + set_error(var->source(), + "v-0022: global variables must have a storage class"); + return false; + } + variable_stack_.set_global(var->name(), var.get()); + } + return true; +} + bool ValidatorImpl::ValidateEntryPoints(const ast::EntryPointList& eps) { for (const auto& ep : eps) { auto* ep_ptr = ep.get(); diff --git a/src/validator_impl.h b/src/validator_impl.h index 3e38060eb4..5f085fdde3 100644 --- a/src/validator_impl.h +++ b/src/validator_impl.h @@ -53,6 +53,10 @@ class ValidatorImpl { /// @param src the source causing the error /// @param msg the error message void set_error(const Source& src, const std::string& msg); + /// Validate global variables + /// @param global_vars list of global variables to check + /// @returns true if the validation was successful + bool ValidateGlobalVariables(const ast::VariableList& global_vars); /// Validates Functions /// @param funcs the functions to check /// @returns true if the validation was successful diff --git a/src/validator_test.cc b/src/validator_test.cc index 3207ae7b33..6dc58c269d 100644 --- a/src/validator_test.cc +++ b/src/validator_test.cc @@ -257,6 +257,30 @@ TEST_F(ValidatorTest, AssignIncompatibleTypesInBlockStatement_Fail) { "12:34: v-000x: invalid assignment of '__i32' to '__f32'"); } +TEST_F(ValidatorTest, GlobalVariableWithStorageClass_Pass) { + // var gloabl_var: f32; + ast::type::F32Type f32; + auto global_var = std::make_unique( + Source{12, 34}, "global_var", ast::StorageClass::kInput, &f32); + mod()->AddGlobalVariable(std::move(global_var)); + EXPECT_TRUE(td()->Determine()) << td()->error(); + tint::ValidatorImpl v; + EXPECT_TRUE(v.Validate(mod())) << v.error(); +} + +TEST_F(ValidatorTest, GlobalVariableNoStorageClass_Fail) { + // var gloabl_var: f32; + ast::type::F32Type f32; + auto global_var = std::make_unique( + Source{12, 34}, "global_var", ast::StorageClass::kNone, &f32); + mod()->AddGlobalVariable(std::move(global_var)); + EXPECT_TRUE(td()->Determine()) << td()->error(); + tint::ValidatorImpl v; + EXPECT_FALSE(v.Validate(mod())); + EXPECT_EQ(v.error(), + "12:34: v-0022: global variables must have a storage class"); +} + TEST_F(ValidatorTest, UsingUndefinedVariableGlobalVariable_Fail) { // var global_var: f32 = 2.1; // fn my_func() -> f32 {