compiler: report correct errors for sink methods
authorIan Lance Taylor <ian@gcc.gnu.org>
Tue, 16 May 2017 00:02:03 +0000 (00:02 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Tue, 16 May 2017 00:02:03 +0000 (00:02 +0000)
    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

gcc/go/gofrontend/MERGE
gcc/go/gofrontend/gogo.cc
gcc/go/gofrontend/gogo.h
gcc/go/gofrontend/types.cc
gcc/go/gofrontend/types.h

index 02219862b359a68b31aa631b3ef84a31490c6e3d..fec0e7978d59279cf1797b36ca57ae0801198579 100644 (file)
@@ -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 b076b87b4911acf3cad3eaba2f297f5c1693660c..daf2ba4cb0bfa728df34453325a4d945181d2f71 100644 (file)
@@ -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.
index 994f23399417af61a5b3778254288002a6fb7669..787a3e3658f0866ee9dbd2b0f4f5c6520a7b030b 100644 (file)
@@ -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 f2056aa62083b0afcf0a82b0fa268e310755d1be..8d542de1b3c24bbe0b602296daffc79b15bc201f 100644 (file)
@@ -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
index e0fcf0cc86ac3d011d0c634e58c7f0dbe1ea3ddf..bae7fd3a541092889e2d8b749d73f6d3812c0d25 100644 (file)
@@ -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);