tint: Have ast::IdentifierExpression use ast::Identifier

The additional nesting is somewhat unfortunate for pointer
indirection overhead, but this simplfies logic like
transform::Renamer, which can continue to find all the
identifier nodes in the program.

Bug: tint:1257
Change-Id: I8d51dd80dc4c51ef59238959029b8511f1edf70d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/118342
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
diff --git a/src/tint/ast/array.cc b/src/tint/ast/array.cc
index 6a898f4..6233381 100644
--- a/src/tint/ast/array.cc
+++ b/src/tint/ast/array.cc
@@ -27,7 +27,7 @@
 // Returns the string representation of an array size expression.
 std::string SizeExprToString(const Expression* size, const SymbolTable& symbols) {
     if (auto* ident = size->As<IdentifierExpression>()) {
-        return symbols.NameFor(ident->symbol);
+        return symbols.NameFor(ident->identifier->symbol);
     }
     if (auto* literal = size->As<IntLiteralExpression>()) {
         return std::to_string(literal->value);
diff --git a/src/tint/ast/identifier_expression.cc b/src/tint/ast/identifier_expression.cc
index 34eadeb..ca4e0cb 100644
--- a/src/tint/ast/identifier_expression.cc
+++ b/src/tint/ast/identifier_expression.cc
@@ -20,10 +20,13 @@
 
 namespace tint::ast {
 
-IdentifierExpression::IdentifierExpression(ProgramID pid, NodeID nid, const Source& src, Symbol sym)
-    : Base(pid, nid, src), symbol(sym) {
-    TINT_ASSERT_PROGRAM_IDS_EQUAL_IF_VALID(AST, symbol, program_id);
-    TINT_ASSERT(AST, symbol.IsValid());
+IdentifierExpression::IdentifierExpression(ProgramID pid,
+                                           NodeID nid,
+                                           const Source& src,
+                                           const Identifier* ident)
+    : Base(pid, nid, src), identifier(ident) {
+    TINT_ASSERT(AST, identifier != nullptr);
+    TINT_ASSERT_PROGRAM_IDS_EQUAL(AST, identifier, program_id);
 }
 
 IdentifierExpression::IdentifierExpression(IdentifierExpression&&) = default;
@@ -33,8 +36,8 @@
 const IdentifierExpression* IdentifierExpression::Clone(CloneContext* ctx) const {
     // Clone arguments outside of create() call to have deterministic ordering
     auto src = ctx->Clone(source);
-    auto sym = ctx->Clone(symbol);
-    return ctx->dst->create<IdentifierExpression>(src, sym);
+    auto ident = ctx->Clone(identifier);
+    return ctx->dst->create<IdentifierExpression>(src, ident);
 }
 
 }  // namespace tint::ast
diff --git a/src/tint/ast/identifier_expression.h b/src/tint/ast/identifier_expression.h
index b583807..475249c 100644
--- a/src/tint/ast/identifier_expression.h
+++ b/src/tint/ast/identifier_expression.h
@@ -17,6 +17,11 @@
 
 #include "src/tint/ast/expression.h"
 
+// Forward declarations
+namespace tint::ast {
+class Identifier;
+}
+
 namespace tint::ast {
 
 /// An identifier expression
@@ -26,8 +31,11 @@
     /// @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 sym the symbol for the identifier
-    IdentifierExpression(ProgramID pid, NodeID nid, const Source& src, Symbol sym);
+    /// @param identifier the identifier
+    IdentifierExpression(ProgramID pid,
+                         NodeID nid,
+                         const Source& src,
+                         const Identifier* identifier);
     /// Move constructor
     IdentifierExpression(IdentifierExpression&&);
     ~IdentifierExpression() override;
@@ -38,8 +46,8 @@
     /// @return the newly cloned node
     const IdentifierExpression* Clone(CloneContext* ctx) const override;
 
-    /// The symbol for the identifier
-    const Symbol symbol;
+    /// The identifier for the expression
+    Identifier const* const identifier;
 };
 
 }  // namespace tint::ast
diff --git a/src/tint/ast/identifier_expression_test.cc b/src/tint/ast/identifier_expression_test.cc
index 1f8033d..3bef4ca 100644
--- a/src/tint/ast/identifier_expression_test.cc
+++ b/src/tint/ast/identifier_expression_test.cc
@@ -22,16 +22,15 @@
 
 TEST_F(IdentifierExpressionTest, Creation) {
     auto* i = Expr("ident");
-    EXPECT_EQ(i->symbol, Symbol(1, ID()));
+    EXPECT_EQ(i->identifier->symbol, Symbol(1, ID()));
 }
 
 TEST_F(IdentifierExpressionTest, Creation_WithSource) {
-    auto* i = Expr(Source{Source::Location{20, 2}}, "ident");
-    EXPECT_EQ(i->symbol, Symbol(1, ID()));
+    auto* i = Expr(Source{{20, 2}}, "ident");
+    EXPECT_EQ(i->identifier->symbol, Symbol(1, ID()));
 
-    auto src = i->source;
-    EXPECT_EQ(src.range.begin.line, 20u);
-    EXPECT_EQ(src.range.begin.column, 2u);
+    EXPECT_EQ(i->source.range, (Source::Range{{20, 2}}));
+    EXPECT_EQ(i->identifier->source.range, (Source::Range{{20, 2}}));
 }
 
 TEST_F(IdentifierExpressionTest, IsIdentifier) {
diff --git a/src/tint/ast/workgroup_attribute_test.cc b/src/tint/ast/workgroup_attribute_test.cc
index d4fb6c7..97a034b 100644
--- a/src/tint/ast/workgroup_attribute_test.cc
+++ b/src/tint/ast/workgroup_attribute_test.cc
@@ -73,7 +73,7 @@
 
     auto* z_ident = As<ast::IdentifierExpression>(values[2]);
     ASSERT_TRUE(z_ident);
-    EXPECT_EQ(Symbols().NameFor(z_ident->symbol), "depth");
+    EXPECT_EQ(Symbols().NameFor(z_ident->identifier->symbol), "depth");
 }
 
 }  // namespace
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index ce3712d..41ec05e 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -1184,52 +1184,52 @@
     /// @param symbol the identifier symbol
     /// @return an ast::IdentifierExpression with the given symbol
     const ast::IdentifierExpression* Expr(const Source& source, Symbol symbol) {
-        return create<ast::IdentifierExpression>(source, symbol);
+        return create<ast::IdentifierExpression>(source, Ident(source, symbol));
     }
 
     /// @param symbol the identifier symbol
     /// @return an ast::IdentifierExpression with the given symbol
     const ast::IdentifierExpression* Expr(Symbol symbol) {
-        return create<ast::IdentifierExpression>(symbol);
-    }
-
-    /// @param source the source information
-    /// @param variable the AST variable
-    /// @return an ast::IdentifierExpression with the variable's symbol
-    const ast::IdentifierExpression* Expr(const Source& source, const ast::Variable* variable) {
-        return create<ast::IdentifierExpression>(source, variable->symbol);
-    }
-
-    /// @param variable the AST variable
-    /// @return an ast::IdentifierExpression with the variable's symbol
-    const ast::IdentifierExpression* Expr(const ast::Variable* variable) {
-        return create<ast::IdentifierExpression>(variable->symbol);
+        return create<ast::IdentifierExpression>(Ident(symbol));
     }
 
     /// @param source the source information
     /// @param name the identifier name
     /// @return an ast::IdentifierExpression with the given name
     const ast::IdentifierExpression* Expr(const Source& source, const char* name) {
-        return create<ast::IdentifierExpression>(source, Symbols().Register(name));
+        return create<ast::IdentifierExpression>(source, Ident(source, name));
     }
 
     /// @param name the identifier name
     /// @return an ast::IdentifierExpression with the given name
     const ast::IdentifierExpression* Expr(const char* name) {
-        return create<ast::IdentifierExpression>(Symbols().Register(name));
+        return create<ast::IdentifierExpression>(Ident(name));
     }
 
     /// @param source the source information
     /// @param name the identifier name
     /// @return an ast::IdentifierExpression with the given name
     const ast::IdentifierExpression* Expr(const Source& source, const std::string& name) {
-        return create<ast::IdentifierExpression>(source, Symbols().Register(name));
+        return create<ast::IdentifierExpression>(source, Ident(source, name));
     }
 
     /// @param name the identifier name
     /// @return an ast::IdentifierExpression with the given name
     const ast::IdentifierExpression* Expr(const std::string& name) {
-        return create<ast::IdentifierExpression>(Symbols().Register(name));
+        return create<ast::IdentifierExpression>(Ident(name));
+    }
+
+    /// @param source the source information
+    /// @param variable the AST variable
+    /// @return an ast::IdentifierExpression with the variable's symbol
+    const ast::IdentifierExpression* Expr(const Source& source, const ast::Variable* variable) {
+        return create<ast::IdentifierExpression>(source, Ident(source, variable->symbol));
+    }
+
+    /// @param variable the AST variable
+    /// @return an ast::IdentifierExpression with the variable's symbol
+    const ast::IdentifierExpression* Expr(const ast::Variable* variable) {
+        return create<ast::IdentifierExpression>(Ident(variable->symbol));
     }
 
     /// @param source the source information
diff --git a/src/tint/reader/spirv/function.cc b/src/tint/reader/spirv/function.cc
index f068a62..98151cc 100644
--- a/src/tint/reader/spirv/function.cc
+++ b/src/tint/reader/spirv/function.cc
@@ -877,8 +877,7 @@
     // as the statement block at the top of the stack.
     const auto& top = statements_stack_.Back();
 
-    auto* cond =
-        create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(guard_name));
+    auto* cond = builder_.Expr(Source{}, guard_name);
     auto* builder = AddStatementBuilder<IfStatementBuilder>(cond);
 
     PushNewStatementBlock(top.GetConstruct(), end_id, [=](const StatementList& stmts) {
@@ -1314,12 +1313,7 @@
     }
 
     // Call the inner function.  It has no parameters.
-    stmts.Push(create<ast::CallStatement>(
-        source,
-        create<ast::CallExpression>(
-            source,
-            create<ast::Identifier>(source, builder_.Symbols().Register(ep_info_->inner_name)),
-            utils::Empty)));
+    stmts.Push(builder_.CallStmt(source, builder_.Call(source, ep_info_->inner_name)));
 
     // Pipeline outputs are mapped to the return value.
     if (ep_info_->outputs.IsEmpty()) {
@@ -2587,8 +2581,7 @@
         case SkipReason::kSampleMaskOutBuiltinPointer: {
             // The result type is always u32.
             auto name = namer_.Name(sample_mask_out_id);
-            return TypedExpression{ty_.U32(), create<ast::IdentifierExpression>(
-                                                  Source{}, builder_.Symbols().Register(name))};
+            return TypedExpression{ty_.U32(), builder_.Expr(Source{}, name)};
         }
     }
     auto type_it = identifier_types_.find(id);
@@ -2597,14 +2590,12 @@
         // declaration.
         auto name = namer_.Name(id);
         auto* type = type_it->second;
-        return TypedExpression{
-            type, create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(name))};
+        return TypedExpression{type, builder_.Expr(Source{}, name)};
     }
     if (parser_impl_.IsScalarSpecConstant(id)) {
         auto name = namer_.Name(id);
-        return TypedExpression{
-            parser_impl_.ConvertType(def_use_mgr_->GetDef(id)->type_id()),
-            create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(name))};
+        return TypedExpression{parser_impl_.ConvertType(def_use_mgr_->GetDef(id)->type_id()),
+                               builder_.Expr(Source{}, name)};
     }
     if (singly_used_values_.count(id)) {
         auto expr = std::move(singly_used_values_[id]);
@@ -2627,8 +2618,7 @@
             // Construct the reference type, mapping storage class correctly.
             const auto* type =
                 RemapPointerProperties(parser_impl_.ConvertType(inst->type_id(), PtrAs::Ref), id);
-            return TypedExpression{type, create<ast::IdentifierExpression>(
-                                             Source{}, builder_.Symbols().Register(name))};
+            return TypedExpression{type, builder_.Expr(Source{}, name)};
         }
         case spv::Op::OpUndef:
             // Substitute a null value for undef.
