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

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

Change-Id: Ib9170a2337597d4d81983c446d50582b518c6d71
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105329
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
diff --git a/src/tint/ast/access.cc b/src/tint/ast/access.cc
index 642d852..3997715 100644
--- a/src/tint/ast/access.cc
+++ b/src/tint/ast/access.cc
@@ -12,30 +12,46 @@
 // 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/access.cc.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
 #include "src/tint/ast/access.h"
 
 namespace tint::ast {
 
-std::ostream& operator<<(std::ostream& out, Access access) {
-    switch (access) {
-        case ast::Access::kUndefined: {
-            out << "undefined";
-            break;
-        }
-        case ast::Access::kRead: {
-            out << "read";
-            break;
-        }
-        case ast::Access::kReadWrite: {
-            out << "read_write";
-            break;
-        }
-        case ast::Access::kWrite: {
-            out << "write";
-            break;
-        }
+/// ParseAccess parses a Access from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or Access::kInvalid if the string could not be parsed.
+Access ParseAccess(std::string_view str) {
+    if (str == "read") {
+        return Access::kRead;
     }
-    return out;
+    if (str == "read_write") {
+        return Access::kReadWrite;
+    }
+    if (str == "write") {
+        return Access::kWrite;
+    }
+    return Access::kInvalid;
+}
+
+std::ostream& operator<<(std::ostream& out, Access value) {
+    switch (value) {
+        case Access::kInvalid:
+            return out << "invalid";
+        case Access::kRead:
+            return out << "read";
+        case Access::kReadWrite:
+            return out << "read_write";
+        case Access::kWrite:
+            return out << "write";
+    }
+    return out << "<unknown>";
 }
 
 }  // namespace tint::ast
diff --git a/src/tint/ast/access.cc.tmpl b/src/tint/ast/access.cc.tmpl
new file mode 100644
index 0000000..bd52a3b
--- /dev/null
+++ b/src/tint/ast/access.cc.tmpl
@@ -0,0 +1,25 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/src/cmd/gen to generate access.cc
+
+To update the generated file, run:
+    ./tools/run gen
+
+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" -}}
+{{- $enum := (Sem.Enum "access") -}}
+
+#include "src/tint/ast/access.h"
+
+namespace tint::ast {
+
+{{ Eval "ParseEnum" $enum}}
+
+{{ Eval "EnumOStream" $enum}}
+
+}  // namespace tint::ast
diff --git a/src/tint/ast/access.h b/src/tint/ast/access.h
index 3714b70..12e1a20 100644
--- a/src/tint/ast/access.h
+++ b/src/tint/ast/access.h
@@ -12,32 +12,44 @@
 // 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/access.h.tmpl
+//
+// Do not modify this file directly
+////////////////////////////////////////////////////////////////////////////////
+
 #ifndef SRC_TINT_AST_ACCESS_H_
 #define SRC_TINT_AST_ACCESS_H_
 
 #include <ostream>
-#include <string>
 
 namespace tint::ast {
 
-/// The access control settings
-enum Access {
-    /// Not declared in the source
-    kUndefined = 0,
-    /// Read only
+/// Address space of a given pointer.
+enum class Access {
+    kInvalid,
     kRead,
-    /// Write only
-    kWrite,
-    /// Read write
     kReadWrite,
-    // Last valid access mode
-    kLastValid = kReadWrite,
+    kWrite,
 };
 
 /// @param out the std::ostream to write to
-/// @param access the Access
-/// @return the std::ostream so calls can be chained
-std::ostream& operator<<(std::ostream& out, Access access);
+/// @param value the Access
+/// @returns `out` so calls can be chained
+std::ostream& operator<<(std::ostream& out, Access value);
+
+/// ParseAccess parses a Access from a string.
+/// @param str the string to parse
+/// @returns the parsed enum, or Access::kInvalid if the string could not be parsed.
+Access ParseAccess(std::string_view str);
+
+constexpr const char* kAccessStrings[] = {
+    "read",
+    "read_write",
+    "write",
+};
 
 }  // namespace tint::ast
 
diff --git a/src/tint/ast/access.h.tmpl b/src/tint/ast/access.h.tmpl
new file mode 100644
index 0000000..ab14fcf
--- /dev/null
+++ b/src/tint/ast/access.h.tmpl
@@ -0,0 +1,29 @@
+{{- /*
+--------------------------------------------------------------------------------
+Template file for use with tools/src/cmd/gen to generate access.h
+
+To update the generated file, run:
+    ./tools/run gen
+
+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" -}}
+{{- $enum := (Sem.Enum "access") -}}
+
+#ifndef SRC_TINT_AST_ACCESS_H_
+#define SRC_TINT_AST_ACCESS_H_
+
+#include <ostream>
+
+namespace tint::ast {
+
+/// Address space of a given pointer.
+{{ Eval "DeclareEnum" $enum}}
+
+}  // namespace tint::ast
+
+#endif  // SRC_TINT_AST_ACCESS_H_
diff --git a/src/tint/ast/pointer.cc b/src/tint/ast/pointer.cc
index 71b7004..96bbdaf 100644
--- a/src/tint/ast/pointer.cc
+++ b/src/tint/ast/pointer.cc
@@ -35,7 +35,7 @@
         out << address_space << ", ";
     }
     out << type->FriendlyName(symbols);
-    if (access != ast::Access::kUndefined) {
+    if (access != ast::Access::kInvalid) {
         out << ", " << access;
     }
     out << ">";
diff --git a/src/tint/ast/pointer_test.cc b/src/tint/ast/pointer_test.cc
index aea260a..56a04b0 100644
--- a/src/tint/ast/pointer_test.cc
+++ b/src/tint/ast/pointer_test.cc
@@ -32,7 +32,7 @@
 
 TEST_F(AstPointerTest, FriendlyName) {
     auto* i32 = create<I32>();
-    auto* p = create<Pointer>(i32, ast::AddressSpace::kWorkgroup, Access::kUndefined);
+    auto* p = create<Pointer>(i32, ast::AddressSpace::kWorkgroup, Access::kInvalid);
     EXPECT_EQ(p->FriendlyName(Symbols()), "ptr<workgroup, i32>");
 }
 
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index 8add387..2c99b3b 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -173,7 +173,7 @@
 
         const ast::Type* type = nullptr;
         ast::AddressSpace address_space = ast::AddressSpace::kNone;
-        ast::Access access = ast::Access::kUndefined;
+        ast::Access access = ast::Access::kInvalid;
         const ast::Expression* constructor = nullptr;
         utils::Vector<const ast::Attribute*, 4> attributes;
 
@@ -902,7 +902,7 @@
         /// @return the pointer to `type` with the given ast::AddressSpace
         const ast::Pointer* pointer(const ast::Type* type,
                                     ast::AddressSpace address_space,
-                                    ast::Access access = ast::Access::kUndefined) const {
+                                    ast::Access access = ast::Access::kInvalid) const {
             return builder->create<ast::Pointer>(type, address_space, access);
         }
 
@@ -914,7 +914,7 @@
         const ast::Pointer* pointer(const Source& source,
                                     const ast::Type* type,
                                     ast::AddressSpace address_space,
-                                    ast::Access access = ast::Access::kUndefined) const {
+                                    ast::Access access = ast::Access::kInvalid) const {
             return builder->create<ast::Pointer>(source, type, address_space, access);
         }
 
@@ -923,7 +923,7 @@
         /// @return the pointer to type `T` with the given ast::AddressSpace.
         template <typename T>
         const ast::Pointer* pointer(ast::AddressSpace address_space,
-                                    ast::Access access = ast::Access::kUndefined) const {
+                                    ast::Access access = ast::Access::kInvalid) const {
             return pointer(Of<T>(), address_space, access);
         }
 
@@ -934,7 +934,7 @@
         template <typename T>
         const ast::Pointer* pointer(const Source& source,
                                     ast::AddressSpace address_space,
-                                    ast::Access access = ast::Access::kUndefined) const {
+                                    ast::Access access = ast::Access::kInvalid) const {
             return pointer(source, Of<T>(), address_space, access);
         }
 
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index 58941eb..7bbb5df 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -4854,7 +4854,7 @@
                 }
                 // Local variables are always Function storage class, with default
                 // access mode.
-                return DefInfo::Pointer{ast::AddressSpace::kFunction, ast::Access::kUndefined};
+                return DefInfo::Pointer{ast::AddressSpace::kFunction, ast::Access::kInvalid};
             }
             case SpvOpFunctionParameter: {
                 const auto* type = As<Pointer>(parser_impl_.ConvertType(inst.type_id()));
@@ -4862,7 +4862,7 @@
                 // Using kUndefined is ok for now, since the only non-default access mode
                 // on a pointer would be for a storage buffer, and baseline SPIR-V doesn't
                 // allow passing pointers to buffers as function parameters.
-                return DefInfo::Pointer{type->address_space, ast::Access::kUndefined};
+                return DefInfo::Pointer{type->address_space, ast::Access::kInvalid};
             }
             default:
                 break;
diff --git a/src/tint/reader/spirv/function.h b/src/tint/reader/spirv/function.h
index 528799a..b8240cf 100644
--- a/src/tint/reader/spirv/function.h
+++ b/src/tint/reader/spirv/function.h
@@ -335,7 +335,7 @@
         ast::AddressSpace address_space = ast::AddressSpace::kInvalid;
 
         /// The declared access mode.
-        ast::Access access = ast::kUndefined;
+        ast::Access access = ast::Access::kInvalid;
     };
 
     /// The expression to use when sinking pointers into their use.
diff --git a/src/tint/reader/spirv/parser_impl.cc b/src/tint/reader/spirv/parser_impl.cc
index 38a3a05..63e5cb4 100644
--- a/src/tint/reader/spirv/parser_impl.cc
+++ b/src/tint/reader/spirv/parser_impl.cc
@@ -1567,7 +1567,7 @@
         return nullptr;
     }
 
-    ast::Access access = ast::Access::kUndefined;
+    ast::Access access = ast::Access::kInvalid;
     if (address_space == ast::AddressSpace::kStorage) {
         bool read_only = false;
         if (auto* tn = storage_type->As<Named>()) {
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index e45beb5..4344753 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -1006,7 +1006,7 @@
             }
             return VariableQualifier{sc.value, ac.value};
         }
-        return Expect<VariableQualifier>{VariableQualifier{sc.value, ast::Access::kUndefined},
+        return Expect<VariableQualifier>{VariableQualifier{sc.value, ast::Access::kInvalid},
                                          source};
     });
 
@@ -1262,7 +1262,7 @@
     const char* use = "ptr declaration";
 
     auto address_space = ast::AddressSpace::kNone;
-    auto access = ast::Access::kUndefined;
+    auto access = ast::Access::kInvalid;
 
     auto subtype = expect_lt_gt_block(use, [&]() -> Expect<const ast::Type*> {
         auto sc = expect_address_space(use);
diff --git a/src/tint/reader/wgsl/parser_impl.h b/src/tint/reader/wgsl/parser_impl.h
index 60b94de..77196a0 100644
--- a/src/tint/reader/wgsl/parser_impl.h
+++ b/src/tint/reader/wgsl/parser_impl.h
@@ -296,7 +296,7 @@
         /// Variable address space
         ast::AddressSpace address_space = ast::AddressSpace::kNone;
         /// Variable access control
-        ast::Access access = ast::Access::kUndefined;
+        ast::Access access = ast::Access::kInvalid;
         /// Variable type
         const ast::Type* type = nullptr;
     };
@@ -306,7 +306,7 @@
         /// The variable's address space
         ast::AddressSpace address_space = ast::AddressSpace::kNone;
         /// The variable's access control
-        ast::Access access = ast::Access::kUndefined;
+        ast::Access access = ast::Access::kInvalid;
     };
 
     /// MatrixDimensions contains the column and row information for a matrix
diff --git a/src/tint/reader/wgsl/parser_impl_variable_qualifier_test.cc b/src/tint/reader/wgsl/parser_impl_variable_qualifier_test.cc
index 5c0cd5e..32c1a54 100644
--- a/src/tint/reader/wgsl/parser_impl_variable_qualifier_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_variable_qualifier_test.cc
@@ -47,11 +47,11 @@
     ParserImplTest,
     VariableQualifierTest,
     testing::Values(
-        VariableStorageData{"uniform", ast::AddressSpace::kUniform, ast::Access::kUndefined},
-        VariableStorageData{"workgroup", ast::AddressSpace::kWorkgroup, ast::Access::kUndefined},
-        VariableStorageData{"storage", ast::AddressSpace::kStorage, ast::Access::kUndefined},
-        VariableStorageData{"private", ast::AddressSpace::kPrivate, ast::Access::kUndefined},
-        VariableStorageData{"function", ast::AddressSpace::kFunction, ast::Access::kUndefined},
+        VariableStorageData{"uniform", ast::AddressSpace::kUniform, ast::Access::kInvalid},
+        VariableStorageData{"workgroup", ast::AddressSpace::kWorkgroup, ast::Access::kInvalid},
+        VariableStorageData{"storage", ast::AddressSpace::kStorage, ast::Access::kInvalid},
+        VariableStorageData{"private", ast::AddressSpace::kPrivate, ast::Access::kInvalid},
+        VariableStorageData{"function", ast::AddressSpace::kFunction, ast::Access::kInvalid},
         VariableStorageData{"storage, read", ast::AddressSpace::kStorage, ast::Access::kRead},
         VariableStorageData{"storage, write", ast::AddressSpace::kStorage, ast::Access::kWrite},
         VariableStorageData{"storage, read_write", ast::AddressSpace::kStorage,
diff --git a/src/tint/resolver/attribute_validation_test.cc b/src/tint/resolver/attribute_validation_test.cc
index 8ef01dd..018dbfd 100644
--- a/src/tint/resolver/attribute_validation_test.cc
+++ b/src/tint/resolver/attribute_validation_test.cc
@@ -721,7 +721,7 @@
 }
 
 TEST_F(StructMemberAttributeTest, Align_Attribute_Var) {
-    GlobalVar(Source{{1, 2}}, "val", ty.f32(), ast::AddressSpace::kPrivate, ast::Access::kUndefined,
+    GlobalVar(Source{{1, 2}}, "val", ty.f32(), ast::AddressSpace::kPrivate, ast::Access::kInvalid,
               Expr(1.23_f));
 
     Structure(Source{{6, 4}}, "mystruct",
diff --git a/src/tint/resolver/intrinsic_table.cc b/src/tint/resolver/intrinsic_table.cc
index 6a190de..a82f9e8 100644
--- a/src/tint/resolver/intrinsic_table.cc
+++ b/src/tint/resolver/intrinsic_table.cc
@@ -1186,7 +1186,7 @@
         for (auto& p : match.parameters) {
             params.Push(builder.create<sem::Parameter>(
                 nullptr, static_cast<uint32_t>(params.Length()), p.type, ast::AddressSpace::kNone,
-                ast::Access::kUndefined, p.usage));
+                ast::Access::kInvalid, p.usage));
         }
         sem::PipelineStageSet supported_stages;
         if (match.overload->flags.Contains(OverloadFlag::kSupportsVertexPipeline)) {
@@ -1384,7 +1384,7 @@
         for (auto& p : match.parameters) {
             params.Push(builder.create<sem::Parameter>(
                 nullptr, static_cast<uint32_t>(params.Length()), p.type, ast::AddressSpace::kNone,
-                ast::Access::kUndefined, p.usage));
+                ast::Access::kInvalid, p.usage));
         }
         auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant
                                                         : sem::EvaluationStage::kRuntime;
@@ -1397,9 +1397,9 @@
 
     // Conversion.
     auto* target = utils::GetOrCreate(converters, match, [&]() {
-        auto param = builder.create<sem::Parameter>(
-            nullptr, 0u, match.parameters[0].type, ast::AddressSpace::kNone,
-            ast::Access::kUndefined, match.parameters[0].usage);
+        auto param = builder.create<sem::Parameter>(nullptr, 0u, match.parameters[0].type,
+                                                    ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                                    match.parameters[0].usage);
         auto eval_stage = match.overload->const_eval_fn ? sem::EvaluationStage::kConstant
                                                         : sem::EvaluationStage::kRuntime;
         return builder.create<sem::TypeConversion>(match.return_type, param, eval_stage);
diff --git a/src/tint/resolver/intrinsic_table.inl.tmpl b/src/tint/resolver/intrinsic_table.inl.tmpl
index fb95eae..7b69df0 100644
--- a/src/tint/resolver/intrinsic_table.inl.tmpl
+++ b/src/tint/resolver/intrinsic_table.inl.tmpl
@@ -1,6 +1,6 @@
 {{- /*
 --------------------------------------------------------------------------------
-Template file for use with tools/src/cmd/gen to generate builtin_table.inl
+Template file for use with tools/src/cmd/gen to generate intrinsic_table.inl
 Used by BuiltinTable.cc for builtin overload resolution.
 
 To update the generated file, run:
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 4d31d70..0fe6691 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -251,7 +251,7 @@
         [&](const ast::Pointer* t) -> sem::Pointer* {
             if (auto* el = Type(t->type)) {
                 auto access = t->access;
-                if (access == ast::kUndefined) {
+                if (access == ast::Access::kInvalid) {
                     access = DefaultAccessForAddressSpace(t->address_space);
                 }
                 return builder_->create<sem::Pointer>(el, t->address_space, access);
@@ -386,13 +386,12 @@
     sem::Variable* sem = nullptr;
     if (is_global) {
         sem = builder_->create<sem::GlobalVariable>(
-            v, ty, sem::EvaluationStage::kRuntime, ast::AddressSpace::kNone,
-            ast::Access::kUndefined, /* constant_value */ nullptr, sem::BindingPoint{},
-            std::nullopt);
+            v, ty, sem::EvaluationStage::kRuntime, ast::AddressSpace::kNone, ast::Access::kInvalid,
+            /* constant_value */ nullptr, sem::BindingPoint{}, std::nullopt);
     } else {
         sem = builder_->create<sem::LocalVariable>(v, ty, sem::EvaluationStage::kRuntime,
-                                                   ast::AddressSpace::kNone,
-                                                   ast::Access::kUndefined, current_statement_,
+                                                   ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                                   current_statement_,
                                                    /* constant_value */ nullptr);
     }
 
@@ -442,7 +441,7 @@
     }
 
     auto* sem = builder_->create<sem::GlobalVariable>(
-        v, ty, sem::EvaluationStage::kOverride, ast::AddressSpace::kNone, ast::Access::kUndefined,
+        v, ty, sem::EvaluationStage::kOverride, ast::AddressSpace::kNone, ast::Access::kInvalid,
         /* constant_value */ nullptr, sem::BindingPoint{}, std::nullopt);
     sem->SetConstructor(rhs);
 
@@ -527,10 +526,10 @@
 
     auto* sem = is_global ? static_cast<sem::Variable*>(builder_->create<sem::GlobalVariable>(
                                 c, ty, sem::EvaluationStage::kConstant, ast::AddressSpace::kNone,
-                                ast::Access::kUndefined, value, sem::BindingPoint{}, std::nullopt))
+                                ast::Access::kInvalid, value, sem::BindingPoint{}, std::nullopt))
                           : static_cast<sem::Variable*>(builder_->create<sem::LocalVariable>(
                                 c, ty, sem::EvaluationStage::kConstant, ast::AddressSpace::kNone,
-                                ast::Access::kUndefined, current_statement_, value));
+                                ast::Access::kInvalid, current_statement_, value));
 
     sem->SetConstructor(rhs);
     builder_->Sem().Add(c, sem);
