compiler: Avoid knockon errors for invalid uses of _.

From-SVN: r203006
This commit is contained in:
Ian Lance Taylor 2013-09-28 20:23:43 +00:00
parent 8d60fca50e
commit 7540a2c787
5 changed files with 47 additions and 6 deletions

View File

@ -1061,6 +1061,12 @@ Named_object::get_tree(Gogo* gogo, Named_object* function)
if (this->tree_ != NULL_TREE)
return this->tree_;
if (Gogo::is_erroneous_name(this->name_))
{
this->tree_ = error_mark_node;
return error_mark_node;
}
tree name;
if (this->classification_ == NAMED_OBJECT_TYPE)
name = NULL_TREE;

View File

@ -1192,6 +1192,27 @@ Gogo::record_interface_type(Interface_type* itype)
this->interface_types_.push_back(itype);
}
// Return an erroneous name that indicates that an error has already
// been reported.
std::string
Gogo::erroneous_name()
{
static int erroneous_count;
char name[50];
snprintf(name, sizeof name, "$erroneous%d", erroneous_count);
++erroneous_count;
return name;
}
// Return whether a name is an erroneous name.
bool
Gogo::is_erroneous_name(const std::string& name)
{
return name.compare(0, 10, "$erroneous") == 0;
}
// Return a name for a thunk object.
std::string

View File

@ -387,6 +387,16 @@ class Gogo
void
mark_locals_used();
// Return a name to use for an error case. This should only be used
// after reporting an error, and is used to avoid useless knockon
// errors.
static std::string
erroneous_name();
// Return whether the name indicates an error.
static bool
is_erroneous_name(const std::string&);
// Return a name to use for a thunk function. A thunk function is
// one we create during the compilation, for a go statement or a
// defer statement or a method expression.

View File

@ -213,7 +213,7 @@ Parse::qualified_ident(std::string* pname, Named_object** ppackage)
if (name == "_")
{
error_at(this->location(), "invalid use of %<_%>");
name = "blank";
name = Gogo::erroneous_name();
}
if (package->name() == this->gogo_->package_name())
@ -3104,7 +3104,7 @@ Parse::selector(Expression* left, bool* is_type_switch)
if (token->identifier() == "_")
{
error_at(this->location(), "invalid use of %<_%>");
name = this->gogo_->pack_hidden_name("blank", false);
name = Gogo::erroneous_name();
}
this->advance_token();
return Expression::make_selector(left, name, location);
@ -4929,7 +4929,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
{
error_at(recv_var_loc,
"no new variables on left side of %<:=%>");
recv_var = "blank";
recv_var = Gogo::erroneous_name();
}
*is_send = false;
*varname = gogo->pack_hidden_name(recv_var, is_rv_exported);
@ -4965,7 +4965,7 @@ Parse::send_or_recv_stmt(bool* is_send, Expression** channel, Expression** val,
{
error_at(recv_var_loc,
"no new variables on left side of %<:=%>");
recv_var = "blank";
recv_var = Gogo::erroneous_name();
}
*is_send = false;
if (recv_var != "_")
@ -5502,7 +5502,7 @@ Parse::package_clause()
if (name == "_")
{
error_at(this->location(), "invalid package name _");
name = "blank";
name = Gogo::erroneous_name();
}
this->advance_token();
}

View File

@ -9269,7 +9269,11 @@ Type::bind_field_or_method(Gogo* gogo, const Type* type, Expression* expr,
}
else
{
if (!ambig1.empty())
if (Gogo::is_erroneous_name(name))
{
// An error was already reported.
}
else if (!ambig1.empty())
error_at(location, "%qs is ambiguous via %qs and %qs",
Gogo::message_name(name).c_str(), ambig1.c_str(),
ambig2.c_str());