Commit 80607544 by Ian Lance Taylor

Support method expressions for interface types.

From-SVN: r171631
parent 0b3e0e9e
...@@ -10262,8 +10262,16 @@ Selector_expression::lower_method_expression(Gogo* gogo) ...@@ -10262,8 +10262,16 @@ Selector_expression::lower_method_expression(Gogo* gogo)
bool is_ambiguous; bool is_ambiguous;
Method* method = nt->method_function(name, &is_ambiguous); Method* method = nt->method_function(name, &is_ambiguous);
const Typed_identifier* imethod = NULL;
if (method == NULL) if (method == NULL)
{ {
Interface_type* it = nt->interface_type();
if (it != NULL)
imethod = it->find_method(name);
}
if (method == NULL && imethod == NULL)
{
if (!is_ambiguous) if (!is_ambiguous)
error_at(location, "type %<%s%> has no method %<%s%>", error_at(location, "type %<%s%> has no method %<%s%>",
nt->message_name().c_str(), nt->message_name().c_str(),
...@@ -10275,7 +10283,7 @@ Selector_expression::lower_method_expression(Gogo* gogo) ...@@ -10275,7 +10283,7 @@ Selector_expression::lower_method_expression(Gogo* gogo)
return Expression::make_error(location); return Expression::make_error(location);
} }
if (!is_pointer && !method->is_value_method()) if (method != NULL && !is_pointer && !method->is_value_method())
{ {
error_at(location, "method requires pointer (use %<(*%s).%s)%>", error_at(location, "method requires pointer (use %<(*%s).%s)%>",
nt->message_name().c_str(), nt->message_name().c_str(),
...@@ -10285,8 +10293,17 @@ Selector_expression::lower_method_expression(Gogo* gogo) ...@@ -10285,8 +10293,17 @@ Selector_expression::lower_method_expression(Gogo* gogo)
// Build a new function type in which the receiver becomes the first // Build a new function type in which the receiver becomes the first
// argument. // argument.
Function_type* method_type = method->type(); Function_type* method_type;
gcc_assert(method_type->is_method()); if (method != NULL)
{
method_type = method->type();
gcc_assert(method_type->is_method());
}
else
{
method_type = imethod->type()->function_type();
gcc_assert(method_type != NULL && !method_type->is_method());
}
const char* const receiver_name = "$this"; const char* const receiver_name = "$this";
Typed_identifier_list* parameters = new Typed_identifier_list(); Typed_identifier_list* parameters = new Typed_identifier_list();
...@@ -10325,7 +10342,7 @@ Selector_expression::lower_method_expression(Gogo* gogo) ...@@ -10325,7 +10342,7 @@ Selector_expression::lower_method_expression(Gogo* gogo)
// simply reuse the existing function. We use an internal hack to // simply reuse the existing function. We use an internal hack to
// get the right type. // get the right type.
if (is_pointer) if (method != NULL && is_pointer)
{ {
Named_object* mno = (method->needs_stub_method() Named_object* mno = (method->needs_stub_method()
? method->stub_object() ? method->stub_object()
...@@ -10344,7 +10361,11 @@ Selector_expression::lower_method_expression(Gogo* gogo) ...@@ -10344,7 +10361,11 @@ Selector_expression::lower_method_expression(Gogo* gogo)
Named_object* vno = gogo->lookup(receiver_name, NULL); Named_object* vno = gogo->lookup(receiver_name, NULL);
gcc_assert(vno != NULL); gcc_assert(vno != NULL);
Expression* ve = Expression::make_var_reference(vno, location); Expression* ve = Expression::make_var_reference(vno, location);
Expression* bm = Type::bind_field_or_method(gogo, nt, ve, name, location); Expression* bm;
if (method != NULL)
bm = Type::bind_field_or_method(gogo, nt, ve, name, location);
else
bm = Expression::make_interface_field_reference(ve, name, location);
// Even though we found the method above, if it has an error type we // Even though we found the method above, if it has an error type we
// may see an error here. // may see an error here.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment