validation: Reject var<function> at module-scope

Fixed: tint:1368
Change-Id: I15fd0d2cbd9600500213e3140e9ac4500d179eb2
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/76160
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/resolver/resolver_validation.cc b/src/resolver/resolver_validation.cc
index a457ec3..5a375aa 100644
--- a/src/resolver/resolver_validation.cc
+++ b/src/resolver/resolver_validation.cc
@@ -493,6 +493,14 @@
     }
   }
 
+  if (var->StorageClass() == ast::StorageClass::kFunction) {
+    AddError(
+        "variables declared at module scope must not be in the function "
+        "storage class",
+        decl->source);
+    return false;
+  }
+
   auto binding_point = decl->BindingPoint();
   switch (var->StorageClass()) {
     case ast::StorageClass::kUniform:
diff --git a/src/resolver/storage_class_validation_test.cc b/src/resolver/storage_class_validation_test.cc
index 9391edc..4c6799f 100644
--- a/src/resolver/storage_class_validation_test.cc
+++ b/src/resolver/storage_class_validation_test.cc
@@ -34,6 +34,17 @@
             "12:34 error: global variables must have a storage class");
 }
 
+TEST_F(ResolverStorageClassValidationTest,
+       GlobalVariableFunctionStorageClass_Fail) {
+  // var<function> g : f32;
+  Global(Source{{12, 34}}, "g", ty.f32(), ast::StorageClass::kFunction);
+
+  EXPECT_FALSE(r()->Resolve());
+  EXPECT_EQ(r()->error(),
+            "12:34 error: variables declared at module scope must not be in "
+            "the function storage class");
+}
+
 TEST_F(ResolverStorageClassValidationTest, StorageBufferBool) {
   // var<storage> g : i32;
   Global(Source{{56, 78}}, "g", ty.i32(), ast::StorageClass::kStorage,