Unwrap member accessor aliases

The member accessors end up being aliases in a lot of cases because you
can't have a struct that isn't an alias. This Cl unwraps the aliases at
the start of the determination for member accessors.

Change-Id: Ib090ebd6aedd502c2812d95373c19d8eb831a361
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/20342
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/type_determiner.cc b/src/type_determiner.cc
index 317a8a5..820accd 100644
--- a/src/type_determiner.cc
+++ b/src/type_determiner.cc
@@ -408,6 +408,11 @@
 
   auto* res = expr->structure()->result_type();
   auto* data_type = res->UnwrapPtrIfNeeded();
+
+  while (data_type->IsAlias()) {
+    data_type = data_type->AsAlias()->type();
+  }
+
   ast::type::Type* ret = nullptr;
   if (data_type->IsStruct()) {
     auto* strct = data_type->AsStruct()->impl();
diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc
index 5e626b4..0f4da0d 100644
--- a/src/type_determiner_test.cc
+++ b/src/type_determiner_test.cc
@@ -41,6 +41,7 @@
 #include "src/ast/struct.h"
 #include "src/ast/struct_member.h"
 #include "src/ast/switch_statement.h"
+#include "src/ast/type/alias_type.h"
 #include "src/ast/type/array_type.h"
 #include "src/ast/type/bool_type.h"
 #include "src/ast/type/f32_type.h"
@@ -805,6 +806,43 @@
   EXPECT_TRUE(ptr->type()->IsF32());
 }
 
+TEST_F(TypeDeterminerTest, Expr_MemberAccessor_Struct_Alias) {
+  ast::type::I32Type i32;
+  ast::type::F32Type f32;
+
+  ast::StructMemberDecorationList decos;
+  ast::StructMemberList members;
+  members.push_back(std::make_unique<ast::StructMember>("first_member", &i32,
+                                                        std::move(decos)));
+  members.push_back(std::make_unique<ast::StructMember>("second_member", &f32,
+                                                        std::move(decos)));
+
+  auto strct = std::make_unique<ast::Struct>(ast::StructDecoration::kNone,
+                                             std::move(members));
+
+  auto st = std::make_unique<ast::type::StructType>(std::move(strct));
+  ast::type::AliasType alias("alias", st.get());
+
+  auto var = std::make_unique<ast::Variable>("my_struct",
+                                             ast::StorageClass::kNone, &alias);
+
+  mod()->AddGlobalVariable(std::move(var));
+
+  // Register the global
+  EXPECT_TRUE(td()->Determine());
+
+  auto ident = std::make_unique<ast::IdentifierExpression>("my_struct");
+  auto mem_ident = std::make_unique<ast::IdentifierExpression>("second_member");
+
+  ast::MemberAccessorExpression mem(std::move(ident), std::move(mem_ident));
+  EXPECT_TRUE(td()->DetermineResultType(&mem));
+  ASSERT_NE(mem.result_type(), nullptr);
+  ASSERT_TRUE(mem.result_type()->IsPointer());
+
+  auto* ptr = mem.result_type()->AsPointer();
+  EXPECT_TRUE(ptr->type()->IsF32());
+}
+
 TEST_F(TypeDeterminerTest, Expr_MemberAccessor_VectorSwizzle) {
   ast::type::F32Type f32;
   ast::type::VectorType vec3(&f32, 3);