diff options
author | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-05-16 00:02:03 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2017-05-16 00:02:03 +0000 |
commit | d73b8f8417ebf6f0bbf64f237fa9db11cfc719f4 (patch) | |
tree | b982f2031b658201fc0d5f049e5eaee1a3e90755 /gcc | |
parent | a5768d38a66fc4136208bc8442a4118df2bd588f (diff) | |
download | gcc-d73b8f8417ebf6f0bbf64f237fa9db11cfc719f4.zip gcc-d73b8f8417ebf6f0bbf64f237fa9db11cfc719f4.tar.gz gcc-d73b8f8417ebf6f0bbf64f237fa9db11cfc719f4.tar.bz2 |
compiler: report correct errors for sink methods
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.
Reviewed-on: https://go-review.googlesource.com/43456
From-SVN: r248081
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/go/gofrontend/MERGE | 2 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.cc | 40 | ||||
-rw-r--r-- | gcc/go/gofrontend/gogo.h | 5 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.cc | 11 | ||||
-rw-r--r-- | gcc/go/gofrontend/types.h | 4 |
5 files changed, 59 insertions, 3 deletions
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE index 0221986..fec0e79 100644 --- a/gcc/go/gofrontend/MERGE +++ b/gcc/go/gofrontend/MERGE @@ -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. diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index b076b87..daf2ba4 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -1786,8 +1786,41 @@ Gogo::start_function(const std::string& name, Function_type* type, 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_type* nt) 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. diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 994f233..787a3e3 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -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; diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index f2056aa..8d542de 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -12210,6 +12210,17 @@ Forward_declaration_type::add_method_declaration(const std::string& name, 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 diff --git a/gcc/go/gofrontend/types.h b/gcc/go/gofrontend/types.h index e0fcf0c..bae7fd3 100644 --- a/gcc/go/gofrontend/types.h +++ b/gcc/go/gofrontend/types.h @@ -3379,6 +3379,10 @@ class Forward_declaration_type : public Type 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); |