aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@gcc.gnu.org>2011-03-28 21:22:08 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2011-03-28 21:22:08 +0000
commit8060754453f32ae22612a63a2abe5f116c9bb687 (patch)
tree0f41bbec80132b4f423c758ba3cfdab006d37b11 /gcc
parent0b3e0e9ef1cdb12edb18af5e7e8dc7ef4ecffb3a (diff)
downloadgcc-8060754453f32ae22612a63a2abe5f116c9bb687.zip
gcc-8060754453f32ae22612a63a2abe5f116c9bb687.tar.gz
gcc-8060754453f32ae22612a63a2abe5f116c9bb687.tar.bz2
Support method expressions for interface types.
From-SVN: r171631
Diffstat (limited to 'gcc')
-rw-r--r--gcc/go/gofrontend/expressions.cc31
1 files changed, 26 insertions, 5 deletions
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 7fae4e0..78ae4fa 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -10262,8 +10262,16 @@ Selector_expression::lower_method_expression(Gogo* gogo)
bool is_ambiguous;
Method* method = nt->method_function(name, &is_ambiguous);
+ const Typed_identifier* imethod = 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)
error_at(location, "type %<%s%> has no method %<%s%>",
nt->message_name().c_str(),
@@ -10275,7 +10283,7 @@ Selector_expression::lower_method_expression(Gogo* gogo)
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)%>",
nt->message_name().c_str(),
@@ -10285,8 +10293,17 @@ Selector_expression::lower_method_expression(Gogo* gogo)
// Build a new function type in which the receiver becomes the first
// argument.
- Function_type* method_type = method->type();
- gcc_assert(method_type->is_method());
+ Function_type* method_type;
+ 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";
Typed_identifier_list* parameters = new Typed_identifier_list();
@@ -10325,7 +10342,7 @@ Selector_expression::lower_method_expression(Gogo* gogo)
// simply reuse the existing function. We use an internal hack to
// get the right type.
- if (is_pointer)
+ if (method != NULL && is_pointer)
{
Named_object* mno = (method->needs_stub_method()
? method->stub_object()
@@ -10344,7 +10361,11 @@ Selector_expression::lower_method_expression(Gogo* gogo)
Named_object* vno = gogo->lookup(receiver_name, NULL);
gcc_assert(vno != NULL);
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
// may see an error here.