tint/ast: Generate interpolate_attribute.[h|cc]

Emits all the enum info from the single-source-of-truth `intrinsics.def` file

Change-Id: Ie9deba9e64927945133027cf243777944119ea41
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105327
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/ast/builtin_value.h b/src/tint/ast/builtin_value.h
index eb45b39..f7dd660 100644
--- a/src/tint/ast/builtin_value.h
+++ b/src/tint/ast/builtin_value.h
@@ -27,7 +27,7 @@
 
 namespace tint::ast {
 
-/// Storage class of a given pointer.
+/// Builtin value defined with `@builtin(<name>)`.
 enum class BuiltinValue {
     kInvalid,
     kFragDepth,
diff --git a/src/tint/ast/builtin_value.h.tmpl b/src/tint/ast/builtin_value.h.tmpl
index 1985305..ea63d56 100644
--- a/src/tint/ast/builtin_value.h.tmpl
+++ b/src/tint/ast/builtin_value.h.tmpl
@@ -18,7 +18,7 @@
 
 namespace tint::ast {
 
-/// Storage class of a given pointer.
+/// Builtin value defined with `@builtin(<name>)`.
 {{ Eval "DeclareEnum" $enum}}
 
 }  // namespace tint::ast
diff --git a/src/tint/ast/interpolate_attribute.cc b/src/tint/ast/interpolate_attribute.cc
index 29e3bfe..7c89ee1 100644
--- a/src/tint/ast/interpolate_attribute.cc
+++ b/src/tint/ast/interpolate_attribute.cc
@@ -12,6 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   src/tint/ast/interpolate_attribute.cc.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
 #include "src/tint/ast/interpolate_attribute.h"
 
 #include <string>
@@ -41,44 +49,64 @@
     return ctx->dst->create<InterpolateAttribute>(src, type, sampling);
 }
 
-std::ostream& operator<<(std::ostream& out, InterpolationType type) {
-    switch (type) {
-        case InterpolationType::kPerspective: {
-            out << "perspective";
-            break;
-        }
-        case InterpolationType::kLinear: {
-            out << "linear";
-            break;
-        }
-        case InterpolationType::kFlat: {
-            out << "flat";
-            break;
-        }
+/// ParseInterpolationType parses a InterpolationType from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or InterpolationType::kInvalid if the string could not be parsed.
+InterpolationType ParseInterpolationType(std::string_view str) {
+    if (str == "flat") {
+        return InterpolationType::kFlat;
     }
-    return out;
+    if (str == "linear") {
+        return InterpolationType::kLinear;
+    }
+    if (str == "perspective") {
+        return InterpolationType::kPerspective;
+    }
+    return InterpolationType::kInvalid;
 }
 
-std::ostream& operator<<(std::ostream& out, InterpolationSampling sampling) {
-    switch (sampling) {
-        case InterpolationSampling::kNone: {
-            out << "none";
-            break;
-        }
-        case InterpolationSampling::kCenter: {
-            out << "center";
-            break;
-        }
-        case InterpolationSampling::kCentroid: {
-            out << "centroid";
-            break;
-        }
-        case InterpolationSampling::kSample: {
-            out << "sample";
-            break;
-        }
+std::ostream& operator<<(std::ostream& out, InterpolationType value) {
+    switch (value) {
+        case InterpolationType::kInvalid:
+            return out << "invalid";
+        case InterpolationType::kFlat:
+            return out << "flat";
+        case InterpolationType::kLinear:
+            return out << "linear";
+        case InterpolationType::kPerspective:
+            return out << "perspective";
     }
-    return out;
+    return out << "<unknown>";
+}
+
+/// ParseInterpolationSampling parses a InterpolationSampling from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or InterpolationSampling::kInvalid if the string could not be parsed.
+InterpolationSampling ParseInterpolationSampling(std::string_view str) {
+    if (str == "center") {
+        return InterpolationSampling::kCenter;
+    }
+    if (str == "centroid") {
+        return InterpolationSampling::kCentroid;
+    }
+    if (str == "sample") {
+        return InterpolationSampling::kSample;
+    }
+    return InterpolationSampling::kInvalid;
+}
+
+std::ostream& operator<<(std::ostream& out, InterpolationSampling value) {
+    switch (value) {
+        case InterpolationSampling::kInvalid:
+            return out << "invalid";
+        case InterpolationSampling::kCenter:
+            return out << "center";
+        case InterpolationSampling::kCentroid:
+            return out << "centroid";
+        case InterpolationSampling::kSample:
+            return out << "sample";
+    }
+    return out << "<unknown>";
 }
 
 }  // namespace tint::ast
diff --git a/src/tint/ast/interpolate_attribute.cc.tmpl b/src/tint/ast/interpolate_attribute.cc.tmpl
new file mode 100644
index 0000000..b6f0b35
--- /dev/null
+++ b/src/tint/ast/interpolate_attribute.cc.tmpl
@@ -0,0 +1,50 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/src/cmd/gen to generate builtin_value.cc
+
+See:
+* tools/src/cmd/gen for structures used by this template
+* https://golang.org/pkg/text/template/ for documentation on the template syntax
+--------------------------------------------------------------------------------
+*/ -}}
+
+{{- Import "src/tint/templates/enums.tmpl.inc" -}}
+
+#include "src/tint/ast/interpolate_attribute.h"
+
+#include <string>
+
+#include "src/tint/program_builder.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ast::InterpolateAttribute);
+
+namespace tint::ast {
+
+InterpolateAttribute::InterpolateAttribute(ProgramID pid,
+                                           NodeID nid,
+                                           const Source& src,
+                                           InterpolationType ty,
+                                           InterpolationSampling smpl)
+    : Base(pid, nid, src), type(ty), sampling(smpl) {}
+
+InterpolateAttribute::~InterpolateAttribute() = default;
+
+std::string InterpolateAttribute::Name() const {
+    return "interpolate";
+}
+
+const InterpolateAttribute* InterpolateAttribute::Clone(CloneContext* ctx) const {
+    // Clone arguments outside of create() call to have deterministic ordering
+    auto src = ctx->Clone(source);
+    return ctx->dst->create<InterpolateAttribute>(src, type, sampling);
+}
+
+{{ Eval "ParseEnum" (Sem.Enum "interpolation_type")}}
+
+{{ Eval "EnumOStream" (Sem.Enum "interpolation_type")}}
+
+{{ Eval "ParseEnum" (Sem.Enum "interpolation_sampling")}}
+
+{{ Eval "EnumOStream" (Sem.Enum "interpolation_sampling")}}
+
+}  // namespace tint::ast
diff --git a/src/tint/ast/interpolate_attribute.h b/src/tint/ast/interpolate_attribute.h
index 4f9ea9d..c6b4af0 100644
--- a/src/tint/ast/interpolate_attribute.h
+++ b/src/tint/ast/interpolate_attribute.h
@@ -1,4 +1,4 @@
-// Copyright 2021 The Tint Authors.
+// Copyright 2022 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.
@@ -12,6 +12,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+////////////////////////////////////////////////////////////////////////////////
+// File generated by tools/src/cmd/gen
+// using the template:
+//   src/tint/ast/interpolate_attribute.h.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
 #ifndef SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
 #define SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
 
@@ -23,10 +31,52 @@
 namespace tint::ast {
 
 /// The interpolation type.
-enum class InterpolationType { kPerspective, kLinear, kFlat };
+enum class InterpolationType {
+    kInvalid,
+    kFlat,
+    kLinear,
+    kPerspective,
+};
+
+/// @param out the std::ostream to write to
+/// @param value the InterpolationType
+/// @returns `out` so calls can be chained
+std::ostream& operator<<(std::ostream& out, InterpolationType value);
+
+/// ParseInterpolationType parses a InterpolationType from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or InterpolationType::kInvalid if the string could not be parsed.
+InterpolationType ParseInterpolationType(std::string_view str);
+
+constexpr const char* kInterpolationTypeStrings[] = {
+    "flat",
+    "linear",
+    "perspective",
+};
 
 /// The interpolation sampling.
-enum class InterpolationSampling { kNone = -1, kCenter, kCentroid, kSample };
+enum class InterpolationSampling {
+    kInvalid,
+    kCenter,
+    kCentroid,
+    kSample,
+};
+
+/// @param out the std::ostream to write to
+/// @param value the InterpolationSampling
+/// @returns `out` so calls can be chained
+std::ostream& operator<<(std::ostream& out, InterpolationSampling value);
+
+/// ParseInterpolationSampling parses a InterpolationSampling from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or InterpolationSampling::kInvalid if the string could not be parsed.
+InterpolationSampling ParseInterpolationSampling(std::string_view str);
+
+constexpr const char* kInterpolationSamplingStrings[] = {
+    "center",
+    "centroid",
+    "sample",
+};
 
 /// An interpolate attribute
 class InterpolateAttribute final : public Castable<InterpolateAttribute, Attribute> {
@@ -60,16 +110,6 @@
     const InterpolationSampling sampling;
 };
 
-/// @param out the std::ostream to write to
-/// @param type the interpolation type
-/// @return the std::ostream so calls can be chained
-std::ostream& operator<<(std::ostream& out, InterpolationType type);
-
-/// @param out the std::ostream to write to
-/// @param sampling the interpolation sampling
-/// @return the std::ostream so calls can be chained
-std::ostream& operator<<(std::ostream& out, InterpolationSampling sampling);
-
 }  // namespace tint::ast
 
 #endif  // SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
diff --git a/src/tint/ast/interpolate_attribute.h.tmpl b/src/tint/ast/interpolate_attribute.h.tmpl
new file mode 100644
index 0000000..c225cb6
--- /dev/null
+++ b/src/tint/ast/interpolate_attribute.h.tmpl
@@ -0,0 +1,63 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/src/cmd/gen to generate interpolate_attribute.h
+
+See:
+* tools/src/cmd/gen for structures used by this template
+* https://golang.org/pkg/text/template/ for documentation on the template syntax
+--------------------------------------------------------------------------------
+*/ -}}
+
+{{- Import "src/tint/templates/enums.tmpl.inc" -}}
+
+#ifndef SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
+#define SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
+
+#include <ostream>
+#include <string>
+
+#include "src/tint/ast/attribute.h"
+
+namespace tint::ast {
+
+/// The interpolation type.
+{{ Eval "DeclareEnum" (Sem.Enum "interpolation_type") }}
+
+/// The interpolation sampling.
+{{ Eval "DeclareEnum" (Sem.Enum "interpolation_sampling") }}
+
+/// An interpolate attribute
+class InterpolateAttribute final : public Castable<InterpolateAttribute, Attribute> {
+  public:
+    /// Create an interpolate attribute.
+    /// @param pid the identifier of the program that owns this node
+    /// @param nid the unique node identifier
+    /// @param src the source of this node
+    /// @param type the interpolation type
+    /// @param sampling the interpolation sampling
+    InterpolateAttribute(ProgramID pid,
+                         NodeID nid,
+                         const Source& src,
+                         InterpolationType type,
+                         InterpolationSampling sampling);
+    ~InterpolateAttribute() override;
+
+    /// @returns the WGSL name for the attribute
+    std::string Name() const override;
+
+    /// Clones this node and all transitive child nodes using the `CloneContext`
+    /// `ctx`.
+    /// @param ctx the clone context
+    /// @return the newly cloned node
+    const InterpolateAttribute* Clone(CloneContext* ctx) const override;
+
+    /// The interpolation type
+    const InterpolationType type;
+
+    /// The interpolation sampling
+    const InterpolationSampling sampling;
+};
+
+}  // namespace tint::ast
+
+#endif  // SRC_TINT_AST_INTERPOLATE_ATTRIBUTE_H_
diff --git a/src/tint/inspector/entry_point.cc b/src/tint/inspector/entry_point.cc
index 6d3419f..8cbca14 100644
--- a/src/tint/inspector/entry_point.cc
+++ b/src/tint/inspector/entry_point.cc
@@ -35,32 +35,5 @@
 EntryPoint::EntryPoint(EntryPoint&&) = default;
 EntryPoint::~EntryPoint() = default;
 
