compiler: finalize methods for type aliases of struct types

Previously we would finalize the methods of the alias type itself, but
since its a type alias we really need to finalize the methods of the
aliased type.

Also, handle method expressions of unnamed struct types.

Test case is https://golang.org/cl/251168.

Fixes golang/go#38125

Change-Id: I84c98883ae8641c5fa2b6c5209bf5ef9bb38e57b
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/251279
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/go/expressions.cc b/go/expressions.cc
index 8bbc557..0350e51 100644
--- a/go/expressions.cc
+++ b/go/expressions.cc
@@ -14529,21 +14529,19 @@
       is_pointer = true;
       type = type->points_to();
     }
-  Named_type* nt = type->named_type();
-  if (nt == NULL)
-    {
-      go_error_at(location,
-                  ("method expression requires named type or "
-                   "pointer to named type"));
-      return Expression::make_error(location);
-    }
 
+  Named_type* nt = type->named_type();
+  Struct_type* st = type->struct_type();
   bool is_ambiguous;
-  Method* method = nt->method_function(name, &is_ambiguous);
+  Method* method = NULL;
+  if (nt != NULL)
+    method = nt->method_function(name, &is_ambiguous);
+  else if (st != NULL)
+    method = st->method_function(name, &is_ambiguous);
   const Typed_identifier* imethod = NULL;
   if (method == NULL && !is_pointer)
     {
-      Interface_type* it = nt->interface_type();
+      Interface_type* it = type->interface_type();
       if (it != NULL)
 	imethod = it->find_method(name);
     }
@@ -14551,16 +14549,28 @@
   if ((method == NULL && imethod == NULL)
       || (left_type->named_type() != NULL && left_type->points_to() != NULL))
     {
-      if (!is_ambiguous)
-	go_error_at(location, "type %<%s%s%> has no method %<%s%>",
-                    is_pointer ? "*" : "",
-                    nt->message_name().c_str(),
-                    Gogo::message_name(name).c_str());
+      if (nt != NULL)
+	{
+	  if (!is_ambiguous)
+	    go_error_at(location, "type %<%s%s%> has no method %<%s%>",
+			is_pointer ? "*" : "",
+			nt->message_name().c_str(),
+			Gogo::message_name(name).c_str());
+	  else
+	    go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>",
+			Gogo::message_name(name).c_str(),
+			is_pointer ? "*" : "",
+			nt->message_name().c_str());
+	}
       else
-	go_error_at(location, "method %<%s%s%> is ambiguous in type %<%s%>",
-                    Gogo::message_name(name).c_str(),
-                    is_pointer ? "*" : "",
-                    nt->message_name().c_str());
+	{
+	  if (!is_ambiguous)
+	    go_error_at(location, "type has no method %<%s%>",
+			Gogo::message_name(name).c_str());
+	  else
+	    go_error_at(location, "method %<%s%> is ambiguous",
+			Gogo::message_name(name).c_str());
+	}
       return Expression::make_error(location);
     }
 
@@ -14657,7 +14667,7 @@
   Expression* ve = Expression::make_var_reference(vno, location);
   Expression* bm;
   if (method != NULL)
-    bm = Type::bind_field_or_method(gogo, nt, ve, name, location);
+    bm = Type::bind_field_or_method(gogo, type, ve, name, location);
   else
     bm = Expression::make_interface_field_reference(ve, name, location);
 
diff --git a/go/gogo.cc b/go/gogo.cc
index 82d4c1f..aef1c47 100644
--- a/go/gogo.cc
+++ b/go/gogo.cc
@@ -3508,6 +3508,10 @@
     case Type::TYPE_NAMED:
       {
 	Named_type* nt = t->named_type();
+
+	if (nt->is_alias())
+	  return TRAVERSE_CONTINUE;
+
 	Type* rt = nt->real_type();
 	if (rt->classification() != Type::TYPE_STRUCT)
 	  {