If somebody writes func (s []int) _() {}
we should report an error. Before this patch we were silently accepting this code, because we didn't report any errors about the receiver if the method was a sink. This patch is unfortunately slightly complex to handle the case of func (x int) _() {} which we can only detect after define_global_names. This fixes blank1.go in the current gc testsuite. Bootstrapped and ran Go testsuite on x86_64-pc-linux-gnu. Committed to mainline. Ian
Index: gcc/go/gofrontend/MERGE =================================================================== --- gcc/go/gofrontend/MERGE (revision 247981) +++ gcc/go/gofrontend/MERGE (working copy) @@ -1,4 +1,4 @@ -2f21020c9f61b31bd04d5b814aaa27bf976bf07a +d3997526dc0710e6b9b727a41184ce1770805794 The first line of this file holds the git revision number of the last merge done from the gofrontend repository. Index: gcc/go/gofrontend/gogo.cc =================================================================== --- gcc/go/gofrontend/gogo.cc (revision 247981) +++ gcc/go/gofrontend/gogo.cc (working copy) @@ -1786,8 +1786,41 @@ Gogo::start_function(const std::string& char buf[30]; snprintf(buf, sizeof buf, ".$sink%d", sink_count); ++sink_count; - ret = this->package_->bindings()->add_function(buf, NULL, function); + ret = Named_object::make_function(buf, NULL, function); ret->func_value()->set_is_sink(); + + if (!type->is_method()) + ret = this->package_->bindings()->add_named_object(ret); + else if (add_method_to_type) + { + // We should report errors even for sink methods. + Type* rtype = type->receiver()->type(); + // Avoid points_to and deref to avoid getting an error if + // the type is not yet defined. + if (rtype->classification() == Type::TYPE_POINTER) + rtype = rtype->points_to(); + while (rtype->named_type() != NULL + && rtype->named_type()->is_alias()) + rtype = rtype->named_type()->real_type()->forwarded(); + if (rtype->is_error_type()) + ; + else if (rtype->named_type() != NULL) + { + if (rtype->named_type()->named_object()->package() != NULL) + go_error_at(type->receiver()->location(), + "may not define methods on non-local type"); + } + else if (rtype->forward_declaration_type() != NULL) + { + // Go ahead and add the method in case we need to report + // an error when we see the definition. + rtype->forward_declaration_type()->add_existing_method(ret); + } + else + go_error_at(type->receiver()->location(), + ("invalid receiver type " + "(receiver must be a named type)")); + } } else if (!type->is_method()) { @@ -6985,7 +7018,10 @@ Type_declaration::define_methods(Named_t for (std::vector<Named_object*>::const_iterator p = this->methods_.begin(); p != this->methods_.end(); ++p) - nt->add_existing_method(*p); + { + if (!(*p)->func_value()->is_sink()) + nt->add_existing_method(*p); + } } // We are using the type. Return true if we should issue a warning. Index: gcc/go/gofrontend/gogo.h =================================================================== --- gcc/go/gofrontend/gogo.h (revision 247848) +++ gcc/go/gofrontend/gogo.h (working copy) @@ -2114,6 +2114,11 @@ class Type_declaration add_method_declaration(const std::string& name, Package*, Function_type* type, Location location); + // Add an already created object as a method. + void + add_existing_method(Named_object* no) + { this->methods_.push_back(no); } + // Return whether any methods were defined. bool has_methods() const; Index: gcc/go/gofrontend/types.cc =================================================================== --- gcc/go/gofrontend/types.cc (revision 247848) +++ gcc/go/gofrontend/types.cc (working copy) @@ -12210,6 +12210,17 @@ Forward_declaration_type::add_method_dec return td->add_method_declaration(name, package, type, location); } +// Add an already created object as a method. + +void +Forward_declaration_type::add_existing_method(Named_object* nom) +{ + Named_object* no = this->named_object(); + if (no->is_unknown()) + no->declare_as_type(); + no->type_declaration_value()->add_existing_method(nom); +} + // Traversal. int Index: gcc/go/gofrontend/types.h =================================================================== --- gcc/go/gofrontend/types.h (revision 247848) +++ gcc/go/gofrontend/types.h (working copy) @@ -3379,6 +3379,10 @@ class Forward_declaration_type : public add_method_declaration(const std::string& name, Package*, Function_type*, Location); + // Add an already created object as a method to this type. + void + add_existing_method(Named_object*); + protected: int do_traverse(Traverse* traverse);