-InterpolationType ASTToInspectorInterpolationType(ast::InterpolationType ast_type) {
-    switch (ast_type) {
-        case ast::InterpolationType::kPerspective:
-            return InterpolationType::kPerspective;
-        case ast::InterpolationType::kLinear:
-            return InterpolationType::kLinear;
-        case ast::InterpolationType::kFlat:
-            return InterpolationType::kFlat;
-    }
-
-    return InterpolationType::kUnknown;
-}
-
-InterpolationSampling ASTToInspectorInterpolationSampling(ast::InterpolationSampling sampling) {
-    switch (sampling) {
-        case ast::InterpolationSampling::kNone:
-            return InterpolationSampling::kNone;
-        case ast::InterpolationSampling::kCenter:
-            return InterpolationSampling::kCenter;
-        case ast::InterpolationSampling::kCentroid:
-            return InterpolationSampling::kCentroid;
-        case ast::InterpolationSampling::kSample:
-            return InterpolationSampling::kSample;
-    }
-
-    return InterpolationSampling::kUnknown;
-}
 
 }  // namespace tint::inspector
diff --git a/src/tint/inspector/entry_point.h b/src/tint/inspector/entry_point.h
index 7038ecc..4a4706b 100644
--- a/src/tint/inspector/entry_point.h
+++ b/src/tint/inspector/entry_point.h
@@ -84,17 +84,6 @@
     InterpolationSampling interpolation_sampling = InterpolationSampling::kUnknown;
 };
 