@@ -3322,11 +3312,8 @@
                     *flow_guard_name_ptr = flow_guard;
                 }
                 // Signal an exit from the branch.
-                return create<ast::AssignmentStatement>(
-                    Source{},
-                    create<ast::IdentifierExpression>(Source{},
-                                                      builder_.Symbols().Register(flow_guard)),
-                    MakeFalse(Source{}));
+                return create<ast::AssignmentStatement>(Source{}, builder_.Expr(flow_guard),
+                                                        MakeFalse(Source{}));
             }
 
             // For an unconditional branch, the break out to an if-selection
@@ -3503,10 +3490,7 @@
     if (def_info && def_info->requires_hoisted_var_def) {
         auto name = namer_.Name(result_id);
         // Emit an assignment of the expression to the hoisted variable.
-        AddStatement(create<ast::AssignmentStatement>(
-            Source{},
-            create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(name)),
-            expr.expr));
+        AddStatement(create<ast::AssignmentStatement>(Source{}, builder_.Expr(name), expr.expr));
         return true;
     }
     return false;
@@ -3669,8 +3653,7 @@
                     return true;
                 case SkipReason::kSampleMaskInBuiltinPointer: {
                     auto name = namer_.Name(sample_mask_in_id);
-                    const ast::Expression* id_expr = create<ast::IdentifierExpression>(
-                        Source{}, builder_.Symbols().Register(name));
+                    const ast::Expression* id_expr = builder_.Expr(Source{}, name);
                     // SampleMask is an array in Vulkan SPIR-V. Always access the first
                     // element.
                     id_expr = create<ast::IndexAccessorExpression>(
@@ -3852,11 +3835,7 @@
     if (unary_builtin_name != nullptr) {
         ExpressionList params;
         params.Push(MakeOperand(inst, 0).expr);
-        return {ast_type, create<ast::CallExpression>(
-                              Source{},
-                              create<ast::Identifier>(
-                                  Source{}, builder_.Symbols().Register(unary_builtin_name)),
-                              std::move(params))};
+        return {ast_type, builder_.Call(Source{}, unary_builtin_name, std::move(params))};
     }
 
     const auto builtin = GetBuiltin(op);
@@ -4106,7 +4085,6 @@
         return {};
     }
 
-    auto* func = create<ast::Identifier>(Source{}, builder_.Symbols().Register(name));
     ExpressionList operands;
     const Type* first_operand_type = nullptr;
     // All parameters to GLSL.std.450 extended instructions are IDs.
@@ -4117,7 +4095,7 @@
         }
         operands.Push(operand.expr);
     }
-    auto* call = create<ast::CallExpression>(Source{}, func, std::move(operands));
+    auto* call = builder_.Call(Source{}, name, std::move(operands));
     TypedExpression call_expr{result_type, call};
     return parser_impl_.RectifyForcedResultType(call_expr, inst, first_operand_type);
 }
@@ -4312,23 +4290,23 @@
     return {};
 }
 
-ast::IdentifierExpression* FunctionEmitter::Swizzle(uint32_t i) {
+const ast::IdentifierExpression* FunctionEmitter::Swizzle(uint32_t i) {
     if (i >= kMaxVectorLen) {
         Fail() << "vector component index is larger than " << kMaxVectorLen - 1 << ": " << i;
         return nullptr;
     }
     const char* names[] = {"x", "y", "z", "w"};
-    return create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(names[i & 3]));
+    return builder_.Expr(names[i & 3]);
 }
 
-ast::IdentifierExpression* FunctionEmitter::PrefixSwizzle(uint32_t n) {
+const ast::IdentifierExpression* FunctionEmitter::PrefixSwizzle(uint32_t n) {
     switch (n) {
         case 1:
-            return create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register("x"));
+            return builder_.Expr("x");
         case 2:
-            return create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register("xy"));
+            return builder_.Expr("xy");
         case 3:
-            return create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register("xyz"));
+            return builder_.Expr("xyz");
         default:
             break;
     }
@@ -4433,8 +4411,7 @@
             ptr_ty_id = builtin_position_info.position_member_pointer_type_id;
 
             auto name = namer_.Name(base_id);
-            current_expr.expr =
-                create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(name));
+            current_expr.expr = builder_.Expr(name);
             current_expr.type = parser_impl_.ConvertType(ptr_ty_id, PtrAs::Ref);
         }
     }
@@ -4533,8 +4510,7 @@
                     return {};
                 }
                 auto name = namer_.GetMemberName(pointee_type_id, uint32_t(index_const_val));
-                auto* member_access =
-                    create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(name));
+                auto* member_access = builder_.Expr(name);
 
                 next_expr = create<ast::MemberAccessorExpression>(Source{}, current_expr.expr,
                                                                   member_access);
