Patchwork [gccgo] Clean up error internationalization

login
register
mail settings
Submitter Ian Taylor
Date Nov. 17, 2010, 6:16 a.m.
Message ID <mcrmxp81nm9.fsf@google.com>
Download mbox | patch
Permalink /patch/71526/
State New
Headers show

Comments

Ian Taylor - Nov. 17, 2010, 6:16 a.m.
This gccgo patch cleans up the error internationalization.  With this
patch I think no calls to error_at use _().  All calls which pass
strings to functions which call error_at use _().

Since I want to eventually make the Go frontend proper independent of
gcc, I'm going to have to work out how to handle the special gcc
formatting characters I am currently using, like %< and so forth.  I'm
not sure what the right approach is going to be there.  So this is an
interim patch along the way to gcc-independent error handling, which at
least gets things right for now.

Committed to gccgo branch.

Ian
Joseph S. Myers - Nov. 17, 2010, 12:03 p.m.
On Tue, 16 Nov 2010, Ian Lance Taylor wrote:

> Since I want to eventually make the Go frontend proper independent of
> gcc, I'm going to have to work out how to handle the special gcc
> formatting characters I am currently using, like %< and so forth.  I'm
> not sure what the right approach is going to be there.  So this is an
> interim patch along the way to gcc-independent error handling, which at
> least gets things right for now.

I don't see a particular problem with using those formats and defining 
them to be part of the interface that the front end uses to any back end 
it is hooked up to; it's a reasonably well-defined, reimplementable 
interface.  It's the huge number of direct uses of "tree" interfaces in 
the gofrontend/ directory I'd consider the most obvious major separation 
issue; for a proper separation, I think everything that deals with trees 
should be considered to be on the GCC side rather than part of the front 
end proper (just as with the Ada front end).
Ian Taylor - Nov. 17, 2010, 3:20 p.m.
"Joseph S. Myers" <joseph@codesourcery.com> writes:

> On Tue, 16 Nov 2010, Ian Lance Taylor wrote:
>
>> Since I want to eventually make the Go frontend proper independent of
>> gcc, I'm going to have to work out how to handle the special gcc
>> formatting characters I am currently using, like %< and so forth.  I'm
>> not sure what the right approach is going to be there.  So this is an
>> interim patch along the way to gcc-independent error handling, which at
>> least gets things right for now.
>
> I don't see a particular problem with using those formats and defining 
> them to be part of the interface that the front end uses to any back end 
> it is hooked up to; it's a reasonably well-defined, reimplementable 
> interface.  It's the huge number of direct uses of "tree" interfaces in 
> the gofrontend/ directory I'd consider the most obvious major separation 
> issue; for a proper separation, I think everything that deals with trees 
> should be considered to be on the GCC side rather than part of the front 
> end proper (just as with the Ada front end).

Completely agreed about the tree code.  I'm working on moving them, but
doing it cleanly requires a bunch of plumbing.

Not sure how I feel about the formatting code.

Ian

Patch

diff -r 0d6655cb834b go/expressions.cc
--- a/go/expressions.cc	Tue Nov 16 19:55:56 2010 -0800
+++ b/go/expressions.cc	Tue Nov 16 22:12:32 2010 -0800
@@ -2526,8 +2526,8 @@ 
 	  if (cexpr->float_constant_value(fval, &dummy))
 	    {
 	      if (!mpfr_integer_p(fval))
-		this->report_error("floating point constant "
-				   "truncated to integer");
+		this->report_error(_("floating point constant "
+				     "truncated to integer"));
 	      else
 		{
 		  mpfr_get_z(ival, fval, GMP_RNDN);
@@ -3125,7 +3125,7 @@ 
   if (Type::are_convertible(type, expr_type, &reason))
     return;
 
-  error_at(this->location(), reason.c_str());
+  error_at(this->location(), "%s", reason.c_str());
   this->set_is_error();
 }
 
@@ -5368,7 +5368,7 @@ 
     case OPERATOR_ANDAND:
       if (!type->is_boolean_type())
 	{
-	  error_at(location, _("expected boolean type"));
+	  error_at(location, "expected boolean type");
 	  return false;
 	}
       break;
@@ -5390,9 +5390,9 @@ 
 	  && type->function_type() == NULL)
 	{
 	  error_at(location,
-		   _("expected integer, floating, complex, string, pointer, "
-		     "boolean, interface, slice, map, channel, "
-		     "or function type"));
+		   ("expected integer, floating, complex, string, pointer, "
+		    "boolean, interface, slice, map, channel, "
+		    "or function type"));
 	  return false;
 	}
       break;
@@ -5405,8 +5405,7 @@ 
 	  && type->float_type() == NULL
 	  && !type->is_string_type())
 	{
-	  error_at(location,
-		   _("expected integer, floating, or string type"));
+	  error_at(location, "expected integer, floating, or string type");
 	  return false;
 	}
       break;
@@ -5419,7 +5418,7 @@ 
 	  && !type->is_string_type())
 	{
 	  error_at(location,
-		   _("expected integer, floating, complex, or string type"));
+		   "expected integer, floating, complex, or string type");
 	  return false;
 	}
       break;
@@ -5434,7 +5433,7 @@ 
 	  && type->float_type() == NULL
 	  && type->complex_type() == NULL)
 	{
-	  error_at(location, _("expected integer, floating, or complex type"));
+	  error_at(location, "expected integer, floating, or complex type");
 	  return false;
 	}
       break;