-/// Convert from internal ast::InterpolationType to public ::InterpolationType.
-/// @param ast_type internal value to convert from
-/// @returns the publicly visible equivalent
-InterpolationType ASTToInspectorInterpolationType(ast::InterpolationType ast_type);
-
-/// Convert from internal ast::InterpolationSampling to public
-/// ::InterpolationSampling
-/// @param sampling internal value to convert from
-/// @returns the publicly visible equivalent
-InterpolationSampling ASTToInspectorInterpolationSampling(ast::InterpolationSampling sampling);
-
 /// Reflection data about an override variable referenced by an entry point
 struct Override {
     /// Name of the override
diff --git a/src/tint/inspector/inspector.cc b/src/tint/inspector/inspector.cc
index 48bae48..ddb5b11 100644
--- a/src/tint/inspector/inspector.cc
+++ b/src/tint/inspector/inspector.cc
@@ -117,14 +117,45 @@
         return {InterpolationType::kPerspective, InterpolationSampling::kCenter};
     }
 
-    auto interpolation_type = interpolation_attribute->type;
-    auto sampling = interpolation_attribute->sampling;
-    if (interpolation_type != ast::InterpolationType::kFlat &&
-        sampling == ast::InterpolationSampling::kNone) {
-        sampling = ast::InterpolationSampling::kCenter;
+    auto ast_interpolation_type = interpolation_attribute->type;
+    auto ast_sampling_type = interpolation_attribute->sampling;
+    if (ast_interpolation_type != ast::InterpolationType::kFlat &&
+        ast_sampling_type == ast::InterpolationSampling::kInvalid) {
+        ast_sampling_type = ast::InterpolationSampling::kCenter;
     }
-    return {ASTToInspectorInterpolationType(interpolation_type),
-            ASTToInspectorInterpolationSampling(sampling)};
+
+    auto interpolation_type = InterpolationType::kUnknown;
+    switch (ast_interpolation_type) {
+        case ast::InterpolationType::kPerspective:
+            interpolation_type = InterpolationType::kPerspective;
+            break;
+        case ast::InterpolationType::kLinear:
+            interpolation_type = InterpolationType::kLinear;
+            break;
+        case ast::InterpolationType::kFlat:
+            interpolation_type = InterpolationType::kFlat;
+            break;
+        case ast::InterpolationType::kInvalid:
+            break;
+    }
+
+    auto sampling_type = InterpolationSampling::kUnknown;
+    switch (ast_sampling_type) {
+        case ast::InterpolationSampling::kInvalid:
+            sampling_type = InterpolationSampling::kNone;
+            break;
+        case ast::InterpolationSampling::kCenter:
+            sampling_type = InterpolationSampling::kCenter;
+            break;
+        case ast::InterpolationSampling::kCentroid:
+            sampling_type = InterpolationSampling::kCentroid;
+            break;
+        case ast::InterpolationSampling::kSample:
+            sampling_type = InterpolationSampling::kSample;
+            break;
+    }
+
+    return {interpolation_type, sampling_type};
 }
 
 }  // namespace
