ast: Use IdentifierExpression for call targets

They are always identifiers, and this removes unnecessary type casting
from usages of CallExpression::func().

Change-Id: I7a11dc10658abab578395e20ad830cd5bc5a5b71
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/51960
Auto-Submit: James Price <jrprice@google.com>
Commit-Queue: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
diff --git a/src/ast/call_expression.cc b/src/ast/call_expression.cc
index 0ac44bf..e63b41f 100644
--- a/src/ast/call_expression.cc
+++ b/src/ast/call_expression.cc
@@ -23,7 +23,7 @@
 
 CallExpression::CallExpression(ProgramID program_id,
                                const Source& source,
-                               Expression* func,
+                               IdentifierExpression* func,
                                ExpressionList params)
     : Base(program_id, source), func_(func), params_(params) {
   TINT_ASSERT(func_);
diff --git a/src/ast/call_expression.h b/src/ast/call_expression.h
index c366d91..54d9711 100644
--- a/src/ast/call_expression.h
+++ b/src/ast/call_expression.h
@@ -20,6 +20,9 @@
 namespace tint {
 namespace ast {
 
+// Forward declarations.
+class IdentifierExpression;
+
 /// A call expression
 class CallExpression : public Castable<CallExpression, Expression> {
  public:
@@ -30,14 +33,14 @@
   /// @param params the parameters
   CallExpression(ProgramID program_id,
                  const Source& source,
-                 Expression* func,
+                 IdentifierExpression* func,
                  ExpressionList params);
   /// Move constructor
   CallExpression(CallExpression&&);
   ~CallExpression() override;
 
   /// @returns the func
-  Expression* func() const { return func_; }
+  IdentifierExpression* func() const { return func_; }
   /// @returns the parameters
   const ExpressionList& params() const { return params_; }
 
@@ -58,7 +61,7 @@
  private:
   CallExpression(const CallExpression&) = delete;
 
-  Expression* const func_;
+  IdentifierExpression* const func_;
   ExpressionList const params_;
 };
 
diff --git a/src/reader/wgsl/parser_impl_call_stmt_test.cc b/src/reader/wgsl/parser_impl_call_stmt_test.cc
index ec41195..28dc2c8 100644
--- a/src/reader/wgsl/parser_impl_call_stmt_test.cc
+++ b/src/reader/wgsl/parser_impl_call_stmt_test.cc
@@ -31,9 +31,7 @@
   ASSERT_TRUE(e->Is<ast::CallStatement>());
   auto* c = e->As<ast::CallStatement>()->expr();
 
-  ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
-  auto* ident = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("a"));
 
   EXPECT_EQ(c->params().size(), 0u);
 }
@@ -49,9 +47,7 @@
   ASSERT_TRUE(e->Is<ast::CallStatement>());
   auto* c = e->As<ast::CallStatement>()->expr();
 
-  ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
-  auto* ident = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("a"));
 
   EXPECT_EQ(c->params().size(), 3u);
   EXPECT_TRUE(c->params()[0]->Is<ast::ConstructorExpression>());
@@ -70,9 +66,7 @@
   ASSERT_TRUE(e->Is<ast::CallStatement>());
   auto* c = e->As<ast::CallStatement>()->expr();
 
-  ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
-  auto* ident = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(ident->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("a"));
 
   EXPECT_EQ(c->params().size(), 2u);
   EXPECT_TRUE(c->params()[0]->Is<ast::ConstructorExpression>());
diff --git a/src/reader/wgsl/parser_impl_singular_expression_test.cc b/src/reader/wgsl/parser_impl_singular_expression_test.cc
index d74d1bf..ee73c87 100644
--- a/src/reader/wgsl/parser_impl_singular_expression_test.cc
+++ b/src/reader/wgsl/parser_impl_singular_expression_test.cc
@@ -100,9 +100,7 @@
   ASSERT_TRUE(e->Is<ast::CallExpression>());
   auto* c = e->As<ast::CallExpression>();
 