@@ -4697,8 +4673,7 @@
                     return {};
                 }
                 auto name = namer_.GetMemberName(current_type_id, uint32_t(index_val));
-                auto* member_access =
-                    create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(name));
+                auto* member_access = builder_.Expr(name);
 
                 next_expr = create<ast::MemberAccessorExpression>(Source{}, current_expr.expr,
                                                                   member_access);
@@ -5390,8 +5365,7 @@
         return nullptr;
     }
     auto name = namer_.Name(image->result_id());
-    return create<ast::IdentifierExpression>(GetSourceForInst(inst),
-                                             builder_.Symbols().Register(name));
+    return builder_.Expr(GetSourceForInst(inst), name);
 }
 
 const ast::Expression* FunctionEmitter::GetSamplerExpression(
@@ -5405,8 +5379,7 @@
         return nullptr;
     }
     auto name = namer_.Name(image->result_id());
-    return create<ast::IdentifierExpression>(GetSourceForInst(inst),
-                                             builder_.Symbols().Register(name));
+    return builder_.Expr(GetSourceForInst(inst), name);
 }
 
 bool FunctionEmitter::EmitImageAccess(const spvtools::opt::Instruction& inst) {
@@ -5649,8 +5622,7 @@
         return false;
     }
 
-    auto* ident = create<ast::Identifier>(Source{}, builder_.Symbols().Register(builtin_name));
-    auto* call_expr = create<ast::CallExpression>(Source{}, ident, std::move(args));
+    auto* call_expr = builder_.Call(Source{}, builtin_name, std::move(args));
 
     if (inst.type_id() != 0) {
         // It returns a value.
@@ -5739,14 +5711,12 @@
             // Invoke textureDimensions.
             // If the texture is arrayed, combine with the result from
             // textureNumLayers.
-            auto* dims_ident =
-                create<ast::Identifier>(Source{}, builder_.Symbols().Register("textureDimensions"));
             ExpressionList dims_args{GetImageExpression(inst)};
             if (op == spv::Op::OpImageQuerySizeLod) {
                 dims_args.Push(MakeOperand(inst, 1).expr);
             }
             const ast::Expression* dims_call =
-                create<ast::CallExpression>(Source{}, dims_ident, dims_args);
+                builder_.Call(Source{}, "textureDimensions", std::move(dims_args));
             auto dims = texture_type->dims;
             if ((dims == type::TextureDimension::kCube) ||
                 (dims == type::TextureDimension::kCubeArray)) {
@@ -5756,10 +5726,8 @@
             }
             exprs.Push(dims_call);
             if (ast::IsTextureArray(dims)) {
-                auto* layers_ident = create<ast::Identifier>(
-                    Source{}, builder_.Symbols().Register("textureNumLayers"));
-                auto num_layers = create<ast::CallExpression>(
-                    Source{}, layers_ident, utils::Vector{GetImageExpression(inst)});
+                auto num_layers =
+                    builder_.Call(Source{}, "textureNumLayers", GetImageExpression(inst));
                 exprs.Push(num_layers);
             }
             auto* result_type = parser_impl_.ConvertType(inst.type_id());
@@ -5786,10 +5754,8 @@
         case spv::Op::OpImageQuerySamples: {
             const auto* name =
                 (op == spv::Op::OpImageQueryLevels) ? "textureNumLevels" : "textureNumSamples";
-            auto* levels_ident =
-                create<ast::Identifier>(Source{}, builder_.Symbols().Register(name));
-            const ast::Expression* ast_expr = create<ast::CallExpression>(
-                Source{}, levels_ident, utils::Vector{GetImageExpression(inst)});
+            const ast::Expression* ast_expr =
+                builder_.Call(Source{}, name, GetImageExpression(inst));
             auto* result_type = parser_impl_.ConvertType(inst.type_id());
             // The SPIR-V result type must be integer scalar.
             // The WGSL bulitin returns u32.
@@ -6156,8 +6122,7 @@
     if (member_expr.type->Is<Pointer>()) {
         member_expr = Dereference(member_expr);
     }
-    auto* member_ident =
-        create<ast::IdentifierExpression>(Source{}, builder_.Symbols().Register(field_name));
+    auto* member_ident = builder_.Expr(field_name);
     auto* member_access =
         create<ast::MemberAccessorExpression>(Source{}, member_expr.expr, member_ident);
 
diff --git a/src/tint/reader/spirv/function.h b/src/tint/reader/spirv/function.h
index 53afcdc..5ad2b1b 100644
--- a/src/tint/reader/spirv/function.h
+++ b/src/tint/reader/spirv/function.h
@@ -916,14 +916,14 @@
     /// index is out of range, i.e. 4 or higher.
     /// @param i index of the subcomponent
     /// @returns the identifier expression for the `i`'th component
-    ast::IdentifierExpression* Swizzle(uint32_t i);
+    const ast::IdentifierExpression* Swizzle(uint32_t i);
 
     /// Returns an identifier expression for the swizzle name of the first
     /// `n` elements of a vector.  Emits an error and returns nullptr if `n`
     /// is out of range, i.e. 4 or higher.
     /// @param n the number of components in the swizzle
     /// @returns the swizzle identifier for the first n elements of a vector
-    ast::IdentifierExpression* PrefixSwizzle(uint32_t n);
+    const ast::IdentifierExpression* PrefixSwizzle(uint32_t n);
 
     /// Converts SPIR-V image coordinates from an image access instruction
     /// (e.g. OpImageSampledImplicitLod) into an expression list consisting of
diff --git a/src/tint/reader/wgsl/parser_impl.cc b/src/tint/reader/wgsl/parser_impl.cc
index dd6ef91..7a35092 100644
--- a/src/tint/reader/wgsl/parser_impl.cc
+++ b/src/tint/reader/wgsl/parser_impl.cc
@@ -2648,13 +2648,10 @@
                 return Failure::kErrored;
             }
 
-            auto* ident =
-                create<ast::Identifier>(t.source(), builder_.Symbols().Register(t.to_str()));
-            return create<ast::CallExpression>(t.source(), ident, std::move(params.value));
+            return builder_.Call(t.source(), t.to_str(), std::move(params.value));
         }
 
-        return create<ast::IdentifierExpression>(t.source(),
-                                                 builder_.Symbols().Register(t.to_str()));
+        return builder_.Expr(t.source(), t.to_str());
     }
 
     if (t.Is(Token::Type::kParenLeft)) {
@@ -2709,10 +2706,8 @@
                 return Failure::kErrored;
             }
 
-            prefix = create<ast::MemberAccessorExpression>(
-                ident.source, prefix,
-                create<ast::IdentifierExpression>(ident.source,
-                                                  builder_.Symbols().Register(ident.value)));
+            prefix = builder_.MemberAccessor(ident.source, prefix,
+                                             builder_.Expr(ident.source, ident.value));
             continue;
         }
 
@@ -3267,8 +3262,7 @@
     if (t.IsIdentifier()) {
         next();
 
-        return create<ast::IdentifierExpression>(t.source(),
-                                                 builder_.Symbols().Register(t.to_str()));
+        return builder_.Expr(t.source(), t.to_str());
     }
 
     if (peek_is(Token::Type::kParenLeft)) {
@@ -3780,10 +3774,8 @@
         }
         match(Token::Type::kComma);
 
-        return create<ast::DiagnosticControl>(
-            source, severity_control.value,
-            create<ast::IdentifierExpression>(rule_name.source,
-                                              builder_.Symbols().Register(rule_name.value)));
+        return create<ast::DiagnosticControl>(source, severity_control.value,
+                                              builder_.Expr(rule_name.source, rule_name.value));
     });
 }
 
diff --git a/src/tint/reader/wgsl/parser_impl_additive_expression_test.cc b/src/tint/reader/wgsl/parser_impl_additive_expression_test.cc
index 971c695..27f44e1 100644
--- a/src/tint/reader/wgsl/parser_impl_additive_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_additive_expression_test.cc
@@ -35,12 +35,12 @@
     EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, AdditiveExpression_Parses_Minus) {
@@ -56,12 +56,12 @@
     EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, AdditiveExpression_Parses_MinusMinus) {
@@ -77,16 +77,16 @@
     EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::UnaryOpExpression>());
     auto* unary = rel->rhs->As<ast::UnaryOpExpression>();
     EXPECT_EQ(ast::UnaryOp::kNegation, unary->op);
 
     ASSERT_TRUE(unary->expr->Is<ast::IdentifierExpression>());
