This patch to the Go frontend adds support for method expressions for interface types. Bootstrapped and ran Go testsuite on x86_64-unknown-linux-gnu. Committed to mainline.
Ian
diff -r 0ed415b7ab0e go/expressions.cc --- a/go/expressions.cc Mon Mar 28 14:18:39 2011 -0700 +++ b/go/expressions.cc Mon Mar 28 14:20:19 2011 -0700 @@ -10262,8 +10262,16 @@ 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 @@ 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 @@ // 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 @@ // 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 @@ 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.