[type-determiner] Fixup handling of unknown identifiers.

This Cl updates the identifier type determination check to fail if the
identifier is not found and is not an intrinsic method.

Bug: tint:139
Change-Id: I332dd7fb42dae62bdee459c4a8819bdb5685c903
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/30081
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com>
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 06e8a2a..acc5b53 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -369,7 +369,6 @@
   if (!DetermineResultType(expr->expr())) {
     return false;
   }
-
   expr->set_result_type(expr->type());
   return true;
 }
@@ -787,12 +786,15 @@
     return true;
   }
 
-  SetIntrinsicIfNeeded(expr);
-
+  if (!SetIntrinsicIfNeeded(expr)) {
+    set_error(expr->source(),
+              "v-0006: identifier must be declared before use: " + name);
+    return false;
+  }
   return true;
 }
 
-void TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
+bool TypeDeterminer::SetIntrinsicIfNeeded(ast::IdentifierExpression* ident) {
   if (ident->name() == "abs") {
     ident->set_intrinsic(ast::Intrinsic::kAbs);
   } else if (ident->name() == "acos") {
@@ -927,7 +929,10 @@
     ident->set_intrinsic(ast::Intrinsic::kTextureSampleLevel);
   } else if (ident->name() == "trunc") {
     ident->set_intrinsic(ast::Intrinsic::kTrunc);
+  } else {
+    return false;
   }
+  return true;
 }
 
 bool TypeDeterminer::DetermineMemberAccessor(
diff --git a/src/type_determiner.h b/src/type_determiner.h
index 482a439b..30fc548 100644
--- a/src/type_determiner.h
+++ b/src/type_determiner.h
@@ -108,7 +108,8 @@
 
   /// Sets the intrinsic data information for the identifier if needed
   /// @param ident the identifier expression
-  void SetIntrinsicIfNeeded(ast::IdentifierExpression* ident);
+  /// @returns true if an intrinsic was set
+  bool SetIntrinsicIfNeeded(ast::IdentifierExpression* ident);
 
  private:
   void set_error(const Source& src, const std::string& msg);
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index e80c60f..df8b79c 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -400,7 +400,7 @@
   ast::type::F32Type f32;
   ast::ExpressionList call_params;
   auto call_expr = std::make_unique<ast::CallExpression>(
-      Source{12, 34}, std::make_unique<ast::IdentifierExpression>("func"),
+      std::make_unique<ast::IdentifierExpression>(Source{12, 34}, "func"),
       std::move(call_params));
   ast::VariableList params0;
   auto func_main =
@@ -419,7 +419,7 @@
 
   EXPECT_FALSE(td()->Determine()) << td()->error();
   EXPECT_EQ(td()->error(),
-            "12:34: v-0005: function must be declared before use: 'func'");
+            "12:34: v-0006: identifier must be declared before use: func");
 }
 
 TEST_F(TypeDeterminerTest, Stmt_VariableDecl) {
@@ -615,6 +615,9 @@
   ast::BitcastExpression bitcast(
       &f32, std::make_unique<ast::IdentifierExpression>("name"));
 
+  ast::Variable v("name", ast::StorageClass::kPrivate, &f32);
+  td()->RegisterVariableForTesting(&v);
+
   EXPECT_TRUE(td()->DetermineResultType(&bitcast));
   ASSERT_NE(bitcast.result_type(), nullptr);
   EXPECT_TRUE(bitcast.result_type()->IsF32());
@@ -688,9 +691,11 @@
 
   ast::ExpressionList params;
   params.push_back(std::make_unique<ast::IdentifierExpression>("name"));
-
   ast::TypeConstructorExpression cast(&f32, std::move(params));
 
+  ast::Variable v("name", ast::StorageClass::kPrivate, &f32);
+  td()->RegisterVariableForTesting(&v);
+
   EXPECT_TRUE(td()->DetermineResultType(&cast));
   ASSERT_NE(cast.result_type(), nullptr);
   EXPECT_TRUE(cast.result_type()->IsF32());
@@ -852,6 +857,11 @@
   EXPECT_TRUE(ident.result_type()->IsF32());
 }
 
