validation: fix arrayAcceor/memberAccessor error msg and add unit-tests

Bug: tint:1172
Change-Id: Icbc920dbc6adc9a5c78b8ae7d700b527a4fa48f7
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/64100
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Sarah Mashayekhi <sarahmashay@google.com>
diff --git a/src/resolver/array_accessor_test.cc b/src/resolver/array_accessor_test.cc
index 21883cd..a565d0c 100644
--- a/src/resolver/array_accessor_test.cc
+++ b/src/resolver/array_accessor_test.cc
@@ -257,6 +257,59 @@
   EXPECT_TRUE(r()->Resolve()) << r()->error();
 }
 
+TEST_F(ResolverArrayAccessorTest, EXpr_Deref_FuncGoodParent) {
+  // fn func(p: ptr<function, vec4<f32>>) -> f32 {
+  //     let idx: u32 = u32();
+  //     let x: f32 = (*p)[idx];
+  //     return x;
+  // }
+  auto* p =
+      Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
+  auto* idx = Const("idx", ty.u32(), Construct(ty.u32()));
+  auto* star_p = Deref(p);
+  auto* accessor_expr = IndexAccessor(Source{{12, 34}}, star_p, idx);
+  auto* x = Var("x", ty.f32(), accessor_expr);
+  Func("func", {p}, ty.f32(), {Decl(idx), Decl(x), Return(x)});
+
+  EXPECT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(ResolverArrayAccessorTest, EXpr_Deref_FuncBadParent) {
+  // fn func(p: ptr<function, vec4<f32>>) -> f32 {
+  //     let idx: u32 = u32();
+  //     let x: f32 = *p[idx];
+  //     return x;
+  // }
+  auto* p =
+      Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
+  auto* idx = Const("idx", ty.u32(), Construct(ty.u32()));
+  auto* accessor_expr = IndexAccessor(Source{{12, 34}}, p, idx);
+  auto* star_p = Deref(accessor_expr);
+  auto* x = Var("x", ty.f32(), star_p);
+  Func("func", {p}, ty.f32(), {Decl(idx), Decl(x), Return(x)});
+
+  EXPECT_FALSE(r()->Resolve());
+  EXPECT_EQ(r()->error(),
+            "12:34 error: cannot index type 'ptr<function, vec4<f32>>'");
+}
+
+TEST_F(ResolverArrayAccessorTest, Exr_Deref_BadParent) {
+  // var param: vec4<f32>
+  // let x: f32 = *(&param)[0];
+  auto* param = Var("param", ty.vec4<f32>());
+  auto* idx = Var("idx", ty.u32(), Construct(ty.u32()));
+  auto* addressOf_expr = AddressOf(param);
+  auto* accessor_expr = IndexAccessor(Source{{12, 34}}, addressOf_expr, idx);
+  auto* star_p = Deref(accessor_expr);
+  auto* x = Var("x", ty.f32(), star_p);
+  WrapInFunction(param, idx, x);
+
+  EXPECT_FALSE(r()->Resolve());
+  EXPECT_EQ(
+      r()->error(),
+      "12:34 error: cannot index type 'ptr<function, vec4<f32>, read_write>'");
+}
+
 }  // namespace
 }  // namespace resolver
 }  // namespace tint
diff --git a/src/resolver/resolver.cc b/src/resolver/resolver.cc
index 4abe071..1b26b60 100644
--- a/src/resolver/resolver.cc
+++ b/src/resolver/resolver.cc
@@ -2348,8 +2348,7 @@
   } else if (auto* mat = parent_type->As<sem::Matrix>()) {
     ret = builder_->create<sem::Vector>(mat->type(), mat->rows());
   } else {
-    AddError("invalid parent type (" + parent_type->type_name() +
-                 ") in array accessor",
+    AddError("cannot index type '" + TypeNameOf(expr->array()) + "'",
              expr->source());
     return false;
   }
@@ -3126,9 +3125,10 @@
         expr, builder_->create<sem::Swizzle>(expr, ret, current_statement_,
                                              std::move(swizzle)));
   } else {
-    AddError("invalid use of member accessor on a non-vector/non-struct " +
-                 TypeNameOf(expr->structure()),
-             expr->source());
+    AddError(
+        "invalid member accessor expression. Expected vector or struct, got '" +
+            TypeNameOf(expr->structure()) + "'",
+        expr->structure()->source());
     return false;
   }
 