diff --git a/src/tint/inspector/inspector_test.cc b/src/tint/inspector/inspector_test.cc
index 32697bb..7aa017c 100644
--- a/src/tint/inspector/inspector_test.cc
+++ b/src/tint/inspector/inspector_test.cc
@@ -1250,7 +1250,7 @@
             ast::InterpolationType::kPerspective, ast::InterpolationSampling::kSample,
             InterpolationType::kPerspective, InterpolationSampling::kSample},
         InspectorGetEntryPointInterpolateTestParams{
-            ast::InterpolationType::kPerspective, ast::InterpolationSampling::kNone,
+            ast::InterpolationType::kPerspective, ast::InterpolationSampling::kInvalid,
             InterpolationType::kPerspective, InterpolationSampling::kCenter},
         InspectorGetEntryPointInterpolateTestParams{
             ast::InterpolationType::kLinear, ast::InterpolationSampling::kCenter,
@@ -1262,10 +1262,10 @@
             ast::InterpolationType::kLinear, ast::InterpolationSampling::kSample,
             InterpolationType::kLinear, InterpolationSampling::kSample},
         InspectorGetEntryPointInterpolateTestParams{
-            ast::InterpolationType::kLinear, ast::InterpolationSampling::kNone,
+            ast::InterpolationType::kLinear, ast::InterpolationSampling::kInvalid,
             InterpolationType::kLinear, InterpolationSampling::kCenter},
         InspectorGetEntryPointInterpolateTestParams{
-            ast::InterpolationType::kFlat, ast::InterpolationSampling::kNone,
+            ast::InterpolationType::kFlat, ast::InterpolationSampling::kInvalid,
             InterpolationType::kFlat, InterpolationSampling::kNone}));
 
 TEST_F(InspectorGetOverrideDefaultValuesTest, Bool) {
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index f55b18c..28b78ff 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -94,6 +94,20 @@
   rgba32float
 }
 
