[tint] Resolve requires directives

Resolving is no-op for now, but will eventually check that all
features are allowed by the calling environment.

Bug: tint:2088
Change-Id: Ic2e648a60b33102ffed8edfde706ed49a9a8dd63
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/158626
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/lang/wgsl/resolver/BUILD.bazel b/src/tint/lang/wgsl/resolver/BUILD.bazel
index 719635c..578ead6 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.bazel
+++ b/src/tint/lang/wgsl/resolver/BUILD.bazel
@@ -123,6 +123,7 @@
     "inferred_type_test.cc",
     "is_host_shareable_test.cc",
     "is_storeable_test.cc",
+    "language_features_test.cc",
     "load_test.cc",
     "materialize_test.cc",
     "override_test.cc",
diff --git a/src/tint/lang/wgsl/resolver/BUILD.cmake b/src/tint/lang/wgsl/resolver/BUILD.cmake
index 75280ee..63026bf 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.cmake
+++ b/src/tint/lang/wgsl/resolver/BUILD.cmake
@@ -121,6 +121,7 @@
   lang/wgsl/resolver/inferred_type_test.cc
   lang/wgsl/resolver/is_host_shareable_test.cc
   lang/wgsl/resolver/is_storeable_test.cc
+  lang/wgsl/resolver/language_features_test.cc
   lang/wgsl/resolver/load_test.cc
   lang/wgsl/resolver/materialize_test.cc
   lang/wgsl/resolver/override_test.cc
diff --git a/src/tint/lang/wgsl/resolver/BUILD.gn b/src/tint/lang/wgsl/resolver/BUILD.gn
index b4b367f..86dc084 100644
--- a/src/tint/lang/wgsl/resolver/BUILD.gn
+++ b/src/tint/lang/wgsl/resolver/BUILD.gn
@@ -123,6 +123,7 @@
       "inferred_type_test.cc",
       "is_host_shareable_test.cc",
       "is_storeable_test.cc",
+      "language_features_test.cc",
       "load_test.cc",
       "materialize_test.cc",
       "override_test.cc",
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.cc b/src/tint/lang/wgsl/resolver/dependency_graph.cc
index a261629..dda9251 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.cc
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.cc
@@ -201,6 +201,9 @@
             [&](const ast::Enable*) {
                 // Enable directives do not affect the dependency graph.
             },
+            [&](const ast::Requires*) {
+                // Requires directives do not affect the dependency graph.
+            },
             [&](const ast::ConstAssert* assertion) {
                 TraverseExpression(assertion->condition);
             },  //
@@ -611,6 +614,7 @@
             [&](const ast::Variable* var) { return var->name->symbol; },
             [&](const ast::DiagnosticDirective*) { return Symbol(); },
             [&](const ast::Enable*) { return Symbol(); },
+            [&](const ast::Requires*) { return Symbol(); },
             [&](const ast::ConstAssert*) { return Symbol(); },  //
             TINT_ICE_ON_NO_MATCH);
     }