diff --git a/src/resolver/validation_test.cc b/src/resolver/validation_test.cc
index aea2321..06cc2bb 100644
--- a/src/resolver/validation_test.cc
+++ b/src/resolver/validation_test.cc
@@ -451,6 +451,64 @@
   EXPECT_EQ(r()->error(), "3:3 error: invalid vector swizzle member");
 }
 
+TEST_F(ResolverValidationTest, Expr_MemberAccessor_BadParent) {
+  // var param: vec4<f32>
+  // let ret: f32 = *(&param).x;
+  auto* param = Var("param", ty.vec4<f32>());
+  auto* x = create<ast::IdentifierExpression>(
+      Source{{Source::Location{3, 3}, Source::Location{3, 8}}},
+      Symbols().Register("x"));
+
+  auto* addressOf_expr = AddressOf(Source{{12, 34}}, param);
+  auto* accessor_expr = MemberAccessor(addressOf_expr, x);
+  auto* star_p = Deref(accessor_expr);
+  auto* ret = Var("r", ty.f32(), star_p);
+  WrapInFunction(Decl(param), Decl(ret));
+
+  EXPECT_FALSE(r()->Resolve());
+  EXPECT_EQ(r()->error(),
+            "12:34 error: invalid member accessor expression. Expected vector "
+            "or struct, got 'ptr<function, vec4<f32>, read_write>'");
+}
+
+TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncGoodParent) {
+  // fn func(p: ptr<function, vec4<f32>>) -> f32 {
+  //     let x: f32 = (*p).z;
+  //     return x;
+  // }
+  auto* p =
+      Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
+  auto* star_p = Deref(p);
+  auto* z = create<ast::IdentifierExpression>(
+      Source{{Source::Location{3, 3}, Source::Location{3, 8}}},
+      Symbols().Register("z"));
+  auto* accessor_expr = MemberAccessor(star_p, z);
+  auto* x = Var("x", ty.f32(), accessor_expr);
+  Func("func", {p}, ty.f32(), {Decl(x), Return(x)});
+  EXPECT_TRUE(r()->Resolve()) << r()->error();
+}
+
+TEST_F(ResolverValidationTest, EXpr_MemberAccessor_FuncBadParent) {
+  // fn func(p: ptr<function, vec4<f32>>) -> f32 {
+  //     let x: f32 = *p.z;
+  //     return x;
+  // }
+  auto* p =
+      Param("p", ty.pointer(ty.vec4<f32>(), ast::StorageClass::kFunction));
+  auto* z = create<ast::IdentifierExpression>(
+      Source{{Source::Location{3, 3}, Source::Location{3, 8}}},
+      Symbols().Register("z"));
+  auto* accessor_expr = MemberAccessor(p, z);
+  auto* star_p = Deref(accessor_expr);
+  auto* x = Var("x", ty.f32(), star_p);
+  Func("func", {p}, ty.f32(), {Decl(x), Return(x)});
+
+  EXPECT_FALSE(r()->Resolve());
+  EXPECT_EQ(r()->error(),
+            "error: invalid member accessor expression. Expected vector or "
+            "struct, got 'ptr<function, vec4<f32>>'");
+}
+
 TEST_F(ResolverValidationTest,
        Stmt_Loop_ContinueInLoopBodyBeforeDeclAndAfterDecl_UsageInContinuing) {
   // loop  {