+// https://www.w3.org/TR/WGSL/#interpolation
+enum interpolation_type {
+  perspective
+  linear
+  flat
+}
+
+// https://www.w3.org/TR/WGSL/#interpolation
+enum interpolation_sampling {
+  center
+  centroid
+  sample
+}
+
 ////////////////////////////////////////////////////////////////////////////////
 // WGSL primitive types                                                       //
 // Types may be decorated with @precedence(N) to prioritize which type        //
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index 066cc36..8add387 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -2909,7 +2909,7 @@
     const ast::InterpolateAttribute* Interpolate(
         const Source& source,
         ast::InterpolationType type,
-        ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone) {
+        ast::InterpolationSampling sampling = ast::InterpolationSampling::kInvalid) {
         return create<ast::InterpolateAttribute>(source, type, sampling);
     }
 
@@ -2919,7 +2919,7 @@
     /// @returns the interpolate attribute pointer
     const ast::InterpolateAttribute* Interpolate(
         ast::InterpolationType type,
-        ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone) {
+        ast::InterpolationSampling sampling = ast::InterpolationSampling::kInvalid) {
         return create<ast::InterpolateAttribute>(source_, type, sampling);
     }
 
diff --git a/src/tint/reader/spirv/parser_impl.cc b/src/tint/reader/spirv/parser_impl.cc
index 5aa68eb..b79c663 100644
--- a/src/tint/reader/spirv/parser_impl.cc
+++ b/src/tint/reader/spirv/parser_impl.cc
@@ -1749,7 +1749,7 @@
                                             AttributeList* attributes) {
     // Vulkan defaults to perspective-correct interpolation.
     ast::InterpolationType type = ast::InterpolationType::kPerspective;
-    ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone;
+    ast::InterpolationSampling sampling = ast::InterpolationSampling::kInvalid;
 
     for (const auto& deco : decorations) {
         TINT_ASSERT(Reader, deco.size() > 0);
@@ -1804,7 +1804,7 @@
 
     // Apply interpolation.
     if (type == ast::InterpolationType::kPerspective &&
-        sampling == ast::InterpolationSampling::kNone) {
+        sampling == ast::InterpolationSampling::kInvalid) {
         // This is the default. Don't add a decoration.
     } else {
         attributes->Push(create<ast::InterpolateAttribute>(type, sampling));
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index 93fbc11..6f7ffac 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -3554,7 +3554,7 @@
                 return Failure::kErrored;
             }
 
-            ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone;
+            ast::InterpolationSampling sampling = ast::InterpolationSampling::kInvalid;
             if (match(Token::Type::kComma)) {
                 if (!peek_is(Token::Type::kParenRight)) {
                     auto sample = expect_interpolation_sample_name();
diff --git a/src/tint/reader/wgsl/parser_impl_variable_attribute_test.cc b/src/tint/reader/wgsl/parser_impl_variable_attribute_test.cc
index 32387a0..de60add 100644
--- a/src/tint/reader/wgsl/parser_impl_variable_attribute_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_variable_attribute_test.cc
@@ -227,7 +227,7 @@
 
     auto* interp = var_attr->As<ast::InterpolateAttribute>();
     EXPECT_EQ(interp->type, ast::InterpolationType::kFlat);
-    EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kNone);
+    EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kInvalid);
 }
 
 TEST_F(ParserImplTest, Attribute_Interpolate_Single_TrailingComma) {
@@ -243,7 +243,7 @@
 
     auto* interp = var_attr->As<ast::InterpolateAttribute>();
     EXPECT_EQ(interp->type, ast::InterpolationType::kFlat);
-    EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kNone);
+    EXPECT_EQ(interp->sampling, ast::InterpolationSampling::kInvalid);
 }
 
 TEST_F(ParserImplTest, Attribute_Interpolate_Single_DoubleTrailingComma) {
diff --git a/src/tint/resolver/attribute_validation_test.cc b/src/tint/resolver/attribute_validation_test.cc
index 796487b..8ef01dd 100644
--- a/src/tint/resolver/attribute_validation_test.cc
+++ b/src/tint/resolver/attribute_validation_test.cc
@@ -1386,16 +1386,16 @@
     ResolverAttributeValidationTest,
     InterpolateParameterTest,
     testing::Values(
-        Params{ast::InterpolationType::kPerspective, ast::InterpolationSampling::kNone, true},
+        Params{ast::InterpolationType::kPerspective, ast::InterpolationSampling::kInvalid, true},
         Params{ast::InterpolationType::kPerspective, ast::InterpolationSampling::kCenter, true},
         Params{ast::InterpolationType::kPerspective, ast::InterpolationSampling::kCentroid, true},
         Params{ast::InterpolationType::kPerspective, ast::InterpolationSampling::kSample, true},
-        Params{ast::InterpolationType::kLinear, ast::InterpolationSampling::kNone, true},
+        Params{ast::InterpolationType::kLinear, ast::InterpolationSampling::kInvalid, true},
         Params{ast::InterpolationType::kLinear, ast::InterpolationSampling::kCenter, true},
         Params{ast::InterpolationType::kLinear, ast::InterpolationSampling::kCentroid, true},
         Params{ast::InterpolationType::kLinear, ast::InterpolationSampling::kSample, true},
         // flat interpolation must not have a sampling type
-        Params{ast::InterpolationType::kFlat, ast::InterpolationSampling::kNone, true},
+        Params{ast::InterpolationType::kFlat, ast::InterpolationSampling::kInvalid, true},
         Params{ast::InterpolationType::kFlat, ast::InterpolationSampling::kCenter, false},
         Params{ast::InterpolationType::kFlat, ast::InterpolationSampling::kCentroid, false},
         Params{ast::InterpolationType::kFlat, ast::InterpolationSampling::kSample, false}));