+TEST_F(TypeDeterminerTest, Expr_Identifier_Unknown) {
+  ast::IdentifierExpression a("a");
+  EXPECT_FALSE(td()->DetermineResultType(&a));
+}
+
 TEST_F(TypeDeterminerTest, Function_RegisterInputOutputVariables) {
   ast::type::F32Type f32;
 
@@ -1005,8 +1015,11 @@
 
   mod()->AddFunction(std::move(func));
 
+  ast::Variable v("var", ast::StorageClass::kFunction, &f32);
+  td()->RegisterVariableForTesting(&v);
+
   // Register the function
-  EXPECT_TRUE(td()->Determine());
+  EXPECT_TRUE(td()->Determine()) << td()->error();
 
   EXPECT_EQ(func_ptr->referenced_module_variables().size(), 0u);
 }
@@ -2478,7 +2491,7 @@
   auto param = GetParam();
 
   ast::IdentifierExpression ident(param.name);
-  td()->SetIntrinsicIfNeeded(&ident);
+  EXPECT_TRUE(td()->SetIntrinsicIfNeeded(&ident));
   EXPECT_EQ(ident.intrinsic(), param.intrinsic);
   EXPECT_TRUE(ident.IsIntrinsic());
 }
@@ -2558,7 +2571,7 @@
 
 TEST_F(TypeDeterminerTest, IntrinsicNotSetIfNotMatched) {
   ast::IdentifierExpression ident("not_intrinsic");
-  td()->SetIntrinsicIfNeeded(&ident);
+  EXPECT_FALSE(td()->SetIntrinsicIfNeeded(&ident));
   EXPECT_EQ(ident.intrinsic(), ast::Intrinsic::kNone);
   EXPECT_FALSE(ident.IsIntrinsic());
 }
@@ -4726,6 +4739,17 @@
   mod()->AddFunction(std::move(ep_1));
   mod()->AddFunction(std::move(ep_2));
 
+  mod()->AddGlobalVariable(std::make_unique<ast::Variable>(
+      "first", ast::StorageClass::kPrivate, &f32));
+  mod()->AddGlobalVariable(std::make_unique<ast::Variable>(
+      "second", ast::StorageClass::kPrivate, &f32));
+  mod()->AddGlobalVariable(std::make_unique<ast::Variable>(
+      "call_a", ast::StorageClass::kPrivate, &f32));
+  mod()->AddGlobalVariable(std::make_unique<ast::Variable>(
+      "call_b", ast::StorageClass::kPrivate, &f32));
+  mod()->AddGlobalVariable(std::make_unique<ast::Variable>(
+      "call_c", ast::StorageClass::kPrivate, &f32));
+
   // Register the functions and calculate the callers
   ASSERT_TRUE(td()->Determine()) << td()->error();
 
diff --git a/src/validator_test.cc b/src/validator_test.cc
index 62ada22..4bcab97 100644
--- a/src/validator_test.cc
+++ b/src/validator_test.cc
@@ -87,9 +87,9 @@
   auto assign = std::make_unique<ast::AssignmentStatement>(
       Source{12, 34}, std::move(lhs), std::move(rhs));
 
