compiler: fix glitch when inlining method with empty param/receiver
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
This commit is contained in:
parent
6aa6cbacc8
commit
ce0f706246
@ -1,4 +1,4 @@
|
|||||||
56fe6a00892252edb4b28f8660ce29a985c48702
|
cb6fb7285bac72389bdce7ecfe87f9366022571a
|
||||||
|
|
||||||
The first line of this file holds the git revision number of the last
|
The first line of this file holds the git revision number of the last
|
||||||
merge done from the gofrontend repository.
|
merge done from the gofrontend repository.
|
||||||
|
@ -1832,21 +1832,18 @@ Gogo::start_function(const std::string& name, Function_type* type,
|
|||||||
Variable* this_param = new Variable(receiver->type(), NULL, false,
|
Variable* this_param = new Variable(receiver->type(), NULL, false,
|
||||||
true, true, location);
|
true, true, location);
|
||||||
std::string rname = receiver->name();
|
std::string rname = receiver->name();
|
||||||
if (rname.empty() || Gogo::is_sink_name(rname))
|
unsigned rcounter = 0;
|
||||||
{
|
|
||||||
// We need to give receivers a name since they wind up in
|
// We need to give a nameless receiver parameter a synthesized name to
|
||||||
// DECL_ARGUMENTS. FIXME.
|
// avoid having it clash with some other nameless param. FIXME.
|
||||||
static unsigned int count;
|
Gogo::rename_if_empty(&rname, "r", &rcounter);
|
||||||
char buf[50];
|
|
||||||
snprintf(buf, sizeof buf, "r.%u", count);
|
|
||||||
++count;
|
|
||||||
rname = buf;
|
|
||||||
}
|
|
||||||
block->bindings()->add_variable(rname, NULL, this_param);
|
block->bindings()->add_variable(rname, NULL, this_param);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Typed_identifier_list* parameters = type->parameters();
|
const Typed_identifier_list* parameters = type->parameters();
|
||||||
bool is_varargs = type->is_varargs();
|
bool is_varargs = type->is_varargs();
|
||||||
|
unsigned pcounter = 0;
|
||||||
if (parameters != NULL)
|
if (parameters != NULL)
|
||||||
{
|
{
|
||||||
for (Typed_identifier_list::const_iterator p = parameters->begin();
|
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();
|
param->set_is_varargs_parameter();
|
||||||
|
|
||||||
std::string pname = p->name();
|
std::string pname = p->name();
|
||||||
if (pname.empty() || Gogo::is_sink_name(pname))
|
|
||||||
{
|
// We need to give each nameless parameter a non-empty name to avoid
|
||||||
// We need to give parameters a name since they wind up
|
// having it clash with some other nameless param. FIXME.
|
||||||
// in DECL_ARGUMENTS. FIXME.
|
Gogo::rename_if_empty(&pname, "p", &pcounter);
|
||||||
static unsigned int count;
|
|
||||||
char buf[50];
|
|
||||||
snprintf(buf, sizeof buf, "p.%u", count);
|
|
||||||
++count;
|
|
||||||
pname = buf;
|
|
||||||
}
|
|
||||||
block->bindings()->add_variable(pname, NULL, param);
|
block->bindings()->add_variable(pname, NULL, param);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2313,6 +2305,20 @@ Gogo::add_variable(const std::string& name, Variable* variable)
|
|||||||
return no;
|
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 _.
|
// Add a sink--a reference to the blank identifier _.
|
||||||
|
|
||||||
Named_object*
|
Named_object*
|
||||||
@ -6904,11 +6910,20 @@ Function_declaration::import_function_body(Gogo* gogo, Named_object* no)
|
|||||||
const Typed_identifier* receiver = fntype->receiver();
|
const Typed_identifier* receiver = fntype->receiver();
|
||||||
Variable* recv_param = new Variable(receiver->type(), NULL, false,
|
Variable* recv_param = new Variable(receiver->type(), NULL, false,
|
||||||
true, true, start_loc);
|
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();
|
const Typed_identifier_list* params = fntype->parameters();
|
||||||
bool is_varargs = fntype->is_varargs();
|
bool is_varargs = fntype->is_varargs();
|
||||||
|
unsigned pcounter = 0;
|
||||||
if (params != NULL)
|
if (params != NULL)
|
||||||
{
|
{
|
||||||
for (Typed_identifier_list::const_iterator p = params->begin();
|
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);
|
start_loc);
|
||||||
if (is_varargs && p + 1 == params->end())
|
if (is_varargs && p + 1 == params->end())
|
||||||
param->set_is_varargs_parameter();
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -220,6 +220,16 @@ class Gogo
|
|||||||
&& name[name.length() - 2] == '.');
|
&& 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
|
// Convert a pkgpath into a string suitable for a symbol
|
||||||
static std::string
|
static std::string
|
||||||
pkgpath_for_symbol(const std::string& pkgpath);
|
pkgpath_for_symbol(const std::string& pkgpath);
|
||||||
|
Loading…
Reference in New Issue
Block a user