compiler: fix glitch when inlining method with empty param/receiver
authorIan Lance Taylor <ian@gcc.gnu.org>
Thu, 25 Apr 2019 01:13:22 +0000 (01:13 +0000)
committerIan Lance Taylor <ian@gcc.gnu.org>
Thu, 25 Apr 2019 01:13:22 +0000 (01:13 +0000)
    Fix a problem with Function_declaration::import_function relating to
    how no-name or "sink" parameters are handled. In Gogo::start_function
    (for the non-inline case) when parameter bindings are being added,
    parameters with empty/sink names are renamed to synthesized "r.%d" /
    "p.%d" names so as to avoid collisions. This same handling needs to be
    present when creating the bindings for an inline function that's being
    instantiated after being read from export data.

    Fixes golang/go#31637.

    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/173538

From-SVN: r270564

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

index 2e1c39947bb07ff0d23209955c214c3fc69f0674..fd53ada097c1860c775626c824191e53f8a781bf 100644 (file)
@@ -1,4 +1,4 @@
-56fe6a00892252edb4b28f8660ce29a985c48702
+cb6fb7285bac72389bdce7ecfe87f9366022571a
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
index a9630b28bc0a07863883ee8f42e68e71d5c6766c..1efaadf8c9d0d79bc744b18cc0d0b8230991c74c 100644 (file)
@@ -1832,21 +1832,18 @@ Gogo::start_function(const std::string& name, Function_type* type,
       Variable* this_param = new Variable(receiver->type(), NULL, false,
                                          true, true, location);
       std::string rname = receiver->name();
-      if (rname.empty() || Gogo::is_sink_name(rname))
-       {
-         // We need to give receivers a name since they wind up in
-         // DECL_ARGUMENTS.  FIXME.
-         static unsigned int count;
-         char buf[50];
-         snprintf(buf, sizeof buf, "r.%u", count);
-         ++count;
-         rname = buf;
-       }
+      unsigned rcounter = 0;
+
+      // We need to give a nameless receiver parameter a synthesized name to
+      // avoid having it clash with some other nameless param. FIXME.
+      Gogo::rename_if_empty(&rname, "r", &rcounter);
+
       block->bindings()->add_variable(rname, NULL, this_param);
     }
 
   const Typed_identifier_list* parameters = type->parameters();
   bool is_varargs = type->is_varargs();
+  unsigned pcounter = 0;
   if (parameters != NULL)
     {
       for (Typed_identifier_list::const_iterator p = parameters->begin();
@@ -1859,16 +1856,11 @@ Gogo::start_function(const std::string& name, Function_type* type,
            param->set_is_varargs_parameter();
 
          std::string pname = p->name();
-         if (pname.empty() || Gogo::is_sink_name(pname))
-           {
-             // We need to give parameters a name since they wind up
-             // in DECL_ARGUMENTS.  FIXME.
-             static unsigned int count;
-             char buf[50];
-             snprintf(buf, sizeof buf, "p.%u", count);
-             ++count;
-             pname = buf;
-           }
+
+          // We need to give each nameless parameter a non-empty name to avoid
+          // having it clash with some other nameless param. FIXME.
+          Gogo::rename_if_empty(&pname, "p", &pcounter);
+
          block->bindings()->add_variable(pname, NULL, param);
        }
     }
@@ -2313,6 +2305,20 @@ Gogo::add_variable(const std::string& name, Variable* variable)
   return no;
 }
 
+void
+Gogo::rename_if_empty(std::string* pname, const char* tag, unsigned* count)
+{
+  if (pname->empty() || Gogo::is_sink_name(*pname))
+    {
+      char buf[50];
+      go_assert(strlen(tag) < 10);
+      snprintf(buf, sizeof buf, "%s.%u", tag, *count);
+      ++(*count);
+      *pname = buf;
+    }
+}
+
+
 // Add a sink--a reference to the blank identifier _.
 
 Named_object*
@@ -6904,11 +6910,20 @@ Function_declaration::import_function_body(Gogo* gogo, Named_object* no)
       const Typed_identifier* receiver = fntype->receiver();
       Variable* recv_param = new Variable(receiver->type(), NULL, false,
                                          true, true, start_loc);
-      outer->bindings()->add_variable(receiver->name(), NULL, recv_param);
+
+      std::string rname = receiver->name();
+      unsigned rcounter = 0;
+
+      // We need to give a nameless receiver a name to avoid having it
+      // clash with some other nameless param. FIXME.
+      Gogo::rename_if_empty(&rname, "r", &rcounter);
+
+      outer->bindings()->add_variable(rname, NULL, recv_param);
     }
 
   const Typed_identifier_list* params = fntype->parameters();
   bool is_varargs = fntype->is_varargs();
+  unsigned pcounter = 0;
   if (params != NULL)
     {
       for (Typed_identifier_list::const_iterator p = params->begin();
@@ -6919,7 +6934,14 @@ Function_declaration::import_function_body(Gogo* gogo, Named_object* no)
                                         start_loc);
          if (is_varargs && p + 1 == params->end())
            param->set_is_varargs_parameter();
-         outer->bindings()->add_variable(p->name(), NULL, param);
+
+         std::string pname = p->name();
+
+          // We need to give each nameless parameter a non-empty name to avoid
+          // having it clash with some other nameless param. FIXME.
+          Gogo::rename_if_empty(&pname, "p", &pcounter);
+
+         outer->bindings()->add_variable(pname, NULL, param);
        }
     }
 
index b850ceabe9b8a993fb652292875ac36e86038578..1c9f0de0b366e60b1795e8108182d16df9a7adc6 100644 (file)
@@ -220,6 +220,16 @@ class Gogo
            && name[name.length() - 2] == '.');
   }
 
+  // Helper used when adding parameters (including receiver param) to the
+  // bindings of a function. If the specified parameter name is empty or
+  // corresponds to the sink name, param name is replaced with a new unique
+  // name. PNAME is the address of a string containing the parameter variable
+  // name to be checked/updated; TAG is a descriptive tag to be used in
+  // manufacturing the new unique name, and COUNT is the address of a counter
+  // holding the number of params renamed so far with the tag in question.
+  static void
+  rename_if_empty(std::string* pname, const char* tag, unsigned* count);
+
   // Convert a pkgpath into a string suitable for a symbol
   static std::string
   pkgpath_for_symbol(const std::string& pkgpath);