diff --git a/gcc/go/gofrontend/gogo-tree.cc b/gcc/go/gofrontend/gogo-tree.cc index 7813cc18822..a95f2901509 100644 --- a/gcc/go/gofrontend/gogo-tree.cc +++ b/gcc/go/gofrontend/gogo-tree.cc @@ -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; diff --git a/gcc/go/gofrontend/gogo.cc b/gcc/go/gofrontend/gogo.cc index 17cbb6b9b49..9f918cb81c7 100644 --- a/gcc/go/gofrontend/gogo.cc +++ b/gcc/go/gofrontend/gogo.cc @@ -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 diff --git a/gcc/go/gofrontend/gogo.h b/gcc/go/gofrontend/gogo.h index 6a87f2d562c..23968d4a191 100644 --- a/gcc/go/gofrontend/gogo.h +++ b/gcc/go/gofrontend/gogo.h @@ -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. diff --git a/gcc/go/gofrontend/parse.cc b/gcc/go/gofrontend/parse.cc index befe4bc7d83..e68f1753f87 100644 --- a/gcc/go/gofrontend/parse.cc +++ b/gcc/go/gofrontend/parse.cc @@ -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(); } diff --git a/gcc/go/gofrontend/types.cc b/gcc/go/gofrontend/types.cc index 32f827dd316..a4a60706b7a 100644 --- a/gcc/go/gofrontend/types.cc +++ b/gcc/go/gofrontend/types.cc @@ -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());