@@ -5451,7 +5450,7 @@ 
     case OPERATOR_BITCLEAREQ:
       if (type->integer_type() == NULL)
 	{
-	  error_at(location, _("expected integer type"));
+	  error_at(location, "expected integer type");
 	  return false;
 	}
       break;
@@ -6426,7 +6425,7 @@ 
 	  Expression* arg = args->front();
 	  if (!arg->is_type_expression())
 	    {
-	      error_at(arg->location(), _("expected type"));
+	      error_at(arg->location(), "expected type");
 	      this->set_is_error();
 	    }
 	  else
@@ -6443,7 +6442,7 @@ 
 	  Expression* arg = args->front();
 	  if (!arg->is_type_expression())
 	    {
-	      error_at(arg->location(), _("expected type"));
+	      error_at(arg->location(), "expected type");
 	      this->set_is_error();
 	    }
 	  else
@@ -6538,8 +6537,7 @@ 
       Type* slice_type = args->front()->type();
       if (!slice_type->is_open_array_type())
 	{
-	  error_at(args->front()->location(),
-		   _("argument 1 must be a slice"));
+	  error_at(args->front()->location(), "argument 1 must be a slice");
 	  this->set_is_error();
 	  return this;
 	}
@@ -7982,7 +7980,7 @@ 
 	new_args->push_back(*pa);
       else if (this->is_varargs_)
 	{
-	  this->report_error("too many arguments");
+	  this->report_error(_("too many arguments"));
 	  return this;
 	}
       else if (pa + 1 == old_args->end()
@@ -8274,7 +8272,7 @@ 
 				    first_arg_type, &reason))
 	    {
 	      if (reason.empty())
-		this->report_error("incompatible type for receiver");
+		this->report_error(_("incompatible type for receiver"));
 	      else
 		{
 		  error_at(this->location(),
@@ -10294,7 +10292,7 @@ 
   Struct_type* st = this->type_->struct_type();
   if (this->vals_->size() > st->field_count())
     {
-      this->report_error("too many expressions for struct");
+      this->report_error(_("too many expressions for struct"));
       return;
     }
 
@@ -10307,7 +10305,7 @@ 
     {
       if (pv == this->vals_->end())
 	{
-	  this->report_error("too few expressions for struct");
+	  this->report_error(_("too few expressions for struct"));
 	  break;
 	}
 
@@ -11875,7 +11873,8 @@ 
   Channel_type* channel_type = type->channel_type();
   if (channel_type == NULL)
     {
-      this->report_error(_("left operand of %<<-%> must be channel"));
+      error_at(this->location(), "left operand of %<<-%> must be channel");
+      this->set_is_error();
       return;
     }
   Type* element_type = channel_type->element_type();
diff -r 0d6655cb834b go/lex.cc
--- a/go/lex.cc	Tue Nov 16 19:55:56 2010 -0800
+++ b/go/lex.cc	Tue Nov 16 22:12:32 2010 -0800
@@ -470,7 +470,7 @@ 
 	{
 	  size_t ns = 2 * size + 1;
 	  if (ns < size || static_cast<ssize_t>(ns) < 0)
-	    this->error("out of memory");
+	    error_at(this->location(), "out of memory");
 	  char* nb = new char[ns];
 	  memcpy(nb, buf, cur);
 	  delete[] buf;
@@ -810,9 +810,9 @@ 
   if (adv == 0)
     {
       if (*p == '\0')
-	this->error("invalid NUL byte");
+	error_at(this->location(), "invalid NUL byte");
       else
-	this->error("invalid UTF-8 encoding");
+	error_at(this->location(), "invalid UTF-8 encoding");
       *issued_error = true;
       return p + 1;
     }
@@ -1092,7 +1092,7 @@ 
       if (is_single_quote
 	  && (*value == '\'' || *value == '\n')
 	  && !issued_error)
-	this->error("invalid character literal");
+	error_at(this->location(), "invalid character literal");
       return ret;
     }
   else
@@ -1111,12 +1111,12 @@ 
 			+ Lex::octal_value(p[2]));
 	      if (*value > 255)
 		{
-		  this->error("invalid octal constant");
+		  error_at(this->location(), "invalid octal constant");
 		  *value = 255;
 		}
 	      return p + 3;
 	    }
-	  this->error("invalid octal character");
+	      error_at(this->location(), "invalid octal character");
 	  return (p[1] >= '0' && p[1] <= '7'
 		  ? p + 2
 		  : p + 1);
@@ -1129,7 +1129,7 @@ 
 	      *value = (hex_value(p[1]) << 4) + hex_value(p[2]);
 	      return p + 3;
 	    }
-	  this->error("invalid hex character");
+	  error_at(this->location(), "invalid hex character");
 	  return (Lex::is_hex_digit(p[1])
 		  ? p + 2
 		  : p + 1);
@@ -1160,12 +1160,12 @@ 
 	  return p + 1;
 	case '\'':
 	  if (!is_single_quote)
-	    this->error("invalid quoted character");
+	    error_at(this->location(), "invalid quoted character");
 	  *value = '\'';
 	  return p + 1;
 	case '"':
 	  if (is_single_quote)
-	    this->error("invalid quoted character");
+	    error_at(this->location(), "invalid quoted character");
 	  *value = '"';
 	  return p + 1;
 
@@ -1179,14 +1179,15 @@ 
 			+ hex_value(p[4]));
 	      if (*value >= 0xd800 && *value < 0xe000)
 		{
-		  error_at(this->location(),"invalid unicode code point 0x%x",
+		  error_at(this->location(),
+			   "invalid unicode code point 0x%x",
 			   *value);
 		  // Use the replacement character.
 		  *value = 0xfffd;
 		}
 	      return p + 5;
 	    }