@@ -589,7 +588,7 @@
     }
 
     auto access = var->declared_access;
-    if (access == ast::Access::kUndefined) {
+    if (access == ast::Access::kInvalid) {
         access = DefaultAccessForAddressSpace(address_space);
     }
 
@@ -753,9 +752,9 @@
         location = c->As<uint32_t>();
     }
 
-    auto* sem = builder_->create<sem::Parameter>(
-        param, index, ty, ast::AddressSpace::kNone, ast::Access::kUndefined,
-        sem::ParameterUsage::kNone, binding_point, location);
+    auto* sem = builder_->create<sem::Parameter>(param, index, ty, ast::AddressSpace::kNone,
+                                                 ast::Access::kInvalid, sem::ParameterUsage::kNone,
+                                                 binding_point, location);
     builder_->Sem().Add(param, sem);
     return sem;
 }
@@ -1789,7 +1788,7 @@
                                 static_cast<uint32_t>(i),  // index
                                 arr->ElemType(),           // type
                                 ast::AddressSpace::kNone,  // address_space
-                                ast::Access::kUndefined);
+                                ast::Access::kInvalid);
                         });
                         return builder_->create<sem::TypeConstructor>(arr, std::move(params),
                                                                       args_stage);
@@ -1818,7 +1817,7 @@
                                 static_cast<uint32_t>(i),   // index
                                 str->Members()[i]->Type(),  // type
                                 ast::AddressSpace::kNone,   // address_space
