Add a symbol to the Identifier AST node

This CL adds a Symbol to the identifier to represent the name. The name
still exists but will be removed in a future CL when the namers are in
place.

Change-Id: Ic3cc8ad0d99e3bea6eb1ff1ce212e7de67991aec
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35460
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Auto-Submit: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/ast/array_accessor_expression_test.cc b/src/ast/array_accessor_expression_test.cc
index 9526284..9bb30e0 100644
--- a/src/ast/array_accessor_expression_test.cc
+++ b/src/ast/array_accessor_expression_test.cc
@@ -24,8 +24,8 @@
 using ArrayAccessorExpressionTest = TestHelper;
 
 TEST_F(ArrayAccessorExpressionTest, Create) {
-  auto* ary = create<IdentifierExpression>("ary");
-  auto* idx = create<IdentifierExpression>("idx");
+  auto* ary = create<IdentifierExpression>(mod.RegisterSymbol("ary"), "ary");
+  auto* idx = create<IdentifierExpression>(mod.RegisterSymbol("idx"), "idx");
 
   ArrayAccessorExpression exp(ary, idx);
   ASSERT_EQ(exp.array(), ary);
@@ -33,8 +33,8 @@
 }
 
 TEST_F(ArrayAccessorExpressionTest, CreateWithSource) {
-  auto* ary = create<IdentifierExpression>("ary");
-  auto* idx = create<IdentifierExpression>("idx");
+  auto* ary = create<IdentifierExpression>(mod.RegisterSymbol("ary"), "ary");
+  auto* idx = create<IdentifierExpression>(mod.RegisterSymbol("idx"), "idx");
 
   ArrayAccessorExpression exp(Source{Source::Location{20, 2}}, ary, idx);
   auto src = exp.source();
@@ -43,58 +43,58 @@
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsArrayAccessor) {
-  auto* ary = create<IdentifierExpression>("ary");
-  auto* idx = create<IdentifierExpression>("idx");
+  auto* ary = create<IdentifierExpression>(mod.RegisterSymbol("ary"), "ary");
+  auto* idx = create<IdentifierExpression>(mod.RegisterSymbol("idx"), "idx");
 
   ArrayAccessorExpression exp(ary, idx);
   EXPECT_TRUE(exp.Is<ArrayAccessorExpression>());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid) {
-  auto* ary = create<IdentifierExpression>("ary");
-  auto* idx = create<IdentifierExpression>("idx");
+  auto* ary = create<IdentifierExpression>(mod.RegisterSymbol("ary"), "ary");
+  auto* idx = create<IdentifierExpression>(mod.RegisterSymbol("idx"), "idx");
 
   ArrayAccessorExpression exp(ary, idx);
   EXPECT_TRUE(exp.IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid_MissingArray) {
-  auto* idx = create<IdentifierExpression>("idx");
+  auto* idx = create<IdentifierExpression>(mod.RegisterSymbol("idx"), "idx");
 
   ArrayAccessorExpression exp(nullptr, idx);
   EXPECT_FALSE(exp.IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid_MissingIndex) {
-  auto* ary = create<IdentifierExpression>("ary");
+  auto* ary = create<IdentifierExpression>(mod.RegisterSymbol("ary"), "ary");
 
   ArrayAccessorExpression exp(ary, nullptr);
   EXPECT_FALSE(exp.IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid_InvalidArray) {
-  auto* ary = create<IdentifierExpression>("");
-  auto* idx = create<IdentifierExpression>("idx");
+  auto* ary = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
+  auto* idx = create<IdentifierExpression>(mod.RegisterSymbol("idx"), "idx");
   ArrayAccessorExpression exp(ary, idx);
   EXPECT_FALSE(exp.IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, IsValid_InvalidIndex) {
-  auto* ary = create<IdentifierExpression>("ary");
-  auto* idx = create<IdentifierExpression>("");
+  auto* ary = create<IdentifierExpression>(mod.RegisterSymbol("ary"), "ary");
+  auto* idx = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
   ArrayAccessorExpression exp(ary, idx);
   EXPECT_FALSE(exp.IsValid());
 }
 
 TEST_F(ArrayAccessorExpressionTest, ToStr) {
-  auto* ary = create<IdentifierExpression>("ary");
-  auto* idx = create<IdentifierExpression>("idx");
+  auto* ary = create<IdentifierExpression>(mod.RegisterSymbol("ary"), "ary");
+  auto* idx = create<IdentifierExpression>(mod.RegisterSymbol("idx"), "idx");
 
   ArrayAccessorExpression exp(ary, idx);
   std::ostringstream out;
   exp.to_str(out, 2);
 
-  EXPECT_EQ(out.str(), R"(  ArrayAccessor[not set]{
+  EXPECT_EQ(demangle(out.str()), R"(  ArrayAccessor[not set]{
     Identifier[not set]{ary}
     Identifier[not set]{idx}
   }
diff --git a/src/ast/assignment_statement_test.cc b/src/ast/assignment_statement_test.cc
index 8fa68a4..4f69c58 100644
--- a/src/ast/assignment_statement_test.cc
+++ b/src/ast/assignment_statement_test.cc
@@ -24,8 +24,8 @@
 using AssignmentStatementTest = TestHelper;
 
 TEST_F(AssignmentStatementTest, Creation) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   AssignmentStatement stmt(lhs, rhs);
   EXPECT_EQ(stmt.lhs(), lhs);
@@ -33,8 +33,8 @@
 }
 
 TEST_F(AssignmentStatementTest, CreationWithSource) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   AssignmentStatement stmt(Source{Source::Location{20, 2}}, lhs, rhs);
   auto src = stmt.source();
@@ -43,58 +43,58 @@
 }
 
 TEST_F(AssignmentStatementTest, IsAssign) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   AssignmentStatement stmt(lhs, rhs);
   EXPECT_TRUE(stmt.Is<AssignmentStatement>());
 }
 
 TEST_F(AssignmentStatementTest, IsValid) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   AssignmentStatement stmt(lhs, rhs);
   EXPECT_TRUE(stmt.IsValid());
 }
 
 TEST_F(AssignmentStatementTest, IsValid_MissingLHS) {
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   AssignmentStatement stmt(nullptr, rhs);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(AssignmentStatementTest, IsValid_MissingRHS) {
-  auto* lhs = create<IdentifierExpression>("lhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
 
   AssignmentStatement stmt(lhs, nullptr);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(AssignmentStatementTest, IsValid_InvalidLHS) {
-  auto* lhs = create<IdentifierExpression>("");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
   AssignmentStatement stmt(lhs, rhs);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(AssignmentStatementTest, IsValid_InvalidRHS) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
   AssignmentStatement stmt(lhs, rhs);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(AssignmentStatementTest, ToStr) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   AssignmentStatement stmt(lhs, rhs);
   std::ostringstream out;
   stmt.to_str(out, 2);
 
-  EXPECT_EQ(out.str(), R"(  Assignment{
+  EXPECT_EQ(demangle(out.str()), R"(  Assignment{
     Identifier[not set]{lhs}
     Identifier[not set]{rhs}
   }
diff --git a/src/ast/binary_expression_test.cc b/src/ast/binary_expression_test.cc
index 6494a78..ecba1ac 100644
--- a/src/ast/binary_expression_test.cc
+++ b/src/ast/binary_expression_test.cc
@@ -26,8 +26,8 @@
 using BinaryExpressionTest = TestHelper;
 
 TEST_F(BinaryExpressionTest, Creation) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   BinaryExpression r(BinaryOp::kEqual, lhs, rhs);
   EXPECT_EQ(r.lhs(), lhs);
@@ -36,8 +36,8 @@
 }
 
 TEST_F(BinaryExpressionTest, Creation_WithSource) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   BinaryExpression r(Source{Source::Location{20, 2}}, BinaryOp::kEqual, lhs,
                      rhs);
@@ -47,67 +47,67 @@
 }
 
 TEST_F(BinaryExpressionTest, IsBinary) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   BinaryExpression r(BinaryOp::kEqual, lhs, rhs);
   EXPECT_TRUE(r.Is<BinaryExpression>());
 }
 
 TEST_F(BinaryExpressionTest, IsValid) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   BinaryExpression r(BinaryOp::kEqual, lhs, rhs);
   EXPECT_TRUE(r.IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Null_LHS) {
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   BinaryExpression r(BinaryOp::kEqual, nullptr, rhs);
   EXPECT_FALSE(r.IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Invalid_LHS) {
-  auto* lhs = create<IdentifierExpression>("");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   BinaryExpression r(BinaryOp::kEqual, lhs, rhs);
   EXPECT_FALSE(r.IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Null_RHS) {
-  auto* lhs = create<IdentifierExpression>("lhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
 
   BinaryExpression r(BinaryOp::kEqual, lhs, nullptr);
   EXPECT_FALSE(r.IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Invalid_RHS) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
 
   BinaryExpression r(BinaryOp::kEqual, lhs, rhs);
   EXPECT_FALSE(r.IsValid());
 }
 
 TEST_F(BinaryExpressionTest, IsValid_Binary_None) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   BinaryExpression r(BinaryOp::kNone, lhs, rhs);
   EXPECT_FALSE(r.IsValid());
 }
 
 TEST_F(BinaryExpressionTest, ToStr) {
-  auto* lhs = create<IdentifierExpression>("lhs");
-  auto* rhs = create<IdentifierExpression>("rhs");
+  auto* lhs = create<IdentifierExpression>(mod.RegisterSymbol("lhs"), "lhs");
+  auto* rhs = create<IdentifierExpression>(mod.RegisterSymbol("rhs"), "rhs");
 
   BinaryExpression r(BinaryOp::kEqual, lhs, rhs);
   std::ostringstream out;
   r.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Binary[not set]{
+  EXPECT_EQ(demangle(out.str()), R"(  Binary[not set]{
     Identifier[not set]{lhs}
     equal
     Identifier[not set]{rhs}
diff --git a/src/ast/bitcast_expression_test.cc b/src/ast/bitcast_expression_test.cc
index 1c8afc1..ebf8ec0 100644
--- a/src/ast/bitcast_expression_test.cc
+++ b/src/ast/bitcast_expression_test.cc
@@ -26,7 +26,7 @@
 
 TEST_F(BitcastExpressionTest, Create) {
   type::F32 f32;
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
 
   BitcastExpression exp(&f32, expr);
   ASSERT_EQ(exp.type(), &f32);
@@ -35,7 +35,7 @@
 
 TEST_F(BitcastExpressionTest, CreateWithSource) {
   type::F32 f32;
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
 
   BitcastExpression exp(Source{Source::Location{20, 2}}, &f32, expr);
   auto src = exp.source();
@@ -45,7 +45,7 @@
 
 TEST_F(BitcastExpressionTest, IsBitcast) {
   type::F32 f32;
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
 
   BitcastExpression exp(&f32, expr);
   EXPECT_TRUE(exp.Is<BitcastExpression>());
@@ -53,14 +53,14 @@
 
 TEST_F(BitcastExpressionTest, IsValid) {
   type::F32 f32;
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
 
   BitcastExpression exp(&f32, expr);
   EXPECT_TRUE(exp.IsValid());
 }
 
 TEST_F(BitcastExpressionTest, IsValid_MissingType) {
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
 
   BitcastExpression exp(nullptr, expr);
   EXPECT_FALSE(exp.IsValid());
@@ -75,20 +75,20 @@
 
 TEST_F(BitcastExpressionTest, IsValid_InvalidExpr) {
   type::F32 f32;
-  auto* expr = create<IdentifierExpression>("");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
   BitcastExpression e(&f32, expr);
   EXPECT_FALSE(e.IsValid());
 }
 
 TEST_F(BitcastExpressionTest, ToStr) {
   type::F32 f32;
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
 
   BitcastExpression exp(&f32, expr);
   std::ostringstream out;
   exp.to_str(out, 2);
 
-  EXPECT_EQ(out.str(), R"(  Bitcast[not set]<__f32>{
+  EXPECT_EQ(demangle(out.str()), R"(  Bitcast[not set]<__f32>{
     Identifier[not set]{expr}
   }
 )");
diff --git a/src/ast/builder.h b/src/ast/builder.h
index 4a01d50..189ebdb 100644
--- a/src/ast/builder.h
+++ b/src/ast/builder.h
@@ -206,13 +206,13 @@
   /// @param name the identifier name
   /// @return an IdentifierExpression with the given name
   IdentifierExpression* Expr(const std::string& name) {
-    return create<IdentifierExpression>(name);
+    return create<IdentifierExpression>(mod->RegisterSymbol(name), name);
   }
 
   /// @param name the identifier name
   /// @return an IdentifierExpression with the given name
   IdentifierExpression* Expr(const char* name) {
-    return create<IdentifierExpression>(name);
+    return create<IdentifierExpression>(mod->RegisterSymbol(name), name);
   }
 
   /// @param value the boolean value
diff --git a/src/ast/call_expression_test.cc b/src/ast/call_expression_test.cc
index be84072..4b59395 100644
--- a/src/ast/call_expression_test.cc
+++ b/src/ast/call_expression_test.cc
@@ -24,10 +24,12 @@
 using CallExpressionTest = TestHelper;
 
 TEST_F(CallExpressionTest, Creation) {
-  auto* func = create<IdentifierExpression>("func");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol("func"), "func");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>("param1"));
-  params.push_back(create<IdentifierExpression>("param2"));
+  params.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("param1"), "param1"));
+  params.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("param2"), "param2"));
 
   CallExpression stmt(func, params);
   EXPECT_EQ(stmt.func(), func);
@@ -39,7 +41,7 @@
 }
 
 TEST_F(CallExpressionTest, Creation_WithSource) {
-  auto* func = create<IdentifierExpression>("func");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol("func"), "func");
   CallExpression stmt(Source{Source::Location{20, 2}}, func, {});
   auto src = stmt.source();
   EXPECT_EQ(src.range.begin.line, 20u);
@@ -47,13 +49,13 @@
 }
 
 TEST_F(CallExpressionTest, IsCall) {
-  auto* func = create<IdentifierExpression>("func");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol("func"), "func");
   CallExpression stmt(func, {});
   EXPECT_TRUE(stmt.Is<CallExpression>());
 }
 
 TEST_F(CallExpressionTest, IsValid) {
-  auto* func = create<IdentifierExpression>("func");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol("func"), "func");
   CallExpression stmt(func, {});
   EXPECT_TRUE(stmt.IsValid());
 }
@@ -64,40 +66,43 @@
 }
 
 TEST_F(CallExpressionTest, IsValid_NullParam) {
-  auto* func = create<IdentifierExpression>("func");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol("func"), "func");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>("param1"));
+  params.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("param1"), "param1"));
   params.push_back(nullptr);
-  params.push_back(create<IdentifierExpression>("param2"));
+  params.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("param2"), "param2"));
 
   CallExpression stmt(func, params);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(CallExpressionTest, IsValid_InvalidFunction) {
-  auto* func = create<IdentifierExpression>("");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>("param1"));
+  params.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("param1"), "param1"));
 
   CallExpression stmt(func, params);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(CallExpressionTest, IsValid_InvalidParam) {
-  auto* func = create<IdentifierExpression>("func");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol("func"), "func");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>(""));
+  params.push_back(create<IdentifierExpression>(mod.RegisterSymbol(""), ""));
 
   CallExpression stmt(func, params);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(CallExpressionTest, ToStr_NoParams) {
-  auto* func = create<IdentifierExpression>("func");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol("func"), "func");
   CallExpression stmt(func, {});
   std::ostringstream out;
   stmt.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Call[not set]{
+  EXPECT_EQ(demangle(out.str()), R"(  Call[not set]{
     Identifier[not set]{func}
     (
     )
@@ -106,15 +111,17 @@
 }
 
 TEST_F(CallExpressionTest, ToStr_WithParams) {
-  auto* func = create<IdentifierExpression>("func");
+  auto* func = create<IdentifierExpression>(mod.RegisterSymbol("func"), "func");
   ExpressionList params;
-  params.push_back(create<IdentifierExpression>("param1"));
-  params.push_back(create<IdentifierExpression>("param2"));
+  params.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("param1"), "param1"));
+  params.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("param2"), "param2"));
 
   CallExpression stmt(func, params);
   std::ostringstream out;
   stmt.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Call[not set]{
+  EXPECT_EQ(demangle(out.str()), R"(  Call[not set]{
     Identifier[not set]{func}
     (
       Identifier[not set]{param1}
diff --git a/src/ast/call_statement_test.cc b/src/ast/call_statement_test.cc
index 8a0e7b5..44f3604 100644
--- a/src/ast/call_statement_test.cc
+++ b/src/ast/call_statement_test.cc
@@ -25,8 +25,9 @@
 using CallStatementTest = TestHelper;
 
 TEST_F(CallStatementTest, Creation) {
-  auto* expr = create<CallExpression>(create<IdentifierExpression>("func"),
-                                      ExpressionList{});
+  auto* expr = create<CallExpression>(
+      create<IdentifierExpression>(mod.RegisterSymbol("func"), "func"),
+      ExpressionList{});
 
   CallStatement c(expr);
   EXPECT_EQ(c.expr(), expr);
@@ -38,8 +39,9 @@
 }
 
 TEST_F(CallStatementTest, IsValid) {
-  CallStatement c(create<CallExpression>(create<IdentifierExpression>("func"),
-                                         ExpressionList{}));
+  CallStatement c(create<CallExpression>(
+      create<IdentifierExpression>(mod.RegisterSymbol("func"), "func"),
+      ExpressionList{}));
   EXPECT_TRUE(c.IsValid());
 }
 
@@ -55,12 +57,13 @@
 }
 
 TEST_F(CallStatementTest, ToStr) {
-  CallStatement c(create<CallExpression>(create<IdentifierExpression>("func"),
-                                         ExpressionList{}));
+  CallStatement c(create<CallExpression>(
+      create<IdentifierExpression>(mod.RegisterSymbol("func"), "func"),
+      ExpressionList{}));
 
   std::ostringstream out;
   c.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Call[not set]{
+  EXPECT_EQ(demangle(out.str()), R"(  Call[not set]{
     Identifier[not set]{func}
     (
     )
diff --git a/src/ast/identifier_expression.cc b/src/ast/identifier_expression.cc
index d4770db..04ae344 100644
--- a/src/ast/identifier_expression.cc
+++ b/src/ast/identifier_expression.cc
@@ -22,28 +22,30 @@
 namespace tint {
 namespace ast {
 
-IdentifierExpression::IdentifierExpression(const std::string& name)
-    : Base(), name_(name) {}
+IdentifierExpression::IdentifierExpression(Symbol sym, const std::string& name)
+    : Base(), sym_(sym), name_(name) {}
 
 IdentifierExpression::IdentifierExpression(const Source& source,
+                                           Symbol sym,
                                            const std::string& name)
-    : Base(source), name_(name) {}
+    : Base(source), sym_(sym), name_(name) {}
 
 IdentifierExpression::IdentifierExpression(IdentifierExpression&&) = default;
 
 IdentifierExpression::~IdentifierExpression() = default;
 
 IdentifierExpression* IdentifierExpression::Clone(CloneContext* ctx) const {
-  return ctx->mod->create<IdentifierExpression>(ctx->Clone(source()), name_);
+  return ctx->mod->create<IdentifierExpression>(ctx->Clone(source()), sym_,
+                                                name_);
 }
 
 bool IdentifierExpression::IsValid() const {
-  return !name_.empty();
+  return sym_.IsValid();
 }
 
 void IdentifierExpression::to_str(std::ostream& out, size_t indent) const {
   make_indent(out, indent);
-  out << "Identifier[" << result_type_str() << "]{" << name_ << "}"
+  out << "Identifier[" << result_type_str() << "]{" << sym_.to_str() << "}"
       << std::endl;
 }
 
diff --git a/src/ast/identifier_expression.h b/src/ast/identifier_expression.h
index 703c041..9fa2660 100644
--- a/src/ast/identifier_expression.h
+++ b/src/ast/identifier_expression.h
@@ -21,6 +21,7 @@
 
 #include "src/ast/expression.h"
 #include "src/ast/intrinsic.h"
+#include "src/symbol.h"
 
 namespace tint {
 namespace ast {
@@ -29,16 +30,22 @@
 class IdentifierExpression : public Castable<IdentifierExpression, Expression> {
  public:
   /// Constructor
+  /// @param sym the symbol for the identifier
   /// @param name the name
-  explicit IdentifierExpression(const std::string& name);
+  explicit IdentifierExpression(Symbol sym, const std::string& name);
   /// Constructor
   /// @param source the source
+  /// @param sym the symbol for the identifier
   /// @param name the name
-  IdentifierExpression(const Source& source, const std::string& name);
+  IdentifierExpression(const Source& source,
+                       Symbol sym,
+                       const std::string& name);
   /// Move constructor
   IdentifierExpression(IdentifierExpression&&);
   ~IdentifierExpression() override;
 
+  /// @returns the symbol for the identifier
+  Symbol symbol() const { return sym_; }
   /// @returns the name part of the identifier
   std::string name() const { return name_; }
 
@@ -82,6 +89,7 @@
 
   Intrinsic intrinsic_ = Intrinsic::kNone;
   std::unique_ptr<intrinsic::Signature> intrinsic_sig_;
+  Symbol sym_;
   std::string name_;
 };
 
diff --git a/src/ast/identifier_expression_test.cc b/src/ast/identifier_expression_test.cc
index 7ef416e..a81f9cd 100644
--- a/src/ast/identifier_expression_test.cc
+++ b/src/ast/identifier_expression_test.cc
@@ -23,12 +23,15 @@
 using IdentifierExpressionTest = TestHelper;
 
 TEST_F(IdentifierExpressionTest, Creation) {
-  IdentifierExpression i("ident");
+  IdentifierExpression i(mod.RegisterSymbol("ident"), "ident");
+  EXPECT_EQ(i.symbol(), Symbol(1));
   EXPECT_EQ(i.name(), "ident");
 }
 
 TEST_F(IdentifierExpressionTest, Creation_WithSource) {
-  IdentifierExpression i(Source{Source::Location{20, 2}}, "ident");
+  IdentifierExpression i(Source{Source::Location{20, 2}},
+                         mod.RegisterSymbol("ident"), "ident");
+  EXPECT_EQ(i.symbol(), Symbol(1));
   EXPECT_EQ(i.name(), "ident");
 
   auto src = i.source();
@@ -37,25 +40,20 @@
 }
 
 TEST_F(IdentifierExpressionTest, IsIdentifier) {
-  IdentifierExpression i("ident");
+  IdentifierExpression i(mod.RegisterSymbol("ident"), "ident");
   EXPECT_TRUE(i.Is<IdentifierExpression>());
 }
 
 TEST_F(IdentifierExpressionTest, IsValid) {
-  IdentifierExpression i("ident");
+  IdentifierExpression i(mod.RegisterSymbol("ident"), "ident");
   EXPECT_TRUE(i.IsValid());
 }
 
-TEST_F(IdentifierExpressionTest, IsValid_BlankName) {
-  IdentifierExpression i("");
-  EXPECT_FALSE(i.IsValid());
-}
-
 TEST_F(IdentifierExpressionTest, ToStr) {
-  IdentifierExpression i("ident");
+  IdentifierExpression i(mod.RegisterSymbol("ident"), "ident");
   std::ostringstream out;
   i.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Identifier[not set]{ident}
+  EXPECT_EQ(demangle(out.str()), R"(  Identifier[not set]{ident}
 )");
 }
 
diff --git a/src/ast/if_statement_test.cc b/src/ast/if_statement_test.cc
index e3117cd..3314e9d 100644
--- a/src/ast/if_statement_test.cc
+++ b/src/ast/if_statement_test.cc
@@ -25,7 +25,7 @@
 using IfStatementTest = TestHelper;
 
 TEST_F(IfStatementTest, Creation) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
@@ -43,7 +43,7 @@
 }
 
 TEST_F(IfStatementTest, IsValid) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
@@ -52,14 +52,15 @@
 }
 
 TEST_F(IfStatementTest, IsValid_WithElseStatements) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
   IfStatement stmt(
       Source{}, cond, body,
       {
-          create<ElseStatement>(create<IdentifierExpression>("Ident"),
+          create<ElseStatement>(create<IdentifierExpression>(
+                                    mod.RegisterSymbol("Ident"), "Ident"),
                                 create<BlockStatement>()),
           create<ElseStatement>(create<BlockStatement>()),
       });
@@ -75,7 +76,7 @@
 }
 
 TEST_F(IfStatementTest, IsValid_InvalidCondition) {
-  auto* cond = create<IdentifierExpression>("");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
@@ -84,7 +85,7 @@
 }
 
 TEST_F(IfStatementTest, IsValid_NullBodyStatement) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
   body->append(nullptr);
@@ -94,7 +95,7 @@
 }
 
 TEST_F(IfStatementTest, IsValid_InvalidBodyStatement) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
   body->append(create<IfStatement>(Source{}, nullptr, create<BlockStatement>(),
@@ -105,14 +106,15 @@
 }
 
 TEST_F(IfStatementTest, IsValid_NullElseStatement) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
   IfStatement stmt(
       Source{}, cond, body,
       {
-          create<ElseStatement>(create<IdentifierExpression>("Ident"),
+          create<ElseStatement>(create<IdentifierExpression>(
+                                    mod.RegisterSymbol("Ident"), "Ident"),
                                 create<BlockStatement>()),
           create<ElseStatement>(create<BlockStatement>()),
           nullptr,
@@ -121,20 +123,21 @@
 }
 
 TEST_F(IfStatementTest, IsValid_InvalidElseStatement) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
   IfStatement stmt(Source{}, cond, body,
                    {
-                       create<ElseStatement>(create<IdentifierExpression>(""),
+                       create<ElseStatement>(create<IdentifierExpression>(
+                                                 mod.RegisterSymbol(""), ""),
                                              create<BlockStatement>()),
                    });
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(IfStatementTest, IsValid_MultipleElseWiththoutCondition) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
@@ -147,7 +150,7 @@
 }
 
 TEST_F(IfStatementTest, IsValid_ElseNotLast) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
@@ -155,14 +158,15 @@
       Source{}, cond, body,
       {
           create<ElseStatement>(create<BlockStatement>()),
-          create<ElseStatement>(create<IdentifierExpression>("ident"),
+          create<ElseStatement>(create<IdentifierExpression>(
+                                    mod.RegisterSymbol("ident"), "ident"),
                                 create<BlockStatement>()),
       });
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(IfStatementTest, ToStr) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
@@ -170,7 +174,7 @@
 
   std::ostringstream out;
   stmt.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  If{
+  EXPECT_EQ(demangle(out.str()), R"(  If{
     (
       Identifier[not set]{cond}
     )
@@ -182,7 +186,7 @@
 }
 
 TEST_F(IfStatementTest, ToStr_WithElseStatements) {
-  auto* cond = create<IdentifierExpression>("cond");
+  auto* cond = create<IdentifierExpression>(mod.RegisterSymbol("cond"), "cond");
   auto* body = create<BlockStatement>();
   body->append(create<DiscardStatement>());
 
@@ -193,16 +197,18 @@
   else_body->append(create<DiscardStatement>());
   else_body->append(create<DiscardStatement>());
 
-  IfStatement stmt(Source{}, cond, body,
-                   {
-                       create<ElseStatement>(
-                           create<IdentifierExpression>("ident"), else_if_body),
-                       create<ElseStatement>(else_body),
-                   });
+  IfStatement stmt(
+      Source{}, cond, body,
+      {
+          create<ElseStatement>(create<IdentifierExpression>(
+                                    mod.RegisterSymbol("ident"), "ident"),
+                                else_if_body),
+          create<ElseStatement>(else_body),
+      });
 
   std::ostringstream out;
   stmt.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  If{
+  EXPECT_EQ(demangle(out.str()), R"(  If{
     (
       Identifier[not set]{cond}
     )
diff --git a/src/ast/member_accessor_expression_test.cc b/src/ast/member_accessor_expression_test.cc
index d307b80..3985ce1 100644
--- a/src/ast/member_accessor_expression_test.cc
+++ b/src/ast/member_accessor_expression_test.cc
@@ -26,8 +26,10 @@
 using MemberAccessorExpressionTest = TestHelper;
 
 TEST_F(MemberAccessorExpressionTest, Creation) {
-  auto* str = create<IdentifierExpression>("structure");
-  auto* mem = create<IdentifierExpression>("member");
+  auto* str = create<IdentifierExpression>(mod.RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem =
+      create<IdentifierExpression>(mod.RegisterSymbol("member"), "member");
 
   MemberAccessorExpression stmt(str, mem);
   EXPECT_EQ(stmt.structure(), str);
@@ -35,8 +37,10 @@
 }
 
 TEST_F(MemberAccessorExpressionTest, Creation_WithSource) {
-  auto* str = create<IdentifierExpression>("structure");
-  auto* mem = create<IdentifierExpression>("member");
+  auto* str = create<IdentifierExpression>(mod.RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem =
+      create<IdentifierExpression>(mod.RegisterSymbol("member"), "member");
 
   MemberAccessorExpression stmt(Source{Source::Location{20, 2}}, str, mem);
   auto src = stmt.source();
@@ -45,59 +49,69 @@
 }
 
 TEST_F(MemberAccessorExpressionTest, IsMemberAccessor) {
-  auto* str = create<IdentifierExpression>("structure");
-  auto* mem = create<IdentifierExpression>("member");
+  auto* str = create<IdentifierExpression>(mod.RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem =
+      create<IdentifierExpression>(mod.RegisterSymbol("member"), "member");
 
   MemberAccessorExpression stmt(str, mem);
   EXPECT_TRUE(stmt.Is<MemberAccessorExpression>());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid) {
-  auto* str = create<IdentifierExpression>("structure");
-  auto* mem = create<IdentifierExpression>("member");
+  auto* str = create<IdentifierExpression>(mod.RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem =
+      create<IdentifierExpression>(mod.RegisterSymbol("member"), "member");
 
   MemberAccessorExpression stmt(str, mem);
   EXPECT_TRUE(stmt.IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid_NullStruct) {
-  auto* mem = create<IdentifierExpression>("member");
+  auto* mem =
+      create<IdentifierExpression>(mod.RegisterSymbol("member"), "member");
 
   MemberAccessorExpression stmt(nullptr, mem);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid_InvalidStruct) {
-  auto* str = create<IdentifierExpression>("");
-  auto* mem = create<IdentifierExpression>("member");
+  auto* str = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
+  auto* mem =
+      create<IdentifierExpression>(mod.RegisterSymbol("member"), "member");
 
   MemberAccessorExpression stmt(str, mem);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid_NullMember) {
-  auto* str = create<IdentifierExpression>("structure");
+  auto* str = create<IdentifierExpression>(mod.RegisterSymbol("structure"),
+                                           "structure");
 
   MemberAccessorExpression stmt(str, nullptr);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, IsValid_InvalidMember) {
-  auto* str = create<IdentifierExpression>("structure");
-  auto* mem = create<IdentifierExpression>("");
+  auto* str = create<IdentifierExpression>(mod.RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
 
   MemberAccessorExpression stmt(str, mem);
   EXPECT_FALSE(stmt.IsValid());
 }
 
 TEST_F(MemberAccessorExpressionTest, ToStr) {
-  auto* str = create<IdentifierExpression>("structure");
-  auto* mem = create<IdentifierExpression>("member");
+  auto* str = create<IdentifierExpression>(mod.RegisterSymbol("structure"),
+                                           "structure");
+  auto* mem =
+      create<IdentifierExpression>(mod.RegisterSymbol("member"), "member");
 
   MemberAccessorExpression stmt(str, mem);
   std::ostringstream out;
   stmt.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  MemberAccessor[not set]{
+  EXPECT_EQ(demangle(out.str()), R"(  MemberAccessor[not set]{
     Identifier[not set]{structure}
     Identifier[not set]{member}
   }
diff --git a/src/ast/module.cc b/src/ast/module.cc
index 2132e1f..32dfbef 100644
--- a/src/ast/module.cc
+++ b/src/ast/module.cc
@@ -38,6 +38,10 @@
 }
 
 void Module::Clone(CloneContext* ctx) {
+  // Symbol table must be cloned first so that the resulting module has the
+  // symbols before we start the tree mutations.
+  ctx->mod->symbol_table_ = symbol_table_;
+
   for (auto* ty : constructed_types_) {
     ctx->mod->constructed_types_.emplace_back(ctx->Clone(ty));
   }
@@ -47,8 +51,6 @@
   for (auto* func : functions_) {
     ctx->mod->functions_.emplace_back(ctx->Clone(func));
   }
-
-  ctx->mod->symbol_table_ = symbol_table_;
 }
 
 Function* Module::FindFunctionBySymbol(Symbol sym) const {
diff --git a/src/ast/return_statement_test.cc b/src/ast/return_statement_test.cc
index 8e9e525..c7d46b0 100644
--- a/src/ast/return_statement_test.cc
+++ b/src/ast/return_statement_test.cc
@@ -26,7 +26,7 @@
 using ReturnStatementTest = TestHelper;
 
 TEST_F(ReturnStatementTest, Creation) {
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
 
   ReturnStatement r(Source{}, expr);
   EXPECT_EQ(r.value(), expr);
@@ -50,7 +50,7 @@
 }
 
 TEST_F(ReturnStatementTest, HasValue_WithValue) {
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
   ReturnStatement r(Source{}, expr);
   EXPECT_TRUE(r.has_value());
 }
@@ -61,23 +61,23 @@
 }
 
 TEST_F(ReturnStatementTest, IsValid_WithValue) {
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
   ReturnStatement r(Source{}, expr);
   EXPECT_TRUE(r.IsValid());
 }
 
 TEST_F(ReturnStatementTest, IsValid_InvalidValue) {
-  auto* expr = create<IdentifierExpression>("");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
   ReturnStatement r(Source{}, expr);
   EXPECT_FALSE(r.IsValid());
 }
 
 TEST_F(ReturnStatementTest, ToStr_WithValue) {
-  auto* expr = create<IdentifierExpression>("expr");
+  auto* expr = create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr");
   ReturnStatement r(Source{}, expr);
   std::ostringstream out;
   r.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Return{
+  EXPECT_EQ(demangle(out.str()), R"(  Return{
     {
       Identifier[not set]{expr}
     }
diff --git a/src/ast/switch_statement_test.cc b/src/ast/switch_statement_test.cc
index df82f3d..bd610fa 100644
--- a/src/ast/switch_statement_test.cc
+++ b/src/ast/switch_statement_test.cc
@@ -34,7 +34,8 @@
   CaseSelectorList lit;
   lit.push_back(create<SintLiteral>(&i32, 1));
 
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   CaseStatementList body;
   auto* case_stmt = create<CaseStatement>(lit, create<BlockStatement>());
   body.push_back(case_stmt);
@@ -46,7 +47,8 @@
 }
 
 TEST_F(SwitchStatementTest, Creation_WithSource) {
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
 
   SwitchStatement stmt(Source{Source::Location{20, 2}}, ident,
                        CaseStatementList());
@@ -61,7 +63,8 @@
   CaseSelectorList lit;
   lit.push_back(create<SintLiteral>(&i32, 2));
 
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   CaseStatementList body;
   body.push_back(create<CaseStatement>(lit, create<BlockStatement>()));
 
@@ -75,7 +78,8 @@
   CaseSelectorList lit;
   lit.push_back(create<SintLiteral>(&i32, 2));
 
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   CaseStatementList body;
   body.push_back(create<CaseStatement>(lit, create<BlockStatement>()));
 
@@ -102,7 +106,7 @@
   CaseSelectorList lit;
   lit.push_back(create<SintLiteral>(&i32, 2));
 
-  auto* ident = create<IdentifierExpression>("");
+  auto* ident = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
   CaseStatementList body;
   body.push_back(create<CaseStatement>(lit, create<BlockStatement>()));
 
@@ -116,7 +120,8 @@
   CaseSelectorList lit;
   lit.push_back(create<SintLiteral>(&i32, 2));
 
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   CaseStatementList body;
   body.push_back(create<CaseStatement>(lit, create<BlockStatement>()));
   body.push_back(nullptr);
@@ -126,7 +131,8 @@
 }
 
 TEST_F(SwitchStatementTest, IsValid_Invalid_BodyStatement) {
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
 
   auto* case_body = create<BlockStatement>();
   case_body->append(nullptr);
@@ -139,12 +145,13 @@
 }
 
 TEST_F(SwitchStatementTest, ToStr_Empty) {
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
 
   SwitchStatement stmt(ident, {});
   std::ostringstream out;
   stmt.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Switch{
+  EXPECT_EQ(demangle(out.str()), R"(  Switch{
     Identifier[not set]{ident}
     {
     }
@@ -158,14 +165,15 @@
   CaseSelectorList lit;
   lit.push_back(create<SintLiteral>(&i32, 2));
 
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   CaseStatementList body;
   body.push_back(create<CaseStatement>(lit, create<BlockStatement>()));
 
   SwitchStatement stmt(ident, body);
   std::ostringstream out;
   stmt.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Switch{
+  EXPECT_EQ(demangle(out.str()), R"(  Switch{
     Identifier[not set]{ident}
     {
       Case 2{
diff --git a/src/ast/type_constructor_expression_test.cc b/src/ast/type_constructor_expression_test.cc
index d7efed7..3fbf937 100644
--- a/src/ast/type_constructor_expression_test.cc
+++ b/src/ast/type_constructor_expression_test.cc
@@ -32,7 +32,8 @@
 TEST_F(TypeConstructorExpressionTest, Creation) {
   type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>("expr"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr"));
 
   TypeConstructorExpression t(&f32, expr);
   EXPECT_EQ(t.type(), &f32);
@@ -43,7 +44,8 @@
 TEST_F(TypeConstructorExpressionTest, Creation_WithSource) {
   type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>("expr"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr"));
 
   TypeConstructorExpression t(Source{Source::Location{20, 2}}, &f32, expr);
   auto src = t.source();
@@ -54,7 +56,8 @@
 TEST_F(TypeConstructorExpressionTest, IsTypeConstructor) {
   type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>("expr"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr"));
 
   TypeConstructorExpression t(&f32, expr);
   EXPECT_TRUE(t.Is<TypeConstructorExpression>());
@@ -63,7 +66,8 @@
 TEST_F(TypeConstructorExpressionTest, IsValid) {
   type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>("expr"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr"));
 
   TypeConstructorExpression t(&f32, expr);
   EXPECT_TRUE(t.IsValid());
@@ -79,7 +83,8 @@
 
 TEST_F(TypeConstructorExpressionTest, IsValid_NullType) {
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>("expr"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr"));
 
   TypeConstructorExpression t(nullptr, expr);
   EXPECT_FALSE(t.IsValid());
@@ -88,7 +93,8 @@
 TEST_F(TypeConstructorExpressionTest, IsValid_NullValue) {
   type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>("expr"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr"));
   expr.push_back(nullptr);
 
   TypeConstructorExpression t(&f32, expr);
@@ -98,7 +104,7 @@
 TEST_F(TypeConstructorExpressionTest, IsValid_InvalidValue) {
   type::F32 f32;
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>(""));
+  expr.push_back(create<IdentifierExpression>(mod.RegisterSymbol(""), ""));
 
   TypeConstructorExpression t(&f32, expr);
   EXPECT_FALSE(t.IsValid());
@@ -108,14 +114,17 @@
   type::F32 f32;
   type::Vector vec(&f32, 3);
   ExpressionList expr;
-  expr.push_back(create<IdentifierExpression>("expr_1"));
-  expr.push_back(create<IdentifierExpression>("expr_2"));
-  expr.push_back(create<IdentifierExpression>("expr_3"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr_1"), "expr_1"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr_2"), "expr_2"));
+  expr.push_back(
+      create<IdentifierExpression>(mod.RegisterSymbol("expr_3"), "expr_3"));
 
   TypeConstructorExpression t(&vec, expr);
   std::ostringstream out;
   t.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  TypeConstructor[not set]{
+  EXPECT_EQ(demangle(out.str()), R"(  TypeConstructor[not set]{
     __vec_3__f32
     Identifier[not set]{expr_1}
     Identifier[not set]{expr_2}
diff --git a/src/ast/unary_op_expression_test.cc b/src/ast/unary_op_expression_test.cc
index 5e3ec1f..532d8cb 100644
--- a/src/ast/unary_op_expression_test.cc
+++ b/src/ast/unary_op_expression_test.cc
@@ -26,7 +26,8 @@
 using UnaryOpExpressionTest = TestHelper;
 
 TEST_F(UnaryOpExpressionTest, Creation) {
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
 
   UnaryOpExpression u(UnaryOp::kNot, ident);
   EXPECT_EQ(u.op(), UnaryOp::kNot);
@@ -34,7 +35,8 @@
 }
 
 TEST_F(UnaryOpExpressionTest, Creation_WithSource) {
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   UnaryOpExpression u(Source{Source::Location{20, 2}}, UnaryOp::kNot, ident);
   auto src = u.source();
   EXPECT_EQ(src.range.begin.line, 20u);
@@ -42,13 +44,15 @@
 }
 
 TEST_F(UnaryOpExpressionTest, IsUnaryOp) {
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   UnaryOpExpression u(UnaryOp::kNot, ident);
   EXPECT_TRUE(u.Is<UnaryOpExpression>());
 }
 
 TEST_F(UnaryOpExpressionTest, IsValid) {
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   UnaryOpExpression u(UnaryOp::kNot, ident);
   EXPECT_TRUE(u.IsValid());
 }
@@ -59,17 +63,18 @@
 }
 
 TEST_F(UnaryOpExpressionTest, IsValid_InvalidExpression) {
-  auto* ident = create<IdentifierExpression>("");
+  auto* ident = create<IdentifierExpression>(mod.RegisterSymbol(""), "");
   UnaryOpExpression u(UnaryOp::kNot, ident);
   EXPECT_FALSE(u.IsValid());
 }
 
 TEST_F(UnaryOpExpressionTest, ToStr) {
-  auto* ident = create<IdentifierExpression>("ident");
+  auto* ident =
+      create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident");
   UnaryOpExpression u(UnaryOp::kNot, ident);
   std::ostringstream out;
   u.to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  UnaryOp[not set]{
+  EXPECT_EQ(demangle(out.str()), R"(  UnaryOp[not set]{
     not
     Identifier[not set]{ident}
   }
diff --git a/src/ast/variable_test.cc b/src/ast/variable_test.cc
index 5465883..ac95d69 100644
--- a/src/ast/variable_test.cc
+++ b/src/ast/variable_test.cc
@@ -84,7 +84,7 @@
              StorageClass::kNone,
              &t,
              false,
-             create<IdentifierExpression>("ident"),
+             create<IdentifierExpression>(mod.RegisterSymbol("ident"), "ident"),
              ast::VariableDecorationList{}};
   EXPECT_TRUE(v.IsValid());
 }
@@ -115,7 +115,7 @@
              StorageClass::kNone,
              &t,
              false,
-             create<IdentifierExpression>(""),
+             create<IdentifierExpression>(mod.RegisterSymbol(""), ""),
              ast::VariableDecorationList{}};
   EXPECT_FALSE(v.IsValid());
 }
@@ -162,16 +162,17 @@
 
 TEST_F(VariableTest, Decorated_to_str) {
   type::F32 t;
-  auto* var = create<Variable>(Source{}, "my_var", StorageClass::kFunction, &t,
-                               false, create<IdentifierExpression>("expr"),
-                               VariableDecorationList{
-                                   create<BindingDecoration>(2, Source{}),
-                                   create<SetDecoration>(1, Source{}),
-                               });
+  auto* var = create<Variable>(
+      Source{}, "my_var", StorageClass::kFunction, &t, false,
+      create<IdentifierExpression>(mod.RegisterSymbol("expr"), "expr"),
+      VariableDecorationList{
+          create<BindingDecoration>(2, Source{}),
+          create<SetDecoration>(1, Source{}),
+      });
 
   std::ostringstream out;
   var->to_str(out, 2);
-  EXPECT_EQ(out.str(), R"(  Variable{
+  EXPECT_EQ(demangle(out.str()), R"(  Variable{
     Decorations{
       BindingDecoration{2}
       SetDecoration{1}