-	  this->error("invalid little unicode code point");
+	  error_at(this->location(), "invalid little unicode code point");
 	  return p + 1;
 
 	case 'U':
@@ -1213,11 +1214,11 @@ 
 		}
 	      return p + 9;
 	    }
-	  this->error("invalid big unicode code point");
+	  error_at(this->location(), "invalid big unicode code point");
 	  return p + 1;
 
 	default:
-	  this->error("invalid character after %<\\%>");
+	  error_at(this->location(), "invalid character after %<\\%>");
 	  *value = *p;
 	  return p + 1;
 	}
@@ -1288,7 +1289,7 @@ 
 
   if (*p != '\'')
     {
-      this->error("unterminated character constant");
+      error_at(this->location(), "unterminated character constant");
       this->lineoff_ = p - this->linebuf_;
       return this->make_invalid_token();
     }
@@ -1322,7 +1323,7 @@ 
       p = this->advance_one_char(p, false, &c, &is_character);
       if (p >= pend)
 	{
-	  this->error("unterminated string");
+	  error_at(this->location(), "unterminated string");
 	  --p;
 	  break;
 	}
@@ -1543,7 +1544,7 @@ 
     {
       if (!this->require_line())
 	{
-	  this->error("unterminated comment");
+	  error_at(this->location(), "unterminated comment");
 	  return false;
 	}
 
@@ -1623,14 +1624,6 @@ 
     }
 }
 
-// Report an error.
-
-void
-Lex::error(const char* msg)
-{
-  error_at(this->location(), msg);
-}
-
 // The Unicode tables use this struct.
 
 struct Unicode_range
diff -r 0d6655cb834b go/lex.h
--- a/go/lex.h	Tue Nov 16 19:55:56 2010 -0800
+++ b/go/lex.h	Tue Nov 16 22:12:32 2010 -0800
@@ -343,9 +343,6 @@ 
   fetch_char(const char* str, unsigned int *value);
 
  private:
-  void
-  error(const char*);
-
   ssize_t
   get_line();
 
@@ -428,9 +425,6 @@ 
   void
   skip_cpp_comment();
 
-  void
-  error();
-
   // The input file name.
   const char* input_file_name_;
   // The input file.
diff -r 0d6655cb834b go/parse.cc
--- a/go/parse.cc	Tue Nov 16 19:55:56 2010 -0800
+++ b/go/parse.cc	Tue Nov 16 22:12:32 2010 -0800
@@ -108,7 +108,7 @@ 
     {
       if (!token->is_identifier())
 	{
-	  this->error("expected identifier");
+	  error_at(this->location(), "expected identifier");
 	  return;
 	}
       std::string name =
@@ -167,7 +167,7 @@ 
   const Token* token = this->peek_token();
   if (!token->is_identifier())
     {
-      this->error("expected identifier");
+      error_at(this->location(), "expected identifier");
       return false;
     }
 
@@ -186,7 +186,7 @@ 
   Named_object* package = this->gogo_->lookup(name, NULL);
   if (package == NULL || !package->is_package())
     {
-      this->error("expected package");
+      error_at(this->location(), "expected package");
       // We expect . IDENTIFIER; skip both.
       if (this->advance_token()->is_identifier())
 	this->advance_token();
@@ -198,7 +198,7 @@ 
   token = this->advance_token();
   if (!token->is_identifier())
     {
-      this->error("expected identifier");
+      error_at(this->location(), "expected identifier");
       return false;
     }
 
@@ -206,7 +206,7 @@ 
 
   if (name == "_")
     {
-      this->error("invalid use of %<_%>");
+      error_at(this->location(), "invalid use of %<_%>");
       name = "blank";
     }
 
@@ -261,7 +261,7 @@ 
       else
 	{
 	  if (!ret->is_error_type())
-	    this->error("expected %<)%>");
+	    error_at(this->location(), "expected %<)%>");
 	}
       return ret;
     }
@@ -388,13 +388,14 @@ 
 	}
       else
 	{
-	  this->error("use of %<[...]%> outside of array literal");
+	  error_at(this->location(),
+		   "use of %<[...]%> outside of array literal");
 	  length = Expression::make_error(this->location());
 	  this->advance_token();
 	}
       if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
 	{
-	  this->error("expected %<]%>");
+	  error_at(this->location(), "expected %<]%>");
 	  return Type::make_error_type();
 	}
       this->advance_token();
@@ -416,7 +417,7 @@ 
   gcc_assert(this->peek_token()->is_keyword(KEYWORD_MAP));
   if (!this->advance_token()->is_op(OPERATOR_LSQUARE))
     {
-      this->error("expected %<[%>");
+      error_at(this->location(), "expected %<[%>");
       return Type::make_error_type();
     }
   this->advance_token();
@@ -425,7 +426,7 @@ 
 
   if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
     {
-      this->error("expected %<]%>");
+      error_at(this->location(), "expected %<]%>");
       return Type::make_error_type();
     }
   this->advance_token();