-                                ast::Access::kUndefined);   // access
+                                ast::Access::kInvalid);     // access
                         }
                         return builder_->create<sem::TypeConstructor>(str, std::move(params),
                                                                       args_stage);
diff --git a/src/tint/resolver/type_validation_test.cc b/src/tint/resolver/type_validation_test.cc
index 7cc5cef..1271f06 100644
--- a/src/tint/resolver/type_validation_test.cc
+++ b/src/tint/resolver/type_validation_test.cc
@@ -1165,7 +1165,7 @@
     // var a : texture_storage_1d<ru32int>;
 
     auto* st = ty.storage_texture(Source{{12, 34}}, ast::TextureDimension::k1d,
-                                  ast::TexelFormat::kR32Uint, ast::Access::kUndefined);
+                                  ast::TexelFormat::kR32Uint, ast::Access::kInvalid);
 
     GlobalVar("a", st, Group(0_a), Binding(0_a));
 
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index 59f5b93..35ba7e99 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -263,7 +263,7 @@
     switch (t->access) {
         case ast::Access::kWrite:
             break;
-        case ast::Access::kUndefined:
+        case ast::Access::kInvalid:
             AddError("storage texture missing access control", t->source);
             return false;
         default:
@@ -621,7 +621,7 @@
             // https://gpuweb.github.io/gpuweb/wgsl/#variable-declaration
             // The access mode always has a default, and except for variables in the storage address
             // space, must not be written.
-            if (var->declared_access != ast::Access::kUndefined) {
+            if (var->declared_access != ast::Access::kInvalid) {
                 if (global->AddressSpace() == ast::AddressSpace::kStorage) {
                     // The access mode for the storage address space can only be 'read' or
                     // 'read_write'.
diff --git a/src/tint/sem/pointer.cc b/src/tint/sem/pointer.cc
index 3918233..cb73724 100644
--- a/src/tint/sem/pointer.cc
+++ b/src/tint/sem/pointer.cc
@@ -25,7 +25,7 @@
 Pointer::Pointer(const Type* subtype, ast::AddressSpace address_space, ast::Access access)
     : subtype_(subtype), address_space_(address_space), access_(access) {
     TINT_ASSERT(Semantic, !subtype->Is<Reference>());
-    TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
+    TINT_ASSERT(Semantic, access != ast::Access::kInvalid);
 }
 
 size_t Pointer::Hash() const {
diff --git a/src/tint/sem/reference.cc b/src/tint/sem/reference.cc
index a3a9f24..297b779 100644
--- a/src/tint/sem/reference.cc
+++ b/src/tint/sem/reference.cc
@@ -24,7 +24,7 @@
 Reference::Reference(const Type* subtype, ast::AddressSpace address_space, ast::Access access)
     : subtype_(subtype), address_space_(address_space), access_(access) {
     TINT_ASSERT(Semantic, !subtype->Is<Reference>());
-    TINT_ASSERT(Semantic, access != ast::Access::kUndefined);
+    TINT_ASSERT(Semantic, access != ast::Access::kInvalid);
 }
 
 size_t Reference::Hash() const {
diff --git a/src/tint/transform/binding_remapper.cc b/src/tint/transform/binding_remapper.cc
index a9a3dfb..66d8e99 100644
--- a/src/tint/transform/binding_remapper.cc
+++ b/src/tint/transform/binding_remapper.cc
@@ -121,7 +121,7 @@
             auto ac_it = remappings->access_controls.find(from);
             if (ac_it != remappings->access_controls.end()) {
                 ast::Access ac = ac_it->second;
-                if (ac > ast::Access::kLastValid) {
+                if (ac == ast::Access::kInvalid) {
                     ctx.dst->Diagnostics().add_error(
                         diag::System::Transform,
                         "invalid access mode (" + std::to_string(static_cast<uint32_t>(ac)) + ")");
diff --git a/src/tint/writer/append_vector.cc b/src/tint/writer/append_vector.cc
index edf9132..98e9efc 100644
--- a/src/tint/writer/append_vector.cc
+++ b/src/tint/writer/append_vector.cc
@@ -137,7 +137,7 @@
         auto* scalar_cast_target = b->create<sem::TypeConversion>(
             packed_el_sem_ty,
             b->create<sem::Parameter>(nullptr, 0u, scalar_sem->Type()->UnwrapRef(),
-                                      ast::AddressSpace::kNone, ast::Access::kUndefined),
+                                      ast::AddressSpace::kNone, ast::Access::kInvalid),
             sem::EvaluationStage::kRuntime);
         auto* scalar_cast_sem = b->create<sem::Call>(
             scalar_cast_ast, scalar_cast_target, sem::EvaluationStage::kRuntime,
@@ -158,7 +158,7 @@
                          [&](const tint::sem::Expression* arg, size_t i) -> const sem::Parameter* {
                              return b->create<sem::Parameter>(
                                  nullptr, static_cast<uint32_t>(i), arg->Type()->UnwrapRef(),
-                                 ast::AddressSpace::kNone, ast::Access::kUndefined);
+                                 ast::AddressSpace::kNone, ast::Access::kInvalid);
                          }),
         sem::EvaluationStage::kRuntime);
     auto* constructor_sem =
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index d884bb7..da67b3d 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -509,20 +509,20 @@
                                 {
                                     auto decl = line(&b);
                                     if (!EmitTypeAndName(decl, ret_ty, ast::AddressSpace::kNone,
-                                                         ast::Access::kUndefined, fn_name)) {
+                                                         ast::Access::kInvalid, fn_name)) {
                                         return "";
                                     }
                                     {
                                         ScopedParen sp(decl);
                                         const auto* ty = TypeOf(expr->lhs)->UnwrapRef();
                                         if (!EmitTypeAndName(decl, ty, ast::AddressSpace::kNone,
-                                                             ast::Access::kUndefined, "lhs")) {
+                                                             ast::Access::kInvalid, "lhs")) {
                                             return "";
                                         }
                                         decl << ", ";
                                         ty = TypeOf(expr->rhs)->UnwrapRef();
                                         if (!EmitTypeAndName(decl, ty, ast::AddressSpace::kNone,
-                                                             ast::Access::kUndefined, "rhs")) {
+                                                             ast::Access::kInvalid, "rhs")) {
                                             return "";
                                         }
                                     }
@@ -935,7 +935,7 @@
             {
                 auto pre = line();
                 if (!EmitTypeAndName(pre, builtin->ReturnType(), ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, result)) {
+                                     ast::Access::kInvalid, result)) {
                     return false;
                 }
                 pre << ";";
@@ -1213,7 +1213,7 @@
             {
                 auto l = line(b);
                 if (!EmitType(l, builtin->ReturnType(), ast::AddressSpace::kNone,
-                              ast::Access::kUndefined, "")) {
+                              ast::Access::kInvalid, "")) {
                     return false;
                 }
                 l << " result;";
@@ -1239,7 +1239,7 @@
             {
                 auto l = line(b);
                 if (!EmitType(l, builtin->ReturnType(), ast::AddressSpace::kNone,
-                              ast::Access::kUndefined, "")) {
+                              ast::Access::kInvalid, "")) {
                     return false;
                 }
                 l << " result;";
@@ -2198,7 +2198,7 @@
             return true;
         },
         [&](const sem::Vector* v) {
-            if (!EmitType(out, v, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+            if (!EmitType(out, v, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                 return false;
             }
 
@@ -2219,7 +2219,7 @@
             return true;
         },
         [&](const sem::Matrix* m) {
-            if (!EmitType(out, m, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+            if (!EmitType(out, m, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                 return false;
             }
 
@@ -2236,7 +2236,7 @@
             return true;
         },
         [&](const sem::Array* a) {
-            if (!EmitType(out, a, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+            if (!EmitType(out, a, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                 return false;
             }
 
@@ -2260,7 +2260,7 @@
             return true;
         },
         [&](const sem::Struct* s) {
-            if (!EmitType(out, s, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+            if (!EmitType(out, s, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                 return false;
             }
 
@@ -2351,7 +2351,7 @@
             }
         }
     } else if (auto* str = type->As<sem::Struct>()) {
-        if (!EmitType(out, type, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+        if (!EmitType(out, type, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
             return false;
         }
         bool first = true;
@@ -2365,7 +2365,7 @@
             EmitZeroValue(out, member->Type());
         }
     } else if (auto* arr = type->As<sem::Array>()) {
-        if (!EmitType(out, type, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+        if (!EmitType(out, type, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
             return false;
         }
         ScopedParen sp(out);
@@ -2972,7 +2972,7 @@
 
     auto out = line();
     // TODO(senorblanco): handle const
-    if (!EmitTypeAndName(out, type, ast::AddressSpace::kNone, ast::Access::kUndefined,
+    if (!EmitTypeAndName(out, type, ast::AddressSpace::kNone, ast::Access::kInvalid,
                          builder_.Symbols().NameFor(let->symbol))) {
         return false;
     }
@@ -2994,7 +2994,7 @@
 
     auto out = line();
     out << "const ";
-    if (!EmitTypeAndName(out, type, ast::AddressSpace::kNone, ast::Access::kUndefined,
+    if (!EmitTypeAndName(out, type, ast::AddressSpace::kNone, ast::Access::kInvalid,
                          builder_.Symbols().NameFor(var->symbol))) {
         return false;
     }
@@ -3022,7 +3022,7 @@
         {
             auto decl = line(&b);
             if (!EmitTypeAndName(decl, builtin->ReturnType(), ast::AddressSpace::kNone,
-                                 ast::Access::kUndefined, fn_name)) {
+                                 ast::Access::kInvalid, fn_name)) {
                 return "";
             }
             {
@@ -3037,8 +3037,8 @@
                         decl << "inout ";
                         ty = ptr->StoreType();
                     }
-                    if (!EmitTypeAndName(decl, ty, ast::AddressSpace::kNone,
-                                         ast::Access::kUndefined, param_name)) {
+                    if (!EmitTypeAndName(decl, ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                         param_name)) {
                         return "";
                     }
                     parameter_names.emplace_back(std::move(param_name));
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index 67eab5e2..94e80e8 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -325,8 +325,7 @@
         std::string fn;
         {
             std::ostringstream ss;
-            if (!EmitType(ss, vec, tint::ast::AddressSpace::kInvalid, ast::Access::kUndefined,
-                          "")) {
+            if (!EmitType(ss, vec, tint::ast::AddressSpace::kInvalid, ast::Access::kInvalid, "")) {
                 return "";
             }
             fn = UniqueIdentifier("set_" + ss.str());
@@ -334,13 +333,13 @@
         {
             auto out = line(&helpers_);
             out << "void " << fn << "(inout ";
-            if (!EmitTypeAndName(out, vec, ast::AddressSpace::kInvalid, ast::Access::kUndefined,
+            if (!EmitTypeAndName(out, vec, ast::AddressSpace::kInvalid, ast::Access::kInvalid,
                                  "vec")) {
                 return "";
             }
             out << ", int idx, ";
             if (!EmitTypeAndName(out, vec->type(), ast::AddressSpace::kInvalid,
-                                 ast::Access::kUndefined, "val")) {
+                                 ast::Access::kInvalid, "val")) {
                 return "";
             }
             out << ") {";
@@ -399,8 +398,7 @@
         std::string fn;
         {
             std::ostringstream ss;
-            if (!EmitType(ss, mat, tint::ast::AddressSpace::kInvalid, ast::Access::kUndefined,
-                          "")) {
+            if (!EmitType(ss, mat, tint::ast::AddressSpace::kInvalid, ast::Access::kInvalid, "")) {
                 return "";
             }
             fn = UniqueIdentifier("set_vector_" + ss.str());
@@ -408,13 +406,13 @@
         {
             auto out = line(&helpers_);
             out << "void " << fn << "(inout ";
-            if (!EmitTypeAndName(out, mat, ast::AddressSpace::kInvalid, ast::Access::kUndefined,
+            if (!EmitTypeAndName(out, mat, ast::AddressSpace::kInvalid, ast::Access::kInvalid,
                                  "mat")) {
                 return "";
             }
             out << ", int col, ";
             if (!EmitTypeAndName(out, mat->ColumnType(), ast::AddressSpace::kInvalid,
-                                 ast::Access::kUndefined, "val")) {
+                                 ast::Access::kInvalid, "val")) {
                 return "";
             }
             out << ") {";
@@ -468,8 +466,7 @@
         std::string fn;
         {
             std::ostringstream ss;
-            if (!EmitType(ss, mat, tint::ast::AddressSpace::kInvalid, ast::Access::kUndefined,
-                          "")) {
+            if (!EmitType(ss, mat, tint::ast::AddressSpace::kInvalid, ast::Access::kInvalid, "")) {
                 return "";
             }
             fn = UniqueIdentifier("set_scalar_" + ss.str());
@@ -477,13 +474,13 @@
         {
             auto out = line(&helpers_);
             out << "void " << fn << "(inout ";
-            if (!EmitTypeAndName(out, mat, ast::AddressSpace::kInvalid, ast::Access::kUndefined,
+            if (!EmitTypeAndName(out, mat, ast::AddressSpace::kInvalid, ast::Access::kInvalid,
                                  "mat")) {
                 return "";
             }
             out << ", int col, int row, ";
             if (!EmitTypeAndName(out, mat->type(), ast::AddressSpace::kInvalid,
-                                 ast::Access::kUndefined, "val")) {
+                                 ast::Access::kInvalid, "val")) {
                 return "";
             }
             out << ") {";
@@ -658,7 +655,7 @@
         if (auto* vec = ty->As<sem::Vector>()) {
             auto* elem_ty = vec->type();
 
-            if (!EmitType(out, ty, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+            if (!EmitType(out, ty, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                 return false;
             }
 
@@ -723,7 +720,7 @@
         std::string ty_name;
         {
             std::ostringstream ss;
-            if (!EmitType(ss, ty, tint::ast::AddressSpace::kInvalid, ast::Access::kUndefined, "")) {
+            if (!EmitType(ss, ty, tint::ast::AddressSpace::kInvalid, ast::Access::kInvalid, "")) {
                 return "";
             }
             ty_name = ss.str();
@@ -1431,12 +1428,12 @@
     auto rmw = [&](const char* hlsl) -> bool {
         {
             auto fn = line(&buf);
-            if (!EmitTypeAndName(fn, result_ty, ast::AddressSpace::kNone, ast::Access::kUndefined,
+            if (!EmitTypeAndName(fn, result_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
                                  name)) {
                 return false;
             }
             fn << "(RWByteAddressBuffer buffer, uint offset, ";
-            if (!EmitTypeAndName(fn, result_ty, ast::AddressSpace::kNone, ast::Access::kUndefined,
+            if (!EmitTypeAndName(fn, result_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
                                  "value")) {
                 return false;
             }
@@ -1452,7 +1449,7 @@
 
         {
             auto l = line(&buf);
-            if (!EmitTypeAndName(l, result_ty, ast::AddressSpace::kNone, ast::Access::kUndefined,
+            if (!EmitTypeAndName(l, result_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
                                  "original_value")) {
                 return false;
             }
@@ -1501,8 +1498,8 @@
             // InterlockedOr using 0 as the OR value
             {
                 auto fn = line(&buf);
-                if (!EmitTypeAndName(fn, result_ty, ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, name)) {
+                if (!EmitTypeAndName(fn, result_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                     name)) {
                     return false;
                 }
                 fn << "(RWByteAddressBuffer buffer, uint offset) {";
@@ -1517,8 +1514,8 @@
 
             {
                 auto l = line(&buf);
-                if (!EmitTypeAndName(l, result_ty, ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, "value")) {
+                if (!EmitTypeAndName(l, result_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                     "value")) {
                     return false;
                 }
                 l << " = 0;";
@@ -1535,8 +1532,8 @@
             {
                 auto fn = line(&buf);
                 fn << "void " << name << "(RWByteAddressBuffer buffer, uint offset, ";
-                if (!EmitTypeAndName(fn, value_ty, ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, "value")) {
+                if (!EmitTypeAndName(fn, value_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                     "value")) {
                     return false;
                 }
                 fn << ") {";
@@ -1551,7 +1548,7 @@
 
             {
                 auto l = line(&buf);
-                if (!EmitTypeAndName(l, value_ty, ast::AddressSpace::kNone, ast::Access::kUndefined,
+                if (!EmitTypeAndName(l, value_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
                                      "ignored")) {
                     return false;
                 }
@@ -1566,18 +1563,18 @@
             auto* value_ty = params[2]->Type()->UnwrapRef();
             {
                 auto fn = line(&buf);
-                if (!EmitTypeAndName(fn, result_ty, ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, name)) {
+                if (!EmitTypeAndName(fn, result_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                     name)) {
                     return false;
                 }
                 fn << "(RWByteAddressBuffer buffer, uint offset, ";
-                if (!EmitTypeAndName(fn, value_ty, ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, "compare")) {
+                if (!EmitTypeAndName(fn, value_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                     "compare")) {
                     return false;
                 }
                 fn << ", ";
-                if (!EmitTypeAndName(fn, value_ty, ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, "value")) {
+                if (!EmitTypeAndName(fn, value_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                     "value")) {
                     return false;
                 }
                 fn << ") {";
@@ -1592,8 +1589,8 @@
 
             {  // T result = {0};
                 auto l = line(&buf);
-                if (!EmitTypeAndName(l, result_ty, ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, "result")) {
+                if (!EmitTypeAndName(l, result_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                     "result")) {
                     return false;
                 }
                 l << "=";
@@ -1628,7 +1625,7 @@
     if (!builtin->ReturnType()->Is<sem::Void>()) {
         auto pre = line();
         if (!EmitTypeAndName(pre, builtin->ReturnType(), ast::AddressSpace::kNone,
-                             ast::Access::kUndefined, result)) {
+                             ast::Access::kInvalid, result)) {
             return false;
         }
         pre << " = ";
@@ -1691,8 +1688,8 @@
             {  // T result = 0;
                 auto pre = line();
                 auto* value_ty = builtin->Parameters()[1]->Type()->UnwrapRef();
-                if (!EmitTypeAndName(pre, value_ty, ast::AddressSpace::kNone,
-                                     ast::Access::kUndefined, result)) {
+                if (!EmitTypeAndName(pre, value_ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                     result)) {
                     return false;
                 }
                 pre << " = ";
@@ -1732,7 +1729,7 @@
             {  // T compare_value = <compare_value>;
                 auto pre = line();
                 if (!EmitTypeAndName(pre, TypeOf(compare_value)->UnwrapRef(),
-                                     ast::AddressSpace::kNone, ast::Access::kUndefined, compare)) {
+                                     ast::AddressSpace::kNone, ast::Access::kInvalid, compare)) {
                     return false;
                 }
                 pre << " = ";
@@ -1842,7 +1839,7 @@
             {
                 auto l = line(b);
                 if (!EmitType(l, builtin->ReturnType(), ast::AddressSpace::kNone,
-                              ast::Access::kUndefined, "")) {
+                              ast::Access::kInvalid, "")) {
                     return false;
                 }
                 l << " result;";
@@ -1884,7 +1881,7 @@
             {
                 auto l = line(b);
                 if (!EmitType(l, builtin->ReturnType(), ast::AddressSpace::kNone,
-                              ast::Access::kUndefined, "")) {
+                              ast::Access::kInvalid, "")) {
                     return false;
                 }
                 l << " result = {sig, int" << width << "(exp)};";
@@ -2721,7 +2718,7 @@
 
             auto const* type = v->Type();
             auto address_space = ast::AddressSpace::kNone;
-            auto access = ast::Access::kUndefined;
+            auto access = ast::Access::kInvalid;
 
             if (auto* ptr = type->As<sem::Pointer>()) {
                 type = ptr->StoreType();
@@ -3143,7 +3140,7 @@
                 return true;
             }
 
-            if (!EmitType(out, v, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+            if (!EmitType(out, v, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                 return false;
             }
 
@@ -3160,7 +3157,7 @@
             return true;
         },
         [&](const sem::Matrix* m) {
-            if (!EmitType(out, m, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+            if (!EmitType(out, m, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                 return false;
             }
 
@@ -3179,7 +3176,7 @@
         [&](const sem::Array* a) {
             if (constant->AllZero()) {
                 out << "(";
-                if (!EmitType(out, a, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+                if (!EmitType(out, a, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                     return false;
                 }
                 out << ")0";
@@ -3209,7 +3206,7 @@
         [&](const sem::Struct* s) {
             if (constant->AllZero()) {
                 out << "(";
-                if (!EmitType(out, s, ast::AddressSpace::kNone, ast::Access::kUndefined, "")) {
+                if (!EmitType(out, s, ast::AddressSpace::kNone, ast::Access::kInvalid, "")) {
                     return false;
                 }
                 out << ")0";
@@ -3330,12 +3327,12 @@
         [&](const sem::Struct*) {
             out << "(";
             TINT_DEFER(out << ")" << value);
-            return EmitType(out, type, ast::AddressSpace::kNone, ast::Access::kUndefined, "");
+            return EmitType(out, type, ast::AddressSpace::kNone, ast::Access::kInvalid, "");
         },
         [&](const sem::Array*) {
             out << "(";
             TINT_DEFER(out << ")" << value);
-            return EmitType(out, type, ast::AddressSpace::kNone, ast::Access::kUndefined, "");
+            return EmitType(out, type, ast::AddressSpace::kNone, ast::Access::kInvalid, "");
         },
         [&](Default) {
             diagnostics_.add_error(
@@ -4083,7 +4080,7 @@
 
     auto out = line();
     out << "const ";
-    if (!EmitTypeAndName(out, type, ast::AddressSpace::kNone, ast::Access::kUndefined,
+    if (!EmitTypeAndName(out, type, ast::AddressSpace::kNone, ast::Access::kInvalid,
                          builder_.Symbols().NameFor(let->symbol))) {
         return false;
     }
@@ -4111,7 +4108,7 @@
         {
             auto decl = line(&b);
             if (!EmitTypeAndName(decl, builtin->ReturnType(), ast::AddressSpace::kNone,
-                                 ast::Access::kUndefined, fn_name)) {
+                                 ast::Access::kInvalid, fn_name)) {
                 return "";
             }
             {
@@ -4126,8 +4123,8 @@
                         decl << "inout ";
                         ty = ptr->StoreType();
                     }
-                    if (!EmitTypeAndName(decl, ty, ast::AddressSpace::kNone,
-                                         ast::Access::kUndefined, param_name)) {
+                    if (!EmitTypeAndName(decl, ty, ast::AddressSpace::kNone, ast::Access::kInvalid,
+                                         param_name)) {
                         return "";
                     }
                     parameter_names.emplace_back(std::move(param_name));
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index d86fc73..57a363d 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -766,7 +766,7 @@
                     push_annot(spv::Op::OpDecorate,
                                {Operand(var_id), U32Operand(SpvDecorationNonWritable)});
                     break;
-                case ast::Access::kUndefined:
+                case ast::Access::kInvalid:
                 case ast::Access::kReadWrite:
                     break;
             }
@@ -3684,11 +3684,11 @@
     // references are not legal in WGSL, so only considering the top-level type is
     // fine.
     if (auto* ptr = type->As<sem::Pointer>()) {
-        type =
-            builder_.create<sem::Pointer>(ptr->StoreType(), ptr->AddressSpace(), ast::kReadWrite);
+        type = builder_.create<sem::Pointer>(ptr->StoreType(), ptr->AddressSpace(),
+                                             ast::Access::kReadWrite);
     } else if (auto* ref = type->As<sem::Reference>()) {
-        type =
-            builder_.create<sem::Pointer>(ref->StoreType(), ref->AddressSpace(), ast::kReadWrite);
+        type = builder_.create<sem::Pointer>(ref->StoreType(), ref->AddressSpace(),
+                                             ast::Access::kReadWrite);
     }
 
     return utils::GetOrCreate(type_to_id_, type, [&]() -> uint32_t {
diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc
index ecd640b..cf43f23 100644
--- a/src/tint/writer/wgsl/generator_impl.cc
+++ b/src/tint/writer/wgsl/generator_impl.cc
@@ -433,7 +433,7 @@
             if (!EmitType(out, ptr->type)) {
                 return false;
             }
-            if (ptr->access != ast::Access::kUndefined) {
+            if (ptr->access != ast::Access::kInvalid) {
                 out << ", ";
                 if (!EmitAccess(out, ptr->access)) {
                     return false;
@@ -656,9 +656,9 @@
             out << "var";
             auto address_space = var->declared_address_space;
             auto ac = var->declared_access;
-            if (address_space != ast::AddressSpace::kNone || ac != ast::Access::kUndefined) {
+            if (address_space != ast::AddressSpace::kNone || ac != ast::Access::kInvalid) {
                 out << "<" << address_space;
-                if (ac != ast::Access::kUndefined) {
+                if (ac != ast::Access::kInvalid) {
                     out << ", ";
                     if (!EmitAccess(out, ac)) {
                         return false;