-    ident = unary->expr->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = unary->expr->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, AdditiveExpression_Parses_MultipleOps) {
@@ -105,8 +105,8 @@
     EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("d"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: a - b
@@ -116,8 +116,8 @@
     EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("c"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: a
@@ -127,12 +127,12 @@
     EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, AdditiveExpression_Parses_MultipleOps_MixedMultiplication) {
@@ -151,8 +151,8 @@
     EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("d"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: a
@@ -162,8 +162,8 @@
     EXPECT_EQ(ast::BinaryOp::kSubtract, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BinaryExpression>());
     // lhs: b
@@ -173,12 +173,12 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("c"));
 }
 
 TEST_F(ParserImplTest, AdditiveExpression_InvalidRHS) {
diff --git a/src/tint/reader/wgsl/parser_impl_assignment_stmt_test.cc b/src/tint/reader/wgsl/parser_impl_assignment_stmt_test.cc
index fd76c34..e6adcb2 100644
--- a/src/tint/reader/wgsl/parser_impl_assignment_stmt_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_assignment_stmt_test.cc
@@ -36,8 +36,8 @@
     EXPECT_EQ(a->source.range.end.column, 4u);
 
     ASSERT_TRUE(a->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = a->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = a->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(a->rhs->Is<ast::IntLiteralExpression>());
     EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->value, 123);
@@ -72,8 +72,8 @@
     auto* mem = a->lhs->As<ast::MemberAccessorExpression>();
 
     ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
-    auto* ident = mem->member->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
+    auto* ident_expr = mem->member->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("d"));
 
     ASSERT_TRUE(mem->structure->Is<ast::IndexAccessorExpression>());
     auto* idx = mem->structure->As<ast::IndexAccessorExpression>();
@@ -85,19 +85,19 @@
     ASSERT_TRUE(idx->object->Is<ast::MemberAccessorExpression>());
     mem = idx->object->As<ast::MemberAccessorExpression>();
     ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
-    ident = mem->member->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
+    ident_expr = mem->member->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("c"));
 
     ASSERT_TRUE(mem->structure->Is<ast::MemberAccessorExpression>());
     mem = mem->structure->As<ast::MemberAccessorExpression>();
 
     ASSERT_TRUE(mem->structure->Is<ast::IdentifierExpression>());
-    ident = mem->structure->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = mem->structure->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
-    ident = mem->member->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = mem->member->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, AssignmentStmt_Parses_ToPhony) {
@@ -184,8 +184,8 @@
     EXPECT_EQ(a->source.range.end.column, 3u + params.str.length());
 
     ASSERT_TRUE(a->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = a->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = a->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(a->rhs->Is<ast::IntLiteralExpression>());
     EXPECT_EQ(a->rhs->As<ast::IntLiteralExpression>()->value, 123);
diff --git a/src/tint/reader/wgsl/parser_impl_bitwise_expression_test.cc b/src/tint/reader/wgsl/parser_impl_bitwise_expression_test.cc
index 9e95a3c..fcdeeb6 100644
--- a/src/tint/reader/wgsl/parser_impl_bitwise_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_bitwise_expression_test.cc
@@ -46,8 +46,8 @@
     EXPECT_EQ(ast::BinaryOp::kOr, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -70,8 +70,8 @@
     EXPECT_EQ(ast::BinaryOp::kOr, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
 
@@ -80,8 +80,8 @@
     rel = rel->lhs->As<ast::BinaryExpression>();
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -117,8 +117,8 @@
     EXPECT_EQ(ast::BinaryOp::kXor, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -140,8 +140,8 @@
     EXPECT_EQ(ast::BinaryOp::kXor, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
 
@@ -150,8 +150,8 @@
     rel = rel->lhs->As<ast::BinaryExpression>();
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -187,8 +187,8 @@
     EXPECT_EQ(ast::BinaryOp::kAnd, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Register("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -210,8 +210,8 @@
     EXPECT_EQ(ast::BinaryOp::kAnd, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("b"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Register("b"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
 
@@ -220,8 +220,8 @@
     rel = rel->lhs->As<ast::BinaryExpression>();
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Register("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
diff --git a/src/tint/reader/wgsl/parser_impl_core_lhs_expression_test.cc b/src/tint/reader/wgsl/parser_impl_core_lhs_expression_test.cc
index 81984eb..4264865 100644
--- a/src/tint/reader/wgsl/parser_impl_core_lhs_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_core_lhs_expression_test.cc
@@ -34,8 +34,8 @@
     ASSERT_NE(e.value, nullptr);
     ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
 
-    auto* ident = e->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("identifier"));
+    auto* ident_expr = e->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("identifier"));
 }
 
 TEST_F(ParserImplTest, CoreLHS_ParenStmt) {
@@ -47,8 +47,8 @@
     ASSERT_NE(e.value, nullptr);
     ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
 
-    auto* ident = e->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = e->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 }
 
 TEST_F(ParserImplTest, CoreLHS_MissingRightParen) {
diff --git a/src/tint/reader/wgsl/parser_impl_diagnostic_attribute_test.cc b/src/tint/reader/wgsl/parser_impl_diagnostic_attribute_test.cc
index aebd1a0..5f1fe72 100644
--- a/src/tint/reader/wgsl/parser_impl_diagnostic_attribute_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_diagnostic_attribute_test.cc
@@ -29,7 +29,7 @@
     EXPECT_EQ(d->control->severity, ast::DiagnosticSeverity::kOff);
     auto* r = As<ast::IdentifierExpression>(d->control->rule_name);
     ASSERT_NE(r, nullptr);
-    EXPECT_EQ(p->builder().Symbols().NameFor(r->symbol), "foo");
+    EXPECT_EQ(p->builder().Symbols().NameFor(r->identifier->symbol), "foo");
 }
 
 }  // namespace
diff --git a/src/tint/reader/wgsl/parser_impl_diagnostic_control_test.cc b/src/tint/reader/wgsl/parser_impl_diagnostic_control_test.cc
index 36de427..720340f 100644
--- a/src/tint/reader/wgsl/parser_impl_diagnostic_control_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_diagnostic_control_test.cc
@@ -34,7 +34,7 @@
 
     auto* r = As<ast::IdentifierExpression>(e->rule_name);
     ASSERT_NE(r, nullptr);
-    EXPECT_EQ(p->builder().Symbols().NameFor(r->symbol), "foo");
+    EXPECT_EQ(p->builder().Symbols().NameFor(r->identifier->symbol), "foo");
 }
 INSTANTIATE_TEST_SUITE_P(DiagnosticControlParserTest,
                          DiagnosticControlParserTest,
@@ -54,7 +54,7 @@
 
     auto* r = As<ast::IdentifierExpression>(e->rule_name);
     ASSERT_NE(r, nullptr);
-    EXPECT_EQ(p->builder().Symbols().NameFor(r->symbol), "foo");
+    EXPECT_EQ(p->builder().Symbols().NameFor(r->identifier->symbol), "foo");
 }
 
 TEST_F(ParserImplTest, DiagnosticControl_MissingOpenParen) {
diff --git a/src/tint/reader/wgsl/parser_impl_diagnostic_directive_test.cc b/src/tint/reader/wgsl/parser_impl_diagnostic_directive_test.cc
index c91b7d1..0eb5f7c 100644
--- a/src/tint/reader/wgsl/parser_impl_diagnostic_directive_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_diagnostic_directive_test.cc
@@ -32,7 +32,7 @@
 
     auto* r = As<ast::IdentifierExpression>(control->rule_name);
     ASSERT_NE(r, nullptr);
-    EXPECT_EQ(p->builder().Symbols().NameFor(r->symbol), "foo");
+    EXPECT_EQ(p->builder().Symbols().NameFor(r->identifier->symbol), "foo");
 }
 
 TEST_F(ParserImplTest, DiagnosticDirective_MissingSemicolon) {
diff --git a/src/tint/reader/wgsl/parser_impl_element_count_expression_test.cc b/src/tint/reader/wgsl/parser_impl_element_count_expression_test.cc
index 0dd287d..b629ef7 100644
--- a/src/tint/reader/wgsl/parser_impl_element_count_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_element_count_expression_test.cc
@@ -30,12 +30,12 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, ElementCountExpression_Bitwise) {
@@ -51,8 +51,8 @@
     EXPECT_EQ(ast::BinaryOp::kOr, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
diff --git a/src/tint/reader/wgsl/parser_impl_expression_test.cc b/src/tint/reader/wgsl/parser_impl_expression_test.cc
index 9ae4591..68b3be3 100644
--- a/src/tint/reader/wgsl/parser_impl_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_expression_test.cc
@@ -44,8 +44,8 @@
     EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -66,8 +66,8 @@
     EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: a
@@ -76,8 +76,8 @@
     EXPECT_EQ(ast::BinaryOp::kLogicalOr, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -111,8 +111,8 @@
     EXPECT_EQ(ast::BinaryOp::kLogicalAnd, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -133,16 +133,16 @@
     EXPECT_EQ(ast::BinaryOp::kLogicalAnd, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: a
     // rhs: true
     rel = rel->lhs->As<ast::BinaryExpression>();
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -191,12 +191,12 @@
     EXPECT_EQ(ast::BinaryOp::kAnd, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, Expression_Relational) {
@@ -212,12 +212,12 @@
     EXPECT_EQ(ast::BinaryOp::kLessThanEqual, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, Expression_InvalidUnary) {
diff --git a/src/tint/reader/wgsl/parser_impl_function_attribute_test.cc b/src/tint/reader/wgsl/parser_impl_function_attribute_test.cc
index 186c86a..a9b9818 100644
--- a/src/tint/reader/wgsl/parser_impl_function_attribute_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_function_attribute_test.cc
@@ -312,7 +312,7 @@
     ASSERT_NE(values[1], nullptr);
     auto* y_ident = values[1]->As<ast::IdentifierExpression>();
     ASSERT_NE(y_ident, nullptr);
-    EXPECT_EQ(p->builder().Symbols().NameFor(y_ident->symbol), "height");
+    EXPECT_EQ(p->builder().Symbols().NameFor(y_ident->identifier->symbol), "height");
 
     ASSERT_EQ(values[2], nullptr);
 }
diff --git a/src/tint/reader/wgsl/parser_impl_increment_decrement_stmt_test.cc b/src/tint/reader/wgsl/parser_impl_increment_decrement_stmt_test.cc
index 79220e4..7b273f5 100644
--- a/src/tint/reader/wgsl/parser_impl_increment_decrement_stmt_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_increment_decrement_stmt_test.cc
@@ -30,8 +30,8 @@
     ASSERT_NE(i->lhs, nullptr);
 
     ASSERT_TRUE(i->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = i->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = i->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     EXPECT_TRUE(i->increment);
 }
@@ -49,8 +49,8 @@
     ASSERT_NE(i->lhs, nullptr);
 
     ASSERT_TRUE(i->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = i->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = i->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     EXPECT_FALSE(i->increment);
 }
@@ -68,8 +68,8 @@
     ASSERT_NE(i->lhs, nullptr);
 
     ASSERT_TRUE(i->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = i->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = i->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     EXPECT_TRUE(i->increment);
 }
@@ -91,8 +91,8 @@
     auto* mem = i->lhs->As<ast::MemberAccessorExpression>();
 
     ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
-    auto* ident = mem->member->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
+    auto* ident_expr = mem->member->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("d"));
 
     ASSERT_TRUE(mem->structure->Is<ast::IndexAccessorExpression>());
     auto* idx = mem->structure->As<ast::IndexAccessorExpression>();
@@ -104,19 +104,19 @@
     ASSERT_TRUE(idx->object->Is<ast::MemberAccessorExpression>());
     mem = idx->object->As<ast::MemberAccessorExpression>();
     ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
-    ident = mem->member->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
+    ident_expr = mem->member->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("c"));
 
     ASSERT_TRUE(mem->structure->Is<ast::MemberAccessorExpression>());
     mem = mem->structure->As<ast::MemberAccessorExpression>();
 
     ASSERT_TRUE(mem->structure->Is<ast::IdentifierExpression>());
-    ident = mem->structure->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = mem->structure->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(mem->member->Is<ast::IdentifierExpression>());
-    ident = mem->member->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = mem->member->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, IncrementDecrementStmt_InvalidLHS) {
diff --git a/src/tint/reader/wgsl/parser_impl_lhs_expression_test.cc b/src/tint/reader/wgsl/parser_impl_lhs_expression_test.cc
index a8a476b..4801a01 100644
--- a/src/tint/reader/wgsl/parser_impl_lhs_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_lhs_expression_test.cc
@@ -121,7 +121,7 @@
     ASSERT_TRUE(access->object->Is<ast::IdentifierExpression>());
 
     auto* obj = access->object->As<ast::IdentifierExpression>();
-    EXPECT_EQ(obj->symbol, p->builder().Symbols().Get("a"));
+    EXPECT_EQ(obj->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(access->index->Is<ast::IntLiteralExpression>());
     auto* idx = access->index->As<ast::IntLiteralExpression>();
@@ -146,11 +146,11 @@
     ASSERT_TRUE(access->structure->Is<ast::IdentifierExpression>());
 
     auto* struct_ident = access->structure->As<ast::IdentifierExpression>();
-    EXPECT_EQ(struct_ident->symbol, p->builder().Symbols().Get("a"));
+    EXPECT_EQ(struct_ident->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(access->member->Is<ast::IdentifierExpression>());
     auto* member_ident = access->member->As<ast::IdentifierExpression>();
-    EXPECT_EQ(member_ident->symbol, p->builder().Symbols().Get("foo"));
+    EXPECT_EQ(member_ident->identifier->symbol, p->builder().Symbols().Get("foo"));
 }
 
 TEST_F(ParserImplTest, LHSExpression_InvalidPostfixExpression) {
diff --git a/src/tint/reader/wgsl/parser_impl_math_expression_test.cc b/src/tint/reader/wgsl/parser_impl_math_expression_test.cc
index 27b5870..2b05500 100644
--- a/src/tint/reader/wgsl/parser_impl_math_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_math_expression_test.cc
@@ -30,12 +30,12 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, MathExpression_Parses_Mixed_MultiplicativeStart) {
@@ -54,8 +54,8 @@
     EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("c"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: a
@@ -65,12 +65,12 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, MathExpression_Parses_Additive) {
@@ -86,12 +86,12 @@
     EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, MathExpression_Parses_Mixed_AdditiveStart) {
@@ -110,8 +110,8 @@
     EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BinaryExpression>());
     // lhs: b
@@ -121,12 +121,12 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("c"));
 }
 
 TEST_F(ParserImplTest, MathExpression_NoMatch_ReturnLHS) {
diff --git a/src/tint/reader/wgsl/parser_impl_multiplicative_expression_test.cc b/src/tint/reader/wgsl/parser_impl_multiplicative_expression_test.cc
index 9417477..10ed0fb 100644
--- a/src/tint/reader/wgsl/parser_impl_multiplicative_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_multiplicative_expression_test.cc
@@ -30,12 +30,12 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Multiply_UnaryIndirect) {
@@ -51,16 +51,16 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::UnaryOpExpression>());
     auto* unary = rel->rhs->As<ast::UnaryOpExpression>();
     EXPECT_EQ(ast::UnaryOp::kIndirection, unary->op);
 
     ASSERT_TRUE(unary->expr->Is<ast::IdentifierExpression>());
-    ident = unary->expr->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = unary->expr->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Divide) {
@@ -76,12 +76,12 @@
     EXPECT_EQ(ast::BinaryOp::kDivide, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Modulo) {
@@ -97,12 +97,12 @@
     EXPECT_EQ(ast::BinaryOp::kModulo, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, MultiplicativeExpression_Parses_Grouping) {
@@ -121,8 +121,8 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("e"));
+    auto* ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("e"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: (a * b) / c
@@ -132,8 +132,8 @@
     EXPECT_EQ(ast::BinaryOp::kModulo, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("d"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("d"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: a * b
@@ -143,8 +143,8 @@
     EXPECT_EQ(ast::BinaryOp::kDivide, rel->op);
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("c"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("c"));
 
     ASSERT_TRUE(rel->lhs->Is<ast::BinaryExpression>());
     // lhs: a
@@ -154,12 +154,12 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, MultiplicativeExpression_InvalidRHS) {
diff --git a/src/tint/reader/wgsl/parser_impl_primary_expression_test.cc b/src/tint/reader/wgsl/parser_impl_primary_expression_test.cc
index ec6561f..1ced9dd 100644
--- a/src/tint/reader/wgsl/parser_impl_primary_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_primary_expression_test.cc
@@ -26,8 +26,8 @@
     EXPECT_FALSE(p->has_error()) << p->error();
     ASSERT_NE(e.value, nullptr);
     ASSERT_TRUE(e->Is<ast::IdentifierExpression>());
-    auto* ident = e->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = e->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 }
 
 TEST_F(ParserImplTest, PrimaryExpression_TypeDecl) {
diff --git a/src/tint/reader/wgsl/parser_impl_relational_expression_test.cc b/src/tint/reader/wgsl/parser_impl_relational_expression_test.cc
index ebd8ffd..ddd275d 100644
--- a/src/tint/reader/wgsl/parser_impl_relational_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_relational_expression_test.cc
@@ -35,8 +35,8 @@
     EXPECT_EQ(ast::BinaryOp::kLessThan, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Register("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -60,8 +60,8 @@
     EXPECT_EQ(ast::BinaryOp::kGreaterThan, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Register("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -85,8 +85,8 @@
     EXPECT_EQ(ast::BinaryOp::kLessThanEqual, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Register("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -110,8 +110,8 @@
     EXPECT_EQ(ast::BinaryOp::kGreaterThanEqual, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Register("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -135,8 +135,8 @@
     EXPECT_EQ(ast::BinaryOp::kEqual, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -160,8 +160,8 @@
     EXPECT_EQ(ast::BinaryOp::kNotEqual, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -199,8 +199,8 @@
     EXPECT_EQ(ast::BinaryOp::kGreaterThanEqual, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Register("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Register("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -243,8 +243,8 @@
     EXPECT_EQ(ast::BinaryOp::kEqual, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -268,8 +268,8 @@
     EXPECT_EQ(ast::BinaryOp::kNotEqual, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
diff --git a/src/tint/reader/wgsl/parser_impl_shift_expression_test.cc b/src/tint/reader/wgsl/parser_impl_shift_expression_test.cc
index 016f86f..4e5c785 100644
--- a/src/tint/reader/wgsl/parser_impl_shift_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_shift_expression_test.cc
@@ -35,8 +35,8 @@
     EXPECT_EQ(ast::BinaryOp::kShiftLeft, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -60,8 +60,8 @@
     EXPECT_EQ(ast::BinaryOp::kShiftRight, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
@@ -80,12 +80,12 @@
     EXPECT_EQ(ast::BinaryOp::kAdd, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, ShiftExpression_PostUnary_Parses_Multiplicative) {
@@ -101,12 +101,12 @@
     EXPECT_EQ(ast::BinaryOp::kMultiply, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::IdentifierExpression>());
-    ident = rel->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("b"));
+    ident_expr = rel->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, ShiftExpression_PostUnary_InvalidSpaceLeft) {
@@ -160,8 +160,8 @@
     EXPECT_EQ(ast::BinaryOp::kShiftLeft, rel->op);
 
     ASSERT_TRUE(rel->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = rel->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = rel->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(rel->rhs->Is<ast::BoolLiteralExpression>());
     ASSERT_TRUE(rel->rhs->As<ast::BoolLiteralExpression>()->value);
diff --git a/src/tint/reader/wgsl/parser_impl_singular_expression_test.cc b/src/tint/reader/wgsl/parser_impl_singular_expression_test.cc
index a08b45a..3945693 100644
--- a/src/tint/reader/wgsl/parser_impl_singular_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_singular_expression_test.cc
@@ -29,8 +29,8 @@
     auto* idx = e->As<ast::IndexAccessorExpression>();
 
     ASSERT_TRUE(idx->object->Is<ast::IdentifierExpression>());
-    auto* ident = idx->object->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = idx->object->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(idx->index->Is<ast::IntLiteralExpression>());
     EXPECT_EQ(idx->index->As<ast::IntLiteralExpression>()->value, 1);
@@ -50,8 +50,8 @@
     auto* idx = e->As<ast::IndexAccessorExpression>();
 
     ASSERT_TRUE(idx->object->Is<ast::IdentifierExpression>());
-    auto* ident = idx->object->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = idx->object->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(idx->index->Is<ast::BinaryExpression>());
 }
@@ -164,11 +164,10 @@
 
     auto* m = e->As<ast::MemberAccessorExpression>();
     ASSERT_TRUE(m->structure->Is<ast::IdentifierExpression>());
-    EXPECT_EQ(m->structure->As<ast::IdentifierExpression>()->symbol,
+    EXPECT_EQ(m->structure->As<ast::IdentifierExpression>()->identifier->symbol,
               p->builder().Symbols().Get("a"));
 
-    ASSERT_TRUE(m->member->Is<ast::IdentifierExpression>());
-    EXPECT_EQ(m->member->As<ast::IdentifierExpression>()->symbol, p->builder().Symbols().Get("b"));
+    EXPECT_EQ(m->member->identifier->symbol, p->builder().Symbols().Get("b"));
 }
 
 TEST_F(ParserImplTest, SingularExpression_MemberAccesssor_InvalidIdent) {
@@ -214,18 +213,18 @@
 
     const auto* outer_object = outer_accessor->object->As<ast::IdentifierExpression>();
     ASSERT_TRUE(outer_object);
-    EXPECT_EQ(outer_object->symbol, p->builder().Symbols().Get("a"));
+    EXPECT_EQ(outer_object->identifier->symbol, p->builder().Symbols().Get("a"));
 
     const auto* inner_accessor = outer_accessor->index->As<ast::IndexAccessorExpression>();
     ASSERT_TRUE(inner_accessor);
 
     const auto* inner_object = inner_accessor->object->As<ast::IdentifierExpression>();
     ASSERT_TRUE(inner_object);
-    EXPECT_EQ(inner_object->symbol, p->builder().Symbols().Get("b"));
+    EXPECT_EQ(inner_object->identifier->symbol, p->builder().Symbols().Get("b"));
 
     const auto* index_expr = inner_accessor->index->As<ast::IdentifierExpression>();
     ASSERT_TRUE(index_expr);
-    EXPECT_EQ(index_expr->symbol, p->builder().Symbols().Get("c"));
+    EXPECT_EQ(index_expr->identifier->symbol, p->builder().Symbols().Get("c"));
 }
 
 }  // namespace
diff --git a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
index 0a4198e..0195d9b 100644
--- a/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_type_decl_test.cc
@@ -473,7 +473,7 @@
 
     auto* count_expr = a->count->As<ast::IdentifierExpression>();
     ASSERT_NE(count_expr, nullptr);
-    EXPECT_EQ(p->builder().Symbols().NameFor(count_expr->symbol), "size");
+    EXPECT_EQ(p->builder().Symbols().NameFor(count_expr->identifier->symbol), "size");
 }
 
 TEST_F(ParserImplTest, TypeDecl_Array_ExpressionSize) {
@@ -495,8 +495,8 @@
     EXPECT_EQ(ast::BinaryOp::kAdd, count_expr->op);
 
     ASSERT_TRUE(count_expr->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = count_expr->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(p->builder().Symbols().NameFor(ident->symbol), "size");
+    auto* ident_expr = count_expr->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(p->builder().Symbols().NameFor(ident_expr->identifier->symbol), "size");
 
     ASSERT_TRUE(count_expr->rhs->Is<ast::IntLiteralExpression>());
     auto* val = count_expr->rhs->As<ast::IntLiteralExpression>();
diff --git a/src/tint/reader/wgsl/parser_impl_type_decl_without_ident_test.cc b/src/tint/reader/wgsl/parser_impl_type_decl_without_ident_test.cc
index 409062a..0c9eb6e 100644
--- a/src/tint/reader/wgsl/parser_impl_type_decl_without_ident_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_type_decl_without_ident_test.cc
@@ -464,7 +464,7 @@
 
     auto* count_expr = a->count->As<ast::IdentifierExpression>();
     ASSERT_NE(count_expr, nullptr);
-    EXPECT_EQ(p->builder().Symbols().NameFor(count_expr->symbol), "size");
+    EXPECT_EQ(p->builder().Symbols().NameFor(count_expr->identifier->symbol), "size");
 }
 
 TEST_F(ParserImplTest, TypeDeclWithoutIdent_Array_ExpressionSize) {
@@ -487,7 +487,7 @@
 
     ASSERT_TRUE(count_expr->lhs->Is<ast::IdentifierExpression>());
     auto* ident = count_expr->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(p->builder().Symbols().NameFor(ident->symbol), "size");
+    EXPECT_EQ(p->builder().Symbols().NameFor(ident->identifier->symbol), "size");
 
     ASSERT_TRUE(count_expr->rhs->Is<ast::IntLiteralExpression>());
     auto* val = count_expr->rhs->As<ast::IntLiteralExpression>();
diff --git a/src/tint/reader/wgsl/parser_impl_unary_expression_test.cc b/src/tint/reader/wgsl/parser_impl_unary_expression_test.cc
index 29598d9..7d117f5 100644
--- a/src/tint/reader/wgsl/parser_impl_unary_expression_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_unary_expression_test.cc
@@ -29,8 +29,8 @@
     ASSERT_TRUE(e->Is<ast::IndexAccessorExpression>());
     auto* idx = e->As<ast::IndexAccessorExpression>();
     ASSERT_TRUE(idx->object->Is<ast::IdentifierExpression>());
-    auto* ident = idx->object->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("a"));
+    auto* ident_expr = idx->object->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("a"));
 
     ASSERT_TRUE(idx->index->Is<ast::IntLiteralExpression>());
     ASSERT_EQ(idx->index->As<ast::IntLiteralExpression>()->value, 2);
diff --git a/src/tint/reader/wgsl/parser_impl_variable_stmt_test.cc b/src/tint/reader/wgsl/parser_impl_variable_stmt_test.cc
index 05f2976..58d9a58 100644
--- a/src/tint/reader/wgsl/parser_impl_variable_stmt_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_variable_stmt_test.cc
@@ -171,12 +171,12 @@
     EXPECT_EQ(expr->op, ast::BinaryOp::kAdd);
 
     ASSERT_TRUE(expr->lhs->Is<ast::IdentifierExpression>());
-    auto* ident = expr->lhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("collide"));
+    auto* ident_expr = expr->lhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("collide"));
 
     ASSERT_TRUE(expr->rhs->Is<ast::IdentifierExpression>());
-    ident = expr->rhs->As<ast::IdentifierExpression>();
-    EXPECT_EQ(ident->symbol, p->builder().Symbols().Get("collide_1"));
+    ident_expr = expr->rhs->As<ast::IdentifierExpression>();
+    EXPECT_EQ(ident_expr->identifier->symbol, p->builder().Symbols().Get("collide_1"));
 }
 
 TEST_F(ParserImplTest, VariableStmt_Let_MissingEqual) {
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index 5da6303..c6e4e5b 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -354,7 +354,7 @@
             Switch(
                 expr,
                 [&](const ast::IdentifierExpression* ident) {
-                    AddDependency(ident, ident->symbol, "identifier", "references");
+                    AddDependency(ident, ident->identifier->symbol, "identifier", "references");
                 },
                 [&](const ast::CallExpression* call) {
                     if (call->target.name) {
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index ac45aac..69a0df0 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -2660,7 +2660,8 @@
 }
 
 sem::Expression* Resolver::Identifier(const ast::IdentifierExpression* expr) {
-    auto symbol = expr->symbol;
+    Mark(expr->identifier);
+    auto symbol = expr->identifier->symbol;
     auto* sem_resolved = sem_.ResolvedSymbol<sem::Node>(expr);
     if (auto* variable = As<sem::Variable>(sem_resolved)) {
         auto* user = builder_->create<sem::VariableUser>(expr, current_statement_, variable);
@@ -2765,11 +2766,13 @@
     // Object may be a side-effecting expression (e.g. function call).
     bool has_side_effects = object && object->HasSideEffects();
 
+    Mark(expr->member);
+    Mark(expr->member->identifier);
+
     return Switch(
         storage_ty,  //
         [&](const sem::Struct* str) -> sem::Expression* {
-            Mark(expr->member);
-            auto symbol = expr->member->symbol;
+            auto symbol = expr->member->identifier->symbol;
 
             const sem::StructMember* member = nullptr;
             for (auto* m : str->Members()) {
@@ -2802,8 +2805,7 @@
         },
 
         [&](const type::Vector* vec) -> sem::Expression* {
-            Mark(expr->member);
-            std::string s = builder_->Symbols().NameFor(expr->member->symbol);
+            std::string s = builder_->Symbols().NameFor(expr->member->identifier->symbol);
             auto size = s.size();
             utils::Vector<uint32_t, 4> swizzle;
             swizzle.Reserve(s.size());
@@ -3059,7 +3061,9 @@
 
 bool Resolver::DiagnosticControl(const ast::DiagnosticControl* control) {
     Mark(control->rule_name);
-    auto rule_name = builder_->Symbols().NameFor(control->rule_name->symbol);
+    Mark(control->rule_name->identifier);
+
+    auto rule_name = builder_->Symbols().NameFor(control->rule_name->identifier->symbol);
     auto rule = ast::ParseDiagnosticRule(rule_name);
     if (rule != ast::DiagnosticRule::kUndefined) {
         validator_.DiagnosticFilters().Set(rule, control->severity);
diff --git a/src/tint/resolver/resolver_test.cc b/src/tint/resolver/resolver_test.cc
index 0c0a344..32ec3c3 100644
--- a/src/tint/resolver/resolver_test.cc
+++ b/src/tint/resolver/resolver_test.cc
@@ -2074,11 +2074,11 @@
     EXPECT_FATAL_FAILURE(
         {
             ProgramBuilder b;
-            b.Expr("expr");
+            b.Ident("ident");
             Resolver(&b).Resolve();
         },
-        "internal compiler error: AST node 'tint::ast::IdentifierExpression' was not reached by "
-        "the resolver");
+        "internal compiler error: AST node 'tint::ast::Identifier' was not reached by the "
+        "resolver");
 }
 
 TEST_F(ResolverTest, ASTNodeReachedTwice) {
diff --git a/src/tint/resolver/uniformity.cc b/src/tint/resolver/uniformity.cc
index f5463a1..61cc726 100644
--- a/src/tint/resolver/uniformity.cc
+++ b/src/tint/resolver/uniformity.cc
@@ -1144,7 +1144,7 @@
 
         auto* var_user = sem_.Get(ident)->Unwrap()->As<sem::VariableUser>();
         auto* sem = var_user->Variable();
-        auto* node = CreateNode({NameFor(ident), "_ident_expr"}, ident);
+        auto* node = CreateNode({NameFor(ident->identifier), "_ident_expr"}, ident);
         return Switch(
             sem,
 
@@ -1365,7 +1365,7 @@
                     return std::make_pair(cf, current_function_->may_be_non_uniform);
                 } else if (auto* local = sem->Variable()->As<sem::LocalVariable>()) {
                     // Create a new value node for this variable.
-                    auto* value = CreateNode({NameFor(i), "_lvalue"});
+                    auto* value = CreateNode({NameFor(i->identifier), "_lvalue"});
                     auto* old_value = current_function_->variables.Set(local, value);
 
                     // If i is part of an expression that is a partial reference to a variable (e.g.
@@ -1769,10 +1769,10 @@
                 std::ostringstream ss;
                 if (auto* param = var->As<sem::Parameter>()) {
                     auto* func = param->Owner()->As<sem::Function>();
-                    ss << param_type(param) << "'" << NameFor(ident) << "' of '"
+                    ss << param_type(param) << "'" << NameFor(ident->identifier) << "' of '"
                        << NameFor(func->Declaration()) << "' may be non-uniform";
                 } else {
-                    ss << "reading from " << var_type(var) << "'" << NameFor(ident)
+                    ss << "reading from " << var_type(var) << "'" << NameFor(ident->identifier)
                        << "' may result in a non-uniform value";
                 }
                 diagnostics_.add_note(diag::System::Resolver, ss.str(), ident->source);
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index bba2f37..eeeab83 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -2452,7 +2452,7 @@
     // They conflict if the rule name is the same and the severity is different.
     utils::Hashmap<Symbol, const ast::DiagnosticControl*, 8> diagnostics;
     for (auto* dc : controls) {
-        auto diag_added = diagnostics.Add(dc->rule_name->symbol, dc);
+        auto diag_added = diagnostics.Add(dc->rule_name->identifier->symbol, dc);
         if (!diag_added && (*diag_added.value)->severity != dc->severity) {
             {
                 std::ostringstream ss;
@@ -2461,8 +2461,8 @@
             }
             {
                 std::ostringstream ss;
-                ss << "severity of '" << symbols_.NameFor(dc->rule_name->symbol) << "' set to '"
-                   << dc->severity << "' here";
+                ss << "severity of '" << symbols_.NameFor(dc->rule_name->identifier->symbol)
+                   << "' set to '" << dc->severity << "' here";
                 AddNote(ss.str(), (*diag_added.value)->source);
             }
             return false;
diff --git a/src/tint/transform/decompose_memory_access.cc b/src/tint/transform/decompose_memory_access.cc
index abb78b2..fdad12a 100644
--- a/src/tint/transform/decompose_memory_access.cc
+++ b/src/tint/transform/decompose_memory_access.cc
@@ -915,7 +915,7 @@
             } else {
                 if (auto access = state.TakeAccess(accessor->structure)) {
                     auto* str_ty = access.type->As<sem::Struct>();
-                    auto* member = str_ty->FindMember(accessor->member->symbol);
+                    auto* member = str_ty->FindMember(accessor->member->identifier->symbol);
                     auto offset = member->Offset();
                     state.AddAccess(accessor, {
                                                   access.var,
diff --git a/src/tint/transform/num_workgroups_from_uniform.cc b/src/tint/transform/num_workgroups_from_uniform.cc
index 47f4ad1..7fc9361 100644
--- a/src/tint/transform/num_workgroups_from_uniform.cc
+++ b/src/tint/transform/num_workgroups_from_uniform.cc
@@ -177,7 +177,7 @@
             continue;
         }
 
-        if (to_replace.count({ident->symbol, accessor->member->symbol})) {
+        if (to_replace.count({ident->identifier->symbol, accessor->member->identifier->symbol})) {
             ctx.Replace(accessor, b.MemberAccessor(get_ubo()->symbol, kNumWorkgroupsMemberName));
         }
     }
diff --git a/src/tint/transform/renamer.cc b/src/tint/transform/renamer.cc
index 325d3ac..a25b67b 100644
--- a/src/tint/transform/renamer.cc
+++ b/src/tint/transform/renamer.cc
@@ -1263,8 +1263,6 @@
 
     // Identifiers that need to keep their symbols preserved.
     utils::Hashset<const ast::Identifier*, 8> preserved_identifiers;
-    // Identifiers expressions that need to keep their symbols preserved.
-    utils::Hashset<const ast::IdentifierExpression*, 8> preserved_identifiers_expressions;
     // Type names that need to keep their symbols preserved.
     utils::Hashset<const ast::TypeName*, 8> preserved_type_names;
 
@@ -1289,11 +1287,11 @@
             [&](const ast::MemberAccessorExpression* accessor) {
                 auto* sem = src->Sem().Get(accessor)->UnwrapLoad();
                 if (sem->Is<sem::Swizzle>()) {
-                    preserved_identifiers_expressions.Add(accessor->member);
+                    preserved_identifiers.Add(accessor->member->identifier);
                 } else if (auto* str_expr = src->Sem().Get(accessor->structure)) {
                     if (auto* ty = str_expr->Type()->UnwrapRef()->As<sem::Struct>()) {
                         if (ty->Declaration() == nullptr) {  // Builtin structure
-                            preserved_identifiers_expressions.Add(accessor->member);
+                            preserved_identifiers.Add(accessor->member->identifier);
                         }
                     }
                 }
@@ -1316,7 +1314,7 @@
                 }
             },
             [&](const ast::DiagnosticControl* diagnostic) {
-                preserved_identifiers_expressions.Add(diagnostic->rule_name);
+                preserved_identifiers.Add(diagnostic->rule_name->identifier);
             },
             [&](const ast::TypeName* type_name) {
                 if (is_type_short_name(type_name->name)) {
@@ -1388,16 +1386,6 @@
         return nullptr;  // Clone ident. Uses the symbol remapping above.
     });
 
-    ctx.ReplaceAll([&](const ast::IdentifierExpression* ident) -> const ast::IdentifierExpression* {
-        if (preserved_identifiers_expressions.Contains(ident)) {
-            auto sym_in = ident->symbol;
-            auto str = src->Symbols().NameFor(sym_in);
-            auto sym_out = b.Symbols().Register(str);
-            return ctx.dst->create<ast::IdentifierExpression>(ctx.Clone(ident->source), sym_out);
-        }
-        return nullptr;  // Clone ident. Uses the symbol remapping above.
-    });
-
     ctx.ReplaceAll([&](const ast::TypeName* type_name) -> const ast::TypeName* {
         if (preserved_type_names.Contains(type_name)) {
             auto sym_in = type_name->name;
diff --git a/src/tint/writer/glsl/generator_impl.cc b/src/tint/writer/glsl/generator_impl.cc
index df49694..d28c900 100644
--- a/src/tint/writer/glsl/generator_impl.cc
+++ b/src/tint/writer/glsl/generator_impl.cc
@@ -1837,7 +1837,7 @@
 }
 
 bool GeneratorImpl::EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr) {
-    out << builder_.Symbols().NameFor(expr->symbol);
+    out << builder_.Symbols().NameFor(expr->identifier->symbol);
     return true;
 }
 
@@ -2731,7 +2731,7 @@
         sem,
         [&](const sem::Swizzle*) {
             // Swizzles output the name directly
-            out << builder_.Symbols().NameFor(expr->member->symbol);
+            out << builder_.Symbols().NameFor(expr->member->identifier->symbol);
             return true;
         },
         [&](const sem::StructMemberAccess* member_access) {
diff --git a/src/tint/writer/hlsl/generator_impl.cc b/src/tint/writer/hlsl/generator_impl.cc
index d49bcc9..df50d73 100644
--- a/src/tint/writer/hlsl/generator_impl.cc
+++ b/src/tint/writer/hlsl/generator_impl.cc
@@ -2816,7 +2816,7 @@
 }
 
 bool GeneratorImpl::EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr) {
-    out << builder_.Symbols().NameFor(expr->symbol);
+    out << builder_.Symbols().NameFor(expr->identifier->symbol);
     return true;
 }
 
@@ -3753,7 +3753,7 @@
         sem,
         [&](const sem::Swizzle*) {
             // Swizzles output the name directly
-            out << builder_.Symbols().NameFor(expr->member->symbol);
+            out << builder_.Symbols().NameFor(expr->member->identifier->symbol);
             return true;
         },
         [&](const sem::StructMemberAccess* member_access) {
diff --git a/src/tint/writer/msl/generator_impl.cc b/src/tint/writer/msl/generator_impl.cc
index 29ce69f..208c433 100644
--- a/src/tint/writer/msl/generator_impl.cc
+++ b/src/tint/writer/msl/generator_impl.cc
@@ -2101,7 +2101,7 @@
 }
 
 bool GeneratorImpl::EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr) {
-    out << program_->Symbols().NameFor(expr->symbol);
+    out << program_->Symbols().NameFor(expr->identifier->symbol);
     return true;
 }
 
@@ -2369,7 +2369,7 @@
                 if (!write_lhs()) {
                     return false;
                 }
-                out << ")." << program_->Symbols().NameFor(expr->member->symbol);
+                out << ")." << program_->Symbols().NameFor(expr->member->identifier->symbol);
             }
             return true;
         },
diff --git a/src/tint/writer/spirv/builder.cc b/src/tint/writer/spirv/builder.cc
index bab1f23..fab7744 100644
--- a/src/tint/writer/spirv/builder.cc
+++ b/src/tint/writer/spirv/builder.cc
@@ -1153,7 +1153,7 @@
             return LookupVariableID(user->Variable());
         }
     }
-    error_ = "identifier '" + builder_.Symbols().NameFor(expr->symbol) +
+    error_ = "identifier '" + builder_.Symbols().NameFor(expr->identifier->symbol) +
              "' does not resolve to a variable";
     return 0;
 }
diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc
index 3619c57..10a5399 100644
--- a/src/tint/writer/wgsl/generator_impl.cc
+++ b/src/tint/writer/wgsl/generator_impl.cc
@@ -110,7 +110,7 @@
 bool GeneratorImpl::EmitDiagnosticControl(std::ostream& out,
                                           const ast::DiagnosticControl* diagnostic) {
     out << "diagnostic(" << diagnostic->severity << ", "
-        << program_->Symbols().NameFor(diagnostic->rule_name->symbol) << ")";
+        << program_->Symbols().NameFor(diagnostic->rule_name->identifier->symbol) << ")";
     return true;
 }
 
@@ -298,7 +298,7 @@
 }
 
 bool GeneratorImpl::EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr) {
-    out << program_->Symbols().NameFor(expr->symbol);
+    out << program_->Symbols().NameFor(expr->identifier->symbol);
     return true;
 }