mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-09 17:11:20 +08:00
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 Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/251279
This commit is contained in:
parent
1e19ecd79b
commit
27edc6c3e2
@ -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.
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user