Patchwork Go patch committed: Avoid useless knockon errors for _

login
register
mail settings
Submitter Ian Taylor
Date Sept. 28, 2013, 8:23 p.m.
Message ID <mcrhad4eluq.fsf@iant-glaptop.roam.corp.google.com>
Download mbox | patch
Permalink /patch/278769/
State New
Headers show

Comments

Ian Taylor - Sept. 28, 2013, 8:23 p.m.
This patch to the Go compiler avoids useless knockon errors for invalid
uses of the blank identifier "_".  I added a simple general facility for
erroneous names although it is currently only used for _.  Bootstrapped
and ran Go testsuite on x86_64-unknown-linux-gnu.  Committed to mainline
and 4.8 branch.

Ian

Patch

diff -r a8b1cc175cc1 go/gogo-tree.cc
--- a/go/gogo-tree.cc	Fri Sep 27 15:11:52 2013 -0700
+++ b/go/gogo-tree.cc	Sat Sep 28 13:21:19 2013 -0700
@@ -1061,6 +1061,12 @@ 
   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 -r a8b1cc175cc1 go/gogo.cc
--- a/go/gogo.cc	Fri Sep 27 15:11:52 2013 -0700
+++ b/go/gogo.cc	Sat Sep 28 13:21:19 2013 -0700
@@ -1192,6 +1192,27 @@ 
   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 -r a8b1cc175cc1 go/gogo.h
--- a/go/gogo.h	Fri Sep 27 15:11:52 2013 -0700
+++ b/go/gogo.h	Sat Sep 28 13:21:19 2013 -0700
@@ -387,6 +387,16 @@ 
   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 -r a8b1cc175cc1 go/parse.cc
--- a/go/parse.cc	Fri Sep 27 15:11:52 2013 -0700
+++ b/go/parse.cc	Sat Sep 28 13:21:19 2013 -0700
@@ -213,7 +213,7 @@ 
   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 @@ 
       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 @@ 
 	    {
 	      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 @@ 
 		    {
 		      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 @@ 
 	  if (name == "_")
 	    {
 	      error_at(this->location(), "invalid package name _");
-	      name = "blank";
+	      name = Gogo::erroneous_name();
 	    }
 	  this->advance_token();
 	}
diff -r a8b1cc175cc1 go/types.cc
--- a/go/types.cc	Fri Sep 27 15:11:52 2013 -0700
+++ b/go/types.cc	Sat Sep 28 13:21:19 2013 -0700
@@ -9269,7 +9269,11 @@ 
     }
   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());