@@ -453,7 +454,7 @@ 
 	error_at(token_loc, "unexpected semicolon or newline before %<{%>");
       else
 	{
-	  this->error("expected %<{%>");
+	  error_at(this->location(), "expected %<{%>");
 	  return Type::make_error_type();
 	}
     }
@@ -467,7 +468,7 @@ 
 	this->advance_token();
       else if (!this->peek_token()->is_op(OPERATOR_RCURLY))
 	{
-	  this->error("expected %<;%> or %<}%> or newline");
+	  error_at(this->location(), "expected %<;%> or %<}%> or newline");
 	  if (!this->skip_past_error(OPERATOR_RCURLY))
 	    return Type::make_error_type();
 	}
@@ -528,7 +529,7 @@ 
     }
   else
     {
-      this->error("expected field name");
+      error_at(this->location(), "expected field name");
       while (!token->is_op(OPERATOR_SEMICOLON)
 	     && !token->is_op(OPERATOR_RCURLY)
 	     && !token->is_eof())
@@ -543,7 +544,7 @@ 
 	  this->advance_token();
 	  if (!this->peek_token()->is_identifier())
 	    {
-	      this->error("expected field name");
+	      error_at(this->location(), "expected field name");
 	      while (!token->is_op(OPERATOR_SEMICOLON)
 		     && !token->is_op(OPERATOR_RCURLY)
 		     && !token->is_eof())
@@ -577,7 +578,7 @@ 
 	  token = this->peek_token();
 	  if (!token->is_identifier())
 	    {
-	      this->error("expected identifier");
+	      error_at(this->location(), "expected identifier");
 	      return;
 	    }
 	  std::string name =
@@ -638,7 +639,7 @@ 
     {
       if (!this->advance_token()->is_keyword(KEYWORD_CHAN))
 	{
-	  this->error("expected %<chan%>");
+	  error_at(this->location(), "expected %<chan%>");
 	  return Type::make_error_type();
 	}
       send = false;
@@ -687,7 +688,7 @@ 
 {
   if (!this->peek_token()->is_op(OPERATOR_LPAREN))
     {
-      this->error("expected %<(%>");
+      error_at(this->location(), "expected %<(%>");
       return NULL;
     }
 
@@ -703,7 +704,7 @@ 
   // The optional trailing comma is picked up in parameter_list.
 
   if (!token->is_op(OPERATOR_RPAREN))
-    this->error("expected %<)%>");
+    error_at(this->location(), "expected %<)%>");
   else
     this->advance_token();
 
@@ -833,7 +834,7 @@ 
 		type = this->type();
 	      else
 		{
-		  this->error("%<...%> only permits one name");
+		  error_at(this->location(), "%<...%> only permits one name");
 		  this->advance_token();
 		  type = this->type();
 		}
@@ -884,7 +885,7 @@ 
   while (this->peek_token()->is_op(OPERATOR_COMMA))
     {
       if (is_varargs != NULL && *is_varargs)
-	this->error("%<...%> must be last parameter");
+	error_at(this->location(), "%<...%> must be last parameter");
       if (this->advance_token()->is_op(OPERATOR_RPAREN))
 	break;
       this->parameter_decl(parameters_have_names, ret, is_varargs, &mix_error);
@@ -913,7 +914,7 @@ 
 	  else
 	    {
 	      if (is_varargs == NULL)
-		this->error("invalid use of %<...%>");
+		error_at(this->location(), "invalid use of %<...%>");
 	      else
 		*is_varargs = true;
 	      this->advance_token();
@@ -958,9 +959,9 @@ 
       else
 	{
 	  if (is_varargs == NULL)
-	    this->error("invalid use of %<...%>");
+	    error_at(this->location(), "invalid use of %<...%>");
 	  else if (new_count > orig_count + 1)
-	    this->error("%<...%> only permits one name");
+	    error_at(this->location(), "%<...%> only permits one name");
 	  else
 	    *is_varargs = true;
 	  this->advance_token();
@@ -1004,7 +1005,7 @@ 
 	error_at(loc, "unexpected semicolon or newline before %<{%>");
       else
 	{
-	  this->error("expected %<{%>");
+	  error_at(this->location(), "expected %<{%>");
 	  return UNKNOWN_LOCATION;
 	}
     }
@@ -1018,7 +1019,7 @@ 
       if (!token->is_op(OPERATOR_RCURLY))
 	{
 	  if (!token->is_eof() || !saw_errors())
-	    this->error("expected %<}%>");
+	    error_at(this->location(), "expected %<}%>");
 
 	  // Skip ahead to the end of the block, in hopes of avoiding
 	  // lots of meaningless errors.
@@ -1066,7 +1067,7 @@ 
 	error_at(token_loc, "unexpected semicolon or newline before %<{%>");
       else
 	{
-	  this->error("expected %<{%>");
+	  error_at(this->location(), "expected %<{%>");
 	  return Type::make_error_type();
 	}
     }
@@ -1084,7 +1085,7 @@ 
 	}
       if (!this->peek_token()->is_op(OPERATOR_RCURLY))
 	{
-	  this->error("expected %<}%>");
+	  error_at(this->location(), "expected %<}%>");
 	  while (!this->advance_token()->is_op(OPERATOR_RCURLY))
 	    {
 	      if (this->peek_token()->is_eof())
@@ -1115,7 +1116,7 @@ 
   const Token* token = this->peek_token();
   if (!token->is_identifier())
     {
-      this->error("expected identifier");
+      error_at(this->location(), "expected identifier");
       return false;
     }
 
@@ -1140,7 +1141,8 @@ 
 	      && !this->peek_token()->is_op(OPERATOR_RCURLY)))
 	{
 	  if (this->peek_token()->is_op(OPERATOR_COMMA))
-	    this->error("name list not allowed in interface type");
+	    error_at(this->location(),
+		     "name list not allowed in interface type");
 	  else
 	    error_at(location, "expected signature or type name");
 	  token = this->peek_token();
@@ -1175,7 +1177,7 @@ 
     this->function_decl();
   else
     {
-      this->error("expected declaration");
+      error_at(this->location(), "expected declaration");
       this->advance_token();
     }
 }
@@ -1204,7 +1206,7 @@ 
 	  this->list(pfn, varg, true);
 	  if (!this->peek_token()->is_op(OPERATOR_RPAREN))
 	    {
-	      this->error("missing %<)%>");
+	      error_at(this->location(), "missing %<)%>");
 	      while (!this->advance_token()->is_op(OPERATOR_RPAREN))
 		{
 		  if (this->peek_token()->is_eof())
@@ -1230,7 +1232,7 @@ 
 	 || this->peek_token()->is_op(OPERATOR_COMMA))
     {
       if (this->peek_token()->is_op(OPERATOR_COMMA))
-	this->error("unexpected comma");
+	error_at(this->location(), "unexpected comma");
       if (this->advance_token()->is_op(follow))
 	break;
       (this->*pfn)(varg);
@@ -1261,7 +1263,7 @@ 
 	    this->advance_token();
 	  else if (!this->peek_token()->is_op(OPERATOR_RPAREN))
 	    {
-	      this->error("expected %<;%> or %<)%> or newline");
+	      error_at(this->location(), "expected %<;%> or %<)%> or newline");
 	      if (!this->skip_past_error(OPERATOR_RPAREN))
 		return;
 	    }
@@ -1294,7 +1296,7 @@ 
     {
       if (*last_expr_list == NULL)
 	{
-	  this->error("expected %<=%>");
+	  error_at(this->location(), "expected %<=%>");
 	  return;
 	}
       type = *last_type;
@@ -1321,7 +1323,7 @@ 
     {
       if (pe == expr_list->end())
 	{
-	  this->error("not enough initializers");
+	  error_at(this->location(), "not enough initializers");
 	  return;
 	}
       if (type != NULL)
@@ -1331,7 +1333,7 @@ 
 	this->gogo_->add_constant(*pi, *pe, this->iota_value());
     }
   if (pe != expr_list->end())
-    this->error("too many initializers");
+    error_at(this->location(), "too many initializers");
 
   this->increment_iota();
 
@@ -1356,7 +1358,7 @@ 
   const Token* token = this->peek_token();
   if (!token->is_identifier())
     {
-      this->error("expected identifier");
+      error_at(this->location(), "expected identifier");
       return;
     }
   std::string name = token->identifier();
@@ -1379,7 +1381,8 @@ 
     type = this->type();
   else
     {
-      this->error("unexpected semicolon or newline in type declaration");
+      error_at(this->location(),
+	       "unexpected semicolon or newline in type declaration");
       type = Type::make_error_type();
       this->advance_token();
     }
@@ -1921,7 +1924,7 @@ 
 
   if (!token->is_identifier())
     {
-      this->error("expected function name");
+      error_at(this->location(), "expected function name");
       return;
     }
 
@@ -1939,19 +1942,19 @@ 
     {
       if (!this->advance_token()->is_op(OPERATOR_LPAREN))
 	{
-	  this->error("expected %<(%>");
+	  error_at(this->location(), "expected %<(%>");
 	  return;
 	}
       token = this->advance_token();
       if (!token->is_string())
 	{
-	  this->error("expected string");
+	  error_at(this->location(), "expected string");
 	  return;
 	}
       std::string asm_name = token->string_value();
       if (!this->advance_token()->is_op(OPERATOR_RPAREN))
 	{
-	  this->error("expected %<)%>");
+	  error_at(this->location(), "expected %<)%>");
 	  return;
 	}
       this->advance_token();
@@ -1965,7 +1968,8 @@ 
     {
       source_location semi_loc = this->location();
       if (this->advance_token()->is_op(OPERATOR_LCURLY))
-	this->error("unexpected semicolon or newline before %<{%>");
+	error_at(this->location(),
+		 "unexpected semicolon or newline before %<{%>");
       else
 	this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON,
 						     semi_loc));
@@ -1999,7 +2003,7 @@ 
     {
       if (!token->is_identifier())
 	{
-	  this->error("method has no receiver");
+	  error_at(this->location(), "method has no receiver");
 	  while (!token->is_eof() && !token->is_op(OPERATOR_RPAREN))
 	    token = this->advance_token();
 	  if (!token->is_eof())
@@ -2038,7 +2042,7 @@ 
 
   if (!token->is_identifier())
     {
-      this->error("expected receiver name or type");
+      error_at(this->location(), "expected receiver name or type");
       int c = token->is_op(OPERATOR_LPAREN) ? 1 : 0;
       while (!token->is_eof())
 	{
@@ -2067,9 +2071,9 @@ 
   else
     {
       if (this->peek_token()->is_op(OPERATOR_COMMA))
-	this->error("method has multiple receivers");
+	error_at(this->location(), "method has multiple receivers");
       else
-	this->error("expected %<)%>");
+	error_at(this->location(), "expected %<)%>");
       while (!token->is_eof() && !token->is_op(OPERATOR_RPAREN))
 	token = this->advance_token();
       if (!token->is_eof())
@@ -2251,7 +2255,7 @@ 
 	  this->advance_token();
 	  ret = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
 	  if (!this->peek_token()->is_op(OPERATOR_RPAREN))
-	    this->error("missing %<)%>");
+	    error_at(this->location(), "missing %<)%>");
 	  else
 	    this->advance_token();
 	  return ret;
@@ -2269,7 +2273,7 @@ 
       break;
     }
 
-  this->error("expected operand");
+  error_at(this->location(), "expected operand");
   return Expression::make_error(this->location());
 }
 
@@ -2369,7 +2373,7 @@ 
 	{
 	  if (is_type_omitted && !val->is_error_expression())
 	    {
-	      this->error("unexpected %<:%>");
+	      error_at(this->location(), "unexpected %<:%>");
 	      val = Expression::make_error(this->location());
 	    }
 
@@ -2425,7 +2429,7 @@ 
 	}
       else
 	{
-	  this->error("expected %<,%> or %<}%>");
+	  error_at(this->location(), "expected %<,%> or %<}%>");
 
 	  int depth = 0;
 	  while (!token->is_eof()
@@ -2580,7 +2584,7 @@ 
 	  Expression* expr = this->expression(PRECEDENCE_NORMAL, false, true,
 					      NULL);
 	  if (!this->peek_token()->is_op(OPERATOR_RPAREN))
-	    this->error("expected %<)%>");
+	    error_at(this->location(), "expected %<)%>");
 	  else
 	    this->advance_token();
 	  if (expr->is_error_expression())
@@ -2636,7 +2640,7 @@ 
 				      token->is_identifier_exported());
       if (token->identifier() == "_")
 	{
-	  this->error("invalid use of %<_%>");
+	  error_at(this->location(), "invalid use of %<_%>");
 	  name = this->gogo_->pack_hidden_name("blank", false);
 	}
       this->advance_token();
@@ -2655,7 +2659,7 @@ 
 	  this->advance_token();
 	}
       if (!this->peek_token()->is_op(OPERATOR_RPAREN))
-	this->error("missing %<)%>");
+	error_at(this->location(), "missing %<)%>");
       else
 	this->advance_token();
       if (is_type_switch != NULL && *is_type_switch)
@@ -2664,7 +2668,7 @@ 
     }
   else
     {
-      this->error("expected identifier or %<(%>");
+      error_at(this->location(), "expected identifier or %<(%>");
       return left;
     }
 }
@@ -2700,7 +2704,7 @@ 
 	end = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
     }
   if (!this->peek_token()->is_op(OPERATOR_RSQUARE))
-    this->error("missing %<]%>");
+    error_at(this->location(), "missing %<]%>");
   else
     this->advance_token();
   return Expression::make_index(expr, start, end, location);
@@ -2729,7 +2733,7 @@ 
   if (token->is_op(OPERATOR_COMMA))
     token = this->advance_token();
   if (!token->is_op(OPERATOR_RPAREN))
-    this->error("missing %<)%>");
+    error_at(this->location(), "missing %<)%>");
   else
     this->advance_token();
   if (func->is_error_expression())
@@ -2768,7 +2772,7 @@ 
     case Named_object::NAMED_OBJECT_UNKNOWN:
       return Expression::make_unknown_reference(named_object, location);
     default:
-      this->error("unexpected type of identifier");
+      error_at(this->location(), "unexpected type of identifier");
       return Expression::make_error(location);
     }
 }
@@ -3036,7 +3040,7 @@ 
 	    this->for_stat(label);
 	    break;
 	  default:
-	    this->error("expected statement");
+	    error_at(this->location(), "expected statement");
 	    this->advance_token();
 	    break;
 	  }
@@ -3084,7 +3088,7 @@ 
       break;
 
     default:
-      this->error("expected statement");
+      error_at(this->location(), "expected statement");
       this->advance_token();
       break;
     }
@@ -3278,7 +3282,7 @@ 
       else
 	{
 	  if (!this->peek_token()->is_eof() || !saw_errors())
-	    this->error("expected %<;%> or %<}%> or newline");
+	    error_at(this->location(), "expected %<;%> or %<}%> or newline");
 	  if (!this->skip_past_error(OPERATOR_RCURLY))
 	    return;
 	}
@@ -3368,7 +3372,7 @@ 
       && !token->is_op(OPERATOR_ANDEQ)
       && !token->is_op(OPERATOR_BITCLEAREQ))
     {
-      this->error("expected assignment operator");
+      error_at(this->location(), "expected assignment operator");
       return;
     }
   Operator op = token->op();
@@ -3379,7 +3383,7 @@ 
   if (p_range_clause != NULL && token->is_keyword(KEYWORD_RANGE))
     {
       if (op != OPERATOR_EQ)
-	this->error("range clause requires %<=%>");
+	error_at(this->location(), "range clause requires %<=%>");
       this->range_clause_expr(lhs, p_range_clause);
       return;
     }
@@ -3598,7 +3602,8 @@ 
     {
       source_location semi_loc = this->location();
       if (this->advance_token()->is_keyword(KEYWORD_ELSE))
-	this->error("unexpected semicolon or newline before %<else%>");
+	error_at(this->location(),
+		 "unexpected semicolon or newline before %<else%>");
       else
 	this->unget_token(Token::make_operator_token(OPERATOR_SEMICOLON,
 						     semi_loc));
@@ -3701,7 +3706,7 @@ 
 	error_at(token_loc, "unexpected semicolon or newline before %<{%>");
       else
 	{
-	  this->error("expected %<{%>");
+	  error_at(this->location(), "expected %<{%>");
 	  this->gogo_->add_block(this->gogo_->finish_block(this->location()),
 				 location);
 	  return;
@@ -3740,7 +3745,7 @@ 
       if (this->peek_token()->is_eof())
 	{
 	  if (!saw_errors())
-	    this->error("missing %<}%>");
+	    error_at(this->location(), "missing %<}%>");
 	  return NULL;
 	}
       this->expr_case_clause(case_clauses);
@@ -3768,7 +3773,7 @@ 
   if (!this->peek_token()->is_op(OPERATOR_COLON))
     {
       if (!saw_errors())
-	this->error("expected %<:%>");
+	error_at(this->location(), "expected %<:%>");
       return;
     }
   else
@@ -3814,7 +3819,7 @@ 
   else
     {
       if (!saw_errors())
-	this->error("expected %<case%> or %<default%>");
+	error_at(this->location(), "expected %<case%> or %<default%>");
       if (!token->is_op(OPERATOR_RCURLY))
 	this->advance_token();
       return NULL;
@@ -3850,7 +3855,7 @@ 
     {
       if (this->peek_token()->is_eof())
 	{
-	  this->error("missing %<}%>");
+	  error_at(this->location(), "missing %<}%>");
 	  return NULL;
 	}
       this->type_case_clause(switch_no, case_clauses);
@@ -3876,7 +3881,7 @@ 
   this->type_switch_case(&types, &is_default);
 
   if (!this->peek_token()->is_op(OPERATOR_COLON))
-    this->error("expected %<:%>");
+    error_at(this->location(), "expected %<:%>");
   else
     this->advance_token();
 
@@ -3901,7 +3906,8 @@ 
 
   if (this->peek_token()->is_keyword(KEYWORD_FALLTHROUGH))
     {
-      this->error("fallthrough is not permitted in a type switch");
+      error_at(this->location(),
+	       "fallthrough is not permitted in a type switch");
       if (this->advance_token()->is_op(OPERATOR_SEMICOLON))
 	this->advance_token();
     }
@@ -3949,7 +3955,7 @@ 
     }
   else
     {
-      this->error("expected %<case%> or %<default%>");
+      error_at(this->location(), "expected %<case%> or %<default%>");
       if (!token->is_op(OPERATOR_RCURLY))
 	this->advance_token();
     }
@@ -3972,7 +3978,7 @@ 
 	error_at(token_loc, "unexpected semicolon or newline before %<{%>");
       else
 	{
-	  this->error("expected %<{%>");
+	  error_at(this->location(), "expected %<{%>");
 	  return;
 	}
     }
@@ -3987,7 +3993,7 @@ 
     {
       if (this->peek_token()->is_eof())
 	{
-	  this->error("expected %<}%>");
+	  error_at(this->location(), "expected %<}%>");
 	  return;
 	}
       this->comm_clause(select_clauses);
@@ -4061,7 +4067,7 @@ 
     }
   else
     {
-      this->error("expected %<case%> or %<default%>");
+      error_at(this->location(), "expected %<case%> or %<default%>");
       if (!token->is_op(OPERATOR_RCURLY))
 	this->advance_token();
       return false;
@@ -4069,7 +4075,7 @@ 
 
   if (!this->peek_token()->is_op(OPERATOR_COLON))
     {
-      this->error("expected colon");
+      error_at(this->location(), "expected colon");
       return false;
     }
 
@@ -4099,7 +4105,7 @@ 
 	{
 	  if (!this->advance_token()->is_op(OPERATOR_CHANOP))
 	    {
-	      this->error("expected %<<-%>");
+	      error_at(this->location(), "expected %<<-%>");
 	      return false;
 	    }
 	  *is_send = false;
@@ -4124,7 +4130,7 @@ 
 	{
 	  if (!this->advance_token()->is_op(OPERATOR_CHANOP))
 	    {
-	      this->error("missing %<<-%>");
+	      error_at(this->location(), "missing %<<-%>");
 	      return false;
 	    }
 	  *is_send = false;
@@ -4141,7 +4147,7 @@ 
 	}
       else
 	{
-	  this->error("expected %<<-%> or %<=%>");
+	  error_at(this->location(), "expected %<<-%> or %<=%>");
 	  return false;
 	}
     }
@@ -4172,7 +4178,8 @@ 
     {
       if (token->is_keyword(KEYWORD_VAR))
 	{
-	  this->error("var declaration not allowed in for initializer");
+	  error_at(this->location(),
+		   "var declaration not allowed in for initializer");
 	  this->var_decl();
 	}
 
@@ -4186,12 +4193,12 @@ 
 	  if (!this->peek_token()->is_op(OPERATOR_SEMICOLON))
 	    {
 	      if (cond == NULL && !range_clause.found)
-		this->error("parse error in for statement");
+		error_at(this->location(), "parse error in for statement");
 	    }
 	  else
 	    {
 	      if (range_clause.found)
-		this->error("parse error after range clause");
+		error_at(this->location(), "parse error after range clause");
 
 	      if (cond != NULL)
 		{
@@ -4272,7 +4279,8 @@ 
     *cond = NULL;
   else if (this->peek_token()->is_op(OPERATOR_LCURLY))
     {
-      this->error("unexpected semicolon or newline before %<{%>");
+      error_at(this->location(),
+	       "unexpected semicolon or newline before %<{%>");
       *cond = NULL;
       *post = NULL;
       return;
@@ -4280,7 +4288,7 @@ 
   else
     *cond = this->expression(PRECEDENCE_NORMAL, false, true, NULL);
   if (!this->peek_token()->is_op(OPERATOR_SEMICOLON))
-    this->error("expected semicolon");
+    error_at(this->location(), "expected semicolon");
   else
     this->advance_token();
 
@@ -4309,7 +4317,7 @@ 
 
   gcc_assert(til->size() >= 1);
   if (til->size() > 2)
-    this->error("too many variables for range clause");
+    error_at(this->location(), "too many variables for range clause");
 
   this->advance_token();
   Expression* expr = this->expression(PRECEDENCE_NORMAL, false, false, NULL);
@@ -4354,7 +4362,7 @@ 
 
   gcc_assert(vals->size() >= 1);
   if (vals->size() > 2)
-    this->error("too many variables for range clause");
+    error_at(this->location(), "too many variables for range clause");
 
   this->advance_token();
   p_range_clause->range = this->expression(PRECEDENCE_NORMAL, false, false,
@@ -4426,7 +4434,8 @@ 
     {
       if (this->break_stack_.empty())
 	{
-	  this->error("break statement not within for or switch or select");
+	  error_at(this->location(),
+		   "break statement not within for or switch or select");
 	  return;
 	}
       enclosing = this->break_stack_.back().first;
@@ -4479,7 +4488,7 @@ 
     {
       if (this->continue_stack_.empty())
 	{
-	  this->error("continue statement not within for");
+	  error_at(this->location(), "continue statement not within for");
 	  return;
 	}
       enclosing = this->continue_stack_.back().first;
@@ -4520,7 +4529,7 @@ 
   source_location location = this->location();
   const Token* token = this->advance_token();
   if (!token->is_identifier())
-    this->error("expected label for goto");
+    error_at(this->location(), "expected label for goto");
   else
     {
       Label* label = this->gogo_->add_label_reference(token->identifier());
@@ -4540,7 +4549,7 @@ 
   std::string name;
   if (!token->is_keyword(KEYWORD_PACKAGE))
     {
-      this->error("program must start with package clause");
+      error_at(this->location(), "program must start with package clause");
       name = "ERROR";
     }
   else
@@ -4551,14 +4560,14 @@ 
 	  name = token->identifier();
 	  if (name == "_")
 	    {
-	      this->error("invalid package name _");
+	      error_at(this->location(), "invalid package name _");
 	      name = "blank";
 	    }
 	  this->advance_token();
 	}
       else
 	{
-	  this->error("package name must be an identifier");
+	  error_at(this->location(), "package name must be an identifier");
 	  name = "ERROR";
 	}
     }
@@ -4599,7 +4608,7 @@ 
 
   if (!token->is_string())
     {
-      this->error("missing import package name");
+      error_at(this->location(), "missing import package name");
       return;
     }
 
@@ -4621,7 +4630,8 @@ 
   if (token->is_op(OPERATOR_SEMICOLON))
     token = this->advance_token();
   else
-    this->error("expected %<;%> or newline after package clause");
+    error_at(this->location(),
+	     "expected %<;%> or newline after package clause");
 
   while (token->is_keyword(KEYWORD_IMPORT))
     {
@@ -4630,7 +4640,8 @@ 
       if (token->is_op(OPERATOR_SEMICOLON))
 	token = this->advance_token();
       else
-	this->error("expected %<;%> or newline after import declaration");
+	error_at(this->location(),
+		 "expected %<;%> or newline after import declaration");
     }
 
   while (!token->is_eof())
@@ -4639,7 +4650,7 @@ 
 	this->declaration();
       else
 	{
-	  this->error("expected declaration");
+	  error_at(this->location(), "expected declaration");
 	  do
 	    this->advance_token();
 	  while (!this->peek_token()->is_eof()
@@ -4654,7 +4665,8 @@ 
 	token = this->advance_token();
       else if (!token->is_eof() || !saw_errors())
 	{
-	  this->error("expected %<;%> or newline after top level declaration");
+	  error_at(this->location(),
+		   "expected %<;%> or newline after top level declaration");
 	  this->skip_past_error(OPERATOR_INVALID);
 	}
     }
@@ -4719,11 +4731,3 @@ 
     }
   return expr;
 }
-
-// Give an error.
-
-void
-Parse::error(const char* msg)
-{
-  error_at(this->peek_token()->location(), msg);
-}
diff -r 0d6655cb834b go/parse.h
--- a/go/parse.h	Tue Nov 16 19:55:56 2010 -0800
+++ b/go/parse.h	Tue Nov 16 22:12:32 2010 -0800
@@ -269,9 +269,6 @@ 
   int iota_value();
   void increment_iota();
 
-  void
-  error(const char* msg);
-
   // Skip past an error looking for a semicolon or OP.  Return true if
   // all is well, false if we found EOF.
   bool