-  EXPECT_TRUE(td()->DetermineResultType(assign.get())) << td()->error();
-  EXPECT_FALSE(v()->ValidateStatement(assign.get()));
-  EXPECT_EQ(v()->error(), "12:34: v-0006: 'b' is not declared");
+  EXPECT_FALSE(td()->DetermineResultType(assign.get()));
+  EXPECT_EQ(td()->error(),
+            "12:34: v-0006: identifier must be declared before use: b");
 }
 
 TEST_F(ValidatorTest, UsingUndefinedVariableInBlockStatement_Fail) {
@@ -106,9 +106,9 @@
   body->append(std::make_unique<ast::AssignmentStatement>(
       Source{12, 34}, std::move(lhs), std::move(rhs)));
 
-  EXPECT_TRUE(td()->DetermineStatements(body.get())) << td()->error();
-  EXPECT_FALSE(v()->ValidateStatements(body.get()));
-  EXPECT_EQ(v()->error(), "12:34: v-0006: 'b' is not declared");
+  EXPECT_FALSE(td()->DetermineStatements(body.get()));
+  EXPECT_EQ(td()->error(),
+            "12:34: v-0006: identifier must be declared before use: b");
 }
 
 TEST_F(ValidatorTest, AssignCompatibleTypes_Pass) {
diff --git a/src/writer/hlsl/generator_impl_intrinsic_test.cc b/src/writer/hlsl/generator_impl_intrinsic_test.cc
index 7860c75..78db9f9 100644
--- a/src/writer/hlsl/generator_impl_intrinsic_test.cc
+++ b/src/writer/hlsl/generator_impl_intrinsic_test.cc
@@ -108,6 +108,9 @@
 }
 
 TEST_F(HlslGeneratorImplTest_Intrinsic, Intrinsic_Call) {
+  ast::type::F32Type f32;
+  ast::type::VectorType vec(&f32, 3);
+
   ast::ExpressionList params;
   params.push_back(std::make_unique<ast::IdentifierExpression>("param1"));
   params.push_back(std::make_unique<ast::IdentifierExpression>("param2"));
@@ -115,6 +118,12 @@
   ast::CallExpression call(std::make_unique<ast::IdentifierExpression>("dot"),
                            std::move(params));
 
+  ast::Variable v1("param1", ast::StorageClass::kFunction, &vec);
+  ast::Variable v2("param2", ast::StorageClass::kFunction, &vec);
+
+  td().RegisterVariableForTesting(&v1);
+  td().RegisterVariableForTesting(&v2);
+
   ASSERT_TRUE(td().DetermineResultType(&call)) << td().error();
 
   gen().increment_indent();
diff --git a/src/writer/msl/generator_impl_intrinsic_test.cc b/src/writer/msl/generator_impl_intrinsic_test.cc
index 9378229..4f02220 100644
--- a/src/writer/msl/generator_impl_intrinsic_test.cc
+++ b/src/writer/msl/generator_impl_intrinsic_test.cc
@@ -112,6 +112,9 @@
 }
 
 TEST_F(MslGeneratorImplTest, Intrinsic_Call) {
+  ast::type::F32Type f32;
+  ast::type::VectorType vec(&f32, 3);
+
   ast::ExpressionList params;
   params.push_back(std::make_unique<ast::IdentifierExpression>("param1"));
   params.push_back(std::make_unique<ast::IdentifierExpression>("param2"));
@@ -122,6 +125,13 @@
   Context ctx;
   ast::Module m;
   TypeDeterminer td(&ctx, &m);
+
+  ast::Variable v1("param1", ast::StorageClass::kFunction, &vec);
+  ast::Variable v2("param2", ast::StorageClass::kFunction, &vec);
+
+  td.RegisterVariableForTesting(&v1);
+  td.RegisterVariableForTesting(&v2);
+
   ASSERT_TRUE(td.DetermineResultType(&call)) << td.error();
 
   GeneratorImpl g(&m);
diff --git a/src/writer/spirv/builder_constructor_expression_test.cc b/src/writer/spirv/builder_constructor_expression_test.cc
index 35e8730..62c1ab8 100644
--- a/src/writer/spirv/builder_constructor_expression_test.cc
+++ b/src/writer/spirv/builder_constructor_expression_test.cc
@@ -2465,6 +2465,14 @@
   Context ctx;
   ast::Module mod;
   TypeDeterminer td(&ctx, &mod);
+
+  ast::Variable var_a("a", ast::StorageClass::kPrivate, &f32);
+  ast::Variable var_b("b", ast::StorageClass::kPrivate, &f32);
+  ast::Variable var_c("c", ast::StorageClass::kPrivate, &f32);
+  td.RegisterVariableForTesting(&var_a);
+  td.RegisterVariableForTesting(&var_b);
+  td.RegisterVariableForTesting(&var_c);
+
   ASSERT_TRUE(td.DetermineResultType(&t)) << td.error();
 
   Builder b(&mod);
@@ -2614,6 +2622,14 @@
   Context ctx;
   ast::Module mod;
   TypeDeterminer td(&ctx, &mod);
+
+  ast::Variable var_a("a", ast::StorageClass::kPrivate, &f32);
+  ast::Variable var_b("b", ast::StorageClass::kPrivate, &f32);
+  ast::Variable var_c("c", ast::StorageClass::kPrivate, &f32);
+  td.RegisterVariableForTesting(&var_a);
+  td.RegisterVariableForTesting(&var_b);
+  td.RegisterVariableForTesting(&var_c);
+
   ASSERT_TRUE(td.DetermineResultType(&t)) << td.error();
 
   Builder b(&mod);
@@ -2821,6 +2837,12 @@
   Context ctx;
   ast::Module mod;
   TypeDeterminer td(&ctx, &mod);
+
+  ast::Variable var_a("a", ast::StorageClass::kPrivate, &f32);
+  ast::Variable var_b("b", ast::StorageClass::kPrivate, &f32);
+  td.RegisterVariableForTesting(&var_a);
+  td.RegisterVariableForTesting(&var_b);
+
   ASSERT_TRUE(td.DetermineResultType(&t)) << td.error();
 
   Builder b(&mod);