@@ -714,13 +718,13 @@
 
         // Make sure all directives go before any other global declarations.
         for (auto* global : declaration_order_) {
-            if (global->node->IsAnyOf<ast::DiagnosticDirective, ast::Enable>()) {
+            if (global->node->IsAnyOf<ast::DiagnosticDirective, ast::Enable, ast::Requires>()) {
                 sorted_.Add(global->node);
             }
         }
 
         for (auto* global : declaration_order_) {
-            if (global->node->IsAnyOf<ast::DiagnosticDirective, ast::Enable>()) {
+            if (global->node->IsAnyOf<ast::DiagnosticDirective, ast::Enable, ast::Requires>()) {
                 // Skip directives here, as they are already added.
                 continue;
             }
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph_test.cc b/src/tint/lang/wgsl/resolver/dependency_graph_test.cc
index 160df59..8a1f136 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph_test.cc
+++ b/src/tint/lang/wgsl/resolver/dependency_graph_test.cc
@@ -1122,9 +1122,12 @@
     auto* enable = Enable(wgsl::Extension::kF16);
     auto* var_2 = GlobalVar("SYMBOL2", ty.f32());
     auto* diagnostic = DiagnosticDirective(wgsl::DiagnosticSeverity::kWarning, "foo");
+    auto* var_3 = GlobalVar("SYMBOL3", ty.u32());
+    auto* req = Require(wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures);
 
-    EXPECT_THAT(AST().GlobalDeclarations(), ElementsAre(var_1, enable, var_2, diagnostic));
-    EXPECT_THAT(Build().ordered_globals, ElementsAre(enable, diagnostic, var_1, var_2));
+    EXPECT_THAT(AST().GlobalDeclarations(),
+                ElementsAre(var_1, enable, var_2, diagnostic, var_3, req));
+    EXPECT_THAT(Build().ordered_globals, ElementsAre(enable, diagnostic, req, var_1, var_2, var_3));
 }
 }  // namespace ordered_globals
 
diff --git a/src/tint/lang/wgsl/resolver/language_features_test.cc b/src/tint/lang/wgsl/resolver/language_features_test.cc
new file mode 100644
index 0000000..47a1990
--- /dev/null
+++ b/src/tint/lang/wgsl/resolver/language_features_test.cc
@@ -0,0 +1,48 @@
+// Copyright 2023 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/wgsl/resolver/resolver.h"
+
+#include "gmock/gmock.h"
+#include "src/tint/lang/core/fluent_types.h"
+#include "src/tint/lang/wgsl/resolver/resolver_helper_test.h"
+
+using namespace tint::core::number_suffixes;  // NOLINT
+using namespace tint::core::fluent_types;     // NOLINT
+
+namespace tint::resolver {
+namespace {
+
+using ResolverLanguageFeaturesTest = ResolverTest;
+
+TEST_F(ResolverLanguageFeaturesTest, Requires) {
+    Require(wgsl::LanguageFeature::kReadonlyAndReadwriteStorageTextures);
+    ASSERT_TRUE(r()->Resolve()) << r()->error();
+}
+
+}  // namespace
+}  // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 8ea7220..33b4e81 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -189,6 +189,7 @@
                     return DiagnosticControl(d->control);
                 },
                 [&](const ast::Enable* e) { return Enable(e); },
+                [&](const ast::Requires* r) { return Requires(r); },
                 [&](const ast::TypeDecl* td) { return TypeDecl(td); },
                 [&](const ast::Function* func) { return Function(func); },
                 [&](const ast::Variable* var) { return GlobalVariable(var); },
@@ -3958,6 +3959,11 @@
     return true;
 }
 
+bool Resolver::Requires(const ast::Requires*) {
+    // TODO(crbug.com/tint/2081): Check that all features are allowed.
+    return true;
+}
+
 core::type::Type* Resolver::TypeDecl(const ast::TypeDecl* named_type) {
     Mark(named_type->name);
 
diff --git a/src/tint/lang/wgsl/resolver/resolver.h b/src/tint/lang/wgsl/resolver/resolver.h
index fa353d4..887b117 100644
--- a/src/tint/lang/wgsl/resolver/resolver.h
+++ b/src/tint/lang/wgsl/resolver/resolver.h
@@ -466,9 +466,13 @@
     bool DiagnosticControl(const ast::DiagnosticControl& control);
 
     /// @param enable the enable declaration
-    /// @returns the resolved extension
+    /// @returns true on success, false on failure
     bool Enable(const ast::Enable* enable);
 
+    /// @param req the requires declaration
+    /// @returns true on success, false on failure
+    bool Requires(const ast::Requires* req);
+
     /// @param named_type the named type to resolve
     /// @returns the resolved semantic type
     core::type::Type* TypeDecl(const ast::TypeDecl* named_type);