-  ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
-  auto* func = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(func->symbol(), p->builder().Symbols().Get("a"));
+  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("a"));
 
   EXPECT_EQ(c->params().size(), 0u);
 }
@@ -118,9 +116,7 @@
   ASSERT_TRUE(e->Is<ast::CallExpression>());
   auto* c = e->As<ast::CallExpression>();
 
-  ASSERT_TRUE(c->func()->Is<ast::IdentifierExpression>());
-  auto* func = c->func()->As<ast::IdentifierExpression>();
-  EXPECT_EQ(func->symbol(), p->builder().Symbols().Get("test"));
+  EXPECT_EQ(c->func()->symbol(), p->builder().Symbols().Get("test"));
 
   EXPECT_EQ(c->params().size(), 3u);
   EXPECT_TRUE(c->params()[0]->Is<ast::ConstructorExpression>());
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index e63800f..757da88 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -1626,16 +1626,8 @@
     return false;
   }
 
-  // The expression has to be an identifier as you can't store function
-  // pointers but, if it isn't we'll just use the normal result determination
-  // to be on the safe side.
   Mark(call->func());
-  auto* ident = call->func()->As<ast::IdentifierExpression>();
-  if (!ident) {
-    diagnostics_.add_error("call target is not an identifier", call->source());
-    return false;
-  }
-
+  auto* ident = call->func();
   auto name = builder_->Symbols().NameFor(ident->symbol());
 
   auto intrinsic_type = sem::ParseIntrinsicType(name);
diff --git a/src/transform/renamer.cc b/src/transform/renamer.cc
index 9cd9abd..d1371b2 100644
--- a/src/transform/renamer.cc
+++ b/src/transform/renamer.cc
@@ -871,7 +871,7 @@
         continue;
       }
       if (sem->Target()->Is<sem::Intrinsic>()) {
-        preserve.emplace(call->func()->As<ast::IdentifierExpression>());
+        preserve.emplace(call->func());
       }
     }
   }
diff --git a/src/writer/hlsl/generator_impl.cc b/src/writer/hlsl/generator_impl.cc
index 5a3621b..1c2d3f0 100644
--- a/src/writer/hlsl/generator_impl.cc
+++ b/src/writer/hlsl/generator_impl.cc
@@ -461,13 +461,8 @@
 bool GeneratorImpl::EmitCall(std::ostream& pre,
                              std::ostream& out,
                              ast::CallExpression* expr) {
-  auto* ident = expr->func()->As<ast::IdentifierExpression>();
-  if (ident == nullptr) {
-    diagnostics_.add_error("invalid function name");
-    return 0;
-  }
-
   const auto& params = expr->params();
+  auto* ident = expr->func();
   auto* call = builder_.Sem().Get(expr);
   auto* target = call->Target();
 
diff --git a/src/writer/msl/generator_impl.cc b/src/writer/msl/generator_impl.cc
index e569945..ed64bf9 100644
--- a/src/writer/msl/generator_impl.cc
+++ b/src/writer/msl/generator_impl.cc
@@ -319,13 +319,7 @@
 }
 
 bool GeneratorImpl::EmitCall(ast::CallExpression* expr) {
-  auto* ident = expr->func()->As<ast::IdentifierExpression>();
-
-  if (ident == nullptr) {
-    diagnostics_.add_error("invalid function name");
-    return 0;
-  }
-
+  auto* ident = expr->func();
   auto* call = program_->Sem().Get(expr);
   if (auto* intrinsic = call->Target()->As<sem::Intrinsic>()) {
     if (intrinsic->IsTexture()) {
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index e10bab5..a7af47f 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -1892,13 +1892,7 @@
 }
 
 uint32_t Builder::GenerateCallExpression(ast::CallExpression* expr) {
-  auto* ident = expr->func()->As<ast::IdentifierExpression>();
-
-  if (ident == nullptr) {
-    error_ = "invalid function name";
-    return 0;
-  }
-
+  auto* ident = expr->func();
   auto* call = builder_.Sem().Get(expr);
   auto* target = call->Target();
   if (auto* intrinsic = target->As<sem::Intrinsic>()) {