compiler: finalize methods for type aliases of struct types
authorIan Lance Taylor <iant@golang.org>
Fri, 28 Aug 2020 05:18:45 +0000 (22:18 -0700)
committerIan Lance Taylor <iant@golang.org>
Mon, 21 Sep 2020 22:53:48 +0000 (15:53 -0700)
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

Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/251279

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/expressions.cc
gcc/go/gofrontend/gogo.cc

index d8db888e4b6852850fa722492cf677bf51db4846..e4f8fac5ab3a09567cadf97b8df184db6614d3b9 100644 (file)
@@ -1,4 +1,4 @@
-6f309797e4f7eed635950687e902a294126e6fc6
+a59167c29d6ad2ddf533b3a12b365f72df0e1476
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index 8bbc557c65ffbafeb1b447eb0870a4fb9e482379..0350e51d3a69cf681e8eb94a8bdf7d8fbb7bedc8 100644 (file)
@@ -14529,21 +14529,19 @@ Selector_expression::lower_method_expression(Gogo* gogo)
       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 @@ Selector_expression::lower_method_expression(Gogo* gogo)
   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 @@ Selector_expression::lower_method_expression(Gogo* gogo)
   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);
 
index 82d4c1fd54d5b1729a1ff36eba8d85413a8b749f..aef1c47d26e89e1c4ad6fd60e9a6edbc96a5d975 100644 (file)
@@ -3508,6 +3508,10 @@ Finalize_methods::type(Type* t)
     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)
          {