@@ -1443,7 +1443,7 @@
                    utils::Vector{
                        Builtin(ast::BuiltinValue::kPosition),
                        Interpolate(Source{{12, 34}}, ast::InterpolationType::kFlat,
-                                   ast::InterpolationSampling::kNone),
+                                   ast::InterpolationSampling::kInvalid),
                    }),
          },
          ty.void_(), utils::Empty,
@@ -1467,7 +1467,7 @@
          utils::Vector{
              Builtin(ast::BuiltinValue::kPosition),
              Interpolate(Source{{12, 34}}, ast::InterpolationType::kFlat,
-                         ast::InterpolationSampling::kNone),
+                         ast::InterpolationSampling::kInvalid),
          });
 
     EXPECT_FALSE(r()->Resolve());
@@ -1480,7 +1480,7 @@
               utils::Vector{
                   Member("a", ty.f32(),
                          utils::Vector{Interpolate(Source{{12, 34}}, ast::InterpolationType::kFlat,
-                                                   ast::InterpolationSampling::kNone)}),
+                                                   ast::InterpolationSampling::kInvalid)}),
               });
 
     EXPECT_FALSE(r()->Resolve());
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index 687d17d..d9c798c 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -1026,7 +1026,7 @@
     }
 
     if (attr->type == ast::InterpolationType::kFlat &&
-        attr->sampling != ast::InterpolationSampling::kNone) {
+        attr->sampling != ast::InterpolationSampling::kInvalid) {
         AddError("flat interpolation attribute must not have a sampling parameter", attr->source);
         return false;
     }
diff --git a/src/tint/transform/canonicalize_entry_point_io.cc b/src/tint/transform/canonicalize_entry_point_io.cc
index 0b642d7..38a1b28 100644
--- a/src/tint/transform/canonicalize_entry_point_io.cc
+++ b/src/tint/transform/canonicalize_entry_point_io.cc
@@ -223,7 +223,7 @@
                 (ast::HasAttribute<ast::LocationAttribute>(attributes) ||
                  cfg.shader_style == ShaderStyle::kSpirv)) {
                 attributes.Push(ctx.dst->Interpolate(ast::InterpolationType::kFlat,
-                                                     ast::InterpolationSampling::kNone));
+                                                     ast::InterpolationSampling::kInvalid));
             }
 
             // Disable validation for use of the `input` address space.
@@ -292,7 +292,7 @@
             ast::HasAttribute<ast::LocationAttribute>(attributes) &&
             !ast::HasAttribute<ast::InterpolateAttribute>(attributes)) {
             attributes.Push(ctx.dst->Interpolate(ast::InterpolationType::kFlat,
-                                                 ast::InterpolationSampling::kNone));
+                                                 ast::InterpolationSampling::kInvalid));
         }
 
         // In GLSL, if it's a builtin, override the name with the
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index 429249d..d884bb7 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -2049,6 +2049,7 @@
             switch (interpolate->type) {
                 case ast::InterpolationType::kPerspective:
                 case ast::InterpolationType::kLinear:
+                case ast::InterpolationType::kInvalid:
                     break;
                 case ast::InterpolationType::kFlat:
                     out << "flat ";
@@ -2060,7 +2061,7 @@
                     break;
                 case ast::InterpolationSampling::kSample:
                 case ast::InterpolationSampling::kCenter:
-                case ast::InterpolationSampling::kNone:
+                case ast::InterpolationSampling::kInvalid:
                     break;
             }
         }
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index 4ada084..67eab5e 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -3010,6 +3010,8 @@
         case ast::InterpolationType::kFlat:
             modifiers += "nointerpolation ";
             break;
+        case ast::InterpolationType::kInvalid:
+            break;
     }
     switch (sampling) {
         case ast::InterpolationSampling::kCentroid:
@@ -3019,7 +3021,7 @@
             modifiers += "sample ";
             break;
         case ast::InterpolationSampling::kCenter:
-        case ast::InterpolationSampling::kNone:
+        case ast::InterpolationSampling::kInvalid:
             break;
     }
     return modifiers;
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 9517ec8..5db1d8f 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -1947,7 +1947,7 @@
         case ast::InterpolationSampling::kSample:
             attr = "sample_";
             break;
-        case ast::InterpolationSampling::kNone:
+        case ast::InterpolationSampling::kInvalid:
             break;
     }
     switch (type) {
@@ -1960,6 +1960,8 @@
         case ast::InterpolationType::kFlat:
             attr += "flat";
             break;
+        case ast::InterpolationType::kInvalid:
+            break;
     }
     return attr;
 }
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index 5bd6407..d86fc73 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -4088,6 +4088,7 @@
             push_annot(spv::Op::OpDecorate, {Operand(id), U32Operand(SpvDecorationFlat)});
             break;
         case ast::InterpolationType::kPerspective:
+        case ast::InterpolationType::kInvalid:
             break;
     }
     switch (sampling) {
@@ -4099,7 +4100,7 @@
             push_annot(spv::Op::OpDecorate, {Operand(id), U32Operand(SpvDecorationSample)});
             break;
         case ast::InterpolationSampling::kCenter:
-        case ast::InterpolationSampling::kNone:
+        case ast::InterpolationSampling::kInvalid:
             break;
     }
 }
diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc
index 05f1a5a..ecd640b 100644
--- a/src/tint/writer/wgsl/generator_impl.cc
+++ b/src/tint/writer/wgsl/generator_impl.cc
@@ -769,7 +769,7 @@
             },
             [&](const ast::InterpolateAttribute* interpolate) {
                 out << "interpolate(" << interpolate->type;
-                if (interpolate->sampling != ast::InterpolationSampling::kNone) {
+                if (interpolate->sampling != ast::InterpolationSampling::kInvalid) {
                     out << ", " << interpolate->sampling;
                 }
                 out << ")";