public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [patch] PR 31754/C++ - make -fshow-column produce more accurate column  numbers
@ 2008-06-20 10:29 Dodji Seketeli
  2008-06-25  2:01 ` Tom Tromey
  0 siblings, 1 reply; 12+ messages in thread
From: Dodji Seketeli @ 2008-06-20 10:29 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 660 bytes --]

Hello,

This patch tries to fix PR 31754 for the c++ front end.

It modifies the c++ parser to produce more accurate column information
in error messages.

The basic idea of the patch is to not use the global input_location 
variable to generate line/columns info in error messages, but rather to 
pass the right token location to each error message.

It also makes all the tests in testsuite/g++.dg/parse/error*.C be aware 
of column numbers in error messages. It makes those tests run with 
-fshow-column to catch uture breakages of column number generation in 
error messages.

The patch as been regtested on x86 and should apply to trunk.

Cheers,

Dodji.

[-- Attachment #2: gcc-error-location-2008-06-20-patch.txt --]
[-- Type: text/plain, Size: 132309 bytes --]

commit 83a73850df9f4203cdc434ace6e5ce3e15ae4c75
Author: Dodji Seketeli <dodji@tutu.(none)>
Date:   Wed Jun 18 19:52:26 2008 +0200

    fix #31754 - more accurate columns numbers in g++ error messages (wip)
    
    	* cp-tree.h, pt.c, semantic.c:
    	 (qualified_name_lookup_error): add a location_t parameter so that
    	 the error message can have a more accurate location (at least w.r.t
    	 column number). Previously, the location used was the global current
    	 location carried by the "input_location" global variable.
    	 (finish_id_expression): ditto.
    
    	 * parser.c: went through all the calls to error() and passed
    	   specifically the exact location of the token that matters in the
    	   error message. This results in much more precise column numbers
    	   when using g++ with the -fshow-column. This entry should help fix
    	   PR #31754.
    	   What remains to do now is to go through warnings as well and error
    	   messages that are not generated using the error() call.
    	   I also need to find a solution for error messages generated by
    	   semantic analysis, as in that case, there is no token involve but
    	   only instances of tree. The problem is that not all trees have
    	   location information.

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 636ee6a..140aea0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,24 @@
+2008-06-18 Dodji Seketeli <dseketel@redhat.com>
+
+	* cp-tree.h, pt.c, semantic.c:
+	 (qualified_name_lookup_error): add a location_t parameter so that
+	 the error message can have a more accurate location (at least w.r.t
+	 column number). Previously, the location used was the global current
+	 location carried by the "input_location" global variable.
+	 (finish_id_expression): ditto.
+
+	 * parser.c: went through all the calls to error() and passed
+	   specifically the exact location of the token that matters in the
+	   error message. This results in much more precise column numbers
+	   when using g++ with the -fshow-column. This entry should help fix
+	   PR #31754.
+	   What remains to do now is to go through warnings as well and error
+	   messages that are not generated using the error() call.
+	   I also need to find a solution for error messages generated by
+	   semantic analysis, as in that case, there is no token involve but
+	   only instances of tree. The problem is that not all trees have
+	   location information.
+
 2008-06-16  Jan Hubicka  <jh@suse.cz>
 
 	* method.c: Include cgraph.h.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 8ad4fe3..4e6184c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4641,13 +4641,14 @@ extern void finish_template_decl		(tree);
 extern tree finish_template_type		(tree, tree, int);
 extern tree finish_base_specifier		(tree, tree, bool);
 extern void finish_member_declaration		(tree);
-extern void qualified_name_lookup_error		(tree, tree, tree);
+extern void qualified_name_lookup_error		(tree, tree, tree, location_t);
 extern void check_template_keyword		(tree);
 extern tree finish_id_expression		(tree, tree, tree,
 						 cp_id_kind *,
 						 bool, bool, bool *,
 						 bool, bool, bool, bool,
-						 const char **);
+						 const char **,
+                                                 location_t);
 extern tree finish_typeof			(tree);
 extern tree finish_offsetof			(tree);
 extern void finish_decl_cleanup			(tree, tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index a53c029..ea2813c 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1585,7 +1585,7 @@ static tree cp_parser_postfix_expression
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
-  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
+  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
 static tree cp_parser_parenthesized_expression_list
   (cp_parser *, bool, bool, bool, bool *);
 static void cp_parser_pseudo_destructor_name
@@ -1894,15 +1894,15 @@ static tree cp_parser_objc_statement
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
-  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
+  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t);
 static tree cp_parser_lookup_name_simple
-  (cp_parser *, tree);
+  (cp_parser *, tree, location_t);
 static tree cp_parser_maybe_treat_template_as_class
   (tree, bool);
 static bool cp_parser_check_declarator_template_parameters
-  (cp_parser *, cp_declarator *);
+  (cp_parser *, cp_declarator *, location_t);
 static bool cp_parser_check_template_parameters
-  (cp_parser *, unsigned);
+  (cp_parser *, unsigned, location_t);
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
@@ -1938,7 +1938,7 @@ static tree cp_parser_trait_expr
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
-  (cp_parser *, cp_decl_specifier_seq *, enum rid);
+  (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
 static void cp_parser_set_decl_spec_type
   (cp_decl_specifier_seq *, tree, bool);
 static bool cp_parser_friend_p
@@ -1960,7 +1960,7 @@ static enum tag_types cp_parser_token_is_class_key
 static void cp_parser_check_class_key
   (enum tag_types, tree type);
 static void cp_parser_check_access_in_redeclaration
-  (tree type);
+  (tree type, location_t location);
 static bool cp_parser_optional_template_keyword
   (cp_parser *);
 static void cp_parser_pre_parsed_nested_name_specifier
@@ -1982,7 +1982,7 @@ static bool cp_parser_uncommitted_to_tentative_parse_p
 static void cp_parser_error
   (cp_parser *, const char *);
 static void cp_parser_name_lookup_error
-  (cp_parser *, tree, tree, const char *);
+  (cp_parser *, tree, tree, const char *, location_t);
 static bool cp_parser_simulate_error
   (cp_parser *);
 static bool cp_parser_check_type_definition
@@ -1994,7 +1994,7 @@ static void cp_parser_check_for_invalid_template_id
 static bool cp_parser_non_integral_constant_expression
   (cp_parser *, const char *);
 static void cp_parser_diagnose_invalid_type_name
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t);
 static bool cp_parser_parse_and_diagnose_invalid_type_name
   (cp_parser *);
 static int cp_parser_skip_to_closing_parenthesis
@@ -2020,7 +2020,7 @@ static bool cp_parser_is_string_literal
 static bool cp_parser_is_keyword
   (cp_token *, enum rid);
 static tree cp_parser_make_typename_type
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t location);
 static cp_declarator * cp_parser_make_indirect_declarator
   (enum tree_code, tree, cp_cv_quals, cp_declarator *);
 
@@ -2069,7 +2069,7 @@ cp_parser_error (cp_parser* parser, const char* message)
 
       if (token->type == CPP_PRAGMA)
 	{
-	  error ("%<#pragma%> is not allowed here");
+	  error ("%H%<#pragma%> is not allowed here", &token->location);
 	  cp_parser_skip_to_pragma_eol (parser, token);
 	  return;
 	}
@@ -2092,33 +2092,34 @@ static void
 cp_parser_name_lookup_error (cp_parser* parser,
 			     tree name,
 			     tree decl,
-			     const char* desired)
+			     const char* desired,
+			     location_t location)
 {
   /* If name lookup completely failed, tell the user that NAME was not
      declared.  */
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-	error ("%<%E::%E%> has not been declared",
-	       parser->scope, name);
+	error ("%H%<%E::%E%> has not been declared",
+	       &location, parser->scope, name);
       else if (parser->scope == global_namespace)
-	error ("%<::%E%> has not been declared", name);
+	error ("%H%<::%E%> has not been declared", &location, name);
       else if (parser->object_scope
 	       && !CLASS_TYPE_P (parser->object_scope))
-	error ("request for member %qE in non-class type %qT",
-	       name, parser->object_scope);
+	error ("%Hrequest for member %qE in non-class type %qT",
+	       &location, name, parser->object_scope);
       else if (parser->object_scope)
-	error ("%<%T::%E%> has not been declared",
-	       parser->object_scope, name);
+	error ("%H%<%T::%E%> has not been declared",
+	       &location, parser->object_scope, name);
       else
-	error ("%qE has not been declared", name);
+	error ("%H%qE has not been declared", &location, name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("%<%E::%E%> %s", parser->scope, name, desired);
+    error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
   else if (parser->scope == global_namespace)
-    error ("%<::%E%> %s", name, desired);
+    error ("%H%<::%E%> %s", &location, name, desired);
   else
-    error ("%qE %s", name, desired);
+    error ("%H%qE %s", &location, name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -2139,7 +2140,8 @@ cp_parser_simulate_error (cp_parser* parser)
 /* Check for repeated decl-specifiers.  */
 
 static void
-cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
+cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
+			   location_t location)
 {
   cp_decl_spec ds;
 
@@ -2152,10 +2154,11 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
       if (ds == ds_long)
 	{
 	  if (count > 2)
-	    error ("%<long long long%> is too long for GCC");
+	    error ("%H%<long long long%> is too long for GCC", &location);
 	  else if (pedantic && !in_system_header && warn_long_long
                    && cxx_dialect == cxx98)
-	    pedwarn ("ISO C++ 1998 does not support %<long long%>");
+	    pedwarn ("%HISO C++ 1998 does not support %<long long%>",
+		     &location);
 	}
       else if (count > 1)
 	{
@@ -2175,7 +2178,7 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
 	    "__complex",
 	    "__thread"
 	  };
-	  error ("duplicate %qs", decl_spec_names[(int)ds]);
+	  error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
 	}
     }
 }
@@ -2291,13 +2294,15 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
    in duplicate error messages.)  */
 
 static void
-cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
+cp_parser_diagnose_invalid_type_name (cp_parser *parser,
+				      tree scope, tree id,
+				      location_t id_location)
 {
   tree decl, old_scope;
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
-  decl = cp_parser_lookup_name_simple (parser, id);
+  decl = cp_parser_lookup_name_simple (parser, id, id_location);
   parser->scope = old_scope;
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
@@ -2382,6 +2387,7 @@ static bool
 cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
 {
   tree id;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   cp_parser_parse_tentatively (parser);
   id = cp_parser_id_expression (parser,
@@ -2405,7 +2411,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
-  cp_parser_diagnose_invalid_type_name (parser, parser->scope, id);
+  cp_parser_diagnose_invalid_type_name (parser, parser->scope,
+					id, token->location);
   /* Skip to the end of the declaration; there's no point in
      trying to process it.  */
   cp_parser_skip_to_end_of_block_or_statement (parser);
@@ -2693,7 +2700,8 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok)
    using cp_parser_diagnose_invalid_type_name.  */
 
 static tree
-cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
+cp_parser_make_typename_type (cp_parser *parser, tree scope,
+			      tree id, location_t id_location)
 {
   tree result;
   if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -2701,7 +2709,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
       result = make_typename_type (scope, id, typename_type,
 				   /*complain=*/tf_none);
       if (result == error_mark_node)
-	cp_parser_diagnose_invalid_type_name (parser, scope, id);
+	cp_parser_diagnose_invalid_type_name (parser, scope, id, id_location);
       return result;
     }
   return make_typename_type (scope, id, typename_type, tf_error);
@@ -2919,7 +2927,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
 	      if (type == CPP_STRING)
 		type = tok->type;
 	      else if (tok->type != CPP_STRING)
-		error ("unsupported non-standard concatenation of string literals");
+		error ("%Hunsupported non-standard concatenation "
+                       "of string literals", &tok->location);
 	    }
 
 	  obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -3098,7 +3107,7 @@ cp_parser_primary_expression (cp_parser *parser,
 			      bool template_arg_p,
 			      cp_id_kind *idk)
 {
-  cp_token *token;
+  cp_token *token=NULL;
 
   /* Assume the primary expression is not an id-expression.  */
   *idk = CP_ID_KIND_NONE;
@@ -3196,7 +3205,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  {
 	    /* Statement-expressions are not allowed by the standard.  */
 	    if (pedantic)
-	      pedwarn ("ISO C++ forbids braced-groups within expressions");
+	      pedwarn ("%HISO C++ forbids braced-groups within expressions",
+		       &token->location);
 
 	    /* And they're not allowed outside of a function-body; you
 	       cannot, for example, write:
@@ -3207,8 +3217,9 @@ cp_parser_primary_expression (cp_parser *parser,
 	    if (!parser->in_function_body
 		|| parser->in_template_argument_list_p)
 	      {
-		error ("statement-expressions are not allowed outside "
-		       "functions nor in template-argument lists");
+		error ("%Hstatement-expressions are not allowed outside "
+		       "functions nor in template-argument lists",
+		       &token->location);
 		cp_parser_skip_to_end_of_block_or_statement (parser);
 		expr = error_mark_node;
 	      }
@@ -3265,7 +3276,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  cp_lexer_consume_token (parser->lexer);
 	  if (parser->local_variables_forbidden_p)
 	    {
-	      error ("%<this%> may not be used in this context");
+	      error ("%H%<this%> may not be used in this context",
+                     &token->location);
 	      return error_mark_node;
 	    }
 	  /* Pointers cannot appear in constant-expressions.  */
@@ -3365,6 +3377,7 @@ cp_parser_primary_expression (cp_parser *parser,
 	const char *error_msg;
 	bool template_p;
 	bool done;
+	cp_token *id_expr_token;
 
       id_expression:
 	/* Parse the id-expression.  */
@@ -3377,6 +3390,7 @@ cp_parser_primary_expression (cp_parser *parser,
 				     /*optional_p=*/false);
 	if (id_expression == error_mark_node)
 	  return error_mark_node;
+	id_expr_token = token;
 	token = cp_lexer_peek_token (parser->lexer);
 	done = (token->type != CPP_OPEN_SQUARE
 		&& token->type != CPP_OPEN_PAREN
@@ -3400,7 +3414,8 @@ cp_parser_primary_expression (cp_parser *parser,
 					  template_p,
 					  /*is_namespace=*/false,
 					  /*check_dependency=*/true,
-					  &ambiguous_decls);
+					  &ambiguous_decls,
+					  id_expr_token->location);
 	    /* If the lookup was ambiguous, an error will already have
 	       been issued.  */
 	    if (ambiguous_decls)
@@ -3447,8 +3462,8 @@ cp_parser_primary_expression (cp_parser *parser,
 		decl = check_for_out_of_scope_variable (decl);
 		if (local_variable_p (decl))
 		  {
-		    error ("local variable %qD may not appear in this context",
-			   decl);
+		    error ("%Hlocal variable %qD may not appear in this context",
+			   &id_expr_token->location, decl);
 		    return error_mark_node;
 		  }
 	      }
@@ -3462,7 +3477,8 @@ cp_parser_primary_expression (cp_parser *parser,
 		 &parser->non_integral_constant_expression_p,
 		 template_p, done, address_p,
 		 template_arg_p,
-		 &error_msg));
+		 &error_msg,
+                 id_expr_token->location));
 	if (error_msg)
 	  cp_parser_error (parser, error_msg);
 	return decl;
@@ -3746,7 +3762,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	      error ("scope %qT before %<~%> is not a class-name", scope);
+	      error ("%Hscope %qT before %<~%> is not a class-name",
+		     &token->location, scope);
 	    cp_parser_simulate_error (parser);
 	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
 	      cp_lexer_consume_token (parser->lexer);
@@ -3847,8 +3864,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	if (declarator_p && scope && !check_dtor_name (scope, type_decl))
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	      error ("declaration of %<~%T%> as member of %qT",
-		     type_decl, scope);
+	      error ("%Hdeclaration of %<~%T%> as member of %qT",
+		     &token->location, type_decl, scope);
 	    cp_parser_simulate_error (parser);
 	    return error_mark_node;
 	  }
@@ -3861,8 +3878,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	    && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
 	    && !DECL_SELF_REFERENCE_P (type_decl)
 	    && !cp_parser_uncommitted_to_tentative_parse_p (parser))
-	  error ("typedef-name %qD used as destructor declarator",
-		 type_decl);
+	  error ("%Htypedef-name %qD used as destructor declarator",
+		 &token->location, type_decl);
 
 	return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
@@ -4066,20 +4083,23 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
 						    /*is_template=*/false,
 						    /*is_namespace=*/false,
 						    /*check_dependency=*/true,
-						    &ambiguous_decls);
+						    &ambiguous_decls,
+						    token->location);
 		      if (TREE_CODE (decl) == TEMPLATE_DECL)
-			error ("%qD used without template parameters", decl);
+			error ("%H%qD used without template parameters",
+			       &token->location, decl);
 		      else if (ambiguous_decls)
 			{
-			  error ("reference to %qD is ambiguous",
-				 token->u.value);
+			  error ("%Hreference to %qD is ambiguous",
+				 &token->location, token->u.value);
 			  print_candidates (ambiguous_decls);
 			  decl = error_mark_node;
 			}
 		      else
 			cp_parser_name_lookup_error
 			  (parser, token->u.value, decl,
-			   "is not a class or namespace");
+			   "is not a class or namespace",
+			   token->location);
 		    }
 		  parser->scope = error_mark_node;
 		  error_p = true;
@@ -4731,7 +4751,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	  postfix_expression
 	    = cp_parser_postfix_dot_deref_expression (parser, token->type,
 						      postfix_expression,
-						      false, &idk);
+						      false, &idk,
+						      token->location);
 
           is_member_access = true;
 	  break;
@@ -4845,7 +4866,8 @@ static tree
 cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 					enum cpp_ttype token_type,
 					tree postfix_expression,
-					bool for_offsetof, cp_id_kind *idk)
+					bool for_offsetof, cp_id_kind *idk,
+					location_t location)
 {
   tree name;
   bool dependent_p;
@@ -4877,7 +4899,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
 	{
-	  error ("%qE does not have class type", postfix_expression);
+	  error ("%H%qE does not have class type", &location, postfix_expression);
 	  scope = NULL_TREE;
 	}
       else
@@ -4933,6 +4955,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 ordinary class member access expression, rather than a
 	 pseudo-destructor-name.  */
       bool template_p;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
       /* Parse the id-expression.  */
       name = (cp_parser_id_expression
 	      (parser,
@@ -4960,7 +4983,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 TYPE_DECL here.  That is invalid code.  */
       if (TREE_CODE (name) == TYPE_DECL)
 	{
-	  error ("invalid use of %qD", name);
+	  error ("%Hinvalid use of %qD", &token->location, name);
 	  postfix_expression = error_mark_node;
 	}
       else
@@ -5514,18 +5537,21 @@ cp_parser_new_expression (cp_parser* parser)
      type-id.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
+      cp_token *token;
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the type-id.  */
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      token = cp_lexer_peek_token (parser->lexer);
       /* There should not be a direct-new-declarator in this production,
 	 but GCC used to allowed this, so we check and emit a sensible error
 	 message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
 	{
-	  error ("array bound forbidden after parenthesized type-id");
+	  error ("%Harray bound forbidden after parenthesized type-id",
+		 &token->location);
 	  inform ("try removing the parentheses around the type-id");
 	  cp_parser_direct_new_declarator (parser);
 	}
@@ -5702,6 +5728,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       /* The first expression is not required to be constant.  */
       if (!declarator)
 	{
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
 	  expression = cp_parser_expression (parser, /*cast_p=*/false);
 	  /* The standard requires that the expression have integral
 	     type.  DR 74 adds enumeration types.  We believe that the
@@ -5717,8 +5744,8 @@ cp_parser_direct_new_declarator (cp_parser* parser)
 					      /*complain=*/true);
 	      if (!expression)
 		{
-		  error ("expression in new-declarator must have integral "
-			 "or enumeration type");
+		  error ("%Hexpression in new-declarator must have integral "
+			 "or enumeration type", &token->location);
 		  expression = error_mark_node;
 		}
 	    }
@@ -6445,6 +6472,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   int save_ice_p, save_non_ice_p;
   tree type, expr;
   cp_id_kind dummy;
+  cp_token *token;
 
   /* We're about to accept non-integral-constant things, but will
      definitely yield an integral constant expression.  Save and
@@ -6460,6 +6488,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
   cp_parser_require (parser, CPP_COMMA, "%<,%>");
+  token = cp_lexer_peek_token (parser->lexer);
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
   expr = build_static_cast (build_pointer_type (type), null_pointer_node,
@@ -6467,10 +6496,10 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 
   /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
   expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
-						 true, &dummy);
+						 true, &dummy, token->location);
   while (true)
     {
-      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
       switch (token->type)
 	{
 	case CPP_OPEN_SQUARE:
@@ -6482,7 +6511,8 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 	  /* offsetof-member-designator "." identifier */
 	  cp_lexer_consume_token (parser->lexer);
 	  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
-							 true, &dummy);
+							 true, &dummy,
+							 token->location);
 	  break;
 
 	case CPP_CLOSE_PAREN:
@@ -6844,7 +6874,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
 	if (parser->in_switch_statement_p)
 	  finish_case_label (expr, expr_hi);
 	else
-	  error ("case label %qE not within a switch statement", expr);
+	  error ("%Hcase label %qE not within a switch statement",
+		 &token->location, expr);
       }
       break;
 
@@ -6855,7 +6886,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
       if (parser->in_switch_statement_p)
 	finish_case_label (NULL_TREE, NULL_TREE);
       else
-	error ("case label not within a switch statement");
+	error ("%Hcase label not within a switch statement", &token->location);
       break;
 
     default:
@@ -6973,7 +7004,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
 	  else
 	    {
 	      token = cp_lexer_consume_token (parser->lexer);
-	      error ("%<else%> without a previous %<if%>");
+	      error ("%H%<else%> without a previous %<if%>", &token->location);
 	    }
 	}
 
@@ -7457,7 +7488,7 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (in_statement)
 	{
 	case 0:
-	  error ("break statement not within loop or switch");
+	  error ("%Hbreak statement not within loop or switch", &token->location);
 	  break;
 	default:
 	  gcc_assert ((in_statement & IN_SWITCH_STMT)
@@ -7465,10 +7496,10 @@ cp_parser_jump_statement (cp_parser* parser)
 	  statement = finish_break_stmt ();
 	  break;
 	case IN_OMP_BLOCK:
-	  error ("invalid exit from OpenMP structured block");
+	  error ("%Hinvalid exit from OpenMP structured block", &token->location);
 	  break;
 	case IN_OMP_FOR:
-	  error ("break statement used with OpenMP for loop");
+	  error ("%Hbreak statement used with OpenMP for loop", &token->location);
 	  break;
 	}
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
@@ -7478,14 +7509,14 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
 	{
 	case 0:
-	  error ("continue statement not within a loop");
+	  error ("%Hcontinue statement not within a loop", &token->location);
 	  break;
 	case IN_ITERATION_STMT:
 	case IN_OMP_FOR:
 	  statement = finish_continue_stmt ();
 	  break;
 	case IN_OMP_BLOCK:
-	  error ("invalid exit from OpenMP structured block");
+	  error ("%Hinvalid exit from OpenMP structured block", &token->location);
 	  break;
 	default:
 	  gcc_unreachable ();
@@ -7516,7 +7547,7 @@ cp_parser_jump_statement (cp_parser* parser)
 	{
 	  /* Issue a warning about this use of a GNU extension.  */
 	  if (pedantic)
-	    pedwarn ("ISO C++ forbids computed gotos");
+	    pedwarn ("%HISO C++ forbids computed gotos", &token->location);
 	  /* Consume the '*' token.  */
 	  cp_lexer_consume_token (parser->lexer);
 	  /* Parse the dependent expression.  */
@@ -7877,7 +7908,7 @@ cp_parser_block_declaration (cp_parser *parser,
   else if (token1->keyword == RID_LABEL)
     {
       cp_lexer_consume_token (parser->lexer);
-      error ("%<__label__%> not at the beginning of a block");
+      error ("%H%<__label__%> not at the beginning of a block", &token1->location);
       cp_parser_skip_to_end_of_statement (parser);
       /* If the next token is now a `;', consume it.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -8010,7 +8041,11 @@ cp_parser_simple_declaration (cp_parser* parser,
 
 	     which is erroneous.  */
 	  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-	    error ("mixing declarations and function-definitions is forbidden");
+	    {
+	      cp_token *token= cp_lexer_peek_token (parser->lexer);
+	      error ("%Hmixing declarations and function-definitions is forbidden",
+		     &token->location);
+	    }
 	  /* Otherwise, we're done with the list of declarators.  */
 	  else
 	    {
@@ -8106,6 +8141,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 			      int* declares_class_or_enum)
 {
   bool constructor_possible_p = !parser->in_declarator_p;
+  cp_token *start_token = NULL;
 
   /* Clear DECL_SPECS.  */
   clear_decl_specs (decl_specs);
@@ -8122,6 +8158,9 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
+      /*save the first token of the decl spec list for error reporting*/
+      if (!start_token)
+	start_token = token;
       /* Handle attributes.  */
       if (token->keyword == RID_ATTRIBUTE)
 	{
@@ -8198,15 +8237,17 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
                  we're complaining about C++0x compatibility.  */
               warning 
                 (OPT_Wc__0x_compat, 
-                 "%<auto%> will change meaning in C++0x; please remove it");
+                 "%H%<auto%> will change meaning in C++0x; please remove it",
+		 &token->location);
 
               /* Set the storage class anyway.  */
-              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO);
+              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
+					   token->location);
             }
           else 
             /* We do not yet support the use of `auto' as a
                type-specifier.  */
-            error ("C++0x %<auto%> specifier not supported");
+            error ("%HC++0x %<auto%> specifier not supported", &token->location);
           break;
 
 	case RID_REGISTER:
@@ -8215,7 +8256,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 	case RID_MUTABLE:
 	  /* Consume the token.  */
 	  cp_lexer_consume_token (parser->lexer);
-          cp_parser_set_storage_class (parser, decl_specs, token->keyword);
+          cp_parser_set_storage_class (parser, decl_specs, token->keyword,
+				       token->location);
 	  break;
 	case RID_THREAD:
 	  /* Consume the token.  */
@@ -8251,7 +8293,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 					/*is_declaration=*/true,
 					&decl_spec_declares_class_or_enum,
 					&is_cv_qualifier);
-
 	  *declares_class_or_enum |= decl_spec_declares_class_or_enum;
 
 	  /* If this type-specifier referenced a user-defined type
@@ -8311,12 +8352,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
-  cp_parser_check_decl_spec (decl_specs);
+  cp_parser_check_decl_spec (decl_specs, start_token->location);
 
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
-    error ("class definition may not be declared a friend");
+    error ("%Hclass definition may not be declared a friend",
+	    &start_token->location);
 }
 
 /* Parse an (optional) storage-class-specifier.
@@ -8372,7 +8414,8 @@ static tree
 cp_parser_function_specifier_opt (cp_parser* parser,
 				  cp_decl_specifier_seq *decl_specs)
 {
-  switch (cp_lexer_peek_token (parser->lexer)->keyword)
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  switch (token->keyword)
     {
     case RID_INLINE:
       if (decl_specs)
@@ -8384,7 +8427,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
 
 	 A member function template shall not be virtual.  */
       if (PROCESSING_REAL_TEMPLATE_DECL_P ())
-	error ("templates may not be %<virtual%>");
+	error ("%Htemplates may not be %<virtual%>", &token->location);
       else if (decl_specs)
 	++decl_specs->specs[(int) ds_virtual];
       break;
@@ -8538,6 +8581,7 @@ cp_parser_decltype (cp_parser *parser)
   const char *saved_message;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
+  cp_token *id_expr_start_token;
 
   /* Look for the `decltype' token.  */
   if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
@@ -8567,6 +8611,7 @@ cp_parser_decltype (cp_parser *parser)
     return error_mark_node;
   
   /* First, try parsing an id-expression.  */
+  id_expr_start_token = cp_lexer_peek_token (parser->lexer);
   cp_parser_parse_tentatively (parser);
   expr = cp_parser_id_expression (parser,
                                   /*template_keyword_p=*/false,
@@ -8589,7 +8634,8 @@ cp_parser_decltype (cp_parser *parser)
 				      /*is_template=*/false,
 				      /*is_namespace=*/false,
 				      /*check_dependency=*/true,
-				      /*ambiguous_decls=*/NULL);
+				      /*ambiguous_decls=*/NULL,
+				      id_expr_start_token->location);
 
       if (expr
           && expr != error_mark_node
@@ -8609,7 +8655,8 @@ cp_parser_decltype (cp_parser *parser)
                    /*done=*/true,
                    /*address_p=*/false,
                    /*template_arg_p=*/false,
-                   &error_msg));
+                   &error_msg,
+		   id_expr_start_token->location));
 
           if (expr == error_mark_node)
             /* We found an id-expression, but it was something that we
@@ -8852,17 +8899,20 @@ static void
 cp_parser_mem_initializer_list (cp_parser* parser)
 {
   tree mem_initializer_list = NULL_TREE;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Let the semantic analysis code know that we are starting the
      mem-initializer-list.  */
   if (!DECL_CONSTRUCTOR_P (current_function_decl))
-    error ("only constructors take base initializers");
+    error ("%Honly constructors take base initializers",
+	   &token->location);
 
   /* Loop through the list.  */
   while (true)
     {
       tree mem_initializer;
 
+      token = cp_lexer_peek_token (parser->lexer);
       /* Parse the mem-initializer.  */
       mem_initializer = cp_parser_mem_initializer (parser);
       /* If the next token is a `...', we're expanding member initializers. */
@@ -8876,8 +8926,8 @@ cp_parser_mem_initializer_list (cp_parser* parser)
           if (mem_initializer != error_mark_node
               && !TYPE_P (TREE_PURPOSE (mem_initializer)))
             {
-              error ("cannot expand initializer for member %<%D%>", 
-                     TREE_PURPOSE (mem_initializer));
+              error ("%Hcannot expand initializer for member %<%D%>",
+                     &token->location, TREE_PURPOSE (mem_initializer));
               mem_initializer = error_mark_node;
             }
 
@@ -8924,11 +8974,13 @@ cp_parser_mem_initializer (cp_parser* parser)
   tree mem_initializer_id;
   tree expression_list;
   tree member;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
-      pedwarn ("anachronistic old-style base class initializer");
+      pedwarn ("%Hanachronistic old-style base class initializer",
+	       &token->location);
       mem_initializer_id = NULL_TREE;
     }
   else
@@ -8970,11 +9022,14 @@ cp_parser_mem_initializer_id (cp_parser* parser)
   bool template_p = false;
   tree id;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* `typename' is not allowed in this context ([temp.res]).  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
-      error ("keyword %<typename%> not allowed in this context (a qualified "
-	     "member initializer is implicitly a type)");
+      error ("%Hkeyword %<typename%> not allowed in this context (a qualified "
+	     "member initializer is implicitly a type)",
+	     &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the optional `::' operator.  */
@@ -9491,6 +9546,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	 appropriate diagnostic here.  */
 
       /* Consume the `='.  */
+      cp_token *start_token = cp_lexer_peek_token (parser->lexer);
       cp_lexer_consume_token (parser->lexer);
       
       /* Find the name of the parameter pack.  */     
@@ -9499,10 +9555,11 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	id_declarator = id_declarator->declarator;
       
       if (id_declarator && id_declarator->kind == cdk_id)
-	error ("template parameter pack %qD cannot have a default argument",
-	       id_declarator->u.id.unqualified_name);
+	error ("%Htemplate parameter pack %qD cannot have a default argument",
+	       &start_token->location, id_declarator->u.id.unqualified_name);
       else
-	error ("template parameter pack cannot have a default argument");
+	error ("%Htemplate parameter pack cannot have a default argument",
+	       &start_token->location);
       
       /* Parse the default argument, but throw away the result.  */
       cp_parser_default_argument (parser, /*template_parm_p=*/true);
@@ -9596,10 +9653,11 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("template parameter pack %qD cannot have a default argument", 
-                         identifier);
+                  error ("%Htemplate parameter pack %qD cannot have a "
+			 "default argument", &token->location, identifier);
                 else
-                  error ("template parameter packs cannot have default arguments");
+                  error ("%Htemplate parameter packs cannot have "
+			 "default arguments", &token->location);
                 default_argument = NULL_TREE;
               }
 	    pop_deferring_access_checks ();
@@ -9667,6 +9725,9 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 	    cp_lexer_consume_token (parser->lexer);
 	    /* Parse the id-expression.  */
 	    push_deferring_access_checks (dk_no_deferred);
+	    /* save token before parsing the id-expression, for error
+	       reporting */
+	    token = cp_lexer_peek_token (parser->lexer);
 	    default_argument
 	      = cp_parser_id_expression (parser,
 					 /*template_keyword_p=*/false,
@@ -9687,7 +9748,8 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 					 /*is_template=*/is_template,
 					 /*is_namespace=*/false,
 					 /*check_dependency=*/true,
-					 /*ambiguous_decls=*/NULL);
+					 /*ambiguous_decls=*/NULL,
+					 token->location);
 	    /* See if the default argument is valid.  */
 	    default_argument
 	      = check_template_template_default_arg (default_argument);
@@ -9697,10 +9759,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("template parameter pack %qD cannot have a default argument", 
-                         identifier);
+                  error ("%Htemplate parameter pack %qD cannot "
+			 "have a default argument",
+			 &token->location, identifier);
                 else
-                  error ("template parameter packs cannot have default arguments");
+                  error ("%Htemplate parameter packs cannot "
+			 "have default arguments",
+			 &token->location);
                 default_argument = NULL_TREE;
               }
 	    pop_deferring_access_checks ();
@@ -9749,7 +9814,7 @@ cp_parser_template_id (cp_parser *parser,
   cp_token_position start_of_id = 0;
   deferred_access_check *chk;
   VEC (deferred_access_check,gc) *access_check;
-  cp_token *next_token, *next_token_2;
+  cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
   bool is_identifier;
 
   /* If the next token corresponds to a template-id, there is no need
@@ -9797,6 +9862,7 @@ cp_parser_template_id (cp_parser *parser,
 
   /* Parse the template-name.  */
   is_identifier = false;
+  token = cp_lexer_peek_token (parser->lexer);
   template = cp_parser_template_name (parser, template_keyword_p,
 				      check_dependency_p,
 				      is_declaration,
@@ -9823,6 +9889,7 @@ cp_parser_template_id (cp_parser *parser,
       /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
 	 CPP_LESS.  */
       cp_lexer_consume_token (parser->lexer);
+
       /* Parse the arguments.  */
       arguments = cp_parser_enclosed_template_argument_list (parser);
       if (!cp_parser_parse_definitely (parser))
@@ -9837,15 +9904,18 @@ cp_parser_template_id (cp_parser *parser,
 	}
       /* Otherwise, emit an error about the invalid digraph, but continue
 	 parsing because we got our argument list.  */
-      permerror ("%<<::%> cannot begin a template-argument list");
-      inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
-	      "between %<<%> and %<::%>");
+      permerror ("%H%<<::%> cannot begin a template-argument list",
+		 &next_token->location);
+      inform ("%H%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
+	      "between %<<%> and %<::%>",
+	      &next_token->location);
       if (!flag_permissive)
 	{
 	  static bool hint;
 	  if (!hint)
 	    {
-	      inform ("(if you use -fpermissive G++ will accept your code)");
+	      inform ("%H(if you use -fpermissive G++ will accept your code)",
+		      &next_token->location);
 	      hint = true;
 	    }
 	}
@@ -9918,7 +9988,8 @@ cp_parser_template_id (cp_parser *parser,
 	 user, as opposed to simply marking the tentative parse as
 	 failed?  */
       if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
-	error ("parse error in template argument list");
+	error ("%Hparse error in template argument list",
+	       &token->location);
     }
 
   pop_deferring_access_checks ();
@@ -9972,6 +10043,7 @@ cp_parser_template_name (cp_parser* parser,
   tree identifier;
   tree decl;
   tree fns;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* If the next token is `operator', then we have either an
      operator-function-id or a conversion-function-id.  */
@@ -10031,7 +10103,8 @@ cp_parser_template_name (cp_parser* parser,
 	  cp_token_position start = 0;
 
 	  /* Explain what went wrong.  */
-	  error ("non-template %qD used as template", identifier);
+	  error ("%Hnon-template %qD used as template",
+		 &token->location, identifier);
 	  inform ("use %<%T::template %D%> to indicate that it is a template",
 		  parser->scope, identifier);
 	  /* If parsing tentatively, find the location of the "<" token.  */
@@ -10075,7 +10148,8 @@ cp_parser_template_name (cp_parser* parser,
 				/*is_template=*/false,
 				/*is_namespace=*/false,
 				check_dependency_p,
-				/*ambiguous_decls=*/NULL);
+				/*ambiguous_decls=*/NULL,
+				token->location);
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
@@ -10221,7 +10295,7 @@ cp_parser_template_argument (cp_parser* parser)
   bool template_p;
   bool address_p;
   bool maybe_type_id = false;
-  cp_token *token;
+  cp_token *token = NULL, *argument_start_token = NULL;
   cp_id_kind idk;
 
   /* There's really no way to know what we're looking at, so we just
@@ -10268,6 +10342,7 @@ cp_parser_template_argument (cp_parser* parser)
   /* We're still not sure what the argument will be.  */
   cp_parser_parse_tentatively (parser);
   /* Try a template.  */
+  argument_start_token = cp_lexer_peek_token (parser->lexer);
   argument = cp_parser_id_expression (parser,
 				      /*template_keyword_p=*/false,
 				      /*check_dependency_p=*/true,
@@ -10290,7 +10365,8 @@ cp_parser_template_argument (cp_parser* parser)
 					  /*is_template=*/template_p,
 					  /*is_namespace=*/false,
 					  /*check_dependency=*/true,
-					  /*ambiguous_decls=*/NULL);
+					  /*ambiguous_decls=*/NULL,
+					  argument_start_token->location);
       if (TREE_CODE (argument) != TEMPLATE_DECL
 	  && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
 	cp_parser_error (parser, "expected template-name");
@@ -10542,6 +10618,8 @@ static void
 cp_parser_explicit_specialization (cp_parser* parser)
 {
   bool need_lang_pop;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `template' keyword.  */
   cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Look for the `<'.  */
@@ -10556,7 +10634,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
      linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template specialization with C linkage");
+      error ("%Htemplate specialization with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
 	 front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -10881,7 +10959,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
           cp_lexer_consume_token (parser->lexer);
           /* We do not yet support the use of `auto' as a
              type-specifier.  */
-          error ("C++0x %<auto%> specifier not supported");
+          error ("%HC++0x %<auto%> specifier not supported", &token->location);
         }
       break;
 
@@ -11094,12 +11172,13 @@ cp_parser_nonclass_name (cp_parser* parser)
   tree type_decl;
   tree identifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
     return error_mark_node;
 
   /* Look up the type-name.  */
-  type_decl = cp_parser_lookup_name_simple (parser, identifier);
+  type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
 
   if (TREE_CODE (type_decl) != TYPE_DECL
       && (objc_is_id (identifier) || objc_is_class_name (identifier)))
@@ -11116,7 +11195,7 @@ cp_parser_nonclass_name (cp_parser* parser)
     {
       if (!cp_parser_simulate_error (parser))
 	cp_parser_name_lookup_error (parser, identifier, type_decl,
-				     "is not a type");
+				     "is not a type", token->location);
       return error_mark_node;
     }
   /* Remember that the name was used in the definition of the
@@ -11165,6 +11244,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
   tree identifier;
   tree type = NULL_TREE;
   tree attributes = NULL_TREE;
+  cp_token *token = NULL;
 
   /* See if we're looking at the `enum' keyword.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM))
@@ -11234,6 +11314,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (!template_p)
 	cp_parser_parse_tentatively (parser);
       /* Parse the template-id.  */
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_template_id (parser, template_p,
 				    /*check_dependency_p=*/true,
 				    is_declaration);
@@ -11255,6 +11336,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
   if (!type)
     {
+      token = cp_lexer_peek_token (parser->lexer);
       identifier = cp_parser_identifier (parser);
 
       if (identifier == error_mark_node)
@@ -11267,7 +11349,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (tag_type == typename_type
 	  && TREE_CODE (parser->scope) != NAMESPACE_DECL)
 	return cp_parser_make_typename_type (parser, parser->scope,
-					     identifier);
+					     identifier,
+					     token->location);
       /* Look up a qualified name in the usual way.  */
       if (parser->scope)
 	{
@@ -11279,7 +11362,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 					/*is_template=*/false,
 					/*is_namespace=*/false,
 					/*check_dependency=*/true,
-					&ambiguous_decls);
+					&ambiguous_decls,
+					token->location);
 
 	  /* If the lookup was ambiguous, an error will already have been
 	     issued.  */
@@ -11315,7 +11399,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	    {
 	      cp_parser_diagnose_invalid_type_name (parser,
 						    parser->scope,
-						    identifier);
+						    identifier,
+						    token->location);
 	      return error_mark_node;
 	    }
 
@@ -11415,7 +11500,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	  /* An unqualified name was used to reference this type, so
 	     there were no qualifying templates.  */
 	  if (!cp_parser_check_template_parameters (parser,
-						    /*num_templates=*/0))
+						    /*num_templates=*/0,
+						    token->location))
 	    return error_mark_node;
 	  type = xref_tag (tag_type, identifier, ts, template_p);
 	}
@@ -11618,6 +11704,8 @@ cp_parser_namespace_name (cp_parser* parser)
   tree identifier;
   tree namespace_decl;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Get the name of the namespace.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
@@ -11646,13 +11734,14 @@ cp_parser_namespace_name (cp_parser* parser)
 					  /*is_template=*/false,
 					  /*is_namespace=*/true,
 					  /*check_dependency=*/true,
-					  /*ambiguous_decls=*/NULL);
+					  /*ambiguous_decls=*/NULL,
+					  token->location);
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
     {
       if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	error ("%qD is not a namespace-name", identifier);
+	error ("%H%qD is not a namespace-name", &token->location, identifier);
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
@@ -11767,6 +11856,8 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   tree identifier;
   tree namespace_specifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the identifier.  */
@@ -11777,7 +11868,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
       && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) 
     {
-      error ("%<namespace%> definition is not allowed here");
+      error ("%H%<namespace%> definition is not allowed here", &token->location);
       /* Skip the definition.  */
       cp_lexer_consume_token (parser->lexer);
       if (cp_parser_skip_to_closing_brace (parser))
@@ -11892,6 +11983,7 @@ cp_parser_using_declaration (cp_parser* parser,
        cp_parser_parse_definitely will be false, as required.  */
     return cp_parser_parse_definitely (parser);
 
+  token = cp_lexer_peek_token (parser->lexer);
   /* Parse the unqualified-id.  */
   identifier = cp_parser_unqualified_id (parser,
 					 /*template_keyword_p=*/false,
@@ -11916,7 +12008,8 @@ cp_parser_using_declaration (cp_parser* parser,
     /* [namespace.udecl]
 
        A using declaration shall not name a template-id.  */
-    error ("a template-id may not appear in a using-declaration");
+    error ("%Ha template-id may not appear in a using-declaration",
+            &token->location);
   else
     {
       if (at_class_scope_p ())
@@ -11932,9 +12025,13 @@ cp_parser_using_declaration (cp_parser* parser,
 	}
       else
 	{
-	  decl = cp_parser_lookup_name_simple (parser, identifier);
+	  decl = cp_parser_lookup_name_simple (parser,
+					       identifier,
+					       token->location);
 	  if (decl == error_mark_node)
-	    cp_parser_name_lookup_error (parser, identifier, decl, NULL);
+	    cp_parser_name_lookup_error (parser, identifier,
+					 decl, NULL,
+					 token->location);
 	  else if (check_for_bare_parameter_packs (decl))
 	    return false;
 	  else if (!at_namespace_scope_p ())
@@ -12184,7 +12281,7 @@ cp_parser_init_declarator (cp_parser* parser,
 			   int declares_class_or_enum,
 			   bool* function_definition_p)
 {
-  cp_token *token;
+  cp_token *token, *asm_spec_start_token, *attributes_start_token;
   cp_declarator *declarator;
   tree prefix_attributes;
   tree attributes;
@@ -12218,6 +12315,7 @@ cp_parser_init_declarator (cp_parser* parser,
   resume_deferring_access_checks ();
 
   /* Parse the declarator.  */
+  token = cp_lexer_peek_token (parser->lexer);
   declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
 			    &ctor_dtor_or_conv_p,
@@ -12232,7 +12330,8 @@ cp_parser_init_declarator (cp_parser* parser,
     return error_mark_node;
 
   /* Check that the number of template-parameter-lists is OK.  */
-  if (!cp_parser_check_declarator_template_parameters (parser, declarator))
+  if (!cp_parser_check_declarator_template_parameters (parser, declarator,
+						       token->location))
     return error_mark_node;
 
   if (declares_class_or_enum & 2)
@@ -12249,8 +12348,10 @@ cp_parser_init_declarator (cp_parser* parser,
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       /* Look for an asm-specification.  */
+      asm_spec_start_token = cp_lexer_peek_token (parser->lexer);
       asm_specification = cp_parser_asm_specification_opt (parser);
       /* And attributes.  */
+      attributes_start_token = cp_lexer_peek_token (parser->lexer);
       attributes = cp_parser_attributes_opt (parser);
     }
   else
@@ -12278,9 +12379,12 @@ cp_parser_init_declarator (cp_parser* parser,
 	  /* Neither attributes nor an asm-specification are allowed
 	     on a function-definition.  */
 	  if (asm_specification)
-	    error ("an asm-specification is not allowed on a function-definition");
+	    error ("%Han asm-specification is not allowed "
+		   "on a function-definition",
+		   &asm_spec_start_token->location);
 	  if (attributes)
-	    error ("attributes are not allowed on a function-definition");
+	    error ("%Hattributes are not allowed on a function-definition",
+		   &attributes_start_token->location);
 	  /* This is a function-definition.  */
 	  *function_definition_p = true;
 
@@ -12405,6 +12509,7 @@ cp_parser_init_declarator (cp_parser* parser,
     {
       if (function_declarator_p (declarator))
 	{
+	  cp_token *initializer_start_token = cp_lexer_peek_token (parser->lexer);
 	   if (initialization_kind == CPP_EQ)
 	     initializer = cp_parser_pure_specifier (parser);
 	   else
@@ -12413,7 +12518,8 @@ cp_parser_init_declarator (cp_parser* parser,
 		  know what the user intended, so just silently
 		  consume the initializer.  */
 	       if (decl != error_mark_node)
-		 error ("initializer provided for function");
+		 error ("%Hinitializer provided for function",
+			&initializer_start_token->location);
 	       cp_parser_skip_to_closing_parenthesis (parser,
 						      /*recovering=*/true,
 						      /*or_comma=*/false,
@@ -12814,7 +12920,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 		 in function scopes.  */
 	      else if (!parser->in_function_body)
 		{
-		  error ("array bound is not an integer constant");
+		  error ("%Harray bound is not an integer constant",
+			 &token->location);
 		  bounds = error_mark_node;
 		}
 	    }
@@ -12836,6 +12943,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  special_function_kind sfk;
 	  bool abstract_ok;
           bool pack_expansion_p = false;
+	  cp_token *declarator_id_start_token;
 
 	  /* Parse a declarator-id */
 	  abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
@@ -12854,6 +12962,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                 }
             }
 
+	  declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
 	  unqualified_name
 	    = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
 	  qualifying_scope = parser->scope;
@@ -12923,7 +13032,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 					    /*only_current_p=*/false);
 	      /* If that failed, the declarator is invalid.  */
 	      if (TREE_CODE (type) == TYPENAME_TYPE)
-		error ("%<%T::%E%> is not a type",
+		error ("%H%<%T::%E%> is not a type",
+		       &declarator_id_start_token->location,
 		       TYPE_CONTEXT (qualifying_scope),
 		       TYPE_IDENTIFIER (qualifying_scope));
 	      qualifying_scope = type;
@@ -12949,7 +13059,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 		      if (qualifying_scope
 			  && CLASSTYPE_USE_TEMPLATE (name_type))
 			{
-			  error ("invalid use of constructor as a template");
+			  error ("%Hinvalid use of constructor as a template",
+				 &declarator_id_start_token->location);
 			  inform ("use %<%T::%D%> instead of %<%T::%D%> to "
 				  "name the constructor in a qualified name",
 				  class_type,
@@ -13108,6 +13219,7 @@ cp_parser_ptr_operator (cp_parser* parser,
       cp_parser_global_scope_opt (parser,
 				  /*current_scope_valid_p=*/false);
       /* Look for the nested-name specifier.  */
+      token = cp_lexer_peek_token (parser->lexer);
       cp_parser_nested_name_specifier (parser,
 				       /*typename_keyword_p=*/false,
 				       /*check_dependency_p=*/true,
@@ -13122,7 +13234,7 @@ cp_parser_ptr_operator (cp_parser* parser,
 	  code = INDIRECT_REF;
 
 	  if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-	    error ("%qD is a namespace", parser->scope);
+	    error ("%H%qD is a namespace", &token->location, parser->scope);
 	  else
 	    {
 	      /* The type of which the member is a member is given by the
@@ -13197,7 +13309,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 
       if (cv_quals & cv_qualifier)
 	{
-	  error ("duplicate cv-qualifier");
+	  error ("%Hduplicate cv-qualifier", &token->location);
 	  cp_lexer_purge_token (parser->lexer);
 	}
       else
@@ -13307,6 +13419,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 {
   bool seen_type_specifier = false;
   cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
+  cp_token *start_token = NULL;
 
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
@@ -13326,6 +13439,11 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 	  continue;
 	}
 
+      /* record the token of the beginning of the type specifier seq,
+         for error reporting purposes*/
+     if (!start_token)
+       start_token = cp_lexer_peek_token (parser->lexer);
+
       /* Look for the type-specifier.  */
       type_specifier = cp_parser_type_specifier (parser,
 						 flags,
@@ -13369,7 +13487,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 	flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
 
-  cp_parser_check_decl_spec (type_specifier_seq);
+  cp_parser_check_decl_spec (type_specifier_seq, start_token->location);
 }
 
 /* Parse a parameter-declaration-clause.
@@ -13596,7 +13714,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
   cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
   tree default_argument;
-  cp_token *token;
+  cp_token *token, *declarator_token_start;
   const char *saved_message;
 
   /* In a template parameter, `>' is not an operator.
@@ -13665,6 +13783,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	  && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
 	cp_parser_commit_to_tentative_parse (parser);
       /* Parse the declarator.  */
+      declarator_token_start = token;
       declarator = cp_parser_declarator (parser,
 					 CP_PARSER_DECLARATOR_EITHER,
 					 /*ctor_dtor_or_conv_p=*/NULL,
@@ -13823,7 +13942,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 		  /* If we run out of tokens, issue an error message.  */
 		case CPP_EOF:
 		case CPP_PRAGMA_EOL:
-		  error ("file ends in default argument");
+		  error ("%Hfile ends in default argument", &token->location);
 		  done = true;
 		  break;
 
@@ -13860,8 +13979,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
       /* Outside of a class definition, we can just parse the
 	 assignment-expression.  */
       else
-        default_argument 
-          = cp_parser_default_argument (parser, template_parm_p);
+	{
+	  token = cp_lexer_peek_token (parser->lexer);
+	  default_argument 
+	    = cp_parser_default_argument (parser, template_parm_p);
+	}
 
       if (!parser->default_arg_ok_p)
 	{
@@ -13869,7 +13991,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	    warning (0, "deprecated use of default argument for parameter of non-function");
 	  else
 	    {
-	      error ("default arguments are only permitted for function parameters");
+	      error ("%Hdefault arguments are only "
+		     "permitted for function parameters",
+		     &token->location);
 	      default_argument = NULL_TREE;
 	    }
 	}
@@ -13885,11 +14009,12 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	    id_declarator = id_declarator->declarator;
 	  
 	  if (id_declarator && id_declarator->kind == cdk_id)
-	    error ("%sparameter pack %qD cannot have a default argument",
+	    error ("%H%sparameter pack %qD cannot have a default argument",
+		   &declarator_token_start->location,
 		   kind, id_declarator->u.id.unqualified_name);
 	  else
-	    error ("%sparameter pack cannot have a default argument",
-		   kind);
+	    error ("%H%sparameter pack cannot have a default argument",
+		   &declarator_token_start->location, kind);
 	  
 	  default_argument = NULL_TREE;
 	}
@@ -14279,10 +14404,12 @@ cp_parser_class_name (cp_parser *parser,
 					/*is_template=*/false,
 					/*is_namespace=*/false,
 					check_dependency_p,
-					&ambiguous_decls);
+					&ambiguous_decls,
+					identifier_token->location);
 	  if (ambiguous_decls)
 	    {
-	      error ("reference to %qD is ambiguous", identifier);
+	      error ("%Hreference to %qD is ambiguous",
+		     &identifier_token->location, identifier);
 	      print_candidates (ambiguous_decls);
 	      if (cp_parser_parsing_tentatively (parser))
 		{
@@ -14573,7 +14700,7 @@ cp_parser_class_head (cp_parser* parser,
   bool invalid_explicit_specialization_p = false;
   tree pushed_scope = NULL_TREE;
   unsigned num_templates;
-
+  cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL;
   /* Assume no nested-name-specifier will be present.  */
   *nested_name_specifier_p = false;
   /* Assume no template parameter lists will be used in defining the
@@ -14606,6 +14733,7 @@ cp_parser_class_head (cp_parser* parser,
 
   /* Determine the name of the class.  Begin by looking for an
      optional nested-name-specifier.  */
+  nested_name_specifier_token_start = cp_lexer_peek_token (parser->lexer);
   nested_name_specifier
     = cp_parser_nested_name_specifier_opt (parser,
 					   /*typename_keyword_p=*/false,
@@ -14616,6 +14744,7 @@ cp_parser_class_head (cp_parser* parser,
      identifier.  */
   if (nested_name_specifier)
     {
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       /* Although the grammar says `identifier', it really means
 	 `class-name' or `template-name'.  You are only allowed to
 	 define a class that has already been declared with this
@@ -14679,6 +14808,7 @@ cp_parser_class_head (cp_parser* parser,
 	 an identifier, or nothing at all.  */
       cp_parser_parse_tentatively (parser);
       /* Check for a template-id.  */
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       id = cp_parser_template_id (parser,
 				  /*template_keyword_p=*/false,
 				  /*check_dependency_p=*/true,
@@ -14730,7 +14860,8 @@ cp_parser_class_head (cp_parser* parser,
       /* Reject typedef-names in class heads.  */
       if (!DECL_IMPLICIT_TYPEDEF_P (type))
 	{
-	  error ("invalid class name in declaration of %qD", type);
+	  error ("%Hinvalid class name in declaration of %qD",
+		 &type_start_token->location, type);
 	  type = NULL_TREE;
 	  goto done;
 	}
@@ -14742,10 +14873,13 @@ cp_parser_class_head (cp_parser* parser,
       if (scope && !is_ancestor (scope, nested_name_specifier))
 	{
 	  if (at_namespace_scope_p ())
-	    error ("declaration of %qD in namespace %qD which does not "
-		   "enclose %qD", type, scope, nested_name_specifier);
+	    error ("%Hdeclaration of %qD in namespace %qD which does not "
+		   "enclose %qD",
+		   &type_start_token->location,
+		   type, scope, nested_name_specifier);
 	  else
-	    error ("declaration of %qD in %qD which does not enclose %qD",
+	    error ("%Hdeclaration of %qD in %qD which does not enclose %qD",
+		   &type_start_token->location,
 		   type, scope, nested_name_specifier);
 	  type = NULL_TREE;
 	  goto done;
@@ -14758,7 +14892,8 @@ cp_parser_class_head (cp_parser* parser,
 	 class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
 	{
-	  pedwarn ("extra qualification ignored");
+	  pedwarn ("%Hextra qualification ignored",
+		   &nested_name_specifier_token_start->location);
 	  nested_name_specifier = NULL_TREE;
 	  num_templates = 0;
 	}
@@ -14769,7 +14904,8 @@ cp_parser_class_head (cp_parser* parser,
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
-      error ("an explicit specialization must be preceded by %<template <>%>");
+      error ("%Han explicit specialization must be preceded by %<template <>%>",
+	     &type_start_token->location);
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
 	 cp_parser_explicit_specialization.  */
@@ -14781,7 +14917,8 @@ cp_parser_class_head (cp_parser* parser,
      use "goto done;" to return.  */
   /* Make sure that the right number of template parameters were
      present.  */
-  if (!cp_parser_check_template_parameters (parser, num_templates))
+  if (!cp_parser_check_template_parameters (parser, num_templates,
+					    type_start_token->location))
     {
       /* If something went wrong, there is no point in even trying to
 	 process the class-definition.  */
@@ -14796,7 +14933,8 @@ cp_parser_class_head (cp_parser* parser,
 	  && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0))
 	      || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD))
 	{
-	  error ("function template %qD redeclared as a class template", id);
+	  error ("%Hfunction template %qD redeclared as a class template",
+		 &type_start_token->location, id);
 	  type = error_mark_node;
 	}
       else
@@ -14877,8 +15015,10 @@ cp_parser_class_head (cp_parser* parser,
      that's an error.  */
   if (type != error_mark_node && COMPLETE_TYPE_P (type))
     {
-      error ("redefinition of %q#T", type);
-      error ("previous definition of %q+#T", type);
+      error ("%Hredefinition of %q#T",
+	     &type_start_token->location, type);
+      error ("%Hprevious definition of %q+#T",
+	     &type_start_token->location, type);
       type = NULL_TREE;
       goto done;
     }
@@ -15033,7 +15173,9 @@ cp_parser_member_declaration (cp_parser* parser)
   tree decl;
   int declares_class_or_enum;
   bool friend_p;
-  cp_token *token;
+  cp_token *token = NULL;
+  cp_token *decl_spec_token_start = NULL;
+  cp_token *initializer_token_start = NULL;
   int saved_pedantic;
 
   /* Check for the `__extension__' keyword.  */
@@ -15097,6 +15239,7 @@ cp_parser_member_declaration (cp_parser* parser)
     return;
 
   /* Parse the decl-specifier-seq.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -15142,7 +15285,8 @@ cp_parser_member_declaration (cp_parser* parser)
 	      /* If the `friend' keyword was present, the friend must
 		 be introduced with a class-key.  */
 	       if (!declares_class_or_enum)
-		 error ("a class-key must be used when declaring a friend");
+		 error ("%Ha class-key must be used when declaring a friend",
+                        &decl_spec_token_start->location);
 	       /* In this case:
 
 		    template <typename T> struct A {
@@ -15156,8 +15300,8 @@ cp_parser_member_declaration (cp_parser* parser)
 		   && TYPE_P (decl_specifiers.type))
 		 type = decl_specifiers.type;
 	       if (!type || !TYPE_P (type))
-		 error ("friend declaration does not name a class or "
-			"function");
+		 error ("%Hfriend declaration does not name a class or "
+			"function", &decl_spec_token_start->location);
 	       else
 		 make_friend_class (current_class_type, type,
 				    /*complain=*/true);
@@ -15180,7 +15324,8 @@ cp_parser_member_declaration (cp_parser* parser)
 	      finish_member_declaration (decl);
 	    }
 	  else
-	    cp_parser_check_access_in_redeclaration (TYPE_NAME (type));
+	    cp_parser_check_access_in_redeclaration (TYPE_NAME (type),
+                                                     decl_spec_token_start->location);
 	}
     }
   else
@@ -15308,6 +15453,7 @@ cp_parser_member_declaration (cp_parser* parser)
 		     for a pure-specifier; otherwise, we look for a
 		     constant-initializer.  When we call `grokfield', it will
 		     perform more stringent semantics checks.  */
+		  initializer_token_start = cp_lexer_peek_token (parser->lexer);
 		  if (function_declarator_p (declarator))
 		    initializer = cp_parser_pure_specifier (parser);
 		  else
@@ -15332,7 +15478,8 @@ cp_parser_member_declaration (cp_parser* parser)
 		     standard, since a pure function may be defined
 		     outside of the class-specifier.  */
 		  if (initializer)
-		    error ("pure-specifier on function-definition");
+		    error ("%Hpure-specifier on function-definition",
+			   &initializer_token_start->location);
 		  decl = cp_parser_save_member_function_body (parser,
 							      &decl_specifiers,
 							      declarator,
@@ -15423,7 +15570,7 @@ cp_parser_pure_specifier (cp_parser* parser)
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
-      error ("templates may not be %<virtual%>");
+      error ("%Htemplates may not be %<virtual%>", &token->location);
       return error_mark_node;
     }
 
@@ -15625,11 +15772,14 @@ cp_parser_base_specifier (cp_parser* parser)
      as base classes.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
+      token = cp_lexer_peek_token (parser->lexer);
       if (!processing_template_decl)
-	error ("keyword %<typename%> not allowed outside of templates");
+	error ("%Hkeyword %<typename%> not allowed outside of templates",
+	       &token->location);
       else
-	error ("keyword %<typename%> not allowed in this context "
-	       "(the base class is implicitly a type)");
+	error ("%Hkeyword %<typename%> not allowed in this context "
+	       "(the base class is implicitly a type)",
+	       &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
 
@@ -16330,7 +16480,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 		       bool is_template,
 		       bool is_namespace,
 		       bool check_dependency,
-		       tree *ambiguous_decls)
+		       tree *ambiguous_decls,
+		       location_t name_location)
 {
   int flags = 0;
   tree decl;
@@ -16511,7 +16662,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 	 cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
 	{
-	  error ("reference to %qD is ambiguous", name);
+	  error ("%Hreference to %qD is ambiguous",
+		 &name_location, name);
 	  print_candidates (decl);
 	}
       return error_mark_node;
@@ -16541,14 +16693,15 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
    IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE.  */
 
 static tree
-cp_parser_lookup_name_simple (cp_parser* parser, tree name)
+cp_parser_lookup_name_simple (cp_parser* parser, tree name, location_t location)
 {
   return cp_parser_lookup_name (parser, name,
 				none_type,
 				/*is_template=*/false,
 				/*is_namespace=*/false,
 				/*check_dependency=*/true,
-				/*ambiguous_decls=*/NULL);
+				/*ambiguous_decls=*/NULL,
+				location);
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
@@ -16601,7 +16754,8 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
 
 static bool
 cp_parser_check_declarator_template_parameters (cp_parser* parser,
-						cp_declarator *declarator)
+						cp_declarator *declarator,
+						location_t declarator_location)
 {
   unsigned num_templates;
 
@@ -16651,7 +16805,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 	++num_templates;
 
       return cp_parser_check_template_parameters (parser,
-						  num_templates);
+						  num_templates,
+						  declarator_location);
 
     case cdk_function:
     case cdk_array:
@@ -16659,7 +16814,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
     case cdk_reference:
     case cdk_ptrmem:
       return (cp_parser_check_declarator_template_parameters
-	      (parser, declarator->declarator));
+	      (parser, declarator->declarator, declarator_location));
 
     case cdk_error:
       return true;
@@ -16676,7 +16831,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
-				     unsigned num_templates)
+				     unsigned num_templates,
+				     location_t location)
 {
   /* If there are more template classes than parameter lists, we have
      something like:
@@ -16684,7 +16840,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      error ("too few template-parameter-lists");
+      error ("%Htoo few template-parameter-lists", &location);
       return false;
     }
   /* If there are the same number of template classes and parameter
@@ -16699,7 +16855,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
      something like:
 
      template <class T> template <class U> void S::f();  */
-  error ("too many template-parameter-lists");
+  error ("%Htoo many template-parameter-lists", &location);
   return false;
 }
 
@@ -16957,12 +17113,14 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   bool saved_in_unbraced_linkage_specification_p;
   bool saved_in_function_body;
   unsigned saved_num_template_parameter_lists;
+  cp_token *token;
 
   saved_in_function_body = parser->in_function_body;
   parser->in_function_body = true;
   /* If the next token is `return', then the code may be trying to
      make use of the "named return value" extension that G++ used to
      support.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_RETURN))
     {
       /* Consume the `return' keyword.  */
@@ -16971,7 +17129,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
 	 returned.  */
       cp_parser_identifier (parser);
       /* Issue an error message.  */
-      error ("named return values are no longer supported");
+      error ("%Hnamed return values are no longer supported",
+	     &token->location);
       /* Skip tokens until we reach the start of the function body.  */
       while (true)
 	{
@@ -17030,8 +17189,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
+  cp_token *token;
 
   /* Look for the `template' keyword.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
     return;
 
@@ -17043,7 +17204,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* 14.5.2.2 [temp.mem]
 
          A local class shall not have member templates.  */
-      error ("invalid declaration of member template in local class");
+      error ("%Hinvalid declaration of member template in local class",
+	     &token->location);
       cp_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
@@ -17052,7 +17214,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
      A template ... shall not have C linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template with C linkage");
+      error ("%Htemplate with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
 	 front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -17099,6 +17261,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* There are no access checks when parsing a template, as we do not
 	 know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_single_declaration (parser,
 					   checks,
 					   member_p,
@@ -17111,7 +17274,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       if (member_p && !friend_p && decl)
 	{
 	  if (TREE_CODE (decl) == TYPE_DECL)
-	    cp_parser_check_access_in_redeclaration (decl);
+	    cp_parser_check_access_in_redeclaration (decl, token->location);
 
 	  decl = finish_member_template_decl (decl);
 	}
@@ -17175,6 +17338,7 @@ cp_parser_single_declaration (cp_parser* parser,
   tree decl = NULL_TREE;
   cp_decl_specifier_seq decl_specifiers;
   bool function_definition_p = false;
+  cp_token *decl_spec_token_start;
 
   /* This function is only used when processing a template
      declaration.  */
@@ -17186,6 +17350,7 @@ cp_parser_single_declaration (cp_parser* parser,
 
   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
      alternative.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -17196,7 +17361,8 @@ cp_parser_single_declaration (cp_parser* parser,
   /* There are no template typedefs.  */
   if (decl_specifiers.specs[(int) ds_typedef])
     {
-      error ("template declaration of %qs", "typedef");
+      error ("%Htemplate declaration of %qs",
+	     &decl_spec_token_start->location, "typedef");
       decl = error_mark_node;
     }
 
@@ -17259,7 +17425,8 @@ cp_parser_single_declaration (cp_parser* parser,
         && explicit_specialization_p
         && decl_specifiers.storage_class != sc_none)
       {
-        error ("explicit template specialization cannot have a storage class");
+        error ("%Hexplicit template specialization cannot have a storage class",
+	       &decl_spec_token_start->location);
         decl = error_mark_node;
       }
     }
@@ -17461,9 +17628,9 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
 	    is a typo for '>'. Emit an error message and continue.
 	    Same deal about the token location, but here we can get it
 	    right by consuming the '>>' before issuing the diagnostic.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  error ("spurious %<>>%>, use %<>%> to terminate "
-		 "a template argument list");
+	  cp_token *token = cp_lexer_consume_token (parser->lexer);
+	  error ("%Hspurious %<>>%>, use %<>%> to terminate "
+		 "a template argument list", &token->location);
 	}
     }
   else
@@ -17784,14 +17951,15 @@ cp_parser_declares_only_class_p (cp_parser *parser)
 static void
 cp_parser_set_storage_class (cp_parser *parser,
 			     cp_decl_specifier_seq *decl_specs,
-			     enum rid keyword)
+			     enum rid keyword,
+			     location_t location)
 {
   cp_storage_class storage_class;
 
   if (parser->in_unbraced_linkage_specification_p)
     {
-      error ("invalid use of %qD in linkage specification",
-	     ridpointers[keyword]);
+      error ("%Hinvalid use of %qD in linkage specification",
+	     &location, ridpointers[keyword]);
       return;
     }
   else if (decl_specs->storage_class != sc_none)
@@ -17803,7 +17971,7 @@ cp_parser_set_storage_class (cp_parser *parser,
   if ((keyword == RID_EXTERN || keyword == RID_STATIC)
       && decl_specs->specs[(int) ds_thread])
     {
-      error ("%<__thread%> before %qD", ridpointers[keyword]);
+      error ("%H%<__thread%> before %qD", &location, ridpointers[keyword]);
       decl_specs->specs[(int) ds_thread] = 0;
     }
 
@@ -18133,7 +18301,7 @@ cp_parser_check_class_key (enum tag_types class_key, tree type)
    [class.mem/1].  */
 
 static void
-cp_parser_check_access_in_redeclaration (tree decl)
+cp_parser_check_access_in_redeclaration (tree decl, location_t location)
 {
   if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl)))
     return;
@@ -18142,7 +18310,7 @@ cp_parser_check_access_in_redeclaration (tree decl)
        != (current_access_specifier == access_private_node))
       || (TREE_PROTECTED (decl)
 	  != (current_access_specifier == access_protected_node)))
-    error ("%qD redeclared with different access", decl);
+    error ("%H%qD redeclared with different access", &location, decl);
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
@@ -18159,8 +18327,9 @@ cp_parser_optional_template_keyword (cp_parser *parser)
 	 template and what is not.  */
       if (!processing_template_decl)
 	{
-	  error ("%<template%> (as a disambiguator) is only allowed "
-		 "within templates");
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
+	  error ("%H%<template%> (as a disambiguator) is only allowed "
+		 "within templates", &token->location);
 	  /* If this part of the token stream is rescanned, the same
 	     error message would be generated.  So, we purge the token
 	     from the stream.  */
@@ -18412,7 +18581,8 @@ cp_parser_objc_expression (cp_parser* parser)
 	  break;
 	}
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -18545,15 +18715,18 @@ static tree
 cp_parser_objc_encode_expression (cp_parser* parser)
 {
   tree type;
+  cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  token = cp_lexer_peek_token (parser->lexer);
   type = complete_type (cp_parser_type_id (parser));
   cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   if (!type)
     {
-      error ("%<@encode%> must specify a type as an argument");
+      error ("%H%<@encode%> must specify a type as an argument",
+	     &token->location);
       return error_mark_node;
     }
 
@@ -18868,7 +19041,7 @@ cp_parser_objc_selector (cp_parser* parser)
 
   if (!cp_parser_objc_selector_p (token->type))
     {
-      error ("invalid Objective-C++ selector name");
+      error ("%Hinvalid Objective-C++ selector name", &token->location);
       return error_mark_node;
     }
 
@@ -19198,7 +19371,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
     {
-      error ("identifier expected after %<@protocol%>");
+      tok = cp_lexer_peek_token (parser->lexer);
+      error ("%Hidentifier expected after %<@protocol%>", &tok->location);
       goto finish;
     }
 
@@ -19334,7 +19508,8 @@ cp_parser_objc_declaration (cp_parser* parser)
       cp_parser_objc_end_implementation (parser);
       break;
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 }
@@ -19465,7 +19640,8 @@ cp_parser_objc_statement (cp_parser * parser) {
     case RID_AT_THROW:
       return cp_parser_objc_throw_statement (parser);
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -19549,14 +19725,15 @@ cp_parser_omp_clause_name (cp_parser *parser)
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
-check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+check_no_duplicate_clause (tree clauses, enum tree_code code,
+			   const char *name, location_t location)
 {
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
-	error ("too many %qs clauses", name);
+	error ("%Htoo many %qs clauses", &location, name);
 	break;
       }
 }
@@ -19579,10 +19756,12 @@ static tree
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 				tree list)
 {
+  cp_token *token;
   while (1)
     {
       tree name, decl;
 
+      token = cp_lexer_peek_token (parser->lexer);
       name = cp_parser_id_expression (parser, /*template_p=*/false,
 				      /*check_dependency_p=*/true,
 				      /*template_p=*/NULL,
@@ -19591,9 +19770,9 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       if (name == error_mark_node)
 	goto skip_comma;
 
-      decl = cp_parser_lookup_name_simple (parser, name);
+      decl = cp_parser_lookup_name_simple (parser, name, token->location);
       if (decl == error_mark_node)
-	cp_parser_name_lookup_error (parser, name, decl, NULL);
+	cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
       else if (kind != 0)
 	{
 	  tree u = build_omp_clause (kind);
@@ -19643,7 +19822,7 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
    collapse ( constant-expression ) */
 
 static tree
-cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
+cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location)
 {
   tree c, num;
   location_t loc;
@@ -19668,11 +19847,12 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
       || (n = tree_low_cst (num, 0)) <= 0
       || (int) n != n)
     {
-      error ("%Hcollapse argument needs positive constant integer expression", &loc);
+      error ("%Hcollapse argument needs positive constant integer expression",
+	     &loc);
       return list;
     }
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
+  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
   c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
@@ -19684,7 +19864,7 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
    default ( shared | none ) */
 
 static tree
-cp_parser_omp_clause_default (cp_parser *parser, tree list)
+cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
 {
   enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
   tree c;
@@ -19730,7 +19910,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
   if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
     return list;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
   c = build_omp_clause (OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
@@ -19742,7 +19922,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
    if ( expression ) */
 
 static tree
-cp_parser_omp_clause_if (cp_parser *parser, tree list)
+cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
 {
   tree t, c;
 
@@ -19757,7 +19937,7 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
 
   c = build_omp_clause (OMP_CLAUSE_IF);
   OMP_CLAUSE_IF_EXPR (c) = t;
@@ -19770,11 +19950,12 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
    nowait */
 
 static tree
-cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED,
+			     tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait", location);
 
   c = build_omp_clause (OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -19785,7 +19966,8 @@ cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
    num_threads ( expression ) */
 
 static tree
-cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
+cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
+				  location_t location)
 {
   tree t, c;
 
@@ -19800,7 +19982,8 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
+			     "num_threads", location);
 
   c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
   OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
@@ -19813,11 +19996,13 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
    ordered */
 
 static tree
-cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
+			      tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED,
+			     "ordered", location);
 
   c = build_omp_clause (OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -19894,7 +20079,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
      static | dynamic | guided | runtime | auto  */
 
 static tree
-cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
+cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location)
 {
   tree c, t;
 
@@ -19942,18 +20127,20 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
     {
+      cp_token *token;
       cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       t = cp_parser_assignment_expression (parser, false);
 
       if (t == error_mark_node)
 	goto resync_fail;
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-	error ("schedule %<runtime%> does not take "
-	       "a %<chunk_size%> parameter");
+	error ("%Hschedule %<runtime%> does not take "
+	       "a %<chunk_size%> parameter", &token->location);
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
-	error ("schedule %<auto%> does not take "
-	       "a %<chunk_size%> parameter");
+	error ("%Hschedule %<auto%> does not take "
+	       "a %<chunk_size%> parameter", &token->location);
       else
 	OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
@@ -19963,7 +20150,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
   else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<,%> or %<)%>"))
     goto resync_fail;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
@@ -19980,11 +20167,12 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
    untied */
 
 static tree
-cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED,
+			     tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
+  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
 
   c = build_omp_clause (OMP_CLAUSE_UNTIED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -20001,6 +20189,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 {
   tree clauses = NULL;
   bool first = true;
+  cp_token *token = NULL;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
@@ -20011,13 +20200,15 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
       if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
 	cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       c_kind = cp_parser_omp_clause_name (parser);
       first = false;
 
       switch (c_kind)
 	{
 	case PRAGMA_OMP_CLAUSE_COLLAPSE:
-	  clauses = cp_parser_omp_clause_collapse (parser, clauses);
+	  clauses = cp_parser_omp_clause_collapse (parser, clauses,
+						   token->location);
 	  c_name = "collapse";
 	  break;
 	case PRAGMA_OMP_CLAUSE_COPYIN:
@@ -20030,7 +20221,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "copyprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_DEFAULT:
-	  clauses = cp_parser_omp_clause_default (parser, clauses);
+	  clauses = cp_parser_omp_clause_default (parser, clauses,
+						  token->location);
 	  c_name = "default";
 	  break;
 	case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
@@ -20039,7 +20231,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "firstprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_IF:
-	  clauses = cp_parser_omp_clause_if (parser, clauses);
+	  clauses = cp_parser_omp_clause_if (parser, clauses, token->location);
 	  c_name = "if";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -20048,15 +20240,17 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "lastprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NOWAIT:
-	  clauses = cp_parser_omp_clause_nowait (parser, clauses);
+	  clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
 	  c_name = "nowait";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NUM_THREADS:
-	  clauses = cp_parser_omp_clause_num_threads (parser, clauses);
+	  clauses = cp_parser_omp_clause_num_threads (parser, clauses,
+						      token->location);
 	  c_name = "num_threads";
 	  break;
 	case PRAGMA_OMP_CLAUSE_ORDERED:
-	  clauses = cp_parser_omp_clause_ordered (parser, clauses);
+	  clauses = cp_parser_omp_clause_ordered (parser, clauses,
+						  token->location);
 	  c_name = "ordered";
 	  break;
 	case PRAGMA_OMP_CLAUSE_PRIVATE:
@@ -20069,7 +20263,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
-	  clauses = cp_parser_omp_clause_schedule (parser, clauses);
+	  clauses = cp_parser_omp_clause_schedule (parser, clauses,
+						   token->location);
 	  c_name = "schedule";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SHARED:
@@ -20078,7 +20273,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "shared";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
-	  clauses = cp_parser_omp_clause_untied (parser, clauses);
+	  clauses = cp_parser_omp_clause_untied (parser, clauses,
+						 token->location);
 	  c_name = "nowait";
 	  break;
 	default:
@@ -20091,7 +20287,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  /* Remove the invalid clause(s) from the list to avoid
 	     confusing the rest of the compiler.  */
 	  clauses = prev;
-	  error ("%qs is not valid for %qs", c_name, where);
+	  error ("%H%qs is not valid for %qs", &token->location, c_name, where);
 	}
     }
  saw_error:
@@ -21177,10 +21373,11 @@ cp_parser_initial_pragma (cp_token *first_token)
 
       cp_lexer_get_preprocessor_token (NULL, first_token);
       if (first_token->type != CPP_PRAGMA_EOL)
-	error ("junk at end of %<#pragma GCC pch_preprocess%>");
+	error ("%Hjunk at end of %<#pragma GCC pch_preprocess%>",
+               &first_token->location);
     }
   else
-    error ("expected string literal");
+    error ("%Hexpected string literal", &first_token->location);
 
   /* Skip to the end of the pragma.  */
   while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
@@ -21213,7 +21410,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
   switch (id)
     {
     case PRAGMA_GCC_PCH_PREPROCESS:
-      error ("%<#pragma GCC pch_preprocess%> must be first");
+      error ("%H%<#pragma GCC pch_preprocess%> must be first",
+             &pragma_tok->location);
       break;
 
     case PRAGMA_OMP_BARRIER:
@@ -21223,8 +21421,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_barrier (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp barrier%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp barrier%> may only be "
+		 "used in compound statements", &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
@@ -21238,8 +21436,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_flush (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp flush%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp flush%> may only be "
+		 "used in compound statements", &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
@@ -21280,8 +21478,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
       return true;
 
     case PRAGMA_OMP_SECTION:
-      error ("%<#pragma omp section%> may only be used in "
-	     "%<#pragma omp sections%> construct");
+      error ("%H%<#pragma omp section%> may only be used in "
+	     "%<#pragma omp sections%> construct", &pragma_tok->location);
       break;
 
     default:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index eb4a7b7..55ebfd1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9750,7 +9750,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
       if (complain & tf_error)
 	qualified_name_lookup_error (scope,
 				     TREE_OPERAND (qualified_id, 1),
-				     expr);
+				     expr, input_location);
       return error_mark_node;
     }
 
@@ -9759,7 +9759,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
 
   if (expr == error_mark_node && complain & tf_error)
     qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
-				 expr);
+				 expr, input_location);
   else if (TYPE_P (scope))
     {
       expr = (adjust_result_of_qualified_name_lookup
@@ -10491,7 +10491,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 					  /*is_type_p=*/false,
 					  /*complain=*/false);
 	    if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
-	      qualified_name_lookup_error (scope, name, decl);
+	      qualified_name_lookup_error (scope, name, decl, input_location);
 	    else
 	      do_local_using_decl (decl, scope, name);
 	  }
@@ -10938,7 +10938,8 @@ tsubst_copy_and_build (tree t,
 				     /*done=*/true,
 				     /*address_p=*/false,
 				     /*template_arg_p=*/false,
-				     &error_msg);
+				     &error_msg,
+				     input_location);
 	if (error_msg)
 	  error (error_msg);
 	if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
@@ -11467,7 +11468,8 @@ tsubst_copy_and_build (tree t,
 	      }
 	    else
 	      {
-		qualified_name_lookup_error (object_type, tmpl, member);
+		qualified_name_lookup_error (object_type, tmpl, member,
+					     input_location);
 		return error_mark_node;
 	      }
 	  }
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index f39b8d1..ba5ed6d 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2482,29 +2482,33 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
 }
 
 /* Issue a diagnostic that NAME cannot be found in SCOPE.  DECL is
-   what we found when we tried to do the lookup.  */
+   what we found when we tried to do the lookup.
+   LOCATION is the location of the NAME identifier;
+   The location is used in the error message*/
 
 void
-qualified_name_lookup_error (tree scope, tree name, tree decl)
+qualified_name_lookup_error (tree scope, tree name,
+			     tree decl, location_t location)
 {
   if (scope == error_mark_node)
     ; /* We already complained.  */
   else if (TYPE_P (scope))
     {
       if (!COMPLETE_TYPE_P (scope))
-	error ("incomplete type %qT used in nested name specifier", scope);
+	error ("%Hincomplete type %qT used in nested name specifier",
+	       &location, scope);
       else if (TREE_CODE (decl) == TREE_LIST)
 	{
-	  error ("reference to %<%T::%D%> is ambiguous", scope, name);
+	  error ("%Hreference to %<%T::%D%> is ambiguous", &location, scope, name);
 	  print_candidates (decl);
 	}
       else
-	error ("%qD is not a member of %qT", name, scope);
+	error ("%H%qD is not a member of %qT", &location, name, scope);
     }
   else if (scope != global_namespace)
-    error ("%qD is not a member of %qD", name, scope);
+    error ("%H%qD is not a member of %qD", &location, name, scope);
   else
-    error ("%<::%D%> has not been declared", name);
+    error ("%H%<::%D%> has not been declared", &location, name);
 }
 
 /* If FNS is a member function, a set of member functions, or a
@@ -2569,7 +2573,6 @@ baselink_for_fns (tree fns)
    the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
-
 tree
 finish_id_expression (tree id_expression,
 		      tree decl,
@@ -2582,7 +2585,8 @@ finish_id_expression (tree id_expression,
 		      bool done,
 		      bool address_p,
 		      bool template_arg_p,
-		      const char **error_msg)
+		      const char **error_msg,
+		      location_t location)
 {
   /* Initialize the output parameters.  */
   *idk = CP_ID_KIND_NONE;
@@ -2612,7 +2616,7 @@ finish_id_expression (tree id_expression,
 	      /* If the qualifying type is non-dependent (and the name
 		 does not name a conversion operator to a dependent
 		 type), issue an error.  */
-	      qualified_name_lookup_error (scope, id_expression, decl);
+	      qualified_name_lookup_error (scope, id_expression, decl, location);
 	      return error_mark_node;
 	    }
 	  else if (!scope)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 9e70eb6..6fc3305 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2008-06-18 Dodji Seketeli <dseketel@redhat.com>
+
+	* g++.dg/parse/constructor1.C, g++.dg/parse/error*.C: update these
+	  tests to make them catch column number regressions. Make these tests
+	  run with the -fshow-column option.
+	* g++.dg/parse/error-column.C: new column number test.
+
 2008-06-19  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
 	* gfortran.dg/fmt_l.f90: Fix end of line test pattern.
diff --git a/gcc/testsuite/g++.dg/parse/constructor1.C b/gcc/testsuite/g++.dg/parse/constructor1.C
index 3011862..4685c5a 100644
--- a/gcc/testsuite/g++.dg/parse/constructor1.C
+++ b/gcc/testsuite/g++.dg/parse/constructor1.C
@@ -1,4 +1,8 @@
+// { dg-do compile }
+// Make sure column information is correctly shown in error reporting
+// { dg-options "-fshow-column" }
+
 ACE_Process_Descriptor::ACE_Process_Descriptor () : // { dg-error "" }
-  process_ (0)
+  process_ (0) // { dg-error "3: error: only constructors take base initializers" }
 {
 }
diff --git a/gcc/testsuite/g++.dg/parse/error-column.C b/gcc/testsuite/g++.dg/parse/error-column.C
new file mode 100644
index 0000000..812a499
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error-column.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// Make sure column information is correctly shown in error reporting
+// { dg-options "-fshow-column" }
+
+
+void foo ()
+{
+  cout << "blah"; // { dg-error "3: error: 'cout'" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/error1.C b/gcc/testsuite/g++.dg/parse/error1.C
index 8756df6..60e7d65 100644
--- a/gcc/testsuite/g++.dg/parse/error1.C
+++ b/gcc/testsuite/g++.dg/parse/error1.C
@@ -1,6 +1,7 @@
+// { dg-options "-fshow-column" }
 struct INCOMPLETE;
 template <int> struct X {
     static INCOMPLETE value;
 };
-template <> INCOMPLETE X<1>::value = 0; // { dg-error "" }
+template <> INCOMPLETE X<1>::value = 0; // { dg-error "30: error: variable 'INCOMPLETE X<1>::value' has initializer but incomplete type" }
 
diff --git a/gcc/testsuite/g++.dg/parse/error10.C b/gcc/testsuite/g++.dg/parse/error10.C
index 242c421..6e46922 100644
--- a/gcc/testsuite/g++.dg/parse/error10.C
+++ b/gcc/testsuite/g++.dg/parse/error10.C
@@ -1,5 +1,5 @@
 // PR c++/3478
-// { dg-options "" }
+// { dg-options "-fshow-column" }
 
 template <typename> struct A
 {
@@ -11,5 +11,9 @@ template <typename T> void foo()
   enum          A<void>::E e1;
   typename      A<T>::E    e2;
   enum          A<T>::E    e3;
-  enum typename A<T>::E    e4; // { dg-error "" }
+  enum typename A<T>::E    e4;
 }
+
+// Here, columns nums are not very accurate either. Still acceptable though
+// { dg-error "30: error: invalid type in declaration before ';' token" "" { target *-*-* } { 14 } }
+// { dg-error "30: error: two or more data types in declaration of 'e4'" "" { target *-*-* } { 14 } }
diff --git a/gcc/testsuite/g++.dg/parse/error11.C b/gcc/testsuite/g++.dg/parse/error11.C
index 0a8e2e4..9dfb075 100644
--- a/gcc/testsuite/g++.dg/parse/error11.C
+++ b/gcc/testsuite/g++.dg/parse/error11.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }"
 // Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
 // Try to find out when the digraph '<:' is used as a mistake, and parse it
 //  correctly to avoid cascaded errors.
@@ -15,16 +16,16 @@ struct Foo
   };
 
   void method(void) {
-    typename Foo<::B>::template Nested<::B> n; // { dg-error "cannot begin|alternate spelling" }
+    typename Foo<::B>::template Nested<::B> n; // { dg-error "17: error: '<::' cannot begin|17: note: '<:' is an alternate spelling|39: error: '<::' cannot begin|39: note: '<:' is an alternate" }
     n.template Nested<B>::method();
-    n.template Nested<::B>::method();  // { dg-error "cannot begin|alternate spelling" }
+    n.template Nested<::B>::method();  // { dg-error "22: error: '<::' cannot begin|22: note: '<:' is an alternate" }
     Nested<B>::method();
-    Nested<::B>::method(); // { dg-error "cannot begin|alternate spelling" }
+    Nested<::B>::method(); // { dg-error "11: error: '<::' cannot begin|11: note: '<:' is an alternate" }
   }
 };
 
 template <int N> struct Foo2 {};
-template struct Foo2<::B>;  // { dg-error "cannot begin|alternate spelling|type/value mismatch|expected a constant" }
+template struct Foo2<::B>;  // { dg-error "21: error: '<::' cannot begin|21: note: '<:' is an alternate|25: error: type/value mismatch|25: error:   expected a constant" }
 
 int value = 0;
 
@@ -32,22 +33,28 @@ void func(void)
 {
   Foo<::B> f; // { dg-error "cannot begin|alternate spelling" }
   f.Foo<B>::method();
-  f.Foo<::B>::method(); // { dg-error "cannot begin|alternate spelling" }
+  f.Foo<::B>::method(); // { dg-error "8: error|8: note" }
 
   // Check cases where we the token sequence is the correct one, but there
   //  was no digraph or whitespaces in the middle, so we should not emit
   //  the special error message.
   Foo<: :B> k2;     // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" }
   Foo[:B> k1;       // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" } 
-// { dg-error "" "" { target *-*-* } 40 }
-// { dg-error "" "" { target *-*-* } 41 }
-
+// { dg-error "6: error: missing template arguments before" "" { target *-*-* } { 41 } }
+// { dg-error "9: error: expected primary-expression before ':' token" "" { target *-*-* } 41 }
+// { dg-error "9: error: expected '\]' before ':' token" "" { target *-*-* } 41 }
+// { dg-error "9: error: expected ';' before ':' token" "" { target *-*-* } 41 }
+// { dg-error "6: error: missing template arguments before" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected primary-expression before ':' token" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected '\]' before ':' token" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected ';' before ':' token" "" { target *-*-* } 42 }
+//
   int Foo[2];
   Foo[::value] = 0;
 }
 
-template struct Foo<::B>; // { dg-error "cannot begin|alternate spelling" }
+template struct Foo<::B>; // { dg-error "20: error: '<::' cannot begin|20: note: '<:' is an alternate" }
 
 // On the first error message, an additional note about the use of 
 //  -fpermissive should be present
-// { dg-error "-fpermissive" "-fpermissive" { target *-*-* } 18 }
+// { dg-error "17: note: \\(if you use -fpermissive G\\+\\+ will accept your code\\)" "-fpermissive" { target *-*-* } 19 }
diff --git a/gcc/testsuite/g++.dg/parse/error12.C b/gcc/testsuite/g++.dg/parse/error12.C
index ea04fd0..b002588 100644
--- a/gcc/testsuite/g++.dg/parse/error12.C
+++ b/gcc/testsuite/g++.dg/parse/error12.C
@@ -1,7 +1,7 @@
 // { dg-do compile }
 // Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
 // Make sure the error about '<:' can be turned into a warning
-// { dg-options "-fpermissive" }
+// { dg-options "-fpermissive -fshow-column" }
 
 struct B;
 
@@ -9,4 +9,5 @@ template <class A>
 struct Foo {};
 
 Foo<::B> foo;   // { dg-bogus "error" "error in place of warning" }
-// { dg-error "" "" { target *-*-* } 11 }
+// { dg-error "4: warning: '<::' cannot begin a template-argument list" "warning <::" { target *-*-* } 11 }
+// { dg-error "4: note: '<:' is an alternate spelling for '.'. Insert whitespace between '<' and '::'" "note <:" { target *-*-* } 11 }
diff --git a/gcc/testsuite/g++.dg/parse/error13.C b/gcc/testsuite/g++.dg/parse/error13.C
index 15642e3..94ddae8 100644
--- a/gcc/testsuite/g++.dg/parse/error13.C
+++ b/gcc/testsuite/g++.dg/parse/error13.C
@@ -1,13 +1,14 @@
+// { dg-options "-fshow-column" }
 // PR c++/13975
 
-public: // { dg-error "" }
+public: // { dg-error "1: error: expected unqualified-id before 'public'" }
 
 int i;
 
-protected: // { dg-error "" }
+protected: // { dg-error "1: error: expected unqualified-id before 'protected'" }
 
 int j;
 
-private: // { dg-error "" }
+private: // { dg-error "1: error: expected unqualified-id before 'private'" }
 
 int k;
diff --git a/gcc/testsuite/g++.dg/parse/error14.C b/gcc/testsuite/g++.dg/parse/error14.C
index 4b23045..906b98f 100644
--- a/gcc/testsuite/g++.dg/parse/error14.C
+++ b/gcc/testsuite/g++.dg/parse/error14.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column" }
 // PR c++/13970
 
 struct X
@@ -18,5 +19,5 @@ struct X
         Zinc<int>( //);
 		  //    }
 
-}; // { dg-error "" }
+}; // { dg-error "2: error: expected '.' at end of input|1: error: expected primary-expression before '.' token|1: error: expected ';' before '.' token|1: error: expected unqualified-id at end of input" }
 
diff --git a/gcc/testsuite/g++.dg/parse/error15.C b/gcc/testsuite/g++.dg/parse/error15.C
index b343970..9e2972f 100644
--- a/gcc/testsuite/g++.dg/parse/error15.C
+++ b/gcc/testsuite/g++.dg/parse/error15.C
@@ -1,5 +1,6 @@
 // { dg-do compile }
 // Contributed by Volker Reichelt <reichelt at gcc dot gnu dot org> 
+// { dg-options "-fshow-column" }
 // PR c++/14008: Improve diagnostic on invalid types in declarators.
 
 namespace N
@@ -9,29 +10,29 @@ namespace N
   int K;
 }
 
-N::A f2;              // { dg-error "without an argument list" }
-N::INVALID f3;        // { dg-error "in namespace 'N' does not name a type" }
-N::C::INVALID f4;     // { dg-error "in class 'N::C' does not name a type" }
-N::K f6;              // { dg-error "in namespace 'N' does not name a type" }
-typename N::A f7;     // { dg-error "without an argument list|outside of template" }
+N::A f2;              // { dg-error "4: error: invalid use of template-name 'N::A' without an argument list" }
+N::INVALID f3;        // { dg-error "4: error: 'INVALID' in namespace 'N' does not name a type" }
+N::C::INVALID f4;     // { dg-error "7: error: 'INVALID' in class 'N::C' does not name a type" }
+N::K f6;              // { dg-error "4: error: 'K' in namespace 'N' does not name a type" }
+typename N::A f7;     // { dg-error "1: warning: using 'typename' outside of template|13: error: invalid use of template-name 'N::A' without an argument list|17: error: invalid type in declaration before ';' token" }
 
 struct B
 {
-  N::A f2;            // { dg-error "without an argument list" }
-  N::INVALID f3;      // { dg-error "in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "in namespace 'N' does not name a type" }
-  typename N::A f7;   // { dg-error "without an argument list|outside of template" }
+  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  typename N::A f7;   // { dg-error "3: warning: using 'typename' outside of template|15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
 template <int>
 struct C
 {
-  N::A f2;            // { dg-error "without an argument list" }
-  N::INVALID f3;      // { dg-error "in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "in namespace 'N' does not name a type" }
-  typename N::A f7;   // { dg-error "without an argument list" }
+  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  typename N::A f7;   // { dg-error "15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
-// { dg-bogus "" "bogus excess errors in declaration" { xfail *-*-* } 16 }
+// { dg-bogus "bogus excess errors in declaration" "bogus excess errors in declaration" { xfail *-*-* } 17 }
diff --git a/gcc/testsuite/g++.dg/parse/error16.C b/gcc/testsuite/g++.dg/parse/error16.C
index 3dc58ad..ddc302c 100644
--- a/gcc/testsuite/g++.dg/parse/error16.C
+++ b/gcc/testsuite/g++.dg/parse/error16.C
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 // PR c++/16964
 
 struct A
 {
-  struct B {}; // { dg-error "previous" }
+  struct B {}; // { dg-error "12: error: previous definition of 'struct A::B'" }
 };
 
-struct A::B{}; // { dg-error "redefinition" }
+struct A::B{}; // { dg-error "11: error: redefinition of 'struct A::B'" }
diff --git a/gcc/testsuite/g++.dg/parse/error17.C b/gcc/testsuite/g++.dg/parse/error17.C
index 2a8f3f8..0e05217 100644
--- a/gcc/testsuite/g++.dg/parse/error17.C
+++ b/gcc/testsuite/g++.dg/parse/error17.C
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 // PR c++/16965
 
 template <typename T> struct B { 
-  static int Bar(T); // { dg-error "" }
+  static int Bar(T); // { dg-error "19: error: candidates are: |19: error:  " }
 }; 
 struct D : B<int>, B<char> {}; 
  
-int i2 = D::Bar(2); // { dg-error "" }
+int i2 = D::Bar(2); // { dg-error "13: error: reference to 'Bar' is ambiguous|10: error: reference to 'Bar' is ambiguous" }
diff --git a/gcc/testsuite/g++.dg/parse/error18.C b/gcc/testsuite/g++.dg/parse/error18.C
index 363aae9..926af11 100644
--- a/gcc/testsuite/g++.dg/parse/error18.C
+++ b/gcc/testsuite/g++.dg/parse/error18.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column" }
 // PR c++/16002
 
 void f()
 {
-  double Q *= 5.0; // { dg-error "initializer" }
+  double Q *= 5.0; // { dg-error "12: error: expected initializer before '..' token" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error19.C b/gcc/testsuite/g++.dg/parse/error19.C
index 24a66af..b22156a 100644
--- a/gcc/testsuite/g++.dg/parse/error19.C
+++ b/gcc/testsuite/g++.dg/parse/error19.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -fmessage-length=0   -ansi -pedantic-errors -Wno-long-long " }
 // PR C++/17867
 
 struct A
-{  // { dg-error "candidate" }
+{  // { dg-error "1: note: candidates are:" }
   A(int);
 };
 
@@ -9,5 +10,5 @@ const A& foo();
 
 void bar()
 {
-  foo()=A(0); // { dg-error "A" }
+  foo()=A(0); // { dg-error "12: error: no match for 'operator='" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/error2.C b/gcc/testsuite/g++.dg/parse/error2.C
index 8dd1e9d..075dcc2 100644
--- a/gcc/testsuite/g++.dg/parse/error2.C
+++ b/gcc/testsuite/g++.dg/parse/error2.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }
 // Properly print CALL_EXPRs while dumping expressions
 
 double g;
@@ -7,4 +8,8 @@ int func(double);
 template <int>
 struct Foo {};
 
-Foo<func(g)> f; // { dg-error "" "func(g)" }
+Foo<func(g)> f; // { dg-error "5: error: 'int func.double.' cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "10: error: 'g' cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "11: error: a function call cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "12: error: template argument 1 is invalid" "" { target *-*-* } { 11 } }
+// { dg-error "15: error: invalid type in declaration before ';' token" "" { target *-*-* } { 11 } }
diff --git a/gcc/testsuite/g++.dg/parse/error20.C b/gcc/testsuite/g++.dg/parse/error20.C
index ee7390a..9564fab 100644
--- a/gcc/testsuite/g++.dg/parse/error20.C
+++ b/gcc/testsuite/g++.dg/parse/error20.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/17821
 
 struct A {
@@ -11,7 +12,7 @@ struct C {
 };
 int main() {
   C c;
-  A(c.p.i); // { dg-error "member.*non-class" }
+  A(c.p.i); // { dg-error "9: error: request for member 'i' in 'c.C::p', which is of non-class type 'B" }
   return 0;
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error21.C b/gcc/testsuite/g++.dg/parse/error21.C
index 6e24ae2..f60bf2b 100644
--- a/gcc/testsuite/g++.dg/parse/error21.C
+++ b/gcc/testsuite/g++.dg/parse/error21.C
@@ -1,5 +1,5 @@
 // PR c++/17393
-// { dg-options "-Wall" }
+// { dg-options "-Wall -fshow-column" }
 
 struct A { };
 
@@ -7,6 +7,6 @@ void foo()
 {
   // Check that we do not complain about an unused
   // compiler-generated variable.
-  A& = a; // { dg-error "token|declarator|not declared" }
+  A& = a; // { dg-error "6: error: expected unqualified-id before '=' token|8: error: 'a' was not declared in this scope" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error22.C b/gcc/testsuite/g++.dg/parse/error22.C
index da3a62f..3014121 100644
--- a/gcc/testsuite/g++.dg/parse/error22.C
+++ b/gcc/testsuite/g++.dg/parse/error22.C
@@ -1,5 +1,6 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/15786
 
 struct A {
-  void foo(bar* p); /* { dg-error "declared" } */
+  void foo(bar* p); /* { dg-error "12: error: 'bar' has not been declared" } */
 };
diff --git a/gcc/testsuite/g++.dg/parse/error23.C b/gcc/testsuite/g++.dg/parse/error23.C
index 7d6fda2..21b2434 100644
--- a/gcc/testsuite/g++.dg/parse/error23.C
+++ b/gcc/testsuite/g++.dg/parse/error23.C
@@ -1,7 +1,9 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/19149
 
 struct QChar {
   QChar( char c );
   QChar( const QChar& c );
-  static const ; // { dg-error "" }
+  //following column number is not accurate enough but will make it for now
+  static const ; // { dg-error "10: error: declaration does not declare anything" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error24.C b/gcc/testsuite/g++.dg/parse/error24.C
index c072250..e341c34 100644
--- a/gcc/testsuite/g++.dg/parse/error24.C
+++ b/gcc/testsuite/g++.dg/parse/error24.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/19395
 
 struct A {
-  typedef int ::X; // { dg-error "" }
+  typedef int ::X; // { dg-error "17: error: typedef name may not be a nested-name-specifier" }
 };
 
 
diff --git a/gcc/testsuite/g++.dg/parse/error25.C b/gcc/testsuite/g++.dg/parse/error25.C
index 360b40f..b5cb57e 100644
--- a/gcc/testsuite/g++.dg/parse/error25.C
+++ b/gcc/testsuite/g++.dg/parse/error25.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // Origin: Steven Bosscher <steven at gcc dot gnu dot org>
 // PR c++/17401: ICE with invalid pure specifier
 
@@ -8,10 +9,10 @@
 class foo
 {
   virtual void bar1 () = 0;
-  virtual void bar2 () = __null;  // { dg-error "invalid pure specifier" }
-  virtual void bar3 () = 4;       // { dg-error "invalid pure specifier" }
-  virtual void bar4 () = A::f;    // { dg-error "invalid pure specifier" }
-  virtual void bar5 () = 0l;      // { dg-error "invalid pure specifier" }
-  virtual void bar6 () = 00;      // { dg-error "invalid pure specifier" }
-  virtual void bar7 () = 0x0;     // { dg-error "invalid pure specifier" }
+  virtual void bar2 () = __null;  // { dg-error "32: error: invalid pure specifier" }
+  virtual void bar3 () = 4;       // { dg-error "27: error: invalid pure specifier" }
+  virtual void bar4 () = A::f;    // { dg-error "27: error: invalid pure specifier" }
+  virtual void bar5 () = 0l;      // { dg-error "28: error: invalid pure specifier" }
+  virtual void bar6 () = 00;      // { dg-error "28: error: invalid pure specifier" }
+  virtual void bar7 () = 0x0;     // { dg-error "29: error: invalid pure specifier" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error26.C b/gcc/testsuite/g++.dg/parse/error26.C
index 6e2b897..81f7ba6 100644
--- a/gcc/testsuite/g++.dg/parse/error26.C
+++ b/gcc/testsuite/g++.dg/parse/error26.C
@@ -1,12 +1,12 @@
 // PR c++/20148
-// { dg-options "" }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 
 void foo()
 {
-  if (({int c[2];})) ; // { dg-error "\{\.\.\.\}" }
+  if (({int c[2];})) ; // { dg-error "7: error: ISO C.. forbids|20: error: could not convert" }
 }
 
 void bar()
 {
-  if (({})); // { dg-error "\{\.\.\.\}" }
+  if (({})); // { dg-error "7: error: ISO C.. forbids|11: error: could not convert" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/error27.C b/gcc/testsuite/g++.dg/parse/error27.C
index f52d3ce..f1fd537 100644
--- a/gcc/testsuite/g++.dg/parse/error27.C
+++ b/gcc/testsuite/g++.dg/parse/error27.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/20152
 
-struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "previous definition" }
-struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "previous definition" }
-struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "" }
-struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "" }
+struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "24: error: previous definition of 'struct KrSelectionMode'" }
+struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "52: error: previous definition of 'struct KrKDESelectionMode'" }
+struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "8: error: redefinition of 'struct KrSelectionMode'" }
+struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "8: error: redefinition of 'struct KrKDESelectionMode'" }
 KrKDESelectionMode krKDESelectionMode;
diff --git a/gcc/testsuite/g++.dg/parse/error28.C b/gcc/testsuite/g++.dg/parse/error28.C
index 046cc50..fd202a1 100644
--- a/gcc/testsuite/g++.dg/parse/error28.C
+++ b/gcc/testsuite/g++.dg/parse/error28.C
@@ -1,10 +1,11 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/21908
 
 struct virt { virt () {} virt (int i) {} };
-struct der : public virtual virt { // { dg-error "der" }
-  der (int i) : virt(i) {} // { dg-error "der" }
+struct der : public virtual virt { // { dg-error "34: note:                 der::der" }
+  der (int i) : virt(i) {} // { dg-error "13: note: candidates are: der" }
 };
 struct top : public der { 
-  // { dg-error "der\\(\\)" "" { target *-*-* } 9 } 
   top () {} // { dg-bogus "der\\(const" }
 };
+// { dg-error "10: error: no matching function for call to 'der" "" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/parse/error29.C b/gcc/testsuite/g++.dg/parse/error29.C
index b50b275..fcd091b 100644
--- a/gcc/testsuite/g++.dg/parse/error29.C
+++ b/gcc/testsuite/g++.dg/parse/error29.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/25637
 
 struct A { 
@@ -6,7 +7,7 @@ struct A {
   void operator delete(void *);
 };
 struct B { 
-  friend void A::foo() {} // { dg-error "define" }
-  friend void A::operator delete(void*) {} // { dg-error "define" }
-  friend A::A() {} // { dg-error "define" }
+  friend void A::foo() {} // { dg-error "22: error: cannot define member function 'A::foo' within 'B'" }
+  friend void A::operator delete(void*) {} // { dg-error "39: error: cannot define member function 'A::operator delete' within 'B'" }
+  friend A::A() {} // { dg-error "15: error: cannot define member function 'A::A' within 'B'" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error3.C b/gcc/testsuite/g++.dg/parse/error3.C
index a052346..859f27e 100644
--- a/gcc/testsuite/g++.dg/parse/error3.C
+++ b/gcc/testsuite/g++.dg/parse/error3.C
@@ -1,6 +1,19 @@
+// { dg-options "-fshow-column" }
 // PR c++/10779
 
 static void InstantiateConstraint(const float&, unsigned,
-                                  void(*AddFunction)(const TYPE&,bool&, // { dg-error "" }
+                                  void(*AddFunction)(const TYPE&,bool&,
                                                      char*, char*,
-                                                     unsigned*)); // { dg-error "" }
+                                                     unsigned*));
+// { dg-error "64: error: expected ',' or '...' before '&' token" "" { target *-*-* }  { 5 } }
+
+/// in the coming test, the column information is broken as it points to
+//  the end of the declaration instead of pointing to the begining of the
+//  'TYPE' identifier. This is due to the warning being generated by the
+//  declaration groking code (gcc/cp/decl.c) and not the parser. So in that
+//  code, the exact token location information is lost as the declaration
+//  groking code manipulates TREEs only. The token location used is then
+//  the global one that is not accurate enough. Anyway, let's say it is
+//  good enough for now, until we find a way to propagate token location to
+//  code paths that manipulate TREEs only.
+// { dg-error "64: warning: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 7 } }
diff --git a/gcc/testsuite/g++.dg/parse/error30.C b/gcc/testsuite/g++.dg/parse/error30.C
index 734a255..5c52d1e 100644
--- a/gcc/testsuite/g++.dg/parse/error30.C
+++ b/gcc/testsuite/g++.dg/parse/error30.C
@@ -1,5 +1,6 @@
 // PR c++/30854
 // { dg-do compile }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 
 struct A
 {
@@ -7,5 +8,5 @@ struct A
   A(int);
 };
 
-A a = -A();	// { dg-error "no match for.*operator-.*in.*-A\\(\\)" }
-A b = -A(5);	// { dg-error "no match for.*operator-.*in.*-A\\(5\\)" }
+A a = -A();	// { dg-error "10: error: no match for.*operator-.*in.*-A\\(\\)" }
+A b = -A(5);	// { dg-error "11: error: no match for.*operator-.*in.*-A\\(5\\)" }
diff --git a/gcc/testsuite/g++.dg/parse/error31.C b/gcc/testsuite/g++.dg/parse/error31.C
index 5264f44..d354cc3 100644
--- a/gcc/testsuite/g++.dg/parse/error31.C
+++ b/gcc/testsuite/g++.dg/parse/error31.C
@@ -1,10 +1,12 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/32190
 
 template<typename T> class foo{ };
 
 int main() {
     foo<int> i;
-    foo<foo<int> j; // { dg-error "template argument" }
+    // this column number is not accurate yet, but that will make it for now.
+    foo<foo<int> j; // { dg-error "18: error: template argument 1 is invalid" }
     int k;
     int l;
     foo<int> m;
diff --git a/gcc/testsuite/g++.dg/parse/error4.C b/gcc/testsuite/g++.dg/parse/error4.C
index aa1bfad..790e5c9 100644
--- a/gcc/testsuite/g++.dg/parse/error4.C
+++ b/gcc/testsuite/g++.dg/parse/error4.C
@@ -1,7 +1,10 @@
 // PR c++/12160
+// { dg-options "-fshow-column" }
 
-struct X { 
-  virtual void f(int, 
-		 itn,        // { dg-error "declared" }
+struct X {
+  virtual void f(int,
+		 itn,
 		 int);
-}; 
+};
+
+// { dg-error "4: error: 'itn' has not been declared" "" { target *-*-* } { 6 } }
diff --git a/gcc/testsuite/g++.dg/parse/error5.C b/gcc/testsuite/g++.dg/parse/error5.C
index 81356ce..8c9a039 100644
--- a/gcc/testsuite/g++.dg/parse/error5.C
+++ b/gcc/testsuite/g++.dg/parse/error5.C
@@ -1,4 +1,19 @@
 // PR c++/13269
+// { dg-options "-fshow-column" }
 
-class Foo { int foo() return 0; } }; // { dg-error "" }
+class Foo { int foo() return 0; } };
+
+// { dg-error "30: error: expected identifier before numeric constant" "" { target *-*-* } { 4 } }
+
+// { dg-error "23: error: named return values are no longer supported" "" { target *-*-* } { 4 } }
+
+// the column number info of this error output is still wrong because the error
+// message has been generated by cp_parser_error() which does not
+// necessarily allow accurate column number display. At some point, we will
+// need make cp_parser_error() report more accurate column numbers.
+// { dg-error "30: error: expected '\{' at end of input" "" { target *-*-* } { 4 } }
+
+// { dg-error "35: error: expected unqualified-id before '\}' token" "" {target *-*-*  } { 4 } }
+
+// { dg-error "35: error: expected declaration before '\}' token" "" {target *-*-*  } { 4 } }
 
diff --git a/gcc/testsuite/g++.dg/parse/error6.C b/gcc/testsuite/g++.dg/parse/error6.C
index 3a16669..cd1b6b8 100644
--- a/gcc/testsuite/g++.dg/parse/error6.C
+++ b/gcc/testsuite/g++.dg/parse/error6.C
@@ -1,6 +1,11 @@
 // PR c++/10603
+// { dg-options "-fshow-column" }
 
-int f(int not) { // { dg-error "!" }
-  return 1-not; // { dg-error "" }
+int f(int not) {
+  return 1-not;
 } 
 
+// { dg-error "11: error: expected ',' or '...' before '!' token" "" { target *-*-* } { 4 } }
+
+// { dg-error "15: error: expected primary\\-expression before ';' token" "" { target *-*-* }  { 5 } }
+
diff --git a/gcc/testsuite/g++.dg/parse/error7.C b/gcc/testsuite/g++.dg/parse/error7.C
index 50e7f84..f71c9aa 100644
--- a/gcc/testsuite/g++.dg/parse/error7.C
+++ b/gcc/testsuite/g++.dg/parse/error7.C
@@ -1,4 +1,7 @@
 // PR c++/12827
+// { dg-options "-fshow-column" }
 
 void f(int x
-       int y); // { dg-error "," }
+       int y);
+
+// { dg-error "8: error: expected ',' or '...' before 'int'" "" { target *-*-* } { 5 } }
diff --git a/gcc/testsuite/g++.dg/parse/error8.C b/gcc/testsuite/g++.dg/parse/error8.C
index 125f2e4..8b9b352 100644
--- a/gcc/testsuite/g++.dg/parse/error8.C
+++ b/gcc/testsuite/g++.dg/parse/error8.C
@@ -1,4 +1,10 @@
 // PR c++/13438
+// {  dg-options "-fshow-column" }
 
-struct A { friend typename struct B; };  // { dg-error "" }
-  
+struct A { friend typename struct B; };
+
+
+// { dg-error "19: warning: using 'typename' outside of template" "" { target *-*-* } { 4 } }
+// { dg-error "28: error: expected nested-name-specifier before 'struct'" "" { target *-*-* } { 4 } }
+// { dg-error "35: error: multiple types in one declaration" "" { target *-*-* } { 4 } }
+// { dg-error "12: error: friend declaration does not name a class or function" "" { target *-*-* } { 4 } }
diff --git a/gcc/testsuite/g++.dg/parse/error9.C b/gcc/testsuite/g++.dg/parse/error9.C
index aa9109f..c1be697 100644
--- a/gcc/testsuite/g++.dg/parse/error9.C
+++ b/gcc/testsuite/g++.dg/parse/error9.C
@@ -1,5 +1,9 @@
 // PR c++/12613
-// { dg-options "" }
+// { dg-options "-fshow-column" }
 
 enum { FOO = 1, BAR = 2 };
-int a[] = { FOO: 1, BAR: 2 }; // { dg-error "" }
+int a[] = { FOO: 1, BAR: 2 };
+
+// the following 2 column locations are still not accurate enough
+// { dg-error "28: error: name 'FOO' used in a GNU-style designated initializer for an array" "" { target *-*-* }  { 5 } }
+// { dg-error "28: error: name 'BAR' used in a GNU-style designated initializer for an array" "" { target *-*-* }  { 5 } }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
index 42a21fc..7fe07a2 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
@@ -1,8 +1,9 @@
 // { dg-do assemble  }
+// { dg-options "-fshow-column" }
 
 struct A { // { dg-error "" } forward declaration
-  friend struct B : A {		// { dg-error "" } 
+  friend struct B : A {		// { dg-error "invalid use of incomplete type 'struct A'" }
     int x;
-  };	// { dg-error "" } class definition cannot be a friend
+  };	// { dg-error "class definition may not be declared a friend" ""  { target *-*-* } { 5 } }
   int y;
 };
diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
index c188824..938e063 100644
--- a/gcc/testsuite/lib/g++.exp
+++ b/gcc/testsuite/lib/g++.exp
@@ -273,7 +273,8 @@ proc g++_target_compile { source dest type options } {
     }
 
     lappend options "additional_flags=[libio_include_flags]"
-    lappend options "additional_flags=-fno-show-column"
+#don't hardcode -fno-show-column
+#lappend options "additional_flags=-fno-show-column"
     lappend options "compiler=$GXX_UNDER_TEST"
 
     set options [concat $gpp_compile_options $options]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate column  numbers
  2008-06-20 10:29 [patch] PR 31754/C++ - make -fshow-column produce more accurate column numbers Dodji Seketeli
@ 2008-06-25  2:01 ` Tom Tromey
  2008-06-25  6:35   ` Manuel López-Ibáñez
  2008-06-26 13:58   ` Dodji Seketeli
  0 siblings, 2 replies; 12+ messages in thread
From: Tom Tromey @ 2008-06-25  2:01 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: gcc-patches

>>>>> "Dodji" == Dodji Seketeli <dseketel@redhat.com> writes:

Dodji> This patch tries to fix PR 31754 for the c++ front end.
Dodji> It modifies the c++ parser to produce more accurate column information
Dodji> in error messages.

I skimmed this a bit.  I have a few nits... these are nothing serious,
just the usual tiny details that everybody misses their first time
hacking no GCC :)

A lot of the patch looks straightforward at first glance.  I didn't
look at the error calls in detail; but I note that we applied a
similar treatment to the C parser recently.  (Note that I can't
approve or reject this patch in any case.)

Dodji>     	* cp-tree.h, pt.c, semantic.c:
Dodji>     	 (qualified_name_lookup_error): add a location_t parameter so that

The usual GCC style for ChangeLog entries is much less verbose -- just
the file name, function name, plus a description of the change.  Read
through the existing entries to get a feel for this; also the GNU
Coding Standards have a section describing it.

Dodji> diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
Dodji> index 636ee6a..140aea0 100644
[...]

The convention for gcc-patches is to send the ChangeLog entries
in plain format (just the stanza from the ChangeLog) and not as part
of the patch.  There are various ways to automate this; I usually use
an Emacs hack, but there are some scripts around too.

Dodji> +extern void qualified_name_lookup_error		(tree, tree, tree, location_t);

Lines over 80 columns should be wrapped.  I would insert a line break
before the 'location_t'.  This is true for declarations and
expressions, I saw a few instances in the patch.  There are some
(sketchy) guidelines in the standards for where to put line breaks.

Dodji> +  cp_token *token=NULL;

GCC uses spaces around most binary operators, like the '=' here.

Dodji> +      /*save the first token of the decl spec list for error reporting*/

Comments in GCC, by convention, should be full sentences which start
with a capital letter and end with a period followed by two spaces.
Also there is a space before the text; finally, there is a standard
for how to indent subsequent lines... so:

    /* Save the first token of the decl spec list for error
       reporting.  */

Dodji> +// Make sure column information is correctly shown in error reporting

I'm ambivalent about these additions.  The dg-options line explains it
pretty clearly.

Dodji> +  //following column number is not accurate enough but will make it for now
Dodji> +  static const ; // { dg-error "10: error: declaration does not declare anything" }

I don't want things like this to get lost.  It is too easy to forget
about them.

Dodji> diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
Dodji> -    lappend options "additional_flags=-fno-show-column"
Dodji> +#don't hardcode -fno-show-column
Dodji> +#lappend options "additional_flags=-fno-show-column"
Dodji>      lappend options "compiler=$GXX_UNDER_TEST"

Just delete this -- we generally don't comment out dead code in GCC.

thanks,
Tom

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate column numbers
  2008-06-25  2:01 ` Tom Tromey
@ 2008-06-25  6:35   ` Manuel López-Ibáñez
  2008-06-25 14:05     ` Tom Tromey
  2008-06-26 14:10     ` Dodji Seketeli
  2008-06-26 13:58   ` Dodji Seketeli
  1 sibling, 2 replies; 12+ messages in thread
From: Manuel López-Ibáñez @ 2008-06-25  6:35 UTC (permalink / raw)
  To: gcc-patches; +Cc: Dodji Seketeli, tromey, Janis Johnson

2008/6/25 Tom Tromey <tromey@redhat.com>:
>>>>>> "Dodji" == Dodji Seketeli <dseketel@redhat.com> writes:
>
> Dodji> This patch tries to fix PR 31754 for the c++ front end.
> Dodji> It modifies the c++ parser to produce more accurate column information
> Dodji> in error messages.

I think this patch is really useful towards improving GCC column
information and perhaps some day giving caret diagnostics.
Nonetheless, the following:

> Dodji> +  //following column number is not accurate enough but will make it for now
> Dodji> +  static const ; // { dg-error "10: error: declaration does not declare anything" }

... is a hack. dg-error/dg-warning should get an additional (optional)
parameter similar to the line number that allows to define a column
number. That is my opinion, so you should ask a testsuite maintainer,
like Janis Johnson.

Also, if it is not accurate enough, you should use XFAIL.

> Dodji> diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
> Dodji> -    lappend options "additional_flags=-fno-show-column"
> Dodji> +#don't hardcode -fno-show-column
> Dodji> +#lappend options "additional_flags=-fno-show-column"
> Dodji>      lappend options "compiler=$GXX_UNDER_TEST"
>
> Just delete this -- we generally don't comment out dead code in GCC.

Moreover, it is strange that we had this additional flag for nothing.
I think that if it doesn't break any test, we should remove it
straight away.

Cheers,

Manuel.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate column numbers
  2008-06-25  6:35   ` Manuel López-Ibáñez
@ 2008-06-25 14:05     ` Tom Tromey
  2008-06-26 14:10     ` Dodji Seketeli
  1 sibling, 0 replies; 12+ messages in thread
From: Tom Tromey @ 2008-06-25 14:05 UTC (permalink / raw)
  To: Manuel López-Ibáñez
  Cc: gcc-patches, Dodji Seketeli, Janis Johnson

>>>>> "Manuel" == Manuel López-Ibáñez <lopezibanez@gmail.com> writes:

Dodji> diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
Dodji> -    lappend options "additional_flags=-fno-show-column"
Dodji> +#don't hardcode -fno-show-column
Dodji> +#lappend options "additional_flags=-fno-show-column"
Dodji> lappend options "compiler=$GXX_UNDER_TEST"

>> Just delete this -- we generally don't comment out dead code in GCC.

Manuel> Moreover, it is strange that we had this additional flag for nothing.
Manuel> I think that if it doesn't break any test, we should remove it
Manuel> straight away.

I think this line pre-dated the change of default for -fshow-column.
So, I think at one point it did actually do something.

Tom

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate  column  numbers
  2008-06-25  2:01 ` Tom Tromey
  2008-06-25  6:35   ` Manuel López-Ibáñez
@ 2008-06-26 13:58   ` Dodji Seketeli
  2008-06-26 18:39     ` Dodji Seketeli
  1 sibling, 1 reply; 12+ messages in thread
From: Dodji Seketeli @ 2008-06-26 13:58 UTC (permalink / raw)
  Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 2840 bytes --]

Hello,

In reply to your comments to my first patch, here is another version in 
which I tried to address the issues you raised.

In the mean time, I have refreshed the patch to make it apply against 
trunk from 2008-06-25. It still passes the tests on x86.

Tom Tromey a écrit :

[...]

> 
> Dodji>     	* cp-tree.h, pt.c, semantic.c:
> Dodji>     	 (qualified_name_lookup_error): add a location_t parameter so that
> 
> The usual GCC style for ChangeLog entries is much less verbose -- just
> the file name, function name, plus a description of the change.  Read
> through the existing entries to get a feel for this; also the GNU
> Coding Standards have a section describing it.

Fixed.

> Dodji> diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
> Dodji> index 636ee6a..140aea0 100644
> [...]
> 
> The convention for gcc-patches is to send the ChangeLog entries
> in plain format (just the stanza from the ChangeLog) and not as part
> of the patch.  There are various ways to automate this; I usually use
> an Emacs hack, but there are some scripts around too.

Ah, right. Fixed.

[...]

> Lines over 80 columns should be wrapped.

Done.

[...]

> 
> GCC uses spaces around most binary operators, like the '=' here.

Fixed.

[...]


> Dodji> +      /*save the first token of the decl spec list for error reporting*/

Fixed.

> Comments in GCC, by convention, should be full sentences which start
> with a capital letter and end with a period followed by two spaces.

Fixed.

[...]

> 
> Dodji> +// Make sure column information is correctly shown in error reporting
> 
> I'm ambivalent about these additions.  The dg-options line explains it
> pretty clearly.

Right. I have removed that comment.

[...]

> Dodji> +  //following column number is not accurate enough but will make it for now
> Dodji> +  static const ; // { dg-error "10: error: declaration does not declare anything" }
> 
> I don't want things like this to get lost.  It is too easy to forget
> about them.

What should be the preferred way to handle this ? In its initial 
version, that test did not care about column number at all, so the 
information was lost anyway. As I was focusing on that matter, I noticed 
the column number was not accurate enough and I thought adding a comment 
and a more accurate test was better than just leaving it as it was 
initially.

[...]

> Dodji> diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
> Dodji> -    lappend options "additional_flags=-fno-show-column"
> Dodji> +#don't hardcode -fno-show-column
> Dodji> +#lappend options "additional_flags=-fno-show-column"
> Dodji>      lappend options "compiler=$GXX_UNDER_TEST"
> 
> Just delete this -- we generally don't comment out dead code in GCC.

Right. Done.

Thank you for taking time to review this.

Please find attached the updated patch.

Cheers,

Dodji.

[-- Attachment #2: gcc-error-location-2008-06-26-gcc-patch.txt --]
[-- Type: text/plain, Size: 131386 bytes --]

2008-06-18 Dodji Seketeli <dseketel@redhat.com>

	PR c++/31754
	* pt.c, semantic.c:
	* semantic.c (qualified_name_lookup_error, finish_id_expression):
	add a location_t parameter so that
	error message can have a more accurate location.
	* cp-tree.h: updated prototype
	* pt.c (tsubst_qualified_id): use location in error messages.
	* parser.c (cp_parser_postfix_expression,
	cp_parser_objc_statement, cp_parser_trait_expr,
	cp_parser_token_is_class_key,
	cp_parser_uncommitted_to_tentative_parse_p,
	cp_parser_check_for_invalid_template_id, cp_parser_is_string_literal,
	cp_parser_error, cp_parser_name_lookup_error,
	cp_parser_simulate_error, cp_parser_check_decl_spec,
	cp_parser_check_decl_spec, cp_parser_non_integral_constant_expression,
	cp_parser_diagnose_invalid_type_name,
	cp_parser_parse_and_diagnose_invalid_type_name,
	cp_parser_require_pragma_eol, cp_parser_make_typename_type,
	cp_parser_string_literal, cp_parser_primary_expression,
	cp_parser_primary_expression, cp_parser_unqualified_id,
	cp_parser_nested_name_specifier_opt, cp_parser_postfix_expression,
	cp_parser_postfix_dot_deref_expression, cp_parser_new_expression,
	cp_parser_direct_new_declarator, cp_parser_builtin_offsetof,
	cp_parser_label_for_labeled_statement, cp_parser_statement_seq_opt,
	cp_parser_jump_statement, cp_parser_block_declaration,
	cp_parser_simple_declaration, cp_parser_decl_specifier_seq,
	cp_parser_function_specifier_opt, cp_parser_decltype,
	cp_parser_mem_initializer_list, cp_parser_mem_initializer,
	cp_parser_mem_initializer_id, cp_parser_template_parameter,
	cp_parser_type_parameter, cp_parser_template_id, cp_parser_template_name,
	cp_parser_template_argument): likewise.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d090d8f..afea188 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4632,13 +4632,15 @@ extern void finish_template_decl		(tree);
 extern tree finish_template_type		(tree, tree, int);
 extern tree finish_base_specifier		(tree, tree, bool);
 extern void finish_member_declaration		(tree);
-extern void qualified_name_lookup_error		(tree, tree, tree);
+extern void qualified_name_lookup_error		(tree, tree, tree,
+						 location_t);
 extern void check_template_keyword		(tree);
 extern tree finish_id_expression		(tree, tree, tree,
 						 cp_id_kind *,
 						 bool, bool, bool *,
 						 bool, bool, bool, bool,
-						 const char **);
+						 const char **,
+                                                 location_t);
 extern tree finish_typeof			(tree);
 extern tree finish_offsetof			(tree);
 extern void finish_decl_cleanup			(tree, tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7d530f5..184b9ec 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1585,7 +1585,7 @@ static tree cp_parser_postfix_expression
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
-  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
+  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
 static tree cp_parser_parenthesized_expression_list
   (cp_parser *, bool, bool, bool, bool *);
 static void cp_parser_pseudo_destructor_name
@@ -1894,15 +1894,15 @@ static tree cp_parser_objc_statement
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
-  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
+  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t);
 static tree cp_parser_lookup_name_simple
-  (cp_parser *, tree);
+  (cp_parser *, tree, location_t);
 static tree cp_parser_maybe_treat_template_as_class
   (tree, bool);
 static bool cp_parser_check_declarator_template_parameters
-  (cp_parser *, cp_declarator *);
+  (cp_parser *, cp_declarator *, location_t);
 static bool cp_parser_check_template_parameters
-  (cp_parser *, unsigned);
+  (cp_parser *, unsigned, location_t);
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
@@ -1938,7 +1938,7 @@ static tree cp_parser_trait_expr
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
-  (cp_parser *, cp_decl_specifier_seq *, enum rid);
+  (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
 static void cp_parser_set_decl_spec_type
   (cp_decl_specifier_seq *, tree, bool);
 static bool cp_parser_friend_p
@@ -1960,7 +1960,7 @@ static enum tag_types cp_parser_token_is_class_key
 static void cp_parser_check_class_key
   (enum tag_types, tree type);
 static void cp_parser_check_access_in_redeclaration
-  (tree type);
+  (tree type, location_t location);
 static bool cp_parser_optional_template_keyword
   (cp_parser *);
 static void cp_parser_pre_parsed_nested_name_specifier
@@ -1982,7 +1982,7 @@ static bool cp_parser_uncommitted_to_tentative_parse_p
 static void cp_parser_error
   (cp_parser *, const char *);
 static void cp_parser_name_lookup_error
-  (cp_parser *, tree, tree, const char *);
+  (cp_parser *, tree, tree, const char *, location_t);
 static bool cp_parser_simulate_error
   (cp_parser *);
 static bool cp_parser_check_type_definition
@@ -1994,7 +1994,7 @@ static void cp_parser_check_for_invalid_template_id
 static bool cp_parser_non_integral_constant_expression
   (cp_parser *, const char *);
 static void cp_parser_diagnose_invalid_type_name
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t);
 static bool cp_parser_parse_and_diagnose_invalid_type_name
   (cp_parser *);
 static int cp_parser_skip_to_closing_parenthesis
@@ -2020,7 +2020,7 @@ static bool cp_parser_is_string_literal
 static bool cp_parser_is_keyword
   (cp_token *, enum rid);
 static tree cp_parser_make_typename_type
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t location);
 static cp_declarator * cp_parser_make_indirect_declarator
   (enum tree_code, tree, cp_cv_quals, cp_declarator *);
 
@@ -2069,7 +2069,7 @@ cp_parser_error (cp_parser* parser, const char* message)
 
       if (token->type == CPP_PRAGMA)
 	{
-	  error ("%<#pragma%> is not allowed here");
+	  error ("%H%<#pragma%> is not allowed here", &token->location);
 	  cp_parser_skip_to_pragma_eol (parser, token);
 	  return;
 	}
@@ -2092,33 +2092,34 @@ static void
 cp_parser_name_lookup_error (cp_parser* parser,
 			     tree name,
 			     tree decl,
-			     const char* desired)
+			     const char* desired,
+			     location_t location)
 {
   /* If name lookup completely failed, tell the user that NAME was not
      declared.  */
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-	error ("%<%E::%E%> has not been declared",
-	       parser->scope, name);
+	error ("%H%<%E::%E%> has not been declared",
+	       &location, parser->scope, name);
       else if (parser->scope == global_namespace)
-	error ("%<::%E%> has not been declared", name);
+	error ("%H%<::%E%> has not been declared", &location, name);
       else if (parser->object_scope
 	       && !CLASS_TYPE_P (parser->object_scope))
-	error ("request for member %qE in non-class type %qT",
-	       name, parser->object_scope);
+	error ("%Hrequest for member %qE in non-class type %qT",
+	       &location, name, parser->object_scope);
       else if (parser->object_scope)
-	error ("%<%T::%E%> has not been declared",
-	       parser->object_scope, name);
+	error ("%H%<%T::%E%> has not been declared",
+	       &location, parser->object_scope, name);
       else
-	error ("%qE has not been declared", name);
+	error ("%H%qE has not been declared", &location, name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("%<%E::%E%> %s", parser->scope, name, desired);
+    error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
   else if (parser->scope == global_namespace)
-    error ("%<::%E%> %s", name, desired);
+    error ("%H%<::%E%> %s", &location, name, desired);
   else
-    error ("%qE %s", name, desired);
+    error ("%H%qE %s", &location, name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -2139,7 +2140,8 @@ cp_parser_simulate_error (cp_parser* parser)
 /* Check for repeated decl-specifiers.  */
 
 static void
-cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
+cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
+			   location_t location)
 {
   cp_decl_spec ds;
 
@@ -2152,10 +2154,11 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
       if (ds == ds_long)
 	{
 	  if (count > 2)
-	    error ("%<long long long%> is too long for GCC");
+	    error ("%H%<long long long%> is too long for GCC", &location);
 	  else if (pedantic && !in_system_header && warn_long_long
                    && cxx_dialect == cxx98)
-	    pedwarn ("ISO C++ 1998 does not support %<long long%>");
+	    pedwarn ("%HISO C++ 1998 does not support %<long long%>",
+		     &location);
 	}
       else if (count > 1)
 	{
@@ -2175,7 +2178,7 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
 	    "__complex",
 	    "__thread"
 	  };
-	  error ("duplicate %qs", decl_spec_names[(int)ds]);
+	  error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
 	}
     }
 }
@@ -2291,13 +2294,15 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
    in duplicate error messages.)  */
 
 static void
-cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
+cp_parser_diagnose_invalid_type_name (cp_parser *parser,
+				      tree scope, tree id,
+				      location_t id_location)
 {
   tree decl, old_scope;
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
-  decl = cp_parser_lookup_name_simple (parser, id);
+  decl = cp_parser_lookup_name_simple (parser, id, id_location);
   parser->scope = old_scope;
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
@@ -2382,6 +2387,7 @@ static bool
 cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
 {
   tree id;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   cp_parser_parse_tentatively (parser);
   id = cp_parser_id_expression (parser,
@@ -2405,7 +2411,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
-  cp_parser_diagnose_invalid_type_name (parser, parser->scope, id);
+  cp_parser_diagnose_invalid_type_name (parser, parser->scope,
+					id, token->location);
   /* Skip to the end of the declaration; there's no point in
      trying to process it.  */
   cp_parser_skip_to_end_of_block_or_statement (parser);
@@ -2693,7 +2700,8 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok)
    using cp_parser_diagnose_invalid_type_name.  */
 
 static tree
-cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
+cp_parser_make_typename_type (cp_parser *parser, tree scope,
+			      tree id, location_t id_location)
 {
   tree result;
   if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -2701,7 +2709,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
       result = make_typename_type (scope, id, typename_type,
 				   /*complain=*/tf_none);
       if (result == error_mark_node)
-	cp_parser_diagnose_invalid_type_name (parser, scope, id);
+	cp_parser_diagnose_invalid_type_name (parser, scope, id, id_location);
       return result;
     }
   return make_typename_type (scope, id, typename_type, tf_error);
@@ -2919,7 +2927,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
 	      if (type == CPP_STRING)
 		type = tok->type;
 	      else if (tok->type != CPP_STRING)
-		error ("unsupported non-standard concatenation of string literals");
+		error ("%Hunsupported non-standard concatenation "
+                       "of string literals", &tok->location);
 	    }
 
 	  obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -3098,7 +3107,7 @@ cp_parser_primary_expression (cp_parser *parser,
 			      bool template_arg_p,
 			      cp_id_kind *idk)
 {
-  cp_token *token;
+  cp_token *token = NULL;
 
   /* Assume the primary expression is not an id-expression.  */
   *idk = CP_ID_KIND_NONE;
@@ -3196,7 +3205,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  {
 	    /* Statement-expressions are not allowed by the standard.  */
 	    if (pedantic)
-	      pedwarn ("ISO C++ forbids braced-groups within expressions");
+	      pedwarn ("%HISO C++ forbids braced-groups within expressions",
+		       &token->location);
 
 	    /* And they're not allowed outside of a function-body; you
 	       cannot, for example, write:
@@ -3207,8 +3217,9 @@ cp_parser_primary_expression (cp_parser *parser,
 	    if (!parser->in_function_body
 		|| parser->in_template_argument_list_p)
 	      {
-		error ("statement-expressions are not allowed outside "
-		       "functions nor in template-argument lists");
+		error ("%Hstatement-expressions are not allowed outside "
+		       "functions nor in template-argument lists",
+		       &token->location);
 		cp_parser_skip_to_end_of_block_or_statement (parser);
 		expr = error_mark_node;
 	      }
@@ -3265,7 +3276,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  cp_lexer_consume_token (parser->lexer);
 	  if (parser->local_variables_forbidden_p)
 	    {
-	      error ("%<this%> may not be used in this context");
+	      error ("%H%<this%> may not be used in this context",
+                     &token->location);
 	      return error_mark_node;
 	    }
 	  /* Pointers cannot appear in constant-expressions.  */
@@ -3365,6 +3377,7 @@ cp_parser_primary_expression (cp_parser *parser,
 	const char *error_msg;
 	bool template_p;
 	bool done;
+	cp_token *id_expr_token;
 
       id_expression:
 	/* Parse the id-expression.  */
@@ -3377,6 +3390,7 @@ cp_parser_primary_expression (cp_parser *parser,
 				     /*optional_p=*/false);
 	if (id_expression == error_mark_node)
 	  return error_mark_node;
+	id_expr_token = token;
 	token = cp_lexer_peek_token (parser->lexer);
 	done = (token->type != CPP_OPEN_SQUARE
 		&& token->type != CPP_OPEN_PAREN
@@ -3400,7 +3414,8 @@ cp_parser_primary_expression (cp_parser *parser,
 					  template_p,
 					  /*is_namespace=*/false,
 					  /*check_dependency=*/true,
-					  &ambiguous_decls);
+					  &ambiguous_decls,
+					  id_expr_token->location);
 	    /* If the lookup was ambiguous, an error will already have
 	       been issued.  */
 	    if (ambiguous_decls)
@@ -3447,8 +3462,8 @@ cp_parser_primary_expression (cp_parser *parser,
 		decl = check_for_out_of_scope_variable (decl);
 		if (local_variable_p (decl))
 		  {
-		    error ("local variable %qD may not appear in this context",
-			   decl);
+		    error ("%Hlocal variable %qD may not appear in this context",
+			   &id_expr_token->location, decl);
 		    return error_mark_node;
 		  }
 	      }
@@ -3462,7 +3477,8 @@ cp_parser_primary_expression (cp_parser *parser,
 		 &parser->non_integral_constant_expression_p,
 		 template_p, done, address_p,
 		 template_arg_p,
-		 &error_msg));
+		 &error_msg,
+                 id_expr_token->location));
 	if (error_msg)
 	  cp_parser_error (parser, error_msg);
 	return decl;
@@ -3746,7 +3762,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	      error ("scope %qT before %<~%> is not a class-name", scope);
+	      error ("%Hscope %qT before %<~%> is not a class-name",
+		     &token->location, scope);
 	    cp_parser_simulate_error (parser);
 	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
 	      cp_lexer_consume_token (parser->lexer);
@@ -3847,8 +3864,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	if (declarator_p && scope && !check_dtor_name (scope, type_decl))
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	      error ("declaration of %<~%T%> as member of %qT",
-		     type_decl, scope);
+	      error ("%Hdeclaration of %<~%T%> as member of %qT",
+		     &token->location, type_decl, scope);
 	    cp_parser_simulate_error (parser);
 	    return error_mark_node;
 	  }
@@ -3861,8 +3878,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	    && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
 	    && !DECL_SELF_REFERENCE_P (type_decl)
 	    && !cp_parser_uncommitted_to_tentative_parse_p (parser))
-	  error ("typedef-name %qD used as destructor declarator",
-		 type_decl);
+	  error ("%Htypedef-name %qD used as destructor declarator",
+		 &token->location, type_decl);
 
 	return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
@@ -4066,20 +4083,23 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
 						    /*is_template=*/false,
 						    /*is_namespace=*/false,
 						    /*check_dependency=*/true,
-						    &ambiguous_decls);
+						    &ambiguous_decls,
+						    token->location);
 		      if (TREE_CODE (decl) == TEMPLATE_DECL)
-			error ("%qD used without template parameters", decl);
+			error ("%H%qD used without template parameters",
+			       &token->location, decl);
 		      else if (ambiguous_decls)
 			{
-			  error ("reference to %qD is ambiguous",
-				 token->u.value);
+			  error ("%Hreference to %qD is ambiguous",
+				 &token->location, token->u.value);
 			  print_candidates (ambiguous_decls);
 			  decl = error_mark_node;
 			}
 		      else
 			cp_parser_name_lookup_error
 			  (parser, token->u.value, decl,
-			   "is not a class or namespace");
+			   "is not a class or namespace",
+			   token->location);
 		    }
 		  parser->scope = error_mark_node;
 		  error_p = true;
@@ -4731,7 +4751,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	  postfix_expression
 	    = cp_parser_postfix_dot_deref_expression (parser, token->type,
 						      postfix_expression,
-						      false, &idk);
+						      false, &idk,
+						      token->location);
 
           is_member_access = true;
 	  break;
@@ -4845,7 +4866,8 @@ static tree
 cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 					enum cpp_ttype token_type,
 					tree postfix_expression,
-					bool for_offsetof, cp_id_kind *idk)
+					bool for_offsetof, cp_id_kind *idk,
+					location_t location)
 {
   tree name;
   bool dependent_p;
@@ -4877,7 +4899,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
 	{
-	  error ("%qE does not have class type", postfix_expression);
+	  error ("%H%qE does not have class type", &location, postfix_expression);
 	  scope = NULL_TREE;
 	}
       else
@@ -4933,6 +4955,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 ordinary class member access expression, rather than a
 	 pseudo-destructor-name.  */
       bool template_p;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
       /* Parse the id-expression.  */
       name = (cp_parser_id_expression
 	      (parser,
@@ -4960,7 +4983,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 TYPE_DECL here.  That is invalid code.  */
       if (TREE_CODE (name) == TYPE_DECL)
 	{
-	  error ("invalid use of %qD", name);
+	  error ("%Hinvalid use of %qD", &token->location, name);
 	  postfix_expression = error_mark_node;
 	}
       else
@@ -5514,18 +5537,21 @@ cp_parser_new_expression (cp_parser* parser)
      type-id.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
+      cp_token *token;
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the type-id.  */
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      token = cp_lexer_peek_token (parser->lexer);
       /* There should not be a direct-new-declarator in this production,
 	 but GCC used to allowed this, so we check and emit a sensible error
 	 message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
 	{
-	  error ("array bound forbidden after parenthesized type-id");
+	  error ("%Harray bound forbidden after parenthesized type-id",
+		 &token->location);
 	  inform ("try removing the parentheses around the type-id");
 	  cp_parser_direct_new_declarator (parser);
 	}
@@ -5702,6 +5728,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       /* The first expression is not required to be constant.  */
       if (!declarator)
 	{
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
 	  expression = cp_parser_expression (parser, /*cast_p=*/false);
 	  /* The standard requires that the expression have integral
 	     type.  DR 74 adds enumeration types.  We believe that the
@@ -5717,8 +5744,8 @@ cp_parser_direct_new_declarator (cp_parser* parser)
 					      /*complain=*/true);
 	      if (!expression)
 		{
-		  error ("expression in new-declarator must have integral "
-			 "or enumeration type");
+		  error ("%Hexpression in new-declarator must have integral "
+			 "or enumeration type", &token->location);
 		  expression = error_mark_node;
 		}
 	    }
@@ -6445,6 +6472,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   int save_ice_p, save_non_ice_p;
   tree type, expr;
   cp_id_kind dummy;
+  cp_token *token;
 
   /* We're about to accept non-integral-constant things, but will
      definitely yield an integral constant expression.  Save and
@@ -6460,6 +6488,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
   cp_parser_require (parser, CPP_COMMA, "%<,%>");
+  token = cp_lexer_peek_token (parser->lexer);
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
   expr = build_static_cast (build_pointer_type (type), null_pointer_node,
@@ -6467,10 +6496,10 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 
   /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
   expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
-						 true, &dummy);
+						 true, &dummy, token->location);
   while (true)
     {
-      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
       switch (token->type)
 	{
 	case CPP_OPEN_SQUARE:
@@ -6482,7 +6511,8 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 	  /* offsetof-member-designator "." identifier */
 	  cp_lexer_consume_token (parser->lexer);
 	  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
-							 true, &dummy);
+							 true, &dummy,
+							 token->location);
 	  break;
 
 	case CPP_CLOSE_PAREN:
@@ -6844,7 +6874,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
 	if (parser->in_switch_statement_p)
 	  finish_case_label (expr, expr_hi);
 	else
-	  error ("case label %qE not within a switch statement", expr);
+	  error ("%Hcase label %qE not within a switch statement",
+		 &token->location, expr);
       }
       break;
 
@@ -6855,7 +6886,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
       if (parser->in_switch_statement_p)
 	finish_case_label (NULL_TREE, NULL_TREE);
       else
-	error ("case label not within a switch statement");
+	error ("%Hcase label not within a switch statement", &token->location);
       break;
 
     default:
@@ -6973,7 +7004,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
 	  else
 	    {
 	      token = cp_lexer_consume_token (parser->lexer);
-	      error ("%<else%> without a previous %<if%>");
+	      error ("%H%<else%> without a previous %<if%>", &token->location);
 	    }
 	}
 
@@ -7457,7 +7488,7 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (in_statement)
 	{
 	case 0:
-	  error ("break statement not within loop or switch");
+	  error ("%Hbreak statement not within loop or switch", &token->location);
 	  break;
 	default:
 	  gcc_assert ((in_statement & IN_SWITCH_STMT)
@@ -7465,10 +7496,10 @@ cp_parser_jump_statement (cp_parser* parser)
 	  statement = finish_break_stmt ();
 	  break;
 	case IN_OMP_BLOCK:
-	  error ("invalid exit from OpenMP structured block");
+	  error ("%Hinvalid exit from OpenMP structured block", &token->location);
 	  break;
 	case IN_OMP_FOR:
-	  error ("break statement used with OpenMP for loop");
+	  error ("%Hbreak statement used with OpenMP for loop", &token->location);
 	  break;
 	}
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
@@ -7478,14 +7509,14 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
 	{
 	case 0:
-	  error ("continue statement not within a loop");
+	  error ("%Hcontinue statement not within a loop", &token->location);
 	  break;
 	case IN_ITERATION_STMT:
 	case IN_OMP_FOR:
 	  statement = finish_continue_stmt ();
 	  break;
 	case IN_OMP_BLOCK:
-	  error ("invalid exit from OpenMP structured block");
+	  error ("%Hinvalid exit from OpenMP structured block", &token->location);
 	  break;
 	default:
 	  gcc_unreachable ();
@@ -7516,7 +7547,7 @@ cp_parser_jump_statement (cp_parser* parser)
 	{
 	  /* Issue a warning about this use of a GNU extension.  */
 	  if (pedantic)
-	    pedwarn ("ISO C++ forbids computed gotos");
+	    pedwarn ("%HISO C++ forbids computed gotos", &token->location);
 	  /* Consume the '*' token.  */
 	  cp_lexer_consume_token (parser->lexer);
 	  /* Parse the dependent expression.  */
@@ -7877,7 +7908,7 @@ cp_parser_block_declaration (cp_parser *parser,
   else if (token1->keyword == RID_LABEL)
     {
       cp_lexer_consume_token (parser->lexer);
-      error ("%<__label__%> not at the beginning of a block");
+      error ("%H%<__label__%> not at the beginning of a block", &token1->location);
       cp_parser_skip_to_end_of_statement (parser);
       /* If the next token is now a `;', consume it.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -8010,7 +8041,11 @@ cp_parser_simple_declaration (cp_parser* parser,
 
 	     which is erroneous.  */
 	  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-	    error ("mixing declarations and function-definitions is forbidden");
+	    {
+	      cp_token *token = cp_lexer_peek_token (parser->lexer);
+	      error ("%Hmixing declarations and function-definitions is forbidden",
+		     &token->location);
+	    }
 	  /* Otherwise, we're done with the list of declarators.  */
 	  else
 	    {
@@ -8106,6 +8141,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 			      int* declares_class_or_enum)
 {
   bool constructor_possible_p = !parser->in_declarator_p;
+  cp_token *start_token = NULL;
 
   /* Clear DECL_SPECS.  */
   clear_decl_specs (decl_specs);
@@ -8122,6 +8158,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
+
+      /* Save the first token of the decl spec list for error
+         reporting.  */
+      if (!start_token)
+	start_token = token;
       /* Handle attributes.  */
       if (token->keyword == RID_ATTRIBUTE)
 	{
@@ -8198,15 +8239,17 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
                  we're complaining about C++0x compatibility.  */
               warning 
                 (OPT_Wc__0x_compat, 
-                 "%<auto%> will change meaning in C++0x; please remove it");
+                 "%H%<auto%> will change meaning in C++0x; please remove it",
+		 &token->location);
 
               /* Set the storage class anyway.  */
-              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO);
+              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
+					   token->location);
             }
           else 
             /* We do not yet support the use of `auto' as a
                type-specifier.  */
-            error ("C++0x %<auto%> specifier not supported");
+            error ("%HC++0x %<auto%> specifier not supported", &token->location);
           break;
 
 	case RID_REGISTER:
@@ -8215,7 +8258,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 	case RID_MUTABLE:
 	  /* Consume the token.  */
 	  cp_lexer_consume_token (parser->lexer);
-          cp_parser_set_storage_class (parser, decl_specs, token->keyword);
+          cp_parser_set_storage_class (parser, decl_specs, token->keyword,
+				       token->location);
 	  break;
 	case RID_THREAD:
 	  /* Consume the token.  */
@@ -8251,7 +8295,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 					/*is_declaration=*/true,
 					&decl_spec_declares_class_or_enum,
 					&is_cv_qualifier);
-
 	  *declares_class_or_enum |= decl_spec_declares_class_or_enum;
 
 	  /* If this type-specifier referenced a user-defined type
@@ -8311,12 +8354,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
-  cp_parser_check_decl_spec (decl_specs);
+  cp_parser_check_decl_spec (decl_specs, start_token->location);
 
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
-    error ("class definition may not be declared a friend");
+    error ("%Hclass definition may not be declared a friend",
+	    &start_token->location);
 }
 
 /* Parse an (optional) storage-class-specifier.
@@ -8372,7 +8416,8 @@ static tree
 cp_parser_function_specifier_opt (cp_parser* parser,
 				  cp_decl_specifier_seq *decl_specs)
 {
-  switch (cp_lexer_peek_token (parser->lexer)->keyword)
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  switch (token->keyword)
     {
     case RID_INLINE:
       if (decl_specs)
@@ -8384,7 +8429,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
 
 	 A member function template shall not be virtual.  */
       if (PROCESSING_REAL_TEMPLATE_DECL_P ())
-	error ("templates may not be %<virtual%>");
+	error ("%Htemplates may not be %<virtual%>", &token->location);
       else if (decl_specs)
 	++decl_specs->specs[(int) ds_virtual];
       break;
@@ -8538,6 +8583,7 @@ cp_parser_decltype (cp_parser *parser)
   const char *saved_message;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
+  cp_token *id_expr_start_token;
 
   /* Look for the `decltype' token.  */
   if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
@@ -8567,6 +8613,7 @@ cp_parser_decltype (cp_parser *parser)
     return error_mark_node;
   
   /* First, try parsing an id-expression.  */
+  id_expr_start_token = cp_lexer_peek_token (parser->lexer);
   cp_parser_parse_tentatively (parser);
   expr = cp_parser_id_expression (parser,
                                   /*template_keyword_p=*/false,
@@ -8589,7 +8636,8 @@ cp_parser_decltype (cp_parser *parser)
 				      /*is_template=*/false,
 				      /*is_namespace=*/false,
 				      /*check_dependency=*/true,
-				      /*ambiguous_decls=*/NULL);
+				      /*ambiguous_decls=*/NULL,
+				      id_expr_start_token->location);
 
       if (expr
           && expr != error_mark_node
@@ -8609,7 +8657,8 @@ cp_parser_decltype (cp_parser *parser)
                    /*done=*/true,
                    /*address_p=*/false,
                    /*template_arg_p=*/false,
-                   &error_msg));
+                   &error_msg,
+		   id_expr_start_token->location));
 
           if (expr == error_mark_node)
             /* We found an id-expression, but it was something that we
@@ -8852,17 +8901,20 @@ static void
 cp_parser_mem_initializer_list (cp_parser* parser)
 {
   tree mem_initializer_list = NULL_TREE;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Let the semantic analysis code know that we are starting the
      mem-initializer-list.  */
   if (!DECL_CONSTRUCTOR_P (current_function_decl))
-    error ("only constructors take base initializers");
+    error ("%Honly constructors take base initializers",
+	   &token->location);
 
   /* Loop through the list.  */
   while (true)
     {
       tree mem_initializer;
 
+      token = cp_lexer_peek_token (parser->lexer);
       /* Parse the mem-initializer.  */
       mem_initializer = cp_parser_mem_initializer (parser);
       /* If the next token is a `...', we're expanding member initializers. */
@@ -8876,8 +8928,8 @@ cp_parser_mem_initializer_list (cp_parser* parser)
           if (mem_initializer != error_mark_node
               && !TYPE_P (TREE_PURPOSE (mem_initializer)))
             {
-              error ("cannot expand initializer for member %<%D%>", 
-                     TREE_PURPOSE (mem_initializer));
+              error ("%Hcannot expand initializer for member %<%D%>",
+                     &token->location, TREE_PURPOSE (mem_initializer));
               mem_initializer = error_mark_node;
             }
 
@@ -8924,11 +8976,13 @@ cp_parser_mem_initializer (cp_parser* parser)
   tree mem_initializer_id;
   tree expression_list;
   tree member;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
-      permerror ("anachronistic old-style base class initializer");
+      permerror ("%Hanachronistic old-style base class initializer",
+                 &token->location);
       mem_initializer_id = NULL_TREE;
     }
   else
@@ -8970,11 +9024,14 @@ cp_parser_mem_initializer_id (cp_parser* parser)
   bool template_p = false;
   tree id;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* `typename' is not allowed in this context ([temp.res]).  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
-      error ("keyword %<typename%> not allowed in this context (a qualified "
-	     "member initializer is implicitly a type)");
+      error ("%Hkeyword %<typename%> not allowed in this context (a qualified "
+	     "member initializer is implicitly a type)",
+	     &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the optional `::' operator.  */
@@ -9491,6 +9548,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	 appropriate diagnostic here.  */
 
       /* Consume the `='.  */
+      cp_token *start_token = cp_lexer_peek_token (parser->lexer);
       cp_lexer_consume_token (parser->lexer);
       
       /* Find the name of the parameter pack.  */     
@@ -9499,10 +9557,11 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	id_declarator = id_declarator->declarator;
       
       if (id_declarator && id_declarator->kind == cdk_id)
-	error ("template parameter pack %qD cannot have a default argument",
-	       id_declarator->u.id.unqualified_name);
+	error ("%Htemplate parameter pack %qD cannot have a default argument",
+	       &start_token->location, id_declarator->u.id.unqualified_name);
       else
-	error ("template parameter pack cannot have a default argument");
+	error ("%Htemplate parameter pack cannot have a default argument",
+	       &start_token->location);
       
       /* Parse the default argument, but throw away the result.  */
       cp_parser_default_argument (parser, /*template_parm_p=*/true);
@@ -9596,10 +9655,11 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("template parameter pack %qD cannot have a default argument", 
-                         identifier);
+                  error ("%Htemplate parameter pack %qD cannot have a "
+			 "default argument", &token->location, identifier);
                 else
-                  error ("template parameter packs cannot have default arguments");
+                  error ("%Htemplate parameter packs cannot have "
+			 "default arguments", &token->location);
                 default_argument = NULL_TREE;
               }
 	    pop_deferring_access_checks ();
@@ -9667,6 +9727,9 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 	    cp_lexer_consume_token (parser->lexer);
 	    /* Parse the id-expression.  */
 	    push_deferring_access_checks (dk_no_deferred);
+	    /* save token before parsing the id-expression, for error
+	       reporting */
+	    token = cp_lexer_peek_token (parser->lexer);
 	    default_argument
 	      = cp_parser_id_expression (parser,
 					 /*template_keyword_p=*/false,
@@ -9687,7 +9750,8 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 					 /*is_template=*/is_template,
 					 /*is_namespace=*/false,
 					 /*check_dependency=*/true,
-					 /*ambiguous_decls=*/NULL);
+					 /*ambiguous_decls=*/NULL,
+					 token->location);
 	    /* See if the default argument is valid.  */
 	    default_argument
 	      = check_template_template_default_arg (default_argument);
@@ -9697,10 +9761,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("template parameter pack %qD cannot have a default argument", 
-                         identifier);
+                  error ("%Htemplate parameter pack %qD cannot "
+			 "have a default argument",
+			 &token->location, identifier);
                 else
-                  error ("template parameter packs cannot have default arguments");
+                  error ("%Htemplate parameter packs cannot "
+			 "have default arguments",
+			 &token->location);
                 default_argument = NULL_TREE;
               }
 	    pop_deferring_access_checks ();
@@ -9749,7 +9816,7 @@ cp_parser_template_id (cp_parser *parser,
   cp_token_position start_of_id = 0;
   deferred_access_check *chk;
   VEC (deferred_access_check,gc) *access_check;
-  cp_token *next_token, *next_token_2;
+  cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
   bool is_identifier;
 
   /* If the next token corresponds to a template-id, there is no need
@@ -9797,6 +9864,7 @@ cp_parser_template_id (cp_parser *parser,
 
   /* Parse the template-name.  */
   is_identifier = false;
+  token = cp_lexer_peek_token (parser->lexer);
   template = cp_parser_template_name (parser, template_keyword_p,
 				      check_dependency_p,
 				      is_declaration,
@@ -9823,6 +9891,7 @@ cp_parser_template_id (cp_parser *parser,
       /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
 	 CPP_LESS.  */
       cp_lexer_consume_token (parser->lexer);
+
       /* Parse the arguments.  */
       arguments = cp_parser_enclosed_template_argument_list (parser);
       if (!cp_parser_parse_definitely (parser))
@@ -9837,15 +9906,18 @@ cp_parser_template_id (cp_parser *parser,
 	}
       /* Otherwise, emit an error about the invalid digraph, but continue
 	 parsing because we got our argument list.  */
-      permerror ("%<<::%> cannot begin a template-argument list");
-      inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
-	      "between %<<%> and %<::%>");
+      permerror ("%H%<<::%> cannot begin a template-argument list",
+		 &next_token->location);
+      inform ("%H%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
+	      "between %<<%> and %<::%>",
+	      &next_token->location);
       if (!flag_permissive)
 	{
 	  static bool hint;
 	  if (!hint)
 	    {
-	      inform ("(if you use %<-fpermissive%> G++ will accept your code)");
+	      inform ("%H(if you use %<-fpermissive%> G++ will accept your code)",
+                      &next_token->location);
 	      hint = true;
 	    }
 	}
@@ -9918,7 +9990,8 @@ cp_parser_template_id (cp_parser *parser,
 	 user, as opposed to simply marking the tentative parse as
 	 failed?  */
       if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
-	error ("parse error in template argument list");
+	error ("%Hparse error in template argument list",
+	       &token->location);
     }
 
   pop_deferring_access_checks ();
@@ -9972,6 +10045,7 @@ cp_parser_template_name (cp_parser* parser,
   tree identifier;
   tree decl;
   tree fns;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* If the next token is `operator', then we have either an
      operator-function-id or a conversion-function-id.  */
@@ -10031,7 +10105,8 @@ cp_parser_template_name (cp_parser* parser,
 	  cp_token_position start = 0;
 
 	  /* Explain what went wrong.  */
-	  error ("non-template %qD used as template", identifier);
+	  error ("%Hnon-template %qD used as template",
+		 &token->location, identifier);
 	  inform ("use %<%T::template %D%> to indicate that it is a template",
 		  parser->scope, identifier);
 	  /* If parsing tentatively, find the location of the "<" token.  */
@@ -10075,7 +10150,8 @@ cp_parser_template_name (cp_parser* parser,
 				/*is_template=*/false,
 				/*is_namespace=*/false,
 				check_dependency_p,
-				/*ambiguous_decls=*/NULL);
+				/*ambiguous_decls=*/NULL,
+				token->location);
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
@@ -10221,7 +10297,7 @@ cp_parser_template_argument (cp_parser* parser)
   bool template_p;
   bool address_p;
   bool maybe_type_id = false;
-  cp_token *token;
+  cp_token *token = NULL, *argument_start_token = NULL;
   cp_id_kind idk;
 
   /* There's really no way to know what we're looking at, so we just
@@ -10268,6 +10344,7 @@ cp_parser_template_argument (cp_parser* parser)
   /* We're still not sure what the argument will be.  */
   cp_parser_parse_tentatively (parser);
   /* Try a template.  */
+  argument_start_token = cp_lexer_peek_token (parser->lexer);
   argument = cp_parser_id_expression (parser,
 				      /*template_keyword_p=*/false,
 				      /*check_dependency_p=*/true,
@@ -10290,7 +10367,8 @@ cp_parser_template_argument (cp_parser* parser)
 					  /*is_template=*/template_p,
 					  /*is_namespace=*/false,
 					  /*check_dependency=*/true,
-					  /*ambiguous_decls=*/NULL);
+					  /*ambiguous_decls=*/NULL,
+					  argument_start_token->location);
       if (TREE_CODE (argument) != TEMPLATE_DECL
 	  && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
 	cp_parser_error (parser, "expected template-name");
@@ -10542,6 +10620,8 @@ static void
 cp_parser_explicit_specialization (cp_parser* parser)
 {
   bool need_lang_pop;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `template' keyword.  */
   cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Look for the `<'.  */
@@ -10556,7 +10636,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
      linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template specialization with C linkage");
+      error ("%Htemplate specialization with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
 	 front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -10881,7 +10961,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
           cp_lexer_consume_token (parser->lexer);
           /* We do not yet support the use of `auto' as a
              type-specifier.  */
-          error ("C++0x %<auto%> specifier not supported");
+          error ("%HC++0x %<auto%> specifier not supported", &token->location);
         }
       break;
 
@@ -11094,12 +11174,13 @@ cp_parser_nonclass_name (cp_parser* parser)
   tree type_decl;
   tree identifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
     return error_mark_node;
 
   /* Look up the type-name.  */
-  type_decl = cp_parser_lookup_name_simple (parser, identifier);
+  type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
 
   if (TREE_CODE (type_decl) != TYPE_DECL
       && (objc_is_id (identifier) || objc_is_class_name (identifier)))
@@ -11116,7 +11197,7 @@ cp_parser_nonclass_name (cp_parser* parser)
     {
       if (!cp_parser_simulate_error (parser))
 	cp_parser_name_lookup_error (parser, identifier, type_decl,
-				     "is not a type");
+				     "is not a type", token->location);
       return error_mark_node;
     }
   /* Remember that the name was used in the definition of the
@@ -11165,6 +11246,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
   tree identifier;
   tree type = NULL_TREE;
   tree attributes = NULL_TREE;
+  cp_token *token = NULL;
 
   /* See if we're looking at the `enum' keyword.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM))
@@ -11234,6 +11316,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (!template_p)
 	cp_parser_parse_tentatively (parser);
       /* Parse the template-id.  */
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_template_id (parser, template_p,
 				    /*check_dependency_p=*/true,
 				    is_declaration);
@@ -11255,6 +11338,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
   if (!type)
     {
+      token = cp_lexer_peek_token (parser->lexer);
       identifier = cp_parser_identifier (parser);
 
       if (identifier == error_mark_node)
@@ -11267,7 +11351,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (tag_type == typename_type
 	  && TREE_CODE (parser->scope) != NAMESPACE_DECL)
 	return cp_parser_make_typename_type (parser, parser->scope,
-					     identifier);
+					     identifier,
+					     token->location);
       /* Look up a qualified name in the usual way.  */
       if (parser->scope)
 	{
@@ -11279,7 +11364,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 					/*is_template=*/false,
 					/*is_namespace=*/false,
 					/*check_dependency=*/true,
-					&ambiguous_decls);
+					&ambiguous_decls,
+					token->location);
 
 	  /* If the lookup was ambiguous, an error will already have been
 	     issued.  */
@@ -11315,7 +11401,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	    {
 	      cp_parser_diagnose_invalid_type_name (parser,
 						    parser->scope,
-						    identifier);
+						    identifier,
+						    token->location);
 	      return error_mark_node;
 	    }
 
@@ -11415,7 +11502,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	  /* An unqualified name was used to reference this type, so
 	     there were no qualifying templates.  */
 	  if (!cp_parser_check_template_parameters (parser,
-						    /*num_templates=*/0))
+						    /*num_templates=*/0,
+						    token->location))
 	    return error_mark_node;
 	  type = xref_tag (tag_type, identifier, ts, template_p);
 	}
@@ -11618,6 +11706,8 @@ cp_parser_namespace_name (cp_parser* parser)
   tree identifier;
   tree namespace_decl;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Get the name of the namespace.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
@@ -11646,13 +11736,14 @@ cp_parser_namespace_name (cp_parser* parser)
 					  /*is_template=*/false,
 					  /*is_namespace=*/true,
 					  /*check_dependency=*/true,
-					  /*ambiguous_decls=*/NULL);
+					  /*ambiguous_decls=*/NULL,
+					  token->location);
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
     {
       if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	error ("%qD is not a namespace-name", identifier);
+	error ("%H%qD is not a namespace-name", &token->location, identifier);
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
@@ -11767,6 +11858,8 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   tree identifier;
   tree namespace_specifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the identifier.  */
@@ -11777,7 +11870,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
       && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) 
     {
-      error ("%<namespace%> definition is not allowed here");
+      error ("%H%<namespace%> definition is not allowed here", &token->location);
       /* Skip the definition.  */
       cp_lexer_consume_token (parser->lexer);
       if (cp_parser_skip_to_closing_brace (parser))
@@ -11892,6 +11985,7 @@ cp_parser_using_declaration (cp_parser* parser,
        cp_parser_parse_definitely will be false, as required.  */
     return cp_parser_parse_definitely (parser);
 
+  token = cp_lexer_peek_token (parser->lexer);
   /* Parse the unqualified-id.  */
   identifier = cp_parser_unqualified_id (parser,
 					 /*template_keyword_p=*/false,
@@ -11916,7 +12010,8 @@ cp_parser_using_declaration (cp_parser* parser,
     /* [namespace.udecl]
 
        A using declaration shall not name a template-id.  */
-    error ("a template-id may not appear in a using-declaration");
+    error ("%Ha template-id may not appear in a using-declaration",
+            &token->location);
   else
     {
       if (at_class_scope_p ())
@@ -11932,9 +12027,13 @@ cp_parser_using_declaration (cp_parser* parser,
 	}
       else
 	{
-	  decl = cp_parser_lookup_name_simple (parser, identifier);
+	  decl = cp_parser_lookup_name_simple (parser,
+					       identifier,
+					       token->location);
 	  if (decl == error_mark_node)
-	    cp_parser_name_lookup_error (parser, identifier, decl, NULL);
+	    cp_parser_name_lookup_error (parser, identifier,
+					 decl, NULL,
+					 token->location);
 	  else if (check_for_bare_parameter_packs (decl))
 	    return false;
 	  else if (!at_namespace_scope_p ())
@@ -12184,7 +12283,8 @@ cp_parser_init_declarator (cp_parser* parser,
 			   int declares_class_or_enum,
 			   bool* function_definition_p)
 {
-  cp_token *token;
+  cp_token *token = NULL, *asm_spec_start_token = NULL,
+           *attributes_start_token = NULL;
   cp_declarator *declarator;
   tree prefix_attributes;
   tree attributes;
@@ -12218,6 +12318,7 @@ cp_parser_init_declarator (cp_parser* parser,
   resume_deferring_access_checks ();
 
   /* Parse the declarator.  */
+  token = cp_lexer_peek_token (parser->lexer);
   declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
 			    &ctor_dtor_or_conv_p,
@@ -12232,7 +12333,8 @@ cp_parser_init_declarator (cp_parser* parser,
     return error_mark_node;
 
   /* Check that the number of template-parameter-lists is OK.  */
-  if (!cp_parser_check_declarator_template_parameters (parser, declarator))
+  if (!cp_parser_check_declarator_template_parameters (parser, declarator,
+						       token->location))
     return error_mark_node;
 
   if (declares_class_or_enum & 2)
@@ -12249,8 +12351,10 @@ cp_parser_init_declarator (cp_parser* parser,
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       /* Look for an asm-specification.  */
+      asm_spec_start_token = cp_lexer_peek_token (parser->lexer);
       asm_specification = cp_parser_asm_specification_opt (parser);
       /* And attributes.  */
+      attributes_start_token = cp_lexer_peek_token (parser->lexer);
       attributes = cp_parser_attributes_opt (parser);
     }
   else
@@ -12278,9 +12382,12 @@ cp_parser_init_declarator (cp_parser* parser,
 	  /* Neither attributes nor an asm-specification are allowed
 	     on a function-definition.  */
 	  if (asm_specification)
-	    error ("an asm-specification is not allowed on a function-definition");
+	    error ("%Han asm-specification is not allowed "
+		   "on a function-definition",
+		   &asm_spec_start_token->location);
 	  if (attributes)
-	    error ("attributes are not allowed on a function-definition");
+	    error ("%Hattributes are not allowed on a function-definition",
+		   &attributes_start_token->location);
 	  /* This is a function-definition.  */
 	  *function_definition_p = true;
 
@@ -12405,6 +12512,7 @@ cp_parser_init_declarator (cp_parser* parser,
     {
       if (function_declarator_p (declarator))
 	{
+	  cp_token *initializer_start_token = cp_lexer_peek_token (parser->lexer);
 	   if (initialization_kind == CPP_EQ)
 	     initializer = cp_parser_pure_specifier (parser);
 	   else
@@ -12413,7 +12521,8 @@ cp_parser_init_declarator (cp_parser* parser,
 		  know what the user intended, so just silently
 		  consume the initializer.  */
 	       if (decl != error_mark_node)
-		 error ("initializer provided for function");
+		 error ("%Hinitializer provided for function",
+			&initializer_start_token->location);
 	       cp_parser_skip_to_closing_parenthesis (parser,
 						      /*recovering=*/true,
 						      /*or_comma=*/false,
@@ -12814,7 +12923,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 		 in function scopes.  */
 	      else if (!parser->in_function_body)
 		{
-		  error ("array bound is not an integer constant");
+		  error ("%Harray bound is not an integer constant",
+			 &token->location);
 		  bounds = error_mark_node;
 		}
 	    }
@@ -12836,6 +12946,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  special_function_kind sfk;
 	  bool abstract_ok;
           bool pack_expansion_p = false;
+	  cp_token *declarator_id_start_token;
 
 	  /* Parse a declarator-id */
 	  abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
@@ -12854,6 +12965,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                 }
             }
 
+	  declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
 	  unqualified_name
 	    = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
 	  qualifying_scope = parser->scope;
@@ -12923,7 +13035,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 					    /*only_current_p=*/false);
 	      /* If that failed, the declarator is invalid.  */
 	      if (TREE_CODE (type) == TYPENAME_TYPE)
-		error ("%<%T::%E%> is not a type",
+		error ("%H%<%T::%E%> is not a type",
+		       &declarator_id_start_token->location,
 		       TYPE_CONTEXT (qualifying_scope),
 		       TYPE_IDENTIFIER (qualifying_scope));
 	      qualifying_scope = type;
@@ -12949,7 +13062,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 		      if (qualifying_scope
 			  && CLASSTYPE_USE_TEMPLATE (name_type))
 			{
-			  error ("invalid use of constructor as a template");
+			  error ("%Hinvalid use of constructor as a template",
+				 &declarator_id_start_token->location);
 			  inform ("use %<%T::%D%> instead of %<%T::%D%> to "
 				  "name the constructor in a qualified name",
 				  class_type,
@@ -13108,6 +13222,7 @@ cp_parser_ptr_operator (cp_parser* parser,
       cp_parser_global_scope_opt (parser,
 				  /*current_scope_valid_p=*/false);
       /* Look for the nested-name specifier.  */
+      token = cp_lexer_peek_token (parser->lexer);
       cp_parser_nested_name_specifier (parser,
 				       /*typename_keyword_p=*/false,
 				       /*check_dependency_p=*/true,
@@ -13122,7 +13237,7 @@ cp_parser_ptr_operator (cp_parser* parser,
 	  code = INDIRECT_REF;
 
 	  if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-	    error ("%qD is a namespace", parser->scope);
+	    error ("%H%qD is a namespace", &token->location, parser->scope);
 	  else
 	    {
 	      /* The type of which the member is a member is given by the
@@ -13197,7 +13312,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 
       if (cv_quals & cv_qualifier)
 	{
-	  error ("duplicate cv-qualifier");
+	  error ("%Hduplicate cv-qualifier", &token->location);
 	  cp_lexer_purge_token (parser->lexer);
 	}
       else
@@ -13307,6 +13422,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 {
   bool seen_type_specifier = false;
   cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
+  cp_token *start_token = NULL;
 
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
@@ -13326,6 +13442,11 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 	  continue;
 	}
 
+      /* record the token of the beginning of the type specifier seq,
+         for error reporting purposes*/
+     if (!start_token)
+       start_token = cp_lexer_peek_token (parser->lexer);
+
       /* Look for the type-specifier.  */
       type_specifier = cp_parser_type_specifier (parser,
 						 flags,
@@ -13369,7 +13490,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 	flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
 
-  cp_parser_check_decl_spec (type_specifier_seq);
+  cp_parser_check_decl_spec (type_specifier_seq, start_token->location);
 }
 
 /* Parse a parameter-declaration-clause.
@@ -13596,7 +13717,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
   cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
   tree default_argument;
-  cp_token *token;
+  cp_token *token = NULL, *declarator_token_start = NULL;
   const char *saved_message;
 
   /* In a template parameter, `>' is not an operator.
@@ -13665,6 +13786,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	  && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
 	cp_parser_commit_to_tentative_parse (parser);
       /* Parse the declarator.  */
+      declarator_token_start = token;
       declarator = cp_parser_declarator (parser,
 					 CP_PARSER_DECLARATOR_EITHER,
 					 /*ctor_dtor_or_conv_p=*/NULL,
@@ -13823,7 +13945,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 		  /* If we run out of tokens, issue an error message.  */
 		case CPP_EOF:
 		case CPP_PRAGMA_EOL:
-		  error ("file ends in default argument");
+		  error ("%Hfile ends in default argument", &token->location);
 		  done = true;
 		  break;
 
@@ -13860,8 +13982,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
       /* Outside of a class definition, we can just parse the
 	 assignment-expression.  */
       else
-        default_argument 
-          = cp_parser_default_argument (parser, template_parm_p);
+	{
+	  token = cp_lexer_peek_token (parser->lexer);
+	  default_argument 
+	    = cp_parser_default_argument (parser, template_parm_p);
+	}
 
       if (!parser->default_arg_ok_p)
 	{
@@ -13869,7 +13994,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	    warning (0, "deprecated use of default argument for parameter of non-function");
 	  else
 	    {
-	      error ("default arguments are only permitted for function parameters");
+	      error ("%Hdefault arguments are only "
+		     "permitted for function parameters",
+		     &token->location);
 	      default_argument = NULL_TREE;
 	    }
 	}
@@ -13885,11 +14012,12 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	    id_declarator = id_declarator->declarator;
 	  
 	  if (id_declarator && id_declarator->kind == cdk_id)
-	    error ("%sparameter pack %qD cannot have a default argument",
+	    error ("%H%sparameter pack %qD cannot have a default argument",
+		   &declarator_token_start->location,
 		   kind, id_declarator->u.id.unqualified_name);
 	  else
-	    error ("%sparameter pack cannot have a default argument",
-		   kind);
+	    error ("%H%sparameter pack cannot have a default argument",
+		   &declarator_token_start->location, kind);
 	  
 	  default_argument = NULL_TREE;
 	}
@@ -14279,10 +14407,12 @@ cp_parser_class_name (cp_parser *parser,
 					/*is_template=*/false,
 					/*is_namespace=*/false,
 					check_dependency_p,
-					&ambiguous_decls);
+					&ambiguous_decls,
+					identifier_token->location);
 	  if (ambiguous_decls)
 	    {
-	      error ("reference to %qD is ambiguous", identifier);
+	      error ("%Hreference to %qD is ambiguous",
+		     &identifier_token->location, identifier);
 	      print_candidates (ambiguous_decls);
 	      if (cp_parser_parsing_tentatively (parser))
 		{
@@ -14573,7 +14703,7 @@ cp_parser_class_head (cp_parser* parser,
   bool invalid_explicit_specialization_p = false;
   tree pushed_scope = NULL_TREE;
   unsigned num_templates;
-
+  cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL;
   /* Assume no nested-name-specifier will be present.  */
   *nested_name_specifier_p = false;
   /* Assume no template parameter lists will be used in defining the
@@ -14606,6 +14736,7 @@ cp_parser_class_head (cp_parser* parser,
 
   /* Determine the name of the class.  Begin by looking for an
      optional nested-name-specifier.  */
+  nested_name_specifier_token_start = cp_lexer_peek_token (parser->lexer);
   nested_name_specifier
     = cp_parser_nested_name_specifier_opt (parser,
 					   /*typename_keyword_p=*/false,
@@ -14616,6 +14747,7 @@ cp_parser_class_head (cp_parser* parser,
      identifier.  */
   if (nested_name_specifier)
     {
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       /* Although the grammar says `identifier', it really means
 	 `class-name' or `template-name'.  You are only allowed to
 	 define a class that has already been declared with this
@@ -14679,6 +14811,7 @@ cp_parser_class_head (cp_parser* parser,
 	 an identifier, or nothing at all.  */
       cp_parser_parse_tentatively (parser);
       /* Check for a template-id.  */
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       id = cp_parser_template_id (parser,
 				  /*template_keyword_p=*/false,
 				  /*check_dependency_p=*/true,
@@ -14730,7 +14863,8 @@ cp_parser_class_head (cp_parser* parser,
       /* Reject typedef-names in class heads.  */
       if (!DECL_IMPLICIT_TYPEDEF_P (type))
 	{
-	  error ("invalid class name in declaration of %qD", type);
+	  error ("%Hinvalid class name in declaration of %qD",
+		 &type_start_token->location, type);
 	  type = NULL_TREE;
 	  goto done;
 	}
@@ -14742,10 +14876,13 @@ cp_parser_class_head (cp_parser* parser,
       if (scope && !is_ancestor (scope, nested_name_specifier))
 	{
 	  if (at_namespace_scope_p ())
-	    error ("declaration of %qD in namespace %qD which does not "
-		   "enclose %qD", type, scope, nested_name_specifier);
+	    error ("%Hdeclaration of %qD in namespace %qD which does not "
+		   "enclose %qD",
+		   &type_start_token->location,
+		   type, scope, nested_name_specifier);
 	  else
-	    error ("declaration of %qD in %qD which does not enclose %qD",
+	    error ("%Hdeclaration of %qD in %qD which does not enclose %qD",
+		   &type_start_token->location,
 		   type, scope, nested_name_specifier);
 	  type = NULL_TREE;
 	  goto done;
@@ -14758,7 +14895,8 @@ cp_parser_class_head (cp_parser* parser,
 	 class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
 	{
-	  permerror ("extra qualification not allowed");
+	  permerror ("%Hextra qualification not allowed",
+		     &nested_name_specifier_token_start->location);
 	  nested_name_specifier = NULL_TREE;
 	  num_templates = 0;
 	}
@@ -14769,7 +14907,8 @@ cp_parser_class_head (cp_parser* parser,
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
-      error ("an explicit specialization must be preceded by %<template <>%>");
+      error ("%Han explicit specialization must be preceded by %<template <>%>",
+	     &type_start_token->location);
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
 	 cp_parser_explicit_specialization.  */
@@ -14781,7 +14920,8 @@ cp_parser_class_head (cp_parser* parser,
      use "goto done;" to return.  */
   /* Make sure that the right number of template parameters were
      present.  */
-  if (!cp_parser_check_template_parameters (parser, num_templates))
+  if (!cp_parser_check_template_parameters (parser, num_templates,
+					    type_start_token->location))
     {
       /* If something went wrong, there is no point in even trying to
 	 process the class-definition.  */
@@ -14796,7 +14936,8 @@ cp_parser_class_head (cp_parser* parser,
 	  && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0))
 	      || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD))
 	{
-	  error ("function template %qD redeclared as a class template", id);
+	  error ("%Hfunction template %qD redeclared as a class template",
+		 &type_start_token->location, id);
 	  type = error_mark_node;
 	}
       else
@@ -14877,8 +15018,10 @@ cp_parser_class_head (cp_parser* parser,
      that's an error.  */
   if (type != error_mark_node && COMPLETE_TYPE_P (type))
     {
-      error ("redefinition of %q#T", type);
-      error ("previous definition of %q+#T", type);
+      error ("%Hredefinition of %q#T",
+	     &type_start_token->location, type);
+      error ("%Hprevious definition of %q+#T",
+	     &type_start_token->location, type);
       type = NULL_TREE;
       goto done;
     }
@@ -15033,7 +15176,9 @@ cp_parser_member_declaration (cp_parser* parser)
   tree decl;
   int declares_class_or_enum;
   bool friend_p;
-  cp_token *token;
+  cp_token *token = NULL;
+  cp_token *decl_spec_token_start = NULL;
+  cp_token *initializer_token_start = NULL;
   int saved_pedantic;
 
   /* Check for the `__extension__' keyword.  */
@@ -15097,6 +15242,7 @@ cp_parser_member_declaration (cp_parser* parser)
     return;
 
   /* Parse the decl-specifier-seq.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -15142,7 +15288,8 @@ cp_parser_member_declaration (cp_parser* parser)
 	      /* If the `friend' keyword was present, the friend must
 		 be introduced with a class-key.  */
 	       if (!declares_class_or_enum)
-		 error ("a class-key must be used when declaring a friend");
+		 error ("%Ha class-key must be used when declaring a friend",
+                        &decl_spec_token_start->location);
 	       /* In this case:
 
 		    template <typename T> struct A {
@@ -15156,8 +15303,8 @@ cp_parser_member_declaration (cp_parser* parser)
 		   && TYPE_P (decl_specifiers.type))
 		 type = decl_specifiers.type;
 	       if (!type || !TYPE_P (type))
-		 error ("friend declaration does not name a class or "
-			"function");
+		 error ("%Hfriend declaration does not name a class or "
+			"function", &decl_spec_token_start->location);
 	       else
 		 make_friend_class (current_class_type, type,
 				    /*complain=*/true);
@@ -15180,7 +15327,9 @@ cp_parser_member_declaration (cp_parser* parser)
 	      finish_member_declaration (decl);
 	    }
 	  else
-	    cp_parser_check_access_in_redeclaration (TYPE_NAME (type));
+	    cp_parser_check_access_in_redeclaration
+					      (TYPE_NAME (type),
+					       decl_spec_token_start->location);
 	}
     }
   else
@@ -15308,6 +15457,7 @@ cp_parser_member_declaration (cp_parser* parser)
 		     for a pure-specifier; otherwise, we look for a
 		     constant-initializer.  When we call `grokfield', it will
 		     perform more stringent semantics checks.  */
+		  initializer_token_start = cp_lexer_peek_token (parser->lexer);
 		  if (function_declarator_p (declarator))
 		    initializer = cp_parser_pure_specifier (parser);
 		  else
@@ -15332,7 +15482,8 @@ cp_parser_member_declaration (cp_parser* parser)
 		     standard, since a pure function may be defined
 		     outside of the class-specifier.  */
 		  if (initializer)
-		    error ("pure-specifier on function-definition");
+		    error ("%Hpure-specifier on function-definition",
+			   &initializer_token_start->location);
 		  decl = cp_parser_save_member_function_body (parser,
 							      &decl_specifiers,
 							      declarator,
@@ -15423,7 +15574,7 @@ cp_parser_pure_specifier (cp_parser* parser)
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
-      error ("templates may not be %<virtual%>");
+      error ("%Htemplates may not be %<virtual%>", &token->location);
       return error_mark_node;
     }
 
@@ -15625,11 +15776,14 @@ cp_parser_base_specifier (cp_parser* parser)
      as base classes.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
+      token = cp_lexer_peek_token (parser->lexer);
       if (!processing_template_decl)
-	error ("keyword %<typename%> not allowed outside of templates");
+	error ("%Hkeyword %<typename%> not allowed outside of templates",
+	       &token->location);
       else
-	error ("keyword %<typename%> not allowed in this context "
-	       "(the base class is implicitly a type)");
+	error ("%Hkeyword %<typename%> not allowed in this context "
+	       "(the base class is implicitly a type)",
+	       &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
 
@@ -16330,7 +16484,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 		       bool is_template,
 		       bool is_namespace,
 		       bool check_dependency,
-		       tree *ambiguous_decls)
+		       tree *ambiguous_decls,
+		       location_t name_location)
 {
   int flags = 0;
   tree decl;
@@ -16511,7 +16666,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 	 cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
 	{
-	  error ("reference to %qD is ambiguous", name);
+	  error ("%Hreference to %qD is ambiguous",
+		 &name_location, name);
 	  print_candidates (decl);
 	}
       return error_mark_node;
@@ -16541,14 +16697,15 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
    IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE.  */
 
 static tree
-cp_parser_lookup_name_simple (cp_parser* parser, tree name)
+cp_parser_lookup_name_simple (cp_parser* parser, tree name, location_t location)
 {
   return cp_parser_lookup_name (parser, name,
 				none_type,
 				/*is_template=*/false,
 				/*is_namespace=*/false,
 				/*check_dependency=*/true,
-				/*ambiguous_decls=*/NULL);
+				/*ambiguous_decls=*/NULL,
+				location);
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
@@ -16601,7 +16758,8 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
 
 static bool
 cp_parser_check_declarator_template_parameters (cp_parser* parser,
-						cp_declarator *declarator)
+						cp_declarator *declarator,
+						location_t declarator_location)
 {
   unsigned num_templates;
 
@@ -16651,7 +16809,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 	++num_templates;
 
       return cp_parser_check_template_parameters (parser,
-						  num_templates);
+						  num_templates,
+						  declarator_location);
 
     case cdk_function:
     case cdk_array:
@@ -16659,7 +16818,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
     case cdk_reference:
     case cdk_ptrmem:
       return (cp_parser_check_declarator_template_parameters
-	      (parser, declarator->declarator));
+	      (parser, declarator->declarator, declarator_location));
 
     case cdk_error:
       return true;
@@ -16676,7 +16835,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
-				     unsigned num_templates)
+				     unsigned num_templates,
+				     location_t location)
 {
   /* If there are more template classes than parameter lists, we have
      something like:
@@ -16684,7 +16844,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      error ("too few template-parameter-lists");
+      error ("%Htoo few template-parameter-lists", &location);
       return false;
     }
   /* If there are the same number of template classes and parameter
@@ -16699,7 +16859,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
      something like:
 
      template <class T> template <class U> void S::f();  */
-  error ("too many template-parameter-lists");
+  error ("%Htoo many template-parameter-lists", &location);
   return false;
 }
 
@@ -16957,12 +17117,14 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   bool saved_in_unbraced_linkage_specification_p;
   bool saved_in_function_body;
   unsigned saved_num_template_parameter_lists;
+  cp_token *token;
 
   saved_in_function_body = parser->in_function_body;
   parser->in_function_body = true;
   /* If the next token is `return', then the code may be trying to
      make use of the "named return value" extension that G++ used to
      support.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_RETURN))
     {
       /* Consume the `return' keyword.  */
@@ -16971,7 +17133,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
 	 returned.  */
       cp_parser_identifier (parser);
       /* Issue an error message.  */
-      error ("named return values are no longer supported");
+      error ("%Hnamed return values are no longer supported",
+	     &token->location);
       /* Skip tokens until we reach the start of the function body.  */
       while (true)
 	{
@@ -17030,8 +17193,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
+  cp_token *token;
 
   /* Look for the `template' keyword.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
     return;
 
@@ -17043,7 +17208,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* 14.5.2.2 [temp.mem]
 
          A local class shall not have member templates.  */
-      error ("invalid declaration of member template in local class");
+      error ("%Hinvalid declaration of member template in local class",
+	     &token->location);
       cp_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
@@ -17052,7 +17218,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
      A template ... shall not have C linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template with C linkage");
+      error ("%Htemplate with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
 	 front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -17099,6 +17265,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* There are no access checks when parsing a template, as we do not
 	 know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_single_declaration (parser,
 					   checks,
 					   member_p,
@@ -17111,7 +17278,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       if (member_p && !friend_p && decl)
 	{
 	  if (TREE_CODE (decl) == TYPE_DECL)
-	    cp_parser_check_access_in_redeclaration (decl);
+	    cp_parser_check_access_in_redeclaration (decl, token->location);
 
 	  decl = finish_member_template_decl (decl);
 	}
@@ -17175,6 +17342,7 @@ cp_parser_single_declaration (cp_parser* parser,
   tree decl = NULL_TREE;
   cp_decl_specifier_seq decl_specifiers;
   bool function_definition_p = false;
+  cp_token *decl_spec_token_start;
 
   /* This function is only used when processing a template
      declaration.  */
@@ -17186,6 +17354,7 @@ cp_parser_single_declaration (cp_parser* parser,
 
   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
      alternative.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -17196,7 +17365,8 @@ cp_parser_single_declaration (cp_parser* parser,
   /* There are no template typedefs.  */
   if (decl_specifiers.specs[(int) ds_typedef])
     {
-      error ("template declaration of %qs", "typedef");
+      error ("%Htemplate declaration of %qs",
+	     &decl_spec_token_start->location, "typedef");
       decl = error_mark_node;
     }
 
@@ -17259,7 +17429,8 @@ cp_parser_single_declaration (cp_parser* parser,
         && explicit_specialization_p
         && decl_specifiers.storage_class != sc_none)
       {
-        error ("explicit template specialization cannot have a storage class");
+        error ("%Hexplicit template specialization cannot have a storage class",
+	       &decl_spec_token_start->location);
         decl = error_mark_node;
       }
     }
@@ -17461,9 +17632,9 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
 	    is a typo for '>'. Emit an error message and continue.
 	    Same deal about the token location, but here we can get it
 	    right by consuming the '>>' before issuing the diagnostic.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  error ("spurious %<>>%>, use %<>%> to terminate "
-		 "a template argument list");
+	  cp_token *token = cp_lexer_consume_token (parser->lexer);
+	  error ("%Hspurious %<>>%>, use %<>%> to terminate "
+		 "a template argument list", &token->location);
 	}
     }
   else
@@ -17784,14 +17955,15 @@ cp_parser_declares_only_class_p (cp_parser *parser)
 static void
 cp_parser_set_storage_class (cp_parser *parser,
 			     cp_decl_specifier_seq *decl_specs,
-			     enum rid keyword)
+			     enum rid keyword,
+			     location_t location)
 {
   cp_storage_class storage_class;
 
   if (parser->in_unbraced_linkage_specification_p)
     {
-      error ("invalid use of %qD in linkage specification",
-	     ridpointers[keyword]);
+      error ("%Hinvalid use of %qD in linkage specification",
+	     &location, ridpointers[keyword]);
       return;
     }
   else if (decl_specs->storage_class != sc_none)
@@ -17803,7 +17975,7 @@ cp_parser_set_storage_class (cp_parser *parser,
   if ((keyword == RID_EXTERN || keyword == RID_STATIC)
       && decl_specs->specs[(int) ds_thread])
     {
-      error ("%<__thread%> before %qD", ridpointers[keyword]);
+      error ("%H%<__thread%> before %qD", &location, ridpointers[keyword]);
       decl_specs->specs[(int) ds_thread] = 0;
     }
 
@@ -18133,7 +18305,7 @@ cp_parser_check_class_key (enum tag_types class_key, tree type)
    [class.mem/1].  */
 
 static void
-cp_parser_check_access_in_redeclaration (tree decl)
+cp_parser_check_access_in_redeclaration (tree decl, location_t location)
 {
   if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl)))
     return;
@@ -18142,7 +18314,7 @@ cp_parser_check_access_in_redeclaration (tree decl)
        != (current_access_specifier == access_private_node))
       || (TREE_PROTECTED (decl)
 	  != (current_access_specifier == access_protected_node)))
-    error ("%qD redeclared with different access", decl);
+    error ("%H%qD redeclared with different access", &location, decl);
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
@@ -18159,8 +18331,9 @@ cp_parser_optional_template_keyword (cp_parser *parser)
 	 template and what is not.  */
       if (!processing_template_decl)
 	{
-	  error ("%<template%> (as a disambiguator) is only allowed "
-		 "within templates");
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
+	  error ("%H%<template%> (as a disambiguator) is only allowed "
+		 "within templates", &token->location);
 	  /* If this part of the token stream is rescanned, the same
 	     error message would be generated.  So, we purge the token
 	     from the stream.  */
@@ -18412,7 +18585,8 @@ cp_parser_objc_expression (cp_parser* parser)
 	  break;
 	}
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -18545,15 +18719,18 @@ static tree
 cp_parser_objc_encode_expression (cp_parser* parser)
 {
   tree type;
+  cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  token = cp_lexer_peek_token (parser->lexer);
   type = complete_type (cp_parser_type_id (parser));
   cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   if (!type)
     {
-      error ("%<@encode%> must specify a type as an argument");
+      error ("%H%<@encode%> must specify a type as an argument",
+	     &token->location);
       return error_mark_node;
     }
 
@@ -18868,7 +19045,7 @@ cp_parser_objc_selector (cp_parser* parser)
 
   if (!cp_parser_objc_selector_p (token->type))
     {
-      error ("invalid Objective-C++ selector name");
+      error ("%Hinvalid Objective-C++ selector name", &token->location);
       return error_mark_node;
     }
 
@@ -19198,7 +19375,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
     {
-      error ("identifier expected after %<@protocol%>");
+      tok = cp_lexer_peek_token (parser->lexer);
+      error ("%Hidentifier expected after %<@protocol%>", &tok->location);
       goto finish;
     }
 
@@ -19334,7 +19512,8 @@ cp_parser_objc_declaration (cp_parser* parser)
       cp_parser_objc_end_implementation (parser);
       break;
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 }
@@ -19465,7 +19644,8 @@ cp_parser_objc_statement (cp_parser * parser) {
     case RID_AT_THROW:
       return cp_parser_objc_throw_statement (parser);
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -19549,14 +19729,15 @@ cp_parser_omp_clause_name (cp_parser *parser)
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
-check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+check_no_duplicate_clause (tree clauses, enum tree_code code,
+			   const char *name, location_t location)
 {
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
-	error ("too many %qs clauses", name);
+	error ("%Htoo many %qs clauses", &location, name);
 	break;
       }
 }
@@ -19579,10 +19760,12 @@ static tree
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 				tree list)
 {
+  cp_token *token;
   while (1)
     {
       tree name, decl;
 
+      token = cp_lexer_peek_token (parser->lexer);
       name = cp_parser_id_expression (parser, /*template_p=*/false,
 				      /*check_dependency_p=*/true,
 				      /*template_p=*/NULL,
@@ -19591,9 +19774,9 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       if (name == error_mark_node)
 	goto skip_comma;
 
-      decl = cp_parser_lookup_name_simple (parser, name);
+      decl = cp_parser_lookup_name_simple (parser, name, token->location);
       if (decl == error_mark_node)
-	cp_parser_name_lookup_error (parser, name, decl, NULL);
+	cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
       else if (kind != 0)
 	{
 	  tree u = build_omp_clause (kind);
@@ -19643,7 +19826,7 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
    collapse ( constant-expression ) */
 
 static tree
-cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
+cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location)
 {
   tree c, num;
   location_t loc;
@@ -19668,11 +19851,12 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
       || (n = tree_low_cst (num, 0)) <= 0
       || (int) n != n)
     {
-      error ("%Hcollapse argument needs positive constant integer expression", &loc);
+      error ("%Hcollapse argument needs positive constant integer expression",
+	     &loc);
       return list;
     }
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
+  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
   c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
@@ -19684,7 +19868,7 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
    default ( shared | none ) */
 
 static tree
-cp_parser_omp_clause_default (cp_parser *parser, tree list)
+cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
 {
   enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
   tree c;
@@ -19730,7 +19914,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
   if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
     return list;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
   c = build_omp_clause (OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
@@ -19742,7 +19926,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
    if ( expression ) */
 
 static tree
-cp_parser_omp_clause_if (cp_parser *parser, tree list)
+cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
 {
   tree t, c;
 
@@ -19757,7 +19941,7 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
 
   c = build_omp_clause (OMP_CLAUSE_IF);
   OMP_CLAUSE_IF_EXPR (c) = t;
@@ -19770,11 +19954,12 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
    nowait */
 
 static tree
-cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED,
+			     tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait", location);
 
   c = build_omp_clause (OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -19785,7 +19970,8 @@ cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
    num_threads ( expression ) */
 
 static tree
-cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
+cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
+				  location_t location)
 {
   tree t, c;
 
@@ -19800,7 +19986,8 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
+			     "num_threads", location);
 
   c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
   OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
@@ -19813,11 +20000,13 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
    ordered */
 
 static tree
-cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
+			      tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED,
+			     "ordered", location);
 
   c = build_omp_clause (OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -19894,7 +20083,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
      static | dynamic | guided | runtime | auto  */
 
 static tree
-cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
+cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location)
 {
   tree c, t;
 
@@ -19942,18 +20131,20 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
     {
+      cp_token *token;
       cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       t = cp_parser_assignment_expression (parser, false);
 
       if (t == error_mark_node)
 	goto resync_fail;
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-	error ("schedule %<runtime%> does not take "
-	       "a %<chunk_size%> parameter");
+	error ("%Hschedule %<runtime%> does not take "
+	       "a %<chunk_size%> parameter", &token->location);
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
-	error ("schedule %<auto%> does not take "
-	       "a %<chunk_size%> parameter");
+	error ("%Hschedule %<auto%> does not take "
+	       "a %<chunk_size%> parameter", &token->location);
       else
 	OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
@@ -19963,7 +20154,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
   else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<,%> or %<)%>"))
     goto resync_fail;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
@@ -19980,11 +20171,12 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
    untied */
 
 static tree
-cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED,
+			     tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
+  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
 
   c = build_omp_clause (OMP_CLAUSE_UNTIED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -20001,6 +20193,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 {
   tree clauses = NULL;
   bool first = true;
+  cp_token *token = NULL;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
@@ -20011,13 +20204,15 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
       if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
 	cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       c_kind = cp_parser_omp_clause_name (parser);
       first = false;
 
       switch (c_kind)
 	{
 	case PRAGMA_OMP_CLAUSE_COLLAPSE:
-	  clauses = cp_parser_omp_clause_collapse (parser, clauses);
+	  clauses = cp_parser_omp_clause_collapse (parser, clauses,
+						   token->location);
 	  c_name = "collapse";
 	  break;
 	case PRAGMA_OMP_CLAUSE_COPYIN:
@@ -20030,7 +20225,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "copyprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_DEFAULT:
-	  clauses = cp_parser_omp_clause_default (parser, clauses);
+	  clauses = cp_parser_omp_clause_default (parser, clauses,
+						  token->location);
 	  c_name = "default";
 	  break;
 	case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
@@ -20039,7 +20235,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "firstprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_IF:
-	  clauses = cp_parser_omp_clause_if (parser, clauses);
+	  clauses = cp_parser_omp_clause_if (parser, clauses, token->location);
 	  c_name = "if";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -20048,15 +20244,17 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "lastprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NOWAIT:
-	  clauses = cp_parser_omp_clause_nowait (parser, clauses);
+	  clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
 	  c_name = "nowait";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NUM_THREADS:
-	  clauses = cp_parser_omp_clause_num_threads (parser, clauses);
+	  clauses = cp_parser_omp_clause_num_threads (parser, clauses,
+						      token->location);
 	  c_name = "num_threads";
 	  break;
 	case PRAGMA_OMP_CLAUSE_ORDERED:
-	  clauses = cp_parser_omp_clause_ordered (parser, clauses);
+	  clauses = cp_parser_omp_clause_ordered (parser, clauses,
+						  token->location);
 	  c_name = "ordered";
 	  break;
 	case PRAGMA_OMP_CLAUSE_PRIVATE:
@@ -20069,7 +20267,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
-	  clauses = cp_parser_omp_clause_schedule (parser, clauses);
+	  clauses = cp_parser_omp_clause_schedule (parser, clauses,
+						   token->location);
 	  c_name = "schedule";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SHARED:
@@ -20078,7 +20277,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "shared";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
-	  clauses = cp_parser_omp_clause_untied (parser, clauses);
+	  clauses = cp_parser_omp_clause_untied (parser, clauses,
+						 token->location);
 	  c_name = "nowait";
 	  break;
 	default:
@@ -20091,7 +20291,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  /* Remove the invalid clause(s) from the list to avoid
 	     confusing the rest of the compiler.  */
 	  clauses = prev;
-	  error ("%qs is not valid for %qs", c_name, where);
+	  error ("%H%qs is not valid for %qs", &token->location, c_name, where);
 	}
     }
  saw_error:
@@ -21177,10 +21377,11 @@ cp_parser_initial_pragma (cp_token *first_token)
 
       cp_lexer_get_preprocessor_token (NULL, first_token);
       if (first_token->type != CPP_PRAGMA_EOL)
-	error ("junk at end of %<#pragma GCC pch_preprocess%>");
+	error ("%Hjunk at end of %<#pragma GCC pch_preprocess%>",
+               &first_token->location);
     }
   else
-    error ("expected string literal");
+    error ("%Hexpected string literal", &first_token->location);
 
   /* Skip to the end of the pragma.  */
   while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
@@ -21213,7 +21414,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
   switch (id)
     {
     case PRAGMA_GCC_PCH_PREPROCESS:
-      error ("%<#pragma GCC pch_preprocess%> must be first");
+      error ("%H%<#pragma GCC pch_preprocess%> must be first",
+             &pragma_tok->location);
       break;
 
     case PRAGMA_OMP_BARRIER:
@@ -21223,8 +21425,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_barrier (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp barrier%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp barrier%> may only be "
+		 "used in compound statements", &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
@@ -21238,8 +21440,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_flush (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp flush%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp flush%> may only be "
+		 "used in compound statements", &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
@@ -21280,8 +21482,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
       return true;
 
     case PRAGMA_OMP_SECTION:
-      error ("%<#pragma omp section%> may only be used in "
-	     "%<#pragma omp sections%> construct");
+      error ("%H%<#pragma omp section%> may only be used in "
+	     "%<#pragma omp sections%> construct", &pragma_tok->location);
       break;
 
     default:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9926f3d..f283394 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9750,7 +9750,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
       if (complain & tf_error)
 	qualified_name_lookup_error (scope,
 				     TREE_OPERAND (qualified_id, 1),
-				     expr);
+				     expr, input_location);
       return error_mark_node;
     }
 
@@ -9759,7 +9759,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
 
   if (expr == error_mark_node && complain & tf_error)
     qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
-				 expr);
+				 expr, input_location);
   else if (TYPE_P (scope))
     {
       expr = (adjust_result_of_qualified_name_lookup
@@ -10491,7 +10491,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 					  /*is_type_p=*/false,
 					  /*complain=*/false);
 	    if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
-	      qualified_name_lookup_error (scope, name, decl);
+	      qualified_name_lookup_error (scope, name, decl, input_location);
 	    else
 	      do_local_using_decl (decl, scope, name);
 	  }
@@ -10938,7 +10938,8 @@ tsubst_copy_and_build (tree t,
 				     /*done=*/true,
 				     /*address_p=*/false,
 				     /*template_arg_p=*/false,
-				     &error_msg);
+				     &error_msg,
+				     input_location);
 	if (error_msg)
 	  error (error_msg);
 	if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
@@ -11467,7 +11468,8 @@ tsubst_copy_and_build (tree t,
 	      }
 	    else
 	      {
-		qualified_name_lookup_error (object_type, tmpl, member);
+		qualified_name_lookup_error (object_type, tmpl, member,
+					     input_location);
 		return error_mark_node;
 	      }
 	  }
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2400aeb..4ac585b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2482,29 +2482,33 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
 }
 
 /* Issue a diagnostic that NAME cannot be found in SCOPE.  DECL is
-   what we found when we tried to do the lookup.  */
+   what we found when we tried to do the lookup.
+   LOCATION is the location of the NAME identifier;
+   The location is used in the error message*/
 
 void
-qualified_name_lookup_error (tree scope, tree name, tree decl)
+qualified_name_lookup_error (tree scope, tree name,
+			     tree decl, location_t location)
 {
   if (scope == error_mark_node)
     ; /* We already complained.  */
   else if (TYPE_P (scope))
     {
       if (!COMPLETE_TYPE_P (scope))
-	error ("incomplete type %qT used in nested name specifier", scope);
+	error ("%Hincomplete type %qT used in nested name specifier",
+	       &location, scope);
       else if (TREE_CODE (decl) == TREE_LIST)
 	{
-	  error ("reference to %<%T::%D%> is ambiguous", scope, name);
+	  error ("%Hreference to %<%T::%D%> is ambiguous", &location, scope, name);
 	  print_candidates (decl);
 	}
       else
-	error ("%qD is not a member of %qT", name, scope);
+	error ("%H%qD is not a member of %qT", &location, name, scope);
     }
   else if (scope != global_namespace)
-    error ("%qD is not a member of %qD", name, scope);
+    error ("%H%qD is not a member of %qD", &location, name, scope);
   else
-    error ("%<::%D%> has not been declared", name);
+    error ("%H%<::%D%> has not been declared", &location, name);
 }
 
 /* If FNS is a member function, a set of member functions, or a
@@ -2569,7 +2573,6 @@ baselink_for_fns (tree fns)
    the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
-
 tree
 finish_id_expression (tree id_expression,
 		      tree decl,
@@ -2582,7 +2585,8 @@ finish_id_expression (tree id_expression,
 		      bool done,
 		      bool address_p,
 		      bool template_arg_p,
-		      const char **error_msg)
+		      const char **error_msg,
+		      location_t location)
 {
   /* Initialize the output parameters.  */
   *idk = CP_ID_KIND_NONE;
@@ -2612,7 +2616,7 @@ finish_id_expression (tree id_expression,
 	      /* If the qualifying type is non-dependent (and the name
 		 does not name a conversion operator to a dependent
 		 type), issue an error.  */
-	      qualified_name_lookup_error (scope, id_expression, decl);
+	      qualified_name_lookup_error (scope, id_expression, decl, location);
 	      return error_mark_node;
 	    }
 	  else if (!scope)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 6bcc8e7..52eb574 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2008-06-18 Dodji Seketeli <dseketel@redhat.com>
+
+	* g++.dg/parse/constructor1.C, g++.dg/parse/error*.C: update these
+	  tests to make them catch column number regressions. Make these tests
+	  run with the -fshow-column option.
+	* g++.dg/parse/error-column.C: new column number test.
+
 2008-06-25  Richard Guenther  <rguenther@suse.de>
 
 	* gcc.c-torture/compile/20080625-1.c: New testcase.
diff --git a/gcc/testsuite/g++.dg/parse/constructor1.C b/gcc/testsuite/g++.dg/parse/constructor1.C
index 3011862..8f222f8 100644
--- a/gcc/testsuite/g++.dg/parse/constructor1.C
+++ b/gcc/testsuite/g++.dg/parse/constructor1.C
@@ -1,4 +1,7 @@
+// { dg-do compile }
+// { dg-options "-fshow-column" }
+
 ACE_Process_Descriptor::ACE_Process_Descriptor () : // { dg-error "" }
-  process_ (0)
+  process_ (0) // { dg-error "3: error: only constructors take base initializers" }
 {
 }
diff --git a/gcc/testsuite/g++.dg/parse/error-column.C b/gcc/testsuite/g++.dg/parse/error-column.C
new file mode 100644
index 0000000..812a499
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error-column.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// Make sure column information is correctly shown in error reporting
+// { dg-options "-fshow-column" }
+
+
+void foo ()
+{
+  cout << "blah"; // { dg-error "3: error: 'cout'" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/error1.C b/gcc/testsuite/g++.dg/parse/error1.C
index 8756df6..60e7d65 100644
--- a/gcc/testsuite/g++.dg/parse/error1.C
+++ b/gcc/testsuite/g++.dg/parse/error1.C
@@ -1,6 +1,7 @@
+// { dg-options "-fshow-column" }
 struct INCOMPLETE;
 template <int> struct X {
     static INCOMPLETE value;
 };
-template <> INCOMPLETE X<1>::value = 0; // { dg-error "" }
+template <> INCOMPLETE X<1>::value = 0; // { dg-error "30: error: variable 'INCOMPLETE X<1>::value' has initializer but incomplete type" }
 
diff --git a/gcc/testsuite/g++.dg/parse/error10.C b/gcc/testsuite/g++.dg/parse/error10.C
index 242c421..6e46922 100644
--- a/gcc/testsuite/g++.dg/parse/error10.C
+++ b/gcc/testsuite/g++.dg/parse/error10.C
@@ -1,5 +1,5 @@
 // PR c++/3478
-// { dg-options "" }
+// { dg-options "-fshow-column" }
 
 template <typename> struct A
 {
@@ -11,5 +11,9 @@ template <typename T> void foo()
   enum          A<void>::E e1;
   typename      A<T>::E    e2;
   enum          A<T>::E    e3;
-  enum typename A<T>::E    e4; // { dg-error "" }
+  enum typename A<T>::E    e4;
 }
+
+// Here, columns nums are not very accurate either. Still acceptable though
+// { dg-error "30: error: invalid type in declaration before ';' token" "" { target *-*-* } { 14 } }
+// { dg-error "30: error: two or more data types in declaration of 'e4'" "" { target *-*-* } { 14 } }
diff --git a/gcc/testsuite/g++.dg/parse/error11.C b/gcc/testsuite/g++.dg/parse/error11.C
index 0a8e2e4..f7093a8 100644
--- a/gcc/testsuite/g++.dg/parse/error11.C
+++ b/gcc/testsuite/g++.dg/parse/error11.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }"
 // Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
 // Try to find out when the digraph '<:' is used as a mistake, and parse it
 //  correctly to avoid cascaded errors.
@@ -15,16 +16,16 @@ struct Foo
   };
 
   void method(void) {
-    typename Foo<::B>::template Nested<::B> n; // { dg-error "cannot begin|alternate spelling" }
+    typename Foo<::B>::template Nested<::B> n; // { dg-error "17: error: '<::' cannot begin|17: note: '<:' is an alternate spelling|39: error: '<::' cannot begin|39: note: '<:' is an alternate" }
     n.template Nested<B>::method();
-    n.template Nested<::B>::method();  // { dg-error "cannot begin|alternate spelling" }
+    n.template Nested<::B>::method();  // { dg-error "22: error: '<::' cannot begin|22: note: '<:' is an alternate" }
     Nested<B>::method();
-    Nested<::B>::method(); // { dg-error "cannot begin|alternate spelling" }
+    Nested<::B>::method(); // { dg-error "11: error: '<::' cannot begin|11: note: '<:' is an alternate" }
   }
 };
 
 template <int N> struct Foo2 {};
-template struct Foo2<::B>;  // { dg-error "cannot begin|alternate spelling|type/value mismatch|expected a constant" }
+template struct Foo2<::B>;  // { dg-error "21: error: '<::' cannot begin|21: note: '<:' is an alternate|25: error: type/value mismatch|25: error:   expected a constant" }
 
 int value = 0;
 
@@ -32,22 +33,28 @@ void func(void)
 {
   Foo<::B> f; // { dg-error "cannot begin|alternate spelling" }
   f.Foo<B>::method();
-  f.Foo<::B>::method(); // { dg-error "cannot begin|alternate spelling" }
+  f.Foo<::B>::method(); // { dg-error "8: error|8: note" }
 
   // Check cases where we the token sequence is the correct one, but there
   //  was no digraph or whitespaces in the middle, so we should not emit
   //  the special error message.
   Foo<: :B> k2;     // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" }
   Foo[:B> k1;       // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" } 
-// { dg-error "" "" { target *-*-* } 40 }
-// { dg-error "" "" { target *-*-* } 41 }
-
+// { dg-error "6: error: missing template arguments before" "" { target *-*-* } { 41 } }
+// { dg-error "9: error: expected primary-expression before ':' token" "" { target *-*-* } 41 }
+// { dg-error "9: error: expected '\]' before ':' token" "" { target *-*-* } 41 }
+// { dg-error "9: error: expected ';' before ':' token" "" { target *-*-* } 41 }
+// { dg-error "6: error: missing template arguments before" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected primary-expression before ':' token" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected '\]' before ':' token" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected ';' before ':' token" "" { target *-*-* } 42 }
+//
   int Foo[2];
   Foo[::value] = 0;
 }
 
-template struct Foo<::B>; // { dg-error "cannot begin|alternate spelling" }
+template struct Foo<::B>; // { dg-error "20: error: '<::' cannot begin|20: note: '<:' is an alternate" }
 
 // On the first error message, an additional note about the use of 
 //  -fpermissive should be present
-// { dg-error "-fpermissive" "-fpermissive" { target *-*-* } 18 }
+// { dg-error "17: note: \\(if you use '-fpermissive' G\\+\\+ will accept your code\\)" "-fpermissive" { target *-*-* } 19 }
diff --git a/gcc/testsuite/g++.dg/parse/error12.C b/gcc/testsuite/g++.dg/parse/error12.C
index ea04fd0..b002588 100644
--- a/gcc/testsuite/g++.dg/parse/error12.C
+++ b/gcc/testsuite/g++.dg/parse/error12.C
@@ -1,7 +1,7 @@
 // { dg-do compile }
 // Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
 // Make sure the error about '<:' can be turned into a warning
-// { dg-options "-fpermissive" }
+// { dg-options "-fpermissive -fshow-column" }
 
 struct B;
 
@@ -9,4 +9,5 @@ template <class A>
 struct Foo {};
 
 Foo<::B> foo;   // { dg-bogus "error" "error in place of warning" }
-// { dg-error "" "" { target *-*-* } 11 }
+// { dg-error "4: warning: '<::' cannot begin a template-argument list" "warning <::" { target *-*-* } 11 }
+// { dg-error "4: note: '<:' is an alternate spelling for '.'. Insert whitespace between '<' and '::'" "note <:" { target *-*-* } 11 }
diff --git a/gcc/testsuite/g++.dg/parse/error13.C b/gcc/testsuite/g++.dg/parse/error13.C
index 15642e3..94ddae8 100644
--- a/gcc/testsuite/g++.dg/parse/error13.C
+++ b/gcc/testsuite/g++.dg/parse/error13.C
@@ -1,13 +1,14 @@
+// { dg-options "-fshow-column" }
 // PR c++/13975
 
-public: // { dg-error "" }
+public: // { dg-error "1: error: expected unqualified-id before 'public'" }
 
 int i;
 
-protected: // { dg-error "" }
+protected: // { dg-error "1: error: expected unqualified-id before 'protected'" }
 
 int j;
 
-private: // { dg-error "" }
+private: // { dg-error "1: error: expected unqualified-id before 'private'" }
 
 int k;
diff --git a/gcc/testsuite/g++.dg/parse/error14.C b/gcc/testsuite/g++.dg/parse/error14.C
index 4b23045..906b98f 100644
--- a/gcc/testsuite/g++.dg/parse/error14.C
+++ b/gcc/testsuite/g++.dg/parse/error14.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column" }
 // PR c++/13970
 
 struct X
@@ -18,5 +19,5 @@ struct X
         Zinc<int>( //);
 		  //    }
 
-}; // { dg-error "" }
+}; // { dg-error "2: error: expected '.' at end of input|1: error: expected primary-expression before '.' token|1: error: expected ';' before '.' token|1: error: expected unqualified-id at end of input" }
 
diff --git a/gcc/testsuite/g++.dg/parse/error15.C b/gcc/testsuite/g++.dg/parse/error15.C
index b343970..b65175c 100644
--- a/gcc/testsuite/g++.dg/parse/error15.C
+++ b/gcc/testsuite/g++.dg/parse/error15.C
@@ -1,5 +1,6 @@
 // { dg-do compile }
 // Contributed by Volker Reichelt <reichelt at gcc dot gnu dot org> 
+// { dg-options "-fshow-column" }
 // PR c++/14008: Improve diagnostic on invalid types in declarators.
 
 namespace N
@@ -9,29 +10,29 @@ namespace N
   int K;
 }
 
-N::A f2;              // { dg-error "without an argument list" }
-N::INVALID f3;        // { dg-error "in namespace 'N' does not name a type" }
-N::C::INVALID f4;     // { dg-error "in class 'N::C' does not name a type" }
-N::K f6;              // { dg-error "in namespace 'N' does not name a type" }
-typename N::A f7;     // { dg-error "without an argument list|outside of template" }
+N::A f2;              // { dg-error "4: error: invalid use of template-name 'N::A' without an argument list" }
+N::INVALID f3;        // { dg-error "4: error: 'INVALID' in namespace 'N' does not name a type" }
+N::C::INVALID f4;     // { dg-error "7: error: 'INVALID' in class 'N::C' does not name a type" }
+N::K f6;              // { dg-error "4: error: 'K' in namespace 'N' does not name a type" }
+typename N::A f7;     // { dg-error "1: error: using 'typename' outside of template|13: error: invalid use of template-name 'N::A' without an argument list|17: error: invalid type in declaration before ';' token" }
 
 struct B
 {
-  N::A f2;            // { dg-error "without an argument list" }
-  N::INVALID f3;      // { dg-error "in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "in namespace 'N' does not name a type" }
-  typename N::A f7;   // { dg-error "without an argument list|outside of template" }
+  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  typename N::A f7;   // { dg-error "3: error: using 'typename' outside of template|15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
 template <int>
 struct C
 {
-  N::A f2;            // { dg-error "without an argument list" }
-  N::INVALID f3;      // { dg-error "in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "in namespace 'N' does not name a type" }
-  typename N::A f7;   // { dg-error "without an argument list" }
+  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  typename N::A f7;   // { dg-error "15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
-// { dg-bogus "" "bogus excess errors in declaration" { xfail *-*-* } 16 }
+// { dg-bogus "bogus excess errors in declaration" "bogus excess errors in declaration" { xfail *-*-* } 17 }
diff --git a/gcc/testsuite/g++.dg/parse/error16.C b/gcc/testsuite/g++.dg/parse/error16.C
index 3dc58ad..ddc302c 100644
--- a/gcc/testsuite/g++.dg/parse/error16.C
+++ b/gcc/testsuite/g++.dg/parse/error16.C
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 // PR c++/16964
 
 struct A
 {
-  struct B {}; // { dg-error "previous" }
+  struct B {}; // { dg-error "12: error: previous definition of 'struct A::B'" }
 };
 
-struct A::B{}; // { dg-error "redefinition" }
+struct A::B{}; // { dg-error "11: error: redefinition of 'struct A::B'" }
diff --git a/gcc/testsuite/g++.dg/parse/error17.C b/gcc/testsuite/g++.dg/parse/error17.C
index 2a8f3f8..0e05217 100644
--- a/gcc/testsuite/g++.dg/parse/error17.C
+++ b/gcc/testsuite/g++.dg/parse/error17.C
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 // PR c++/16965
 
 template <typename T> struct B { 
-  static int Bar(T); // { dg-error "" }
+  static int Bar(T); // { dg-error "19: error: candidates are: |19: error:  " }
 }; 
 struct D : B<int>, B<char> {}; 
  
-int i2 = D::Bar(2); // { dg-error "" }
+int i2 = D::Bar(2); // { dg-error "13: error: reference to 'Bar' is ambiguous|10: error: reference to 'Bar' is ambiguous" }
diff --git a/gcc/testsuite/g++.dg/parse/error18.C b/gcc/testsuite/g++.dg/parse/error18.C
index 363aae9..926af11 100644
--- a/gcc/testsuite/g++.dg/parse/error18.C
+++ b/gcc/testsuite/g++.dg/parse/error18.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column" }
 // PR c++/16002
 
 void f()
 {
-  double Q *= 5.0; // { dg-error "initializer" }
+  double Q *= 5.0; // { dg-error "12: error: expected initializer before '..' token" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error19.C b/gcc/testsuite/g++.dg/parse/error19.C
index 24a66af..b22156a 100644
--- a/gcc/testsuite/g++.dg/parse/error19.C
+++ b/gcc/testsuite/g++.dg/parse/error19.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -fmessage-length=0   -ansi -pedantic-errors -Wno-long-long " }
 // PR C++/17867
 
 struct A
-{  // { dg-error "candidate" }
+{  // { dg-error "1: note: candidates are:" }
   A(int);
 };
 
@@ -9,5 +10,5 @@ const A& foo();
 
 void bar()
 {
-  foo()=A(0); // { dg-error "A" }
+  foo()=A(0); // { dg-error "12: error: no match for 'operator='" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/error2.C b/gcc/testsuite/g++.dg/parse/error2.C
index 8dd1e9d..075dcc2 100644
--- a/gcc/testsuite/g++.dg/parse/error2.C
+++ b/gcc/testsuite/g++.dg/parse/error2.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }
 // Properly print CALL_EXPRs while dumping expressions
 
 double g;
@@ -7,4 +8,8 @@ int func(double);
 template <int>
 struct Foo {};
 
-Foo<func(g)> f; // { dg-error "" "func(g)" }
+Foo<func(g)> f; // { dg-error "5: error: 'int func.double.' cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "10: error: 'g' cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "11: error: a function call cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "12: error: template argument 1 is invalid" "" { target *-*-* } { 11 } }
+// { dg-error "15: error: invalid type in declaration before ';' token" "" { target *-*-* } { 11 } }
diff --git a/gcc/testsuite/g++.dg/parse/error20.C b/gcc/testsuite/g++.dg/parse/error20.C
index ee7390a..9564fab 100644
--- a/gcc/testsuite/g++.dg/parse/error20.C
+++ b/gcc/testsuite/g++.dg/parse/error20.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/17821
 
 struct A {
@@ -11,7 +12,7 @@ struct C {
 };
 int main() {
   C c;
-  A(c.p.i); // { dg-error "member.*non-class" }
+  A(c.p.i); // { dg-error "9: error: request for member 'i' in 'c.C::p', which is of non-class type 'B" }
   return 0;
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error21.C b/gcc/testsuite/g++.dg/parse/error21.C
index 6e24ae2..f60bf2b 100644
--- a/gcc/testsuite/g++.dg/parse/error21.C
+++ b/gcc/testsuite/g++.dg/parse/error21.C
@@ -1,5 +1,5 @@
 // PR c++/17393
-// { dg-options "-Wall" }
+// { dg-options "-Wall -fshow-column" }
 
 struct A { };
 
@@ -7,6 +7,6 @@ void foo()
 {
   // Check that we do not complain about an unused
   // compiler-generated variable.
-  A& = a; // { dg-error "token|declarator|not declared" }
+  A& = a; // { dg-error "6: error: expected unqualified-id before '=' token|8: error: 'a' was not declared in this scope" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error22.C b/gcc/testsuite/g++.dg/parse/error22.C
index da3a62f..3014121 100644
--- a/gcc/testsuite/g++.dg/parse/error22.C
+++ b/gcc/testsuite/g++.dg/parse/error22.C
@@ -1,5 +1,6 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/15786
 
 struct A {
-  void foo(bar* p); /* { dg-error "declared" } */
+  void foo(bar* p); /* { dg-error "12: error: 'bar' has not been declared" } */
 };
diff --git a/gcc/testsuite/g++.dg/parse/error23.C b/gcc/testsuite/g++.dg/parse/error23.C
index 7d6fda2..21b2434 100644
--- a/gcc/testsuite/g++.dg/parse/error23.C
+++ b/gcc/testsuite/g++.dg/parse/error23.C
@@ -1,7 +1,9 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/19149
 
 struct QChar {
   QChar( char c );
   QChar( const QChar& c );
-  static const ; // { dg-error "" }
+  //following column number is not accurate enough but will make it for now
+  static const ; // { dg-error "10: error: declaration does not declare anything" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error24.C b/gcc/testsuite/g++.dg/parse/error24.C
index c072250..e341c34 100644
--- a/gcc/testsuite/g++.dg/parse/error24.C
+++ b/gcc/testsuite/g++.dg/parse/error24.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/19395
 
 struct A {
-  typedef int ::X; // { dg-error "" }
+  typedef int ::X; // { dg-error "17: error: typedef name may not be a nested-name-specifier" }
 };
 
 
diff --git a/gcc/testsuite/g++.dg/parse/error25.C b/gcc/testsuite/g++.dg/parse/error25.C
index 360b40f..b5cb57e 100644
--- a/gcc/testsuite/g++.dg/parse/error25.C
+++ b/gcc/testsuite/g++.dg/parse/error25.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // Origin: Steven Bosscher <steven at gcc dot gnu dot org>
 // PR c++/17401: ICE with invalid pure specifier
 
@@ -8,10 +9,10 @@
 class foo
 {
   virtual void bar1 () = 0;
-  virtual void bar2 () = __null;  // { dg-error "invalid pure specifier" }
-  virtual void bar3 () = 4;       // { dg-error "invalid pure specifier" }
-  virtual void bar4 () = A::f;    // { dg-error "invalid pure specifier" }
-  virtual void bar5 () = 0l;      // { dg-error "invalid pure specifier" }
-  virtual void bar6 () = 00;      // { dg-error "invalid pure specifier" }
-  virtual void bar7 () = 0x0;     // { dg-error "invalid pure specifier" }
+  virtual void bar2 () = __null;  // { dg-error "32: error: invalid pure specifier" }
+  virtual void bar3 () = 4;       // { dg-error "27: error: invalid pure specifier" }
+  virtual void bar4 () = A::f;    // { dg-error "27: error: invalid pure specifier" }
+  virtual void bar5 () = 0l;      // { dg-error "28: error: invalid pure specifier" }
+  virtual void bar6 () = 00;      // { dg-error "28: error: invalid pure specifier" }
+  virtual void bar7 () = 0x0;     // { dg-error "29: error: invalid pure specifier" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error26.C b/gcc/testsuite/g++.dg/parse/error26.C
index 6e2b897..81f7ba6 100644
--- a/gcc/testsuite/g++.dg/parse/error26.C
+++ b/gcc/testsuite/g++.dg/parse/error26.C
@@ -1,12 +1,12 @@
 // PR c++/20148
-// { dg-options "" }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 
 void foo()
 {
-  if (({int c[2];})) ; // { dg-error "\{\.\.\.\}" }
+  if (({int c[2];})) ; // { dg-error "7: error: ISO C.. forbids|20: error: could not convert" }
 }
 
 void bar()
 {
-  if (({})); // { dg-error "\{\.\.\.\}" }
+  if (({})); // { dg-error "7: error: ISO C.. forbids|11: error: could not convert" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/error27.C b/gcc/testsuite/g++.dg/parse/error27.C
index f52d3ce..f1fd537 100644
--- a/gcc/testsuite/g++.dg/parse/error27.C
+++ b/gcc/testsuite/g++.dg/parse/error27.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/20152
 
-struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "previous definition" }
-struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "previous definition" }
-struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "" }
-struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "" }
+struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "24: error: previous definition of 'struct KrSelectionMode'" }
+struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "52: error: previous definition of 'struct KrKDESelectionMode'" }
+struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "8: error: redefinition of 'struct KrSelectionMode'" }
+struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "8: error: redefinition of 'struct KrKDESelectionMode'" }
 KrKDESelectionMode krKDESelectionMode;
diff --git a/gcc/testsuite/g++.dg/parse/error28.C b/gcc/testsuite/g++.dg/parse/error28.C
index 046cc50..fd202a1 100644
--- a/gcc/testsuite/g++.dg/parse/error28.C
+++ b/gcc/testsuite/g++.dg/parse/error28.C
@@ -1,10 +1,11 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/21908
 
 struct virt { virt () {} virt (int i) {} };
-struct der : public virtual virt { // { dg-error "der" }
-  der (int i) : virt(i) {} // { dg-error "der" }
+struct der : public virtual virt { // { dg-error "34: note:                 der::der" }
+  der (int i) : virt(i) {} // { dg-error "13: note: candidates are: der" }
 };
 struct top : public der { 
-  // { dg-error "der\\(\\)" "" { target *-*-* } 9 } 
   top () {} // { dg-bogus "der\\(const" }
 };
+// { dg-error "10: error: no matching function for call to 'der" "" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/parse/error29.C b/gcc/testsuite/g++.dg/parse/error29.C
index b50b275..fcd091b 100644
--- a/gcc/testsuite/g++.dg/parse/error29.C
+++ b/gcc/testsuite/g++.dg/parse/error29.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/25637
 
 struct A { 
@@ -6,7 +7,7 @@ struct A {
   void operator delete(void *);
 };
 struct B { 
-  friend void A::foo() {} // { dg-error "define" }
-  friend void A::operator delete(void*) {} // { dg-error "define" }
-  friend A::A() {} // { dg-error "define" }
+  friend void A::foo() {} // { dg-error "22: error: cannot define member function 'A::foo' within 'B'" }
+  friend void A::operator delete(void*) {} // { dg-error "39: error: cannot define member function 'A::operator delete' within 'B'" }
+  friend A::A() {} // { dg-error "15: error: cannot define member function 'A::A' within 'B'" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error3.C b/gcc/testsuite/g++.dg/parse/error3.C
index a052346..1f337e9 100644
--- a/gcc/testsuite/g++.dg/parse/error3.C
+++ b/gcc/testsuite/g++.dg/parse/error3.C
@@ -1,6 +1,19 @@
+// { dg-options "-fshow-column" }
 // PR c++/10779
 
 static void InstantiateConstraint(const float&, unsigned,
-                                  void(*AddFunction)(const TYPE&,bool&, // { dg-error "" }
+                                  void(*AddFunction)(const TYPE&,bool&,
                                                      char*, char*,
-                                                     unsigned*)); // { dg-error "" }
+                                                     unsigned*));
+// { dg-error "64: error: expected ',' or '...' before '&' token" "" { target *-*-* }  { 5 } }
+
+/// in the coming test, the column information is broken as it points to
+//  the end of the declaration instead of pointing to the begining of the
+//  'TYPE' identifier. This is due to the warning being generated by the
+//  declaration groking code (gcc/cp/decl.c) and not the parser. So in that
+//  code, the exact token location information is lost as the declaration
+//  groking code manipulates TREEs only. The token location used is then
+//  the global one that is not accurate enough. Anyway, let's say it is
+//  good enough for now, until we find a way to propagate token location to
+//  code paths that manipulate TREEs only.
+// { dg-error "64: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 7 } }
diff --git a/gcc/testsuite/g++.dg/parse/error30.C b/gcc/testsuite/g++.dg/parse/error30.C
index 734a255..5c52d1e 100644
--- a/gcc/testsuite/g++.dg/parse/error30.C
+++ b/gcc/testsuite/g++.dg/parse/error30.C
@@ -1,5 +1,6 @@
 // PR c++/30854
 // { dg-do compile }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 
 struct A
 {
@@ -7,5 +8,5 @@ struct A
   A(int);
 };
 
-A a = -A();	// { dg-error "no match for.*operator-.*in.*-A\\(\\)" }
-A b = -A(5);	// { dg-error "no match for.*operator-.*in.*-A\\(5\\)" }
+A a = -A();	// { dg-error "10: error: no match for.*operator-.*in.*-A\\(\\)" }
+A b = -A(5);	// { dg-error "11: error: no match for.*operator-.*in.*-A\\(5\\)" }
diff --git a/gcc/testsuite/g++.dg/parse/error31.C b/gcc/testsuite/g++.dg/parse/error31.C
index 5264f44..d354cc3 100644
--- a/gcc/testsuite/g++.dg/parse/error31.C
+++ b/gcc/testsuite/g++.dg/parse/error31.C
@@ -1,10 +1,12 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/32190
 
 template<typename T> class foo{ };
 
 int main() {
     foo<int> i;
-    foo<foo<int> j; // { dg-error "template argument" }
+    // this column number is not accurate yet, but that will make it for now.
+    foo<foo<int> j; // { dg-error "18: error: template argument 1 is invalid" }
     int k;
     int l;
     foo<int> m;
diff --git a/gcc/testsuite/g++.dg/parse/error4.C b/gcc/testsuite/g++.dg/parse/error4.C
index aa1bfad..790e5c9 100644
--- a/gcc/testsuite/g++.dg/parse/error4.C
+++ b/gcc/testsuite/g++.dg/parse/error4.C
@@ -1,7 +1,10 @@
 // PR c++/12160
+// { dg-options "-fshow-column" }
 
-struct X { 
-  virtual void f(int, 
-		 itn,        // { dg-error "declared" }
+struct X {
+  virtual void f(int,
+		 itn,
 		 int);
-}; 
+};
+
+// { dg-error "4: error: 'itn' has not been declared" "" { target *-*-* } { 6 } }
diff --git a/gcc/testsuite/g++.dg/parse/error5.C b/gcc/testsuite/g++.dg/parse/error5.C
index 81356ce..8c9a039 100644
--- a/gcc/testsuite/g++.dg/parse/error5.C
+++ b/gcc/testsuite/g++.dg/parse/error5.C
@@ -1,4 +1,19 @@
 // PR c++/13269
+// { dg-options "-fshow-column" }
 
-class Foo { int foo() return 0; } }; // { dg-error "" }
+class Foo { int foo() return 0; } };
+
+// { dg-error "30: error: expected identifier before numeric constant" "" { target *-*-* } { 4 } }
+
+// { dg-error "23: error: named return values are no longer supported" "" { target *-*-* } { 4 } }
+
+// the column number info of this error output is still wrong because the error
+// message has been generated by cp_parser_error() which does not
+// necessarily allow accurate column number display. At some point, we will
+// need make cp_parser_error() report more accurate column numbers.
+// { dg-error "30: error: expected '\{' at end of input" "" { target *-*-* } { 4 } }
+
+// { dg-error "35: error: expected unqualified-id before '\}' token" "" {target *-*-*  } { 4 } }
+
+// { dg-error "35: error: expected declaration before '\}' token" "" {target *-*-*  } { 4 } }
 
diff --git a/gcc/testsuite/g++.dg/parse/error6.C b/gcc/testsuite/g++.dg/parse/error6.C
index 3a16669..cd1b6b8 100644
--- a/gcc/testsuite/g++.dg/parse/error6.C
+++ b/gcc/testsuite/g++.dg/parse/error6.C
@@ -1,6 +1,11 @@
 // PR c++/10603
+// { dg-options "-fshow-column" }
 
-int f(int not) { // { dg-error "!" }
-  return 1-not; // { dg-error "" }
+int f(int not) {
+  return 1-not;
 } 
 
+// { dg-error "11: error: expected ',' or '...' before '!' token" "" { target *-*-* } { 4 } }
+
+// { dg-error "15: error: expected primary\\-expression before ';' token" "" { target *-*-* }  { 5 } }
+
diff --git a/gcc/testsuite/g++.dg/parse/error7.C b/gcc/testsuite/g++.dg/parse/error7.C
index 50e7f84..f71c9aa 100644
--- a/gcc/testsuite/g++.dg/parse/error7.C
+++ b/gcc/testsuite/g++.dg/parse/error7.C
@@ -1,4 +1,7 @@
 // PR c++/12827
+// { dg-options "-fshow-column" }
 
 void f(int x
-       int y); // { dg-error "," }
+       int y);
+
+// { dg-error "8: error: expected ',' or '...' before 'int'" "" { target *-*-* } { 5 } }
diff --git a/gcc/testsuite/g++.dg/parse/error8.C b/gcc/testsuite/g++.dg/parse/error8.C
index 125f2e4..a399cfe 100644
--- a/gcc/testsuite/g++.dg/parse/error8.C
+++ b/gcc/testsuite/g++.dg/parse/error8.C
@@ -1,4 +1,10 @@
 // PR c++/13438
+// {  dg-options "-fshow-column" }
 
-struct A { friend typename struct B; };  // { dg-error "" }
-  
+struct A { friend typename struct B; };
+
+
+// { dg-error "19: error: using 'typename' outside of template" "" { target *-*-* } { 4 } }
+// { dg-error "28: error: expected nested-name-specifier before 'struct'" "" { target *-*-* } { 4 } }
+// { dg-error "35: error: multiple types in one declaration" "" { target *-*-* } { 4 } }
+// { dg-error "12: error: friend declaration does not name a class or function" "" { target *-*-* } { 4 } }
diff --git a/gcc/testsuite/g++.dg/parse/error9.C b/gcc/testsuite/g++.dg/parse/error9.C
index aa9109f..c1be697 100644
--- a/gcc/testsuite/g++.dg/parse/error9.C
+++ b/gcc/testsuite/g++.dg/parse/error9.C
@@ -1,5 +1,9 @@
 // PR c++/12613
-// { dg-options "" }
+// { dg-options "-fshow-column" }
 
 enum { FOO = 1, BAR = 2 };
-int a[] = { FOO: 1, BAR: 2 }; // { dg-error "" }
+int a[] = { FOO: 1, BAR: 2 };
+
+// the following 2 column locations are still not accurate enough
+// { dg-error "28: error: name 'FOO' used in a GNU-style designated initializer for an array" "" { target *-*-* }  { 5 } }
+// { dg-error "28: error: name 'BAR' used in a GNU-style designated initializer for an array" "" { target *-*-* }  { 5 } }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
index 42a21fc..7fe07a2 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
@@ -1,8 +1,9 @@
 // { dg-do assemble  }
+// { dg-options "-fshow-column" }
 
 struct A { // { dg-error "" } forward declaration
-  friend struct B : A {		// { dg-error "" } 
+  friend struct B : A {		// { dg-error "invalid use of incomplete type 'struct A'" }
     int x;
-  };	// { dg-error "" } class definition cannot be a friend
+  };	// { dg-error "class definition may not be declared a friend" ""  { target *-*-* } { 5 } }
   int y;
 };
diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
index c188824..7ca5b73 100644
--- a/gcc/testsuite/lib/g++.exp
+++ b/gcc/testsuite/lib/g++.exp
@@ -273,7 +273,6 @@ proc g++_target_compile { source dest type options } {
     }
 
     lappend options "additional_flags=[libio_include_flags]"
-    lappend options "additional_flags=-fno-show-column"
     lappend options "compiler=$GXX_UNDER_TEST"
 
     set options [concat $gpp_compile_options $options]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate  column numbers
  2008-06-25  6:35   ` Manuel López-Ibáñez
  2008-06-25 14:05     ` Tom Tromey
@ 2008-06-26 14:10     ` Dodji Seketeli
  2008-06-26 14:24       ` Manuel López-Ibáñez
  1 sibling, 1 reply; 12+ messages in thread
From: Dodji Seketeli @ 2008-06-26 14:10 UTC (permalink / raw)
  To: Manuel López-Ibáñez; +Cc: gcc-patches, tromey, Janis Johnson

Manuel López-Ibáñez a écrit :

[...]

> 
>> Dodji> +  //following column number is not accurate enough but will make it for now
>> Dodji> +  static const ; // { dg-error "10: error: declaration does not declare anything" }
> 
> ... is a hack. dg-error/dg-warning should get an additional (optional)
> parameter similar to the line number that allows to define a column
> number. That is my opinion, so you should ask a testsuite maintainer,
> like Janis Johnson.

You are right. Do you think this we proceed via baby steps ? I mean 
could the patch get in like that and then later I will try and add those 
extra parameters to dg-error/dg-warning ?


Cheers,

Dodji.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate column numbers
  2008-06-26 14:10     ` Dodji Seketeli
@ 2008-06-26 14:24       ` Manuel López-Ibáñez
  2008-06-26 19:08         ` Dodji Seketeli
  0 siblings, 1 reply; 12+ messages in thread
From: Manuel López-Ibáñez @ 2008-06-26 14:24 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: gcc-patches, tromey, Janis Johnson

2008/6/26 Dodji Seketeli <dseketel@redhat.com>:
> Manuel López-Ibáñez a écrit :
>
> [...]
>
>>
>>> Dodji> +  //following column number is not accurate enough but will make
>>> it for now
>>> Dodji> +  static const ; // { dg-error "10: error: declaration does not
>>> declare anything" }
>>
>> ... is a hack. dg-error/dg-warning should get an additional (optional)
>> parameter similar to the line number that allows to define a column
>> number. That is my opinion, so you should ask a testsuite maintainer,
>> like Janis Johnson.
>
> You are right. Do you think this we proceed via baby steps ? I mean could
> the patch get in like that and then later I will try and add those extra
> parameters to dg-error/dg-warning ?

On the one hand, if this goes in, it is going to be difficult to
notice it and change it afterwards. On the other hand, I understand
that implementing a column parameter for the various dg-* things may
be difficult. DejaGNU is not the easiest or enjoyable part of GCC to
hack. After all, we are still using the "dg-error "error:" hack
everywhere except in the C testsuite.

Anyway, my opinion doesn't matter since I can't approve patches.
Maintainers should voice their preference here. At the minimum, if
this goes in like this, you could open a PR about the missing
"column-number" parameter to dg-* and point to this testcase, so if it
ever gets fixed, the testcase can be updated.

BTW, if you plan to keep hacking on column numbers. I have an
experimental patch to add caret diagnostics that may help you to
pin-point where a location is actually pointing to.

Cheers,

Manuel.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate   column  numbers
  2008-06-26 13:58   ` Dodji Seketeli
@ 2008-06-26 18:39     ` Dodji Seketeli
  2008-07-02 10:37       ` Dodji Seketeli
  0 siblings, 1 reply; 12+ messages in thread
From: Dodji Seketeli @ 2008-06-26 18:39 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 93 bytes --]

Sorry, I am re-sending my last patch because it had an issue wrt ChangeLog.

Cheers,

Dodji.

[-- Attachment #2: gcc-error-location-2008-06-26-gcc-patch.txt --]
[-- Type: text/plain, Size: 131146 bytes --]

gcc/cp/ChangeLog:
2008-06-18 Dodji Seketeli <dseketel@redhat.com>

	PR c++/31754
	* pt.c, semantic.c:
	* semantic.c (qualified_name_lookup_error, finish_id_expression):
	add a location_t parameter so that
	error message can have a more accurate location.
	* cp-tree.h: updated prototype
	* pt.c (tsubst_qualified_id): use location in error messages.
	* parser.c (cp_parser_postfix_expression,
	cp_parser_objc_statement, cp_parser_trait_expr,
	cp_parser_token_is_class_key,
	cp_parser_uncommitted_to_tentative_parse_p,
	cp_parser_check_for_invalid_template_id, cp_parser_is_string_literal,
	cp_parser_error, cp_parser_name_lookup_error,
	cp_parser_simulate_error, cp_parser_check_decl_spec,
	cp_parser_check_decl_spec, cp_parser_non_integral_constant_expression,
	cp_parser_diagnose_invalid_type_name,
	cp_parser_parse_and_diagnose_invalid_type_name,
	cp_parser_require_pragma_eol, cp_parser_make_typename_type,
	cp_parser_string_literal, cp_parser_primary_expression,
	cp_parser_primary_expression, cp_parser_unqualified_id,
	cp_parser_nested_name_specifier_opt, cp_parser_postfix_expression,
	cp_parser_postfix_dot_deref_expression, cp_parser_new_expression,
	cp_parser_direct_new_declarator, cp_parser_builtin_offsetof,
	cp_parser_label_for_labeled_statement, cp_parser_statement_seq_opt,
	cp_parser_jump_statement, cp_parser_block_declaration,
	cp_parser_simple_declaration, cp_parser_decl_specifier_seq,
	cp_parser_function_specifier_opt, cp_parser_decltype,
	cp_parser_mem_initializer_list, cp_parser_mem_initializer,
	cp_parser_mem_initializer_id, cp_parser_template_parameter,
	cp_parser_type_parameter, cp_parser_template_id, cp_parser_template_name,
	cp_parser_template_argument): likewise.

gcc/testsuite/ChangeLog:
2008-06-18 Dodji Seketeli <dseketel@redhat.com>

	* g++.dg/parse/constructor1.C, g++.dg/parse/error*.C: update these
	  tests to make them catch column number regressions. Make these tests
	  run with the -fshow-column option.
	* g++.dg/parse/error-column.C: new column number test.


diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d090d8f..afea188 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4632,13 +4632,15 @@ extern void finish_template_decl		(tree);
 extern tree finish_template_type		(tree, tree, int);
 extern tree finish_base_specifier		(tree, tree, bool);
 extern void finish_member_declaration		(tree);
-extern void qualified_name_lookup_error		(tree, tree, tree);
+extern void qualified_name_lookup_error		(tree, tree, tree,
+						 location_t);
 extern void check_template_keyword		(tree);
 extern tree finish_id_expression		(tree, tree, tree,
 						 cp_id_kind *,
 						 bool, bool, bool *,
 						 bool, bool, bool, bool,
-						 const char **);
+						 const char **,
+                                                 location_t);
 extern tree finish_typeof			(tree);
 extern tree finish_offsetof			(tree);
 extern void finish_decl_cleanup			(tree, tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7d530f5..184b9ec 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1585,7 +1585,7 @@ static tree cp_parser_postfix_expression
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
-  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
+  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
 static tree cp_parser_parenthesized_expression_list
   (cp_parser *, bool, bool, bool, bool *);
 static void cp_parser_pseudo_destructor_name
@@ -1894,15 +1894,15 @@ static tree cp_parser_objc_statement
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
-  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
+  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t);
 static tree cp_parser_lookup_name_simple
-  (cp_parser *, tree);
+  (cp_parser *, tree, location_t);
 static tree cp_parser_maybe_treat_template_as_class
   (tree, bool);
 static bool cp_parser_check_declarator_template_parameters
-  (cp_parser *, cp_declarator *);
+  (cp_parser *, cp_declarator *, location_t);
 static bool cp_parser_check_template_parameters
-  (cp_parser *, unsigned);
+  (cp_parser *, unsigned, location_t);
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
@@ -1938,7 +1938,7 @@ static tree cp_parser_trait_expr
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
-  (cp_parser *, cp_decl_specifier_seq *, enum rid);
+  (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
 static void cp_parser_set_decl_spec_type
   (cp_decl_specifier_seq *, tree, bool);
 static bool cp_parser_friend_p
@@ -1960,7 +1960,7 @@ static enum tag_types cp_parser_token_is_class_key
 static void cp_parser_check_class_key
   (enum tag_types, tree type);
 static void cp_parser_check_access_in_redeclaration
-  (tree type);
+  (tree type, location_t location);
 static bool cp_parser_optional_template_keyword
   (cp_parser *);
 static void cp_parser_pre_parsed_nested_name_specifier
@@ -1982,7 +1982,7 @@ static bool cp_parser_uncommitted_to_tentative_parse_p
 static void cp_parser_error
   (cp_parser *, const char *);
 static void cp_parser_name_lookup_error
-  (cp_parser *, tree, tree, const char *);
+  (cp_parser *, tree, tree, const char *, location_t);
 static bool cp_parser_simulate_error
   (cp_parser *);
 static bool cp_parser_check_type_definition
@@ -1994,7 +1994,7 @@ static void cp_parser_check_for_invalid_template_id
 static bool cp_parser_non_integral_constant_expression
   (cp_parser *, const char *);
 static void cp_parser_diagnose_invalid_type_name
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t);
 static bool cp_parser_parse_and_diagnose_invalid_type_name
   (cp_parser *);
 static int cp_parser_skip_to_closing_parenthesis
@@ -2020,7 +2020,7 @@ static bool cp_parser_is_string_literal
 static bool cp_parser_is_keyword
   (cp_token *, enum rid);
 static tree cp_parser_make_typename_type
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t location);
 static cp_declarator * cp_parser_make_indirect_declarator
   (enum tree_code, tree, cp_cv_quals, cp_declarator *);
 
@@ -2069,7 +2069,7 @@ cp_parser_error (cp_parser* parser, const char* message)
 
       if (token->type == CPP_PRAGMA)
 	{
-	  error ("%<#pragma%> is not allowed here");
+	  error ("%H%<#pragma%> is not allowed here", &token->location);
 	  cp_parser_skip_to_pragma_eol (parser, token);
 	  return;
 	}
@@ -2092,33 +2092,34 @@ static void
 cp_parser_name_lookup_error (cp_parser* parser,
 			     tree name,
 			     tree decl,
-			     const char* desired)
+			     const char* desired,
+			     location_t location)
 {
   /* If name lookup completely failed, tell the user that NAME was not
      declared.  */
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-	error ("%<%E::%E%> has not been declared",
-	       parser->scope, name);
+	error ("%H%<%E::%E%> has not been declared",
+	       &location, parser->scope, name);
       else if (parser->scope == global_namespace)
-	error ("%<::%E%> has not been declared", name);
+	error ("%H%<::%E%> has not been declared", &location, name);
       else if (parser->object_scope
 	       && !CLASS_TYPE_P (parser->object_scope))
-	error ("request for member %qE in non-class type %qT",
-	       name, parser->object_scope);
+	error ("%Hrequest for member %qE in non-class type %qT",
+	       &location, name, parser->object_scope);
       else if (parser->object_scope)
-	error ("%<%T::%E%> has not been declared",
-	       parser->object_scope, name);
+	error ("%H%<%T::%E%> has not been declared",
+	       &location, parser->object_scope, name);
       else
-	error ("%qE has not been declared", name);
+	error ("%H%qE has not been declared", &location, name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("%<%E::%E%> %s", parser->scope, name, desired);
+    error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
   else if (parser->scope == global_namespace)
-    error ("%<::%E%> %s", name, desired);
+    error ("%H%<::%E%> %s", &location, name, desired);
   else
-    error ("%qE %s", name, desired);
+    error ("%H%qE %s", &location, name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -2139,7 +2140,8 @@ cp_parser_simulate_error (cp_parser* parser)
 /* Check for repeated decl-specifiers.  */
 
 static void
-cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
+cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
+			   location_t location)
 {
   cp_decl_spec ds;
 
@@ -2152,10 +2154,11 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
       if (ds == ds_long)
 	{
 	  if (count > 2)
-	    error ("%<long long long%> is too long for GCC");
+	    error ("%H%<long long long%> is too long for GCC", &location);
 	  else if (pedantic && !in_system_header && warn_long_long
                    && cxx_dialect == cxx98)
-	    pedwarn ("ISO C++ 1998 does not support %<long long%>");
+	    pedwarn ("%HISO C++ 1998 does not support %<long long%>",
+		     &location);
 	}
       else if (count > 1)
 	{
@@ -2175,7 +2178,7 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
 	    "__complex",
 	    "__thread"
 	  };
-	  error ("duplicate %qs", decl_spec_names[(int)ds]);
+	  error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
 	}
     }
 }
@@ -2291,13 +2294,15 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
    in duplicate error messages.)  */
 
 static void
-cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
+cp_parser_diagnose_invalid_type_name (cp_parser *parser,
+				      tree scope, tree id,
+				      location_t id_location)
 {
   tree decl, old_scope;
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
-  decl = cp_parser_lookup_name_simple (parser, id);
+  decl = cp_parser_lookup_name_simple (parser, id, id_location);
   parser->scope = old_scope;
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
@@ -2382,6 +2387,7 @@ static bool
 cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
 {
   tree id;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   cp_parser_parse_tentatively (parser);
   id = cp_parser_id_expression (parser,
@@ -2405,7 +2411,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
-  cp_parser_diagnose_invalid_type_name (parser, parser->scope, id);
+  cp_parser_diagnose_invalid_type_name (parser, parser->scope,
+					id, token->location);
   /* Skip to the end of the declaration; there's no point in
      trying to process it.  */
   cp_parser_skip_to_end_of_block_or_statement (parser);
@@ -2693,7 +2700,8 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok)
    using cp_parser_diagnose_invalid_type_name.  */
 
 static tree
-cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
+cp_parser_make_typename_type (cp_parser *parser, tree scope,
+			      tree id, location_t id_location)
 {
   tree result;
   if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -2701,7 +2709,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
       result = make_typename_type (scope, id, typename_type,
 				   /*complain=*/tf_none);
       if (result == error_mark_node)
-	cp_parser_diagnose_invalid_type_name (parser, scope, id);
+	cp_parser_diagnose_invalid_type_name (parser, scope, id, id_location);
       return result;
     }
   return make_typename_type (scope, id, typename_type, tf_error);
@@ -2919,7 +2927,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
 	      if (type == CPP_STRING)
 		type = tok->type;
 	      else if (tok->type != CPP_STRING)
-		error ("unsupported non-standard concatenation of string literals");
+		error ("%Hunsupported non-standard concatenation "
+                       "of string literals", &tok->location);
 	    }
 
 	  obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -3098,7 +3107,7 @@ cp_parser_primary_expression (cp_parser *parser,
 			      bool template_arg_p,
 			      cp_id_kind *idk)
 {
-  cp_token *token;
+  cp_token *token = NULL;
 
   /* Assume the primary expression is not an id-expression.  */
   *idk = CP_ID_KIND_NONE;
@@ -3196,7 +3205,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  {
 	    /* Statement-expressions are not allowed by the standard.  */
 	    if (pedantic)
-	      pedwarn ("ISO C++ forbids braced-groups within expressions");
+	      pedwarn ("%HISO C++ forbids braced-groups within expressions",
+		       &token->location);
 
 	    /* And they're not allowed outside of a function-body; you
 	       cannot, for example, write:
@@ -3207,8 +3217,9 @@ cp_parser_primary_expression (cp_parser *parser,
 	    if (!parser->in_function_body
 		|| parser->in_template_argument_list_p)
 	      {
-		error ("statement-expressions are not allowed outside "
-		       "functions nor in template-argument lists");
+		error ("%Hstatement-expressions are not allowed outside "
+		       "functions nor in template-argument lists",
+		       &token->location);
 		cp_parser_skip_to_end_of_block_or_statement (parser);
 		expr = error_mark_node;
 	      }
@@ -3265,7 +3276,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  cp_lexer_consume_token (parser->lexer);
 	  if (parser->local_variables_forbidden_p)
 	    {
-	      error ("%<this%> may not be used in this context");
+	      error ("%H%<this%> may not be used in this context",
+                     &token->location);
 	      return error_mark_node;
 	    }
 	  /* Pointers cannot appear in constant-expressions.  */
@@ -3365,6 +3377,7 @@ cp_parser_primary_expression (cp_parser *parser,
 	const char *error_msg;
 	bool template_p;
 	bool done;
+	cp_token *id_expr_token;
 
       id_expression:
 	/* Parse the id-expression.  */
@@ -3377,6 +3390,7 @@ cp_parser_primary_expression (cp_parser *parser,
 				     /*optional_p=*/false);
 	if (id_expression == error_mark_node)
 	  return error_mark_node;
+	id_expr_token = token;
 	token = cp_lexer_peek_token (parser->lexer);
 	done = (token->type != CPP_OPEN_SQUARE
 		&& token->type != CPP_OPEN_PAREN
@@ -3400,7 +3414,8 @@ cp_parser_primary_expression (cp_parser *parser,
 					  template_p,
 					  /*is_namespace=*/false,
 					  /*check_dependency=*/true,
-					  &ambiguous_decls);
+					  &ambiguous_decls,
+					  id_expr_token->location);
 	    /* If the lookup was ambiguous, an error will already have
 	       been issued.  */
 	    if (ambiguous_decls)
@@ -3447,8 +3462,8 @@ cp_parser_primary_expression (cp_parser *parser,
 		decl = check_for_out_of_scope_variable (decl);
 		if (local_variable_p (decl))
 		  {
-		    error ("local variable %qD may not appear in this context",
-			   decl);
+		    error ("%Hlocal variable %qD may not appear in this context",
+			   &id_expr_token->location, decl);
 		    return error_mark_node;
 		  }
 	      }
@@ -3462,7 +3477,8 @@ cp_parser_primary_expression (cp_parser *parser,
 		 &parser->non_integral_constant_expression_p,
 		 template_p, done, address_p,
 		 template_arg_p,
-		 &error_msg));
+		 &error_msg,
+                 id_expr_token->location));
 	if (error_msg)
 	  cp_parser_error (parser, error_msg);
 	return decl;
@@ -3746,7 +3762,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	      error ("scope %qT before %<~%> is not a class-name", scope);
+	      error ("%Hscope %qT before %<~%> is not a class-name",
+		     &token->location, scope);
 	    cp_parser_simulate_error (parser);
 	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
 	      cp_lexer_consume_token (parser->lexer);
@@ -3847,8 +3864,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	if (declarator_p && scope && !check_dtor_name (scope, type_decl))
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	      error ("declaration of %<~%T%> as member of %qT",
-		     type_decl, scope);
+	      error ("%Hdeclaration of %<~%T%> as member of %qT",
+		     &token->location, type_decl, scope);
 	    cp_parser_simulate_error (parser);
 	    return error_mark_node;
 	  }
@@ -3861,8 +3878,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	    && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
 	    && !DECL_SELF_REFERENCE_P (type_decl)
 	    && !cp_parser_uncommitted_to_tentative_parse_p (parser))
-	  error ("typedef-name %qD used as destructor declarator",
-		 type_decl);
+	  error ("%Htypedef-name %qD used as destructor declarator",
+		 &token->location, type_decl);
 
 	return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
@@ -4066,20 +4083,23 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
 						    /*is_template=*/false,
 						    /*is_namespace=*/false,
 						    /*check_dependency=*/true,
-						    &ambiguous_decls);
+						    &ambiguous_decls,
+						    token->location);
 		      if (TREE_CODE (decl) == TEMPLATE_DECL)
-			error ("%qD used without template parameters", decl);
+			error ("%H%qD used without template parameters",
+			       &token->location, decl);
 		      else if (ambiguous_decls)
 			{
-			  error ("reference to %qD is ambiguous",
-				 token->u.value);
+			  error ("%Hreference to %qD is ambiguous",
+				 &token->location, token->u.value);
 			  print_candidates (ambiguous_decls);
 			  decl = error_mark_node;
 			}
 		      else
 			cp_parser_name_lookup_error
 			  (parser, token->u.value, decl,
-			   "is not a class or namespace");
+			   "is not a class or namespace",
+			   token->location);
 		    }
 		  parser->scope = error_mark_node;
 		  error_p = true;
@@ -4731,7 +4751,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	  postfix_expression
 	    = cp_parser_postfix_dot_deref_expression (parser, token->type,
 						      postfix_expression,
-						      false, &idk);
+						      false, &idk,
+						      token->location);
 
           is_member_access = true;
 	  break;
@@ -4845,7 +4866,8 @@ static tree
 cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 					enum cpp_ttype token_type,
 					tree postfix_expression,
-					bool for_offsetof, cp_id_kind *idk)
+					bool for_offsetof, cp_id_kind *idk,
+					location_t location)
 {
   tree name;
   bool dependent_p;
@@ -4877,7 +4899,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
 	{
-	  error ("%qE does not have class type", postfix_expression);
+	  error ("%H%qE does not have class type", &location, postfix_expression);
 	  scope = NULL_TREE;
 	}
       else
@@ -4933,6 +4955,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 ordinary class member access expression, rather than a
 	 pseudo-destructor-name.  */
       bool template_p;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
       /* Parse the id-expression.  */
       name = (cp_parser_id_expression
 	      (parser,
@@ -4960,7 +4983,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 TYPE_DECL here.  That is invalid code.  */
       if (TREE_CODE (name) == TYPE_DECL)
 	{
-	  error ("invalid use of %qD", name);
+	  error ("%Hinvalid use of %qD", &token->location, name);
 	  postfix_expression = error_mark_node;
 	}
       else
@@ -5514,18 +5537,21 @@ cp_parser_new_expression (cp_parser* parser)
      type-id.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
+      cp_token *token;
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the type-id.  */
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      token = cp_lexer_peek_token (parser->lexer);
       /* There should not be a direct-new-declarator in this production,
 	 but GCC used to allowed this, so we check and emit a sensible error
 	 message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
 	{
-	  error ("array bound forbidden after parenthesized type-id");
+	  error ("%Harray bound forbidden after parenthesized type-id",
+		 &token->location);
 	  inform ("try removing the parentheses around the type-id");
 	  cp_parser_direct_new_declarator (parser);
 	}
@@ -5702,6 +5728,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       /* The first expression is not required to be constant.  */
       if (!declarator)
 	{
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
 	  expression = cp_parser_expression (parser, /*cast_p=*/false);
 	  /* The standard requires that the expression have integral
 	     type.  DR 74 adds enumeration types.  We believe that the
@@ -5717,8 +5744,8 @@ cp_parser_direct_new_declarator (cp_parser* parser)
 					      /*complain=*/true);
 	      if (!expression)
 		{
-		  error ("expression in new-declarator must have integral "
-			 "or enumeration type");
+		  error ("%Hexpression in new-declarator must have integral "
+			 "or enumeration type", &token->location);
 		  expression = error_mark_node;
 		}
 	    }
@@ -6445,6 +6472,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   int save_ice_p, save_non_ice_p;
   tree type, expr;
   cp_id_kind dummy;
+  cp_token *token;
 
   /* We're about to accept non-integral-constant things, but will
      definitely yield an integral constant expression.  Save and
@@ -6460,6 +6488,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
   cp_parser_require (parser, CPP_COMMA, "%<,%>");
+  token = cp_lexer_peek_token (parser->lexer);
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
   expr = build_static_cast (build_pointer_type (type), null_pointer_node,
@@ -6467,10 +6496,10 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 
   /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
   expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
-						 true, &dummy);
+						 true, &dummy, token->location);
   while (true)
     {
-      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
       switch (token->type)
 	{
 	case CPP_OPEN_SQUARE:
@@ -6482,7 +6511,8 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 	  /* offsetof-member-designator "." identifier */
 	  cp_lexer_consume_token (parser->lexer);
 	  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
-							 true, &dummy);
+							 true, &dummy,
+							 token->location);
 	  break;
 
 	case CPP_CLOSE_PAREN:
@@ -6844,7 +6874,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
 	if (parser->in_switch_statement_p)
 	  finish_case_label (expr, expr_hi);
 	else
-	  error ("case label %qE not within a switch statement", expr);
+	  error ("%Hcase label %qE not within a switch statement",
+		 &token->location, expr);
       }
       break;
 
@@ -6855,7 +6886,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
       if (parser->in_switch_statement_p)
 	finish_case_label (NULL_TREE, NULL_TREE);
       else
-	error ("case label not within a switch statement");
+	error ("%Hcase label not within a switch statement", &token->location);
       break;
 
     default:
@@ -6973,7 +7004,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
 	  else
 	    {
 	      token = cp_lexer_consume_token (parser->lexer);
-	      error ("%<else%> without a previous %<if%>");
+	      error ("%H%<else%> without a previous %<if%>", &token->location);
 	    }
 	}
 
@@ -7457,7 +7488,7 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (in_statement)
 	{
 	case 0:
-	  error ("break statement not within loop or switch");
+	  error ("%Hbreak statement not within loop or switch", &token->location);
 	  break;
 	default:
 	  gcc_assert ((in_statement & IN_SWITCH_STMT)
@@ -7465,10 +7496,10 @@ cp_parser_jump_statement (cp_parser* parser)
 	  statement = finish_break_stmt ();
 	  break;
 	case IN_OMP_BLOCK:
-	  error ("invalid exit from OpenMP structured block");
+	  error ("%Hinvalid exit from OpenMP structured block", &token->location);
 	  break;
 	case IN_OMP_FOR:
-	  error ("break statement used with OpenMP for loop");
+	  error ("%Hbreak statement used with OpenMP for loop", &token->location);
 	  break;
 	}
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
@@ -7478,14 +7509,14 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
 	{
 	case 0:
-	  error ("continue statement not within a loop");
+	  error ("%Hcontinue statement not within a loop", &token->location);
 	  break;
 	case IN_ITERATION_STMT:
 	case IN_OMP_FOR:
 	  statement = finish_continue_stmt ();
 	  break;
 	case IN_OMP_BLOCK:
-	  error ("invalid exit from OpenMP structured block");
+	  error ("%Hinvalid exit from OpenMP structured block", &token->location);
 	  break;
 	default:
 	  gcc_unreachable ();
@@ -7516,7 +7547,7 @@ cp_parser_jump_statement (cp_parser* parser)
 	{
 	  /* Issue a warning about this use of a GNU extension.  */
 	  if (pedantic)
-	    pedwarn ("ISO C++ forbids computed gotos");
+	    pedwarn ("%HISO C++ forbids computed gotos", &token->location);
 	  /* Consume the '*' token.  */
 	  cp_lexer_consume_token (parser->lexer);
 	  /* Parse the dependent expression.  */
@@ -7877,7 +7908,7 @@ cp_parser_block_declaration (cp_parser *parser,
   else if (token1->keyword == RID_LABEL)
     {
       cp_lexer_consume_token (parser->lexer);
-      error ("%<__label__%> not at the beginning of a block");
+      error ("%H%<__label__%> not at the beginning of a block", &token1->location);
       cp_parser_skip_to_end_of_statement (parser);
       /* If the next token is now a `;', consume it.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -8010,7 +8041,11 @@ cp_parser_simple_declaration (cp_parser* parser,
 
 	     which is erroneous.  */
 	  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-	    error ("mixing declarations and function-definitions is forbidden");
+	    {
+	      cp_token *token = cp_lexer_peek_token (parser->lexer);
+	      error ("%Hmixing declarations and function-definitions is forbidden",
+		     &token->location);
+	    }
 	  /* Otherwise, we're done with the list of declarators.  */
 	  else
 	    {
@@ -8106,6 +8141,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 			      int* declares_class_or_enum)
 {
   bool constructor_possible_p = !parser->in_declarator_p;
+  cp_token *start_token = NULL;
 
   /* Clear DECL_SPECS.  */
   clear_decl_specs (decl_specs);
@@ -8122,6 +8158,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
+
+      /* Save the first token of the decl spec list for error
+         reporting.  */
+      if (!start_token)
+	start_token = token;
       /* Handle attributes.  */
       if (token->keyword == RID_ATTRIBUTE)
 	{
@@ -8198,15 +8239,17 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
                  we're complaining about C++0x compatibility.  */
               warning 
                 (OPT_Wc__0x_compat, 
-                 "%<auto%> will change meaning in C++0x; please remove it");
+                 "%H%<auto%> will change meaning in C++0x; please remove it",
+		 &token->location);
 
               /* Set the storage class anyway.  */
-              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO);
+              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
+					   token->location);
             }
           else 
             /* We do not yet support the use of `auto' as a
                type-specifier.  */
-            error ("C++0x %<auto%> specifier not supported");
+            error ("%HC++0x %<auto%> specifier not supported", &token->location);
           break;
 
 	case RID_REGISTER:
@@ -8215,7 +8258,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 	case RID_MUTABLE:
 	  /* Consume the token.  */
 	  cp_lexer_consume_token (parser->lexer);
-          cp_parser_set_storage_class (parser, decl_specs, token->keyword);
+          cp_parser_set_storage_class (parser, decl_specs, token->keyword,
+				       token->location);
 	  break;
 	case RID_THREAD:
 	  /* Consume the token.  */
@@ -8251,7 +8295,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 					/*is_declaration=*/true,
 					&decl_spec_declares_class_or_enum,
 					&is_cv_qualifier);
-
 	  *declares_class_or_enum |= decl_spec_declares_class_or_enum;
 
 	  /* If this type-specifier referenced a user-defined type
@@ -8311,12 +8354,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
-  cp_parser_check_decl_spec (decl_specs);
+  cp_parser_check_decl_spec (decl_specs, start_token->location);
 
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
-    error ("class definition may not be declared a friend");
+    error ("%Hclass definition may not be declared a friend",
+	    &start_token->location);
 }
 
 /* Parse an (optional) storage-class-specifier.
@@ -8372,7 +8416,8 @@ static tree
 cp_parser_function_specifier_opt (cp_parser* parser,
 				  cp_decl_specifier_seq *decl_specs)
 {
-  switch (cp_lexer_peek_token (parser->lexer)->keyword)
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  switch (token->keyword)
     {
     case RID_INLINE:
       if (decl_specs)
@@ -8384,7 +8429,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
 
 	 A member function template shall not be virtual.  */
       if (PROCESSING_REAL_TEMPLATE_DECL_P ())
-	error ("templates may not be %<virtual%>");
+	error ("%Htemplates may not be %<virtual%>", &token->location);
       else if (decl_specs)
 	++decl_specs->specs[(int) ds_virtual];
       break;
@@ -8538,6 +8583,7 @@ cp_parser_decltype (cp_parser *parser)
   const char *saved_message;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
+  cp_token *id_expr_start_token;
 
   /* Look for the `decltype' token.  */
   if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
@@ -8567,6 +8613,7 @@ cp_parser_decltype (cp_parser *parser)
     return error_mark_node;
   
   /* First, try parsing an id-expression.  */
+  id_expr_start_token = cp_lexer_peek_token (parser->lexer);
   cp_parser_parse_tentatively (parser);
   expr = cp_parser_id_expression (parser,
                                   /*template_keyword_p=*/false,
@@ -8589,7 +8636,8 @@ cp_parser_decltype (cp_parser *parser)
 				      /*is_template=*/false,
 				      /*is_namespace=*/false,
 				      /*check_dependency=*/true,
-				      /*ambiguous_decls=*/NULL);
+				      /*ambiguous_decls=*/NULL,
+				      id_expr_start_token->location);
 
       if (expr
           && expr != error_mark_node
@@ -8609,7 +8657,8 @@ cp_parser_decltype (cp_parser *parser)
                    /*done=*/true,
                    /*address_p=*/false,
                    /*template_arg_p=*/false,
-                   &error_msg));
+                   &error_msg,
+		   id_expr_start_token->location));
 
           if (expr == error_mark_node)
             /* We found an id-expression, but it was something that we
@@ -8852,17 +8901,20 @@ static void
 cp_parser_mem_initializer_list (cp_parser* parser)
 {
   tree mem_initializer_list = NULL_TREE;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Let the semantic analysis code know that we are starting the
      mem-initializer-list.  */
   if (!DECL_CONSTRUCTOR_P (current_function_decl))
-    error ("only constructors take base initializers");
+    error ("%Honly constructors take base initializers",
+	   &token->location);
 
   /* Loop through the list.  */
   while (true)
     {
       tree mem_initializer;
 
+      token = cp_lexer_peek_token (parser->lexer);
       /* Parse the mem-initializer.  */
       mem_initializer = cp_parser_mem_initializer (parser);
       /* If the next token is a `...', we're expanding member initializers. */
@@ -8876,8 +8928,8 @@ cp_parser_mem_initializer_list (cp_parser* parser)
           if (mem_initializer != error_mark_node
               && !TYPE_P (TREE_PURPOSE (mem_initializer)))
             {
-              error ("cannot expand initializer for member %<%D%>", 
-                     TREE_PURPOSE (mem_initializer));
+              error ("%Hcannot expand initializer for member %<%D%>",
+                     &token->location, TREE_PURPOSE (mem_initializer));
               mem_initializer = error_mark_node;
             }
 
@@ -8924,11 +8976,13 @@ cp_parser_mem_initializer (cp_parser* parser)
   tree mem_initializer_id;
   tree expression_list;
   tree member;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
-      permerror ("anachronistic old-style base class initializer");
+      permerror ("%Hanachronistic old-style base class initializer",
+                 &token->location);
       mem_initializer_id = NULL_TREE;
     }
   else
@@ -8970,11 +9024,14 @@ cp_parser_mem_initializer_id (cp_parser* parser)
   bool template_p = false;
   tree id;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* `typename' is not allowed in this context ([temp.res]).  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
-      error ("keyword %<typename%> not allowed in this context (a qualified "
-	     "member initializer is implicitly a type)");
+      error ("%Hkeyword %<typename%> not allowed in this context (a qualified "
+	     "member initializer is implicitly a type)",
+	     &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the optional `::' operator.  */
@@ -9491,6 +9548,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	 appropriate diagnostic here.  */
 
       /* Consume the `='.  */
+      cp_token *start_token = cp_lexer_peek_token (parser->lexer);
       cp_lexer_consume_token (parser->lexer);
       
       /* Find the name of the parameter pack.  */     
@@ -9499,10 +9557,11 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	id_declarator = id_declarator->declarator;
       
       if (id_declarator && id_declarator->kind == cdk_id)
-	error ("template parameter pack %qD cannot have a default argument",
-	       id_declarator->u.id.unqualified_name);
+	error ("%Htemplate parameter pack %qD cannot have a default argument",
+	       &start_token->location, id_declarator->u.id.unqualified_name);
       else
-	error ("template parameter pack cannot have a default argument");
+	error ("%Htemplate parameter pack cannot have a default argument",
+	       &start_token->location);
       
       /* Parse the default argument, but throw away the result.  */
       cp_parser_default_argument (parser, /*template_parm_p=*/true);
@@ -9596,10 +9655,11 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("template parameter pack %qD cannot have a default argument", 
-                         identifier);
+                  error ("%Htemplate parameter pack %qD cannot have a "
+			 "default argument", &token->location, identifier);
                 else
-                  error ("template parameter packs cannot have default arguments");
+                  error ("%Htemplate parameter packs cannot have "
+			 "default arguments", &token->location);
                 default_argument = NULL_TREE;
               }
 	    pop_deferring_access_checks ();
@@ -9667,6 +9727,9 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 	    cp_lexer_consume_token (parser->lexer);
 	    /* Parse the id-expression.  */
 	    push_deferring_access_checks (dk_no_deferred);
+	    /* save token before parsing the id-expression, for error
+	       reporting */
+	    token = cp_lexer_peek_token (parser->lexer);
 	    default_argument
 	      = cp_parser_id_expression (parser,
 					 /*template_keyword_p=*/false,
@@ -9687,7 +9750,8 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 					 /*is_template=*/is_template,
 					 /*is_namespace=*/false,
 					 /*check_dependency=*/true,
-					 /*ambiguous_decls=*/NULL);
+					 /*ambiguous_decls=*/NULL,
+					 token->location);
 	    /* See if the default argument is valid.  */
 	    default_argument
 	      = check_template_template_default_arg (default_argument);
@@ -9697,10 +9761,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("template parameter pack %qD cannot have a default argument", 
-                         identifier);
+                  error ("%Htemplate parameter pack %qD cannot "
+			 "have a default argument",
+			 &token->location, identifier);
                 else
-                  error ("template parameter packs cannot have default arguments");
+                  error ("%Htemplate parameter packs cannot "
+			 "have default arguments",
+			 &token->location);
                 default_argument = NULL_TREE;
               }
 	    pop_deferring_access_checks ();
@@ -9749,7 +9816,7 @@ cp_parser_template_id (cp_parser *parser,
   cp_token_position start_of_id = 0;
   deferred_access_check *chk;
   VEC (deferred_access_check,gc) *access_check;
-  cp_token *next_token, *next_token_2;
+  cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
   bool is_identifier;
 
   /* If the next token corresponds to a template-id, there is no need
@@ -9797,6 +9864,7 @@ cp_parser_template_id (cp_parser *parser,
 
   /* Parse the template-name.  */
   is_identifier = false;
+  token = cp_lexer_peek_token (parser->lexer);
   template = cp_parser_template_name (parser, template_keyword_p,
 				      check_dependency_p,
 				      is_declaration,
@@ -9823,6 +9891,7 @@ cp_parser_template_id (cp_parser *parser,
       /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
 	 CPP_LESS.  */
       cp_lexer_consume_token (parser->lexer);
+
       /* Parse the arguments.  */
       arguments = cp_parser_enclosed_template_argument_list (parser);
       if (!cp_parser_parse_definitely (parser))
@@ -9837,15 +9906,18 @@ cp_parser_template_id (cp_parser *parser,
 	}
       /* Otherwise, emit an error about the invalid digraph, but continue
 	 parsing because we got our argument list.  */
-      permerror ("%<<::%> cannot begin a template-argument list");
-      inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
-	      "between %<<%> and %<::%>");
+      permerror ("%H%<<::%> cannot begin a template-argument list",
+		 &next_token->location);
+      inform ("%H%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
+	      "between %<<%> and %<::%>",
+	      &next_token->location);
       if (!flag_permissive)
 	{
 	  static bool hint;
 	  if (!hint)
 	    {
-	      inform ("(if you use %<-fpermissive%> G++ will accept your code)");
+	      inform ("%H(if you use %<-fpermissive%> G++ will accept your code)",
+                      &next_token->location);
 	      hint = true;
 	    }
 	}
@@ -9918,7 +9990,8 @@ cp_parser_template_id (cp_parser *parser,
 	 user, as opposed to simply marking the tentative parse as
 	 failed?  */
       if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
-	error ("parse error in template argument list");
+	error ("%Hparse error in template argument list",
+	       &token->location);
     }
 
   pop_deferring_access_checks ();
@@ -9972,6 +10045,7 @@ cp_parser_template_name (cp_parser* parser,
   tree identifier;
   tree decl;
   tree fns;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* If the next token is `operator', then we have either an
      operator-function-id or a conversion-function-id.  */
@@ -10031,7 +10105,8 @@ cp_parser_template_name (cp_parser* parser,
 	  cp_token_position start = 0;
 
 	  /* Explain what went wrong.  */
-	  error ("non-template %qD used as template", identifier);
+	  error ("%Hnon-template %qD used as template",
+		 &token->location, identifier);
 	  inform ("use %<%T::template %D%> to indicate that it is a template",
 		  parser->scope, identifier);
 	  /* If parsing tentatively, find the location of the "<" token.  */
@@ -10075,7 +10150,8 @@ cp_parser_template_name (cp_parser* parser,
 				/*is_template=*/false,
 				/*is_namespace=*/false,
 				check_dependency_p,
-				/*ambiguous_decls=*/NULL);
+				/*ambiguous_decls=*/NULL,
+				token->location);
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
@@ -10221,7 +10297,7 @@ cp_parser_template_argument (cp_parser* parser)
   bool template_p;
   bool address_p;
   bool maybe_type_id = false;
-  cp_token *token;
+  cp_token *token = NULL, *argument_start_token = NULL;
   cp_id_kind idk;
 
   /* There's really no way to know what we're looking at, so we just
@@ -10268,6 +10344,7 @@ cp_parser_template_argument (cp_parser* parser)
   /* We're still not sure what the argument will be.  */
   cp_parser_parse_tentatively (parser);
   /* Try a template.  */
+  argument_start_token = cp_lexer_peek_token (parser->lexer);
   argument = cp_parser_id_expression (parser,
 				      /*template_keyword_p=*/false,
 				      /*check_dependency_p=*/true,
@@ -10290,7 +10367,8 @@ cp_parser_template_argument (cp_parser* parser)
 					  /*is_template=*/template_p,
 					  /*is_namespace=*/false,
 					  /*check_dependency=*/true,
-					  /*ambiguous_decls=*/NULL);
+					  /*ambiguous_decls=*/NULL,
+					  argument_start_token->location);
       if (TREE_CODE (argument) != TEMPLATE_DECL
 	  && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
 	cp_parser_error (parser, "expected template-name");
@@ -10542,6 +10620,8 @@ static void
 cp_parser_explicit_specialization (cp_parser* parser)
 {
   bool need_lang_pop;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `template' keyword.  */
   cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Look for the `<'.  */
@@ -10556,7 +10636,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
      linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template specialization with C linkage");
+      error ("%Htemplate specialization with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
 	 front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -10881,7 +10961,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
           cp_lexer_consume_token (parser->lexer);
           /* We do not yet support the use of `auto' as a
              type-specifier.  */
-          error ("C++0x %<auto%> specifier not supported");
+          error ("%HC++0x %<auto%> specifier not supported", &token->location);
         }
       break;
 
@@ -11094,12 +11174,13 @@ cp_parser_nonclass_name (cp_parser* parser)
   tree type_decl;
   tree identifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
     return error_mark_node;
 
   /* Look up the type-name.  */
-  type_decl = cp_parser_lookup_name_simple (parser, identifier);
+  type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
 
   if (TREE_CODE (type_decl) != TYPE_DECL
       && (objc_is_id (identifier) || objc_is_class_name (identifier)))
@@ -11116,7 +11197,7 @@ cp_parser_nonclass_name (cp_parser* parser)
     {
       if (!cp_parser_simulate_error (parser))
 	cp_parser_name_lookup_error (parser, identifier, type_decl,
-				     "is not a type");
+				     "is not a type", token->location);
       return error_mark_node;
     }
   /* Remember that the name was used in the definition of the
@@ -11165,6 +11246,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
   tree identifier;
   tree type = NULL_TREE;
   tree attributes = NULL_TREE;
+  cp_token *token = NULL;
 
   /* See if we're looking at the `enum' keyword.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM))
@@ -11234,6 +11316,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (!template_p)
 	cp_parser_parse_tentatively (parser);
       /* Parse the template-id.  */
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_template_id (parser, template_p,
 				    /*check_dependency_p=*/true,
 				    is_declaration);
@@ -11255,6 +11338,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
   if (!type)
     {
+      token = cp_lexer_peek_token (parser->lexer);
       identifier = cp_parser_identifier (parser);
 
       if (identifier == error_mark_node)
@@ -11267,7 +11351,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (tag_type == typename_type
 	  && TREE_CODE (parser->scope) != NAMESPACE_DECL)
 	return cp_parser_make_typename_type (parser, parser->scope,
-					     identifier);
+					     identifier,
+					     token->location);
       /* Look up a qualified name in the usual way.  */
       if (parser->scope)
 	{
@@ -11279,7 +11364,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 					/*is_template=*/false,
 					/*is_namespace=*/false,
 					/*check_dependency=*/true,
-					&ambiguous_decls);
+					&ambiguous_decls,
+					token->location);
 
 	  /* If the lookup was ambiguous, an error will already have been
 	     issued.  */
@@ -11315,7 +11401,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	    {
 	      cp_parser_diagnose_invalid_type_name (parser,
 						    parser->scope,
-						    identifier);
+						    identifier,
+						    token->location);
 	      return error_mark_node;
 	    }
 
@@ -11415,7 +11502,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	  /* An unqualified name was used to reference this type, so
 	     there were no qualifying templates.  */
 	  if (!cp_parser_check_template_parameters (parser,
-						    /*num_templates=*/0))
+						    /*num_templates=*/0,
+						    token->location))
 	    return error_mark_node;
 	  type = xref_tag (tag_type, identifier, ts, template_p);
 	}
@@ -11618,6 +11706,8 @@ cp_parser_namespace_name (cp_parser* parser)
   tree identifier;
   tree namespace_decl;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Get the name of the namespace.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
@@ -11646,13 +11736,14 @@ cp_parser_namespace_name (cp_parser* parser)
 					  /*is_template=*/false,
 					  /*is_namespace=*/true,
 					  /*check_dependency=*/true,
-					  /*ambiguous_decls=*/NULL);
+					  /*ambiguous_decls=*/NULL,
+					  token->location);
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
     {
       if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	error ("%qD is not a namespace-name", identifier);
+	error ("%H%qD is not a namespace-name", &token->location, identifier);
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
@@ -11767,6 +11858,8 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   tree identifier;
   tree namespace_specifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the identifier.  */
@@ -11777,7 +11870,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
       && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) 
     {
-      error ("%<namespace%> definition is not allowed here");
+      error ("%H%<namespace%> definition is not allowed here", &token->location);
       /* Skip the definition.  */
       cp_lexer_consume_token (parser->lexer);
       if (cp_parser_skip_to_closing_brace (parser))
@@ -11892,6 +11985,7 @@ cp_parser_using_declaration (cp_parser* parser,
        cp_parser_parse_definitely will be false, as required.  */
     return cp_parser_parse_definitely (parser);
 
+  token = cp_lexer_peek_token (parser->lexer);
   /* Parse the unqualified-id.  */
   identifier = cp_parser_unqualified_id (parser,
 					 /*template_keyword_p=*/false,
@@ -11916,7 +12010,8 @@ cp_parser_using_declaration (cp_parser* parser,
     /* [namespace.udecl]
 
        A using declaration shall not name a template-id.  */
-    error ("a template-id may not appear in a using-declaration");
+    error ("%Ha template-id may not appear in a using-declaration",
+            &token->location);
   else
     {
       if (at_class_scope_p ())
@@ -11932,9 +12027,13 @@ cp_parser_using_declaration (cp_parser* parser,
 	}
       else
 	{
-	  decl = cp_parser_lookup_name_simple (parser, identifier);
+	  decl = cp_parser_lookup_name_simple (parser,
+					       identifier,
+					       token->location);
 	  if (decl == error_mark_node)
-	    cp_parser_name_lookup_error (parser, identifier, decl, NULL);
+	    cp_parser_name_lookup_error (parser, identifier,
+					 decl, NULL,
+					 token->location);
 	  else if (check_for_bare_parameter_packs (decl))
 	    return false;
 	  else if (!at_namespace_scope_p ())
@@ -12184,7 +12283,8 @@ cp_parser_init_declarator (cp_parser* parser,
 			   int declares_class_or_enum,
 			   bool* function_definition_p)
 {
-  cp_token *token;
+  cp_token *token = NULL, *asm_spec_start_token = NULL,
+           *attributes_start_token = NULL;
   cp_declarator *declarator;
   tree prefix_attributes;
   tree attributes;
@@ -12218,6 +12318,7 @@ cp_parser_init_declarator (cp_parser* parser,
   resume_deferring_access_checks ();
 
   /* Parse the declarator.  */
+  token = cp_lexer_peek_token (parser->lexer);
   declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
 			    &ctor_dtor_or_conv_p,
@@ -12232,7 +12333,8 @@ cp_parser_init_declarator (cp_parser* parser,
     return error_mark_node;
 
   /* Check that the number of template-parameter-lists is OK.  */
-  if (!cp_parser_check_declarator_template_parameters (parser, declarator))
+  if (!cp_parser_check_declarator_template_parameters (parser, declarator,
+						       token->location))
     return error_mark_node;
 
   if (declares_class_or_enum & 2)
@@ -12249,8 +12351,10 @@ cp_parser_init_declarator (cp_parser* parser,
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       /* Look for an asm-specification.  */
+      asm_spec_start_token = cp_lexer_peek_token (parser->lexer);
       asm_specification = cp_parser_asm_specification_opt (parser);
       /* And attributes.  */
+      attributes_start_token = cp_lexer_peek_token (parser->lexer);
       attributes = cp_parser_attributes_opt (parser);
     }
   else
@@ -12278,9 +12382,12 @@ cp_parser_init_declarator (cp_parser* parser,
 	  /* Neither attributes nor an asm-specification are allowed
 	     on a function-definition.  */
 	  if (asm_specification)
-	    error ("an asm-specification is not allowed on a function-definition");
+	    error ("%Han asm-specification is not allowed "
+		   "on a function-definition",
+		   &asm_spec_start_token->location);
 	  if (attributes)
-	    error ("attributes are not allowed on a function-definition");
+	    error ("%Hattributes are not allowed on a function-definition",
+		   &attributes_start_token->location);
 	  /* This is a function-definition.  */
 	  *function_definition_p = true;
 
@@ -12405,6 +12512,7 @@ cp_parser_init_declarator (cp_parser* parser,
     {
       if (function_declarator_p (declarator))
 	{
+	  cp_token *initializer_start_token = cp_lexer_peek_token (parser->lexer);
 	   if (initialization_kind == CPP_EQ)
 	     initializer = cp_parser_pure_specifier (parser);
 	   else
@@ -12413,7 +12521,8 @@ cp_parser_init_declarator (cp_parser* parser,
 		  know what the user intended, so just silently
 		  consume the initializer.  */
 	       if (decl != error_mark_node)
-		 error ("initializer provided for function");
+		 error ("%Hinitializer provided for function",
+			&initializer_start_token->location);
 	       cp_parser_skip_to_closing_parenthesis (parser,
 						      /*recovering=*/true,
 						      /*or_comma=*/false,
@@ -12814,7 +12923,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 		 in function scopes.  */
 	      else if (!parser->in_function_body)
 		{
-		  error ("array bound is not an integer constant");
+		  error ("%Harray bound is not an integer constant",
+			 &token->location);
 		  bounds = error_mark_node;
 		}
 	    }
@@ -12836,6 +12946,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  special_function_kind sfk;
 	  bool abstract_ok;
           bool pack_expansion_p = false;
+	  cp_token *declarator_id_start_token;
 
 	  /* Parse a declarator-id */
 	  abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
@@ -12854,6 +12965,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                 }
             }
 
+	  declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
 	  unqualified_name
 	    = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
 	  qualifying_scope = parser->scope;
@@ -12923,7 +13035,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 					    /*only_current_p=*/false);
 	      /* If that failed, the declarator is invalid.  */
 	      if (TREE_CODE (type) == TYPENAME_TYPE)
-		error ("%<%T::%E%> is not a type",
+		error ("%H%<%T::%E%> is not a type",
+		       &declarator_id_start_token->location,
 		       TYPE_CONTEXT (qualifying_scope),
 		       TYPE_IDENTIFIER (qualifying_scope));
 	      qualifying_scope = type;
@@ -12949,7 +13062,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 		      if (qualifying_scope
 			  && CLASSTYPE_USE_TEMPLATE (name_type))
 			{
-			  error ("invalid use of constructor as a template");
+			  error ("%Hinvalid use of constructor as a template",
+				 &declarator_id_start_token->location);
 			  inform ("use %<%T::%D%> instead of %<%T::%D%> to "
 				  "name the constructor in a qualified name",
 				  class_type,
@@ -13108,6 +13222,7 @@ cp_parser_ptr_operator (cp_parser* parser,
       cp_parser_global_scope_opt (parser,
 				  /*current_scope_valid_p=*/false);
       /* Look for the nested-name specifier.  */
+      token = cp_lexer_peek_token (parser->lexer);
       cp_parser_nested_name_specifier (parser,
 				       /*typename_keyword_p=*/false,
 				       /*check_dependency_p=*/true,
@@ -13122,7 +13237,7 @@ cp_parser_ptr_operator (cp_parser* parser,
 	  code = INDIRECT_REF;
 
 	  if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-	    error ("%qD is a namespace", parser->scope);
+	    error ("%H%qD is a namespace", &token->location, parser->scope);
 	  else
 	    {
 	      /* The type of which the member is a member is given by the
@@ -13197,7 +13312,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 
       if (cv_quals & cv_qualifier)
 	{
-	  error ("duplicate cv-qualifier");
+	  error ("%Hduplicate cv-qualifier", &token->location);
 	  cp_lexer_purge_token (parser->lexer);
 	}
       else
@@ -13307,6 +13422,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 {
   bool seen_type_specifier = false;
   cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
+  cp_token *start_token = NULL;
 
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
@@ -13326,6 +13442,11 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 	  continue;
 	}
 
+      /* record the token of the beginning of the type specifier seq,
+         for error reporting purposes*/
+     if (!start_token)
+       start_token = cp_lexer_peek_token (parser->lexer);
+
       /* Look for the type-specifier.  */
       type_specifier = cp_parser_type_specifier (parser,
 						 flags,
@@ -13369,7 +13490,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 	flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
 
-  cp_parser_check_decl_spec (type_specifier_seq);
+  cp_parser_check_decl_spec (type_specifier_seq, start_token->location);
 }
 
 /* Parse a parameter-declaration-clause.
@@ -13596,7 +13717,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
   cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
   tree default_argument;
-  cp_token *token;
+  cp_token *token = NULL, *declarator_token_start = NULL;
   const char *saved_message;
 
   /* In a template parameter, `>' is not an operator.
@@ -13665,6 +13786,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	  && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
 	cp_parser_commit_to_tentative_parse (parser);
       /* Parse the declarator.  */
+      declarator_token_start = token;
       declarator = cp_parser_declarator (parser,
 					 CP_PARSER_DECLARATOR_EITHER,
 					 /*ctor_dtor_or_conv_p=*/NULL,
@@ -13823,7 +13945,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 		  /* If we run out of tokens, issue an error message.  */
 		case CPP_EOF:
 		case CPP_PRAGMA_EOL:
-		  error ("file ends in default argument");
+		  error ("%Hfile ends in default argument", &token->location);
 		  done = true;
 		  break;
 
@@ -13860,8 +13982,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
       /* Outside of a class definition, we can just parse the
 	 assignment-expression.  */
       else
-        default_argument 
-          = cp_parser_default_argument (parser, template_parm_p);
+	{
+	  token = cp_lexer_peek_token (parser->lexer);
+	  default_argument 
+	    = cp_parser_default_argument (parser, template_parm_p);
+	}
 
       if (!parser->default_arg_ok_p)
 	{
@@ -13869,7 +13994,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	    warning (0, "deprecated use of default argument for parameter of non-function");
 	  else
 	    {
-	      error ("default arguments are only permitted for function parameters");
+	      error ("%Hdefault arguments are only "
+		     "permitted for function parameters",
+		     &token->location);
 	      default_argument = NULL_TREE;
 	    }
 	}
@@ -13885,11 +14012,12 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	    id_declarator = id_declarator->declarator;
 	  
 	  if (id_declarator && id_declarator->kind == cdk_id)
-	    error ("%sparameter pack %qD cannot have a default argument",
+	    error ("%H%sparameter pack %qD cannot have a default argument",
+		   &declarator_token_start->location,
 		   kind, id_declarator->u.id.unqualified_name);
 	  else
-	    error ("%sparameter pack cannot have a default argument",
-		   kind);
+	    error ("%H%sparameter pack cannot have a default argument",
+		   &declarator_token_start->location, kind);
 	  
 	  default_argument = NULL_TREE;
 	}
@@ -14279,10 +14407,12 @@ cp_parser_class_name (cp_parser *parser,
 					/*is_template=*/false,
 					/*is_namespace=*/false,
 					check_dependency_p,
-					&ambiguous_decls);
+					&ambiguous_decls,
+					identifier_token->location);
 	  if (ambiguous_decls)
 	    {
-	      error ("reference to %qD is ambiguous", identifier);
+	      error ("%Hreference to %qD is ambiguous",
+		     &identifier_token->location, identifier);
 	      print_candidates (ambiguous_decls);
 	      if (cp_parser_parsing_tentatively (parser))
 		{
@@ -14573,7 +14703,7 @@ cp_parser_class_head (cp_parser* parser,
   bool invalid_explicit_specialization_p = false;
   tree pushed_scope = NULL_TREE;
   unsigned num_templates;
-
+  cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL;
   /* Assume no nested-name-specifier will be present.  */
   *nested_name_specifier_p = false;
   /* Assume no template parameter lists will be used in defining the
@@ -14606,6 +14736,7 @@ cp_parser_class_head (cp_parser* parser,
 
   /* Determine the name of the class.  Begin by looking for an
      optional nested-name-specifier.  */
+  nested_name_specifier_token_start = cp_lexer_peek_token (parser->lexer);
   nested_name_specifier
     = cp_parser_nested_name_specifier_opt (parser,
 					   /*typename_keyword_p=*/false,
@@ -14616,6 +14747,7 @@ cp_parser_class_head (cp_parser* parser,
      identifier.  */
   if (nested_name_specifier)
     {
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       /* Although the grammar says `identifier', it really means
 	 `class-name' or `template-name'.  You are only allowed to
 	 define a class that has already been declared with this
@@ -14679,6 +14811,7 @@ cp_parser_class_head (cp_parser* parser,
 	 an identifier, or nothing at all.  */
       cp_parser_parse_tentatively (parser);
       /* Check for a template-id.  */
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       id = cp_parser_template_id (parser,
 				  /*template_keyword_p=*/false,
 				  /*check_dependency_p=*/true,
@@ -14730,7 +14863,8 @@ cp_parser_class_head (cp_parser* parser,
       /* Reject typedef-names in class heads.  */
       if (!DECL_IMPLICIT_TYPEDEF_P (type))
 	{
-	  error ("invalid class name in declaration of %qD", type);
+	  error ("%Hinvalid class name in declaration of %qD",
+		 &type_start_token->location, type);
 	  type = NULL_TREE;
 	  goto done;
 	}
@@ -14742,10 +14876,13 @@ cp_parser_class_head (cp_parser* parser,
       if (scope && !is_ancestor (scope, nested_name_specifier))
 	{
 	  if (at_namespace_scope_p ())
-	    error ("declaration of %qD in namespace %qD which does not "
-		   "enclose %qD", type, scope, nested_name_specifier);
+	    error ("%Hdeclaration of %qD in namespace %qD which does not "
+		   "enclose %qD",
+		   &type_start_token->location,
+		   type, scope, nested_name_specifier);
 	  else
-	    error ("declaration of %qD in %qD which does not enclose %qD",
+	    error ("%Hdeclaration of %qD in %qD which does not enclose %qD",
+		   &type_start_token->location,
 		   type, scope, nested_name_specifier);
 	  type = NULL_TREE;
 	  goto done;
@@ -14758,7 +14895,8 @@ cp_parser_class_head (cp_parser* parser,
 	 class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
 	{
-	  permerror ("extra qualification not allowed");
+	  permerror ("%Hextra qualification not allowed",
+		     &nested_name_specifier_token_start->location);
 	  nested_name_specifier = NULL_TREE;
 	  num_templates = 0;
 	}
@@ -14769,7 +14907,8 @@ cp_parser_class_head (cp_parser* parser,
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
-      error ("an explicit specialization must be preceded by %<template <>%>");
+      error ("%Han explicit specialization must be preceded by %<template <>%>",
+	     &type_start_token->location);
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
 	 cp_parser_explicit_specialization.  */
@@ -14781,7 +14920,8 @@ cp_parser_class_head (cp_parser* parser,
      use "goto done;" to return.  */
   /* Make sure that the right number of template parameters were
      present.  */
-  if (!cp_parser_check_template_parameters (parser, num_templates))
+  if (!cp_parser_check_template_parameters (parser, num_templates,
+					    type_start_token->location))
     {
       /* If something went wrong, there is no point in even trying to
 	 process the class-definition.  */
@@ -14796,7 +14936,8 @@ cp_parser_class_head (cp_parser* parser,
 	  && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0))
 	      || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD))
 	{
-	  error ("function template %qD redeclared as a class template", id);
+	  error ("%Hfunction template %qD redeclared as a class template",
+		 &type_start_token->location, id);
 	  type = error_mark_node;
 	}
       else
@@ -14877,8 +15018,10 @@ cp_parser_class_head (cp_parser* parser,
      that's an error.  */
   if (type != error_mark_node && COMPLETE_TYPE_P (type))
     {
-      error ("redefinition of %q#T", type);
-      error ("previous definition of %q+#T", type);
+      error ("%Hredefinition of %q#T",
+	     &type_start_token->location, type);
+      error ("%Hprevious definition of %q+#T",
+	     &type_start_token->location, type);
       type = NULL_TREE;
       goto done;
     }
@@ -15033,7 +15176,9 @@ cp_parser_member_declaration (cp_parser* parser)
   tree decl;
   int declares_class_or_enum;
   bool friend_p;
-  cp_token *token;
+  cp_token *token = NULL;
+  cp_token *decl_spec_token_start = NULL;
+  cp_token *initializer_token_start = NULL;
   int saved_pedantic;
 
   /* Check for the `__extension__' keyword.  */
@@ -15097,6 +15242,7 @@ cp_parser_member_declaration (cp_parser* parser)
     return;
 
   /* Parse the decl-specifier-seq.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -15142,7 +15288,8 @@ cp_parser_member_declaration (cp_parser* parser)
 	      /* If the `friend' keyword was present, the friend must
 		 be introduced with a class-key.  */
 	       if (!declares_class_or_enum)
-		 error ("a class-key must be used when declaring a friend");
+		 error ("%Ha class-key must be used when declaring a friend",
+                        &decl_spec_token_start->location);
 	       /* In this case:
 
 		    template <typename T> struct A {
@@ -15156,8 +15303,8 @@ cp_parser_member_declaration (cp_parser* parser)
 		   && TYPE_P (decl_specifiers.type))
 		 type = decl_specifiers.type;
 	       if (!type || !TYPE_P (type))
-		 error ("friend declaration does not name a class or "
-			"function");
+		 error ("%Hfriend declaration does not name a class or "
+			"function", &decl_spec_token_start->location);
 	       else
 		 make_friend_class (current_class_type, type,
 				    /*complain=*/true);
@@ -15180,7 +15327,9 @@ cp_parser_member_declaration (cp_parser* parser)
 	      finish_member_declaration (decl);
 	    }
 	  else
-	    cp_parser_check_access_in_redeclaration (TYPE_NAME (type));
+	    cp_parser_check_access_in_redeclaration
+					      (TYPE_NAME (type),
+					       decl_spec_token_start->location);
 	}
     }
   else
@@ -15308,6 +15457,7 @@ cp_parser_member_declaration (cp_parser* parser)
 		     for a pure-specifier; otherwise, we look for a
 		     constant-initializer.  When we call `grokfield', it will
 		     perform more stringent semantics checks.  */
+		  initializer_token_start = cp_lexer_peek_token (parser->lexer);
 		  if (function_declarator_p (declarator))
 		    initializer = cp_parser_pure_specifier (parser);
 		  else
@@ -15332,7 +15482,8 @@ cp_parser_member_declaration (cp_parser* parser)
 		     standard, since a pure function may be defined
 		     outside of the class-specifier.  */
 		  if (initializer)
-		    error ("pure-specifier on function-definition");
+		    error ("%Hpure-specifier on function-definition",
+			   &initializer_token_start->location);
 		  decl = cp_parser_save_member_function_body (parser,
 							      &decl_specifiers,
 							      declarator,
@@ -15423,7 +15574,7 @@ cp_parser_pure_specifier (cp_parser* parser)
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
-      error ("templates may not be %<virtual%>");
+      error ("%Htemplates may not be %<virtual%>", &token->location);
       return error_mark_node;
     }
 
@@ -15625,11 +15776,14 @@ cp_parser_base_specifier (cp_parser* parser)
      as base classes.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
+      token = cp_lexer_peek_token (parser->lexer);
       if (!processing_template_decl)
-	error ("keyword %<typename%> not allowed outside of templates");
+	error ("%Hkeyword %<typename%> not allowed outside of templates",
+	       &token->location);
       else
-	error ("keyword %<typename%> not allowed in this context "
-	       "(the base class is implicitly a type)");
+	error ("%Hkeyword %<typename%> not allowed in this context "
+	       "(the base class is implicitly a type)",
+	       &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
 
@@ -16330,7 +16484,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 		       bool is_template,
 		       bool is_namespace,
 		       bool check_dependency,
-		       tree *ambiguous_decls)
+		       tree *ambiguous_decls,
+		       location_t name_location)
 {
   int flags = 0;
   tree decl;
@@ -16511,7 +16666,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 	 cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
 	{
-	  error ("reference to %qD is ambiguous", name);
+	  error ("%Hreference to %qD is ambiguous",
+		 &name_location, name);
 	  print_candidates (decl);
 	}
       return error_mark_node;
@@ -16541,14 +16697,15 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
    IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE.  */
 
 static tree
-cp_parser_lookup_name_simple (cp_parser* parser, tree name)
+cp_parser_lookup_name_simple (cp_parser* parser, tree name, location_t location)
 {
   return cp_parser_lookup_name (parser, name,
 				none_type,
 				/*is_template=*/false,
 				/*is_namespace=*/false,
 				/*check_dependency=*/true,
-				/*ambiguous_decls=*/NULL);
+				/*ambiguous_decls=*/NULL,
+				location);
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
@@ -16601,7 +16758,8 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
 
 static bool
 cp_parser_check_declarator_template_parameters (cp_parser* parser,
-						cp_declarator *declarator)
+						cp_declarator *declarator,
+						location_t declarator_location)
 {
   unsigned num_templates;
 
@@ -16651,7 +16809,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 	++num_templates;
 
       return cp_parser_check_template_parameters (parser,
-						  num_templates);
+						  num_templates,
+						  declarator_location);
 
     case cdk_function:
     case cdk_array:
@@ -16659,7 +16818,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
     case cdk_reference:
     case cdk_ptrmem:
       return (cp_parser_check_declarator_template_parameters
-	      (parser, declarator->declarator));
+	      (parser, declarator->declarator, declarator_location));
 
     case cdk_error:
       return true;
@@ -16676,7 +16835,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
-				     unsigned num_templates)
+				     unsigned num_templates,
+				     location_t location)
 {
   /* If there are more template classes than parameter lists, we have
      something like:
@@ -16684,7 +16844,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      error ("too few template-parameter-lists");
+      error ("%Htoo few template-parameter-lists", &location);
       return false;
     }
   /* If there are the same number of template classes and parameter
@@ -16699,7 +16859,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
      something like:
 
      template <class T> template <class U> void S::f();  */
-  error ("too many template-parameter-lists");
+  error ("%Htoo many template-parameter-lists", &location);
   return false;
 }
 
@@ -16957,12 +17117,14 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   bool saved_in_unbraced_linkage_specification_p;
   bool saved_in_function_body;
   unsigned saved_num_template_parameter_lists;
+  cp_token *token;
 
   saved_in_function_body = parser->in_function_body;
   parser->in_function_body = true;
   /* If the next token is `return', then the code may be trying to
      make use of the "named return value" extension that G++ used to
      support.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_RETURN))
     {
       /* Consume the `return' keyword.  */
@@ -16971,7 +17133,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
 	 returned.  */
       cp_parser_identifier (parser);
       /* Issue an error message.  */
-      error ("named return values are no longer supported");
+      error ("%Hnamed return values are no longer supported",
+	     &token->location);
       /* Skip tokens until we reach the start of the function body.  */
       while (true)
 	{
@@ -17030,8 +17193,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
+  cp_token *token;
 
   /* Look for the `template' keyword.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
     return;
 
@@ -17043,7 +17208,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* 14.5.2.2 [temp.mem]
 
          A local class shall not have member templates.  */
-      error ("invalid declaration of member template in local class");
+      error ("%Hinvalid declaration of member template in local class",
+	     &token->location);
       cp_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
@@ -17052,7 +17218,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
      A template ... shall not have C linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template with C linkage");
+      error ("%Htemplate with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
 	 front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -17099,6 +17265,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* There are no access checks when parsing a template, as we do not
 	 know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_single_declaration (parser,
 					   checks,
 					   member_p,
@@ -17111,7 +17278,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       if (member_p && !friend_p && decl)
 	{
 	  if (TREE_CODE (decl) == TYPE_DECL)
-	    cp_parser_check_access_in_redeclaration (decl);
+	    cp_parser_check_access_in_redeclaration (decl, token->location);
 
 	  decl = finish_member_template_decl (decl);
 	}
@@ -17175,6 +17342,7 @@ cp_parser_single_declaration (cp_parser* parser,
   tree decl = NULL_TREE;
   cp_decl_specifier_seq decl_specifiers;
   bool function_definition_p = false;
+  cp_token *decl_spec_token_start;
 
   /* This function is only used when processing a template
      declaration.  */
@@ -17186,6 +17354,7 @@ cp_parser_single_declaration (cp_parser* parser,
 
   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
      alternative.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -17196,7 +17365,8 @@ cp_parser_single_declaration (cp_parser* parser,
   /* There are no template typedefs.  */
   if (decl_specifiers.specs[(int) ds_typedef])
     {
-      error ("template declaration of %qs", "typedef");
+      error ("%Htemplate declaration of %qs",
+	     &decl_spec_token_start->location, "typedef");
       decl = error_mark_node;
     }
 
@@ -17259,7 +17429,8 @@ cp_parser_single_declaration (cp_parser* parser,
         && explicit_specialization_p
         && decl_specifiers.storage_class != sc_none)
       {
-        error ("explicit template specialization cannot have a storage class");
+        error ("%Hexplicit template specialization cannot have a storage class",
+	       &decl_spec_token_start->location);
         decl = error_mark_node;
       }
     }
@@ -17461,9 +17632,9 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
 	    is a typo for '>'. Emit an error message and continue.
 	    Same deal about the token location, but here we can get it
 	    right by consuming the '>>' before issuing the diagnostic.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  error ("spurious %<>>%>, use %<>%> to terminate "
-		 "a template argument list");
+	  cp_token *token = cp_lexer_consume_token (parser->lexer);
+	  error ("%Hspurious %<>>%>, use %<>%> to terminate "
+		 "a template argument list", &token->location);
 	}
     }
   else
@@ -17784,14 +17955,15 @@ cp_parser_declares_only_class_p (cp_parser *parser)
 static void
 cp_parser_set_storage_class (cp_parser *parser,
 			     cp_decl_specifier_seq *decl_specs,
-			     enum rid keyword)
+			     enum rid keyword,
+			     location_t location)
 {
   cp_storage_class storage_class;
 
   if (parser->in_unbraced_linkage_specification_p)
     {
-      error ("invalid use of %qD in linkage specification",
-	     ridpointers[keyword]);
+      error ("%Hinvalid use of %qD in linkage specification",
+	     &location, ridpointers[keyword]);
       return;
     }
   else if (decl_specs->storage_class != sc_none)
@@ -17803,7 +17975,7 @@ cp_parser_set_storage_class (cp_parser *parser,
   if ((keyword == RID_EXTERN || keyword == RID_STATIC)
       && decl_specs->specs[(int) ds_thread])
     {
-      error ("%<__thread%> before %qD", ridpointers[keyword]);
+      error ("%H%<__thread%> before %qD", &location, ridpointers[keyword]);
       decl_specs->specs[(int) ds_thread] = 0;
     }
 
@@ -18133,7 +18305,7 @@ cp_parser_check_class_key (enum tag_types class_key, tree type)
    [class.mem/1].  */
 
 static void
-cp_parser_check_access_in_redeclaration (tree decl)
+cp_parser_check_access_in_redeclaration (tree decl, location_t location)
 {
   if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl)))
     return;
@@ -18142,7 +18314,7 @@ cp_parser_check_access_in_redeclaration (tree decl)
        != (current_access_specifier == access_private_node))
       || (TREE_PROTECTED (decl)
 	  != (current_access_specifier == access_protected_node)))
-    error ("%qD redeclared with different access", decl);
+    error ("%H%qD redeclared with different access", &location, decl);
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
@@ -18159,8 +18331,9 @@ cp_parser_optional_template_keyword (cp_parser *parser)
 	 template and what is not.  */
       if (!processing_template_decl)
 	{
-	  error ("%<template%> (as a disambiguator) is only allowed "
-		 "within templates");
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
+	  error ("%H%<template%> (as a disambiguator) is only allowed "
+		 "within templates", &token->location);
 	  /* If this part of the token stream is rescanned, the same
 	     error message would be generated.  So, we purge the token
 	     from the stream.  */
@@ -18412,7 +18585,8 @@ cp_parser_objc_expression (cp_parser* parser)
 	  break;
 	}
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -18545,15 +18719,18 @@ static tree
 cp_parser_objc_encode_expression (cp_parser* parser)
 {
   tree type;
+  cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  token = cp_lexer_peek_token (parser->lexer);
   type = complete_type (cp_parser_type_id (parser));
   cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   if (!type)
     {
-      error ("%<@encode%> must specify a type as an argument");
+      error ("%H%<@encode%> must specify a type as an argument",
+	     &token->location);
       return error_mark_node;
     }
 
@@ -18868,7 +19045,7 @@ cp_parser_objc_selector (cp_parser* parser)
 
   if (!cp_parser_objc_selector_p (token->type))
     {
-      error ("invalid Objective-C++ selector name");
+      error ("%Hinvalid Objective-C++ selector name", &token->location);
       return error_mark_node;
     }
 
@@ -19198,7 +19375,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
     {
-      error ("identifier expected after %<@protocol%>");
+      tok = cp_lexer_peek_token (parser->lexer);
+      error ("%Hidentifier expected after %<@protocol%>", &tok->location);
       goto finish;
     }
 
@@ -19334,7 +19512,8 @@ cp_parser_objc_declaration (cp_parser* parser)
       cp_parser_objc_end_implementation (parser);
       break;
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 }
@@ -19465,7 +19644,8 @@ cp_parser_objc_statement (cp_parser * parser) {
     case RID_AT_THROW:
       return cp_parser_objc_throw_statement (parser);
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -19549,14 +19729,15 @@ cp_parser_omp_clause_name (cp_parser *parser)
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
-check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+check_no_duplicate_clause (tree clauses, enum tree_code code,
+			   const char *name, location_t location)
 {
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
-	error ("too many %qs clauses", name);
+	error ("%Htoo many %qs clauses", &location, name);
 	break;
       }
 }
@@ -19579,10 +19760,12 @@ static tree
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 				tree list)
 {
+  cp_token *token;
   while (1)
     {
       tree name, decl;
 
+      token = cp_lexer_peek_token (parser->lexer);
       name = cp_parser_id_expression (parser, /*template_p=*/false,
 				      /*check_dependency_p=*/true,
 				      /*template_p=*/NULL,
@@ -19591,9 +19774,9 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       if (name == error_mark_node)
 	goto skip_comma;
 
-      decl = cp_parser_lookup_name_simple (parser, name);
+      decl = cp_parser_lookup_name_simple (parser, name, token->location);
       if (decl == error_mark_node)
-	cp_parser_name_lookup_error (parser, name, decl, NULL);
+	cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
       else if (kind != 0)
 	{
 	  tree u = build_omp_clause (kind);
@@ -19643,7 +19826,7 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
    collapse ( constant-expression ) */
 
 static tree
-cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
+cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location)
 {
   tree c, num;
   location_t loc;
@@ -19668,11 +19851,12 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
       || (n = tree_low_cst (num, 0)) <= 0
       || (int) n != n)
     {
-      error ("%Hcollapse argument needs positive constant integer expression", &loc);
+      error ("%Hcollapse argument needs positive constant integer expression",
+	     &loc);
       return list;
     }
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
+  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
   c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
@@ -19684,7 +19868,7 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
    default ( shared | none ) */
 
 static tree
-cp_parser_omp_clause_default (cp_parser *parser, tree list)
+cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
 {
   enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
   tree c;
@@ -19730,7 +19914,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
   if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
     return list;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
   c = build_omp_clause (OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
@@ -19742,7 +19926,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
    if ( expression ) */
 
 static tree
-cp_parser_omp_clause_if (cp_parser *parser, tree list)
+cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
 {
   tree t, c;
 
@@ -19757,7 +19941,7 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
 
   c = build_omp_clause (OMP_CLAUSE_IF);
   OMP_CLAUSE_IF_EXPR (c) = t;
@@ -19770,11 +19954,12 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
    nowait */
 
 static tree
-cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED,
+			     tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait", location);
 
   c = build_omp_clause (OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -19785,7 +19970,8 @@ cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
    num_threads ( expression ) */
 
 static tree
-cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
+cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
+				  location_t location)
 {
   tree t, c;
 
@@ -19800,7 +19986,8 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
+			     "num_threads", location);
 
   c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
   OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
@@ -19813,11 +20000,13 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
    ordered */
 
 static tree
-cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
+			      tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED,
+			     "ordered", location);
 
   c = build_omp_clause (OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -19894,7 +20083,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
      static | dynamic | guided | runtime | auto  */
 
 static tree
-cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
+cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location)
 {
   tree c, t;
 
@@ -19942,18 +20131,20 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
     {
+      cp_token *token;
       cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       t = cp_parser_assignment_expression (parser, false);
 
       if (t == error_mark_node)
 	goto resync_fail;
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-	error ("schedule %<runtime%> does not take "
-	       "a %<chunk_size%> parameter");
+	error ("%Hschedule %<runtime%> does not take "
+	       "a %<chunk_size%> parameter", &token->location);
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
-	error ("schedule %<auto%> does not take "
-	       "a %<chunk_size%> parameter");
+	error ("%Hschedule %<auto%> does not take "
+	       "a %<chunk_size%> parameter", &token->location);
       else
 	OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
@@ -19963,7 +20154,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
   else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<,%> or %<)%>"))
     goto resync_fail;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
@@ -19980,11 +20171,12 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
    untied */
 
 static tree
-cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED,
+			     tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
+  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
 
   c = build_omp_clause (OMP_CLAUSE_UNTIED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -20001,6 +20193,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 {
   tree clauses = NULL;
   bool first = true;
+  cp_token *token = NULL;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
@@ -20011,13 +20204,15 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
       if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
 	cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       c_kind = cp_parser_omp_clause_name (parser);
       first = false;
 
       switch (c_kind)
 	{
 	case PRAGMA_OMP_CLAUSE_COLLAPSE:
-	  clauses = cp_parser_omp_clause_collapse (parser, clauses);
+	  clauses = cp_parser_omp_clause_collapse (parser, clauses,
+						   token->location);
 	  c_name = "collapse";
 	  break;
 	case PRAGMA_OMP_CLAUSE_COPYIN:
@@ -20030,7 +20225,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "copyprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_DEFAULT:
-	  clauses = cp_parser_omp_clause_default (parser, clauses);
+	  clauses = cp_parser_omp_clause_default (parser, clauses,
+						  token->location);
 	  c_name = "default";
 	  break;
 	case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
@@ -20039,7 +20235,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "firstprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_IF:
-	  clauses = cp_parser_omp_clause_if (parser, clauses);
+	  clauses = cp_parser_omp_clause_if (parser, clauses, token->location);
 	  c_name = "if";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -20048,15 +20244,17 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "lastprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NOWAIT:
-	  clauses = cp_parser_omp_clause_nowait (parser, clauses);
+	  clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
 	  c_name = "nowait";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NUM_THREADS:
-	  clauses = cp_parser_omp_clause_num_threads (parser, clauses);
+	  clauses = cp_parser_omp_clause_num_threads (parser, clauses,
+						      token->location);
 	  c_name = "num_threads";
 	  break;
 	case PRAGMA_OMP_CLAUSE_ORDERED:
-	  clauses = cp_parser_omp_clause_ordered (parser, clauses);
+	  clauses = cp_parser_omp_clause_ordered (parser, clauses,
+						  token->location);
 	  c_name = "ordered";
 	  break;
 	case PRAGMA_OMP_CLAUSE_PRIVATE:
@@ -20069,7 +20267,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
-	  clauses = cp_parser_omp_clause_schedule (parser, clauses);
+	  clauses = cp_parser_omp_clause_schedule (parser, clauses,
+						   token->location);
 	  c_name = "schedule";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SHARED:
@@ -20078,7 +20277,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "shared";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
-	  clauses = cp_parser_omp_clause_untied (parser, clauses);
+	  clauses = cp_parser_omp_clause_untied (parser, clauses,
+						 token->location);
 	  c_name = "nowait";
 	  break;
 	default:
@@ -20091,7 +20291,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  /* Remove the invalid clause(s) from the list to avoid
 	     confusing the rest of the compiler.  */
 	  clauses = prev;
-	  error ("%qs is not valid for %qs", c_name, where);
+	  error ("%H%qs is not valid for %qs", &token->location, c_name, where);
 	}
     }
  saw_error:
@@ -21177,10 +21377,11 @@ cp_parser_initial_pragma (cp_token *first_token)
 
       cp_lexer_get_preprocessor_token (NULL, first_token);
       if (first_token->type != CPP_PRAGMA_EOL)
-	error ("junk at end of %<#pragma GCC pch_preprocess%>");
+	error ("%Hjunk at end of %<#pragma GCC pch_preprocess%>",
+               &first_token->location);
     }
   else
-    error ("expected string literal");
+    error ("%Hexpected string literal", &first_token->location);
 
   /* Skip to the end of the pragma.  */
   while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
@@ -21213,7 +21414,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
   switch (id)
     {
     case PRAGMA_GCC_PCH_PREPROCESS:
-      error ("%<#pragma GCC pch_preprocess%> must be first");
+      error ("%H%<#pragma GCC pch_preprocess%> must be first",
+             &pragma_tok->location);
       break;
 
     case PRAGMA_OMP_BARRIER:
@@ -21223,8 +21425,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_barrier (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp barrier%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp barrier%> may only be "
+		 "used in compound statements", &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
@@ -21238,8 +21440,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_flush (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp flush%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp flush%> may only be "
+		 "used in compound statements", &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
@@ -21280,8 +21482,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
       return true;
 
     case PRAGMA_OMP_SECTION:
-      error ("%<#pragma omp section%> may only be used in "
-	     "%<#pragma omp sections%> construct");
+      error ("%H%<#pragma omp section%> may only be used in "
+	     "%<#pragma omp sections%> construct", &pragma_tok->location);
       break;
 
     default:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9926f3d..f283394 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9750,7 +9750,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
       if (complain & tf_error)
 	qualified_name_lookup_error (scope,
 				     TREE_OPERAND (qualified_id, 1),
-				     expr);
+				     expr, input_location);
       return error_mark_node;
     }
 
@@ -9759,7 +9759,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
 
   if (expr == error_mark_node && complain & tf_error)
     qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
-				 expr);
+				 expr, input_location);
   else if (TYPE_P (scope))
     {
       expr = (adjust_result_of_qualified_name_lookup
@@ -10491,7 +10491,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 					  /*is_type_p=*/false,
 					  /*complain=*/false);
 	    if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
-	      qualified_name_lookup_error (scope, name, decl);
+	      qualified_name_lookup_error (scope, name, decl, input_location);
 	    else
 	      do_local_using_decl (decl, scope, name);
 	  }
@@ -10938,7 +10938,8 @@ tsubst_copy_and_build (tree t,
 				     /*done=*/true,
 				     /*address_p=*/false,
 				     /*template_arg_p=*/false,
-				     &error_msg);
+				     &error_msg,
+				     input_location);
 	if (error_msg)
 	  error (error_msg);
 	if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
@@ -11467,7 +11468,8 @@ tsubst_copy_and_build (tree t,
 	      }
 	    else
 	      {
-		qualified_name_lookup_error (object_type, tmpl, member);
+		qualified_name_lookup_error (object_type, tmpl, member,
+					     input_location);
 		return error_mark_node;
 	      }
 	  }
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2400aeb..4ac585b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2482,29 +2482,33 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
 }
 
 /* Issue a diagnostic that NAME cannot be found in SCOPE.  DECL is
-   what we found when we tried to do the lookup.  */
+   what we found when we tried to do the lookup.
+   LOCATION is the location of the NAME identifier;
+   The location is used in the error message*/
 
 void
-qualified_name_lookup_error (tree scope, tree name, tree decl)
+qualified_name_lookup_error (tree scope, tree name,
+			     tree decl, location_t location)
 {
   if (scope == error_mark_node)
     ; /* We already complained.  */
   else if (TYPE_P (scope))
     {
       if (!COMPLETE_TYPE_P (scope))
-	error ("incomplete type %qT used in nested name specifier", scope);
+	error ("%Hincomplete type %qT used in nested name specifier",
+	       &location, scope);
       else if (TREE_CODE (decl) == TREE_LIST)
 	{
-	  error ("reference to %<%T::%D%> is ambiguous", scope, name);
+	  error ("%Hreference to %<%T::%D%> is ambiguous", &location, scope, name);
 	  print_candidates (decl);
 	}
       else
-	error ("%qD is not a member of %qT", name, scope);
+	error ("%H%qD is not a member of %qT", &location, name, scope);
     }
   else if (scope != global_namespace)
-    error ("%qD is not a member of %qD", name, scope);
+    error ("%H%qD is not a member of %qD", &location, name, scope);
   else
-    error ("%<::%D%> has not been declared", name);
+    error ("%H%<::%D%> has not been declared", &location, name);
 }
 
 /* If FNS is a member function, a set of member functions, or a
@@ -2569,7 +2573,6 @@ baselink_for_fns (tree fns)
    the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
-
 tree
 finish_id_expression (tree id_expression,
 		      tree decl,
@@ -2582,7 +2585,8 @@ finish_id_expression (tree id_expression,
 		      bool done,
 		      bool address_p,
 		      bool template_arg_p,
-		      const char **error_msg)
+		      const char **error_msg,
+		      location_t location)
 {
   /* Initialize the output parameters.  */
   *idk = CP_ID_KIND_NONE;
@@ -2612,7 +2616,7 @@ finish_id_expression (tree id_expression,
 	      /* If the qualifying type is non-dependent (and the name
 		 does not name a conversion operator to a dependent
 		 type), issue an error.  */
-	      qualified_name_lookup_error (scope, id_expression, decl);
+	      qualified_name_lookup_error (scope, id_expression, decl, location);
 	      return error_mark_node;
 	    }
 	  else if (!scope)
diff --git a/gcc/testsuite/g++.dg/parse/constructor1.C b/gcc/testsuite/g++.dg/parse/constructor1.C
index 3011862..8f222f8 100644
--- a/gcc/testsuite/g++.dg/parse/constructor1.C
+++ b/gcc/testsuite/g++.dg/parse/constructor1.C
@@ -1,4 +1,7 @@
+// { dg-do compile }
+// { dg-options "-fshow-column" }
+
 ACE_Process_Descriptor::ACE_Process_Descriptor () : // { dg-error "" }
-  process_ (0)
+  process_ (0) // { dg-error "3: error: only constructors take base initializers" }
 {
 }
diff --git a/gcc/testsuite/g++.dg/parse/error-column.C b/gcc/testsuite/g++.dg/parse/error-column.C
new file mode 100644
index 0000000..812a499
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error-column.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// Make sure column information is correctly shown in error reporting
+// { dg-options "-fshow-column" }
+
+
+void foo ()
+{
+  cout << "blah"; // { dg-error "3: error: 'cout'" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/error1.C b/gcc/testsuite/g++.dg/parse/error1.C
index 8756df6..60e7d65 100644
--- a/gcc/testsuite/g++.dg/parse/error1.C
+++ b/gcc/testsuite/g++.dg/parse/error1.C
@@ -1,6 +1,7 @@
+// { dg-options "-fshow-column" }
 struct INCOMPLETE;
 template <int> struct X {
     static INCOMPLETE value;
 };
-template <> INCOMPLETE X<1>::value = 0; // { dg-error "" }
+template <> INCOMPLETE X<1>::value = 0; // { dg-error "30: error: variable 'INCOMPLETE X<1>::value' has initializer but incomplete type" }
 
diff --git a/gcc/testsuite/g++.dg/parse/error10.C b/gcc/testsuite/g++.dg/parse/error10.C
index 242c421..6e46922 100644
--- a/gcc/testsuite/g++.dg/parse/error10.C
+++ b/gcc/testsuite/g++.dg/parse/error10.C
@@ -1,5 +1,5 @@
 // PR c++/3478
-// { dg-options "" }
+// { dg-options "-fshow-column" }
 
 template <typename> struct A
 {
@@ -11,5 +11,9 @@ template <typename T> void foo()
   enum          A<void>::E e1;
   typename      A<T>::E    e2;
   enum          A<T>::E    e3;
-  enum typename A<T>::E    e4; // { dg-error "" }
+  enum typename A<T>::E    e4;
 }
+
+// Here, columns nums are not very accurate either. Still acceptable though
+// { dg-error "30: error: invalid type in declaration before ';' token" "" { target *-*-* } { 14 } }
+// { dg-error "30: error: two or more data types in declaration of 'e4'" "" { target *-*-* } { 14 } }
diff --git a/gcc/testsuite/g++.dg/parse/error11.C b/gcc/testsuite/g++.dg/parse/error11.C
index 0a8e2e4..f7093a8 100644
--- a/gcc/testsuite/g++.dg/parse/error11.C
+++ b/gcc/testsuite/g++.dg/parse/error11.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }"
 // Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
 // Try to find out when the digraph '<:' is used as a mistake, and parse it
 //  correctly to avoid cascaded errors.
@@ -15,16 +16,16 @@ struct Foo
   };
 
   void method(void) {
-    typename Foo<::B>::template Nested<::B> n; // { dg-error "cannot begin|alternate spelling" }
+    typename Foo<::B>::template Nested<::B> n; // { dg-error "17: error: '<::' cannot begin|17: note: '<:' is an alternate spelling|39: error: '<::' cannot begin|39: note: '<:' is an alternate" }
     n.template Nested<B>::method();
-    n.template Nested<::B>::method();  // { dg-error "cannot begin|alternate spelling" }
+    n.template Nested<::B>::method();  // { dg-error "22: error: '<::' cannot begin|22: note: '<:' is an alternate" }
     Nested<B>::method();
-    Nested<::B>::method(); // { dg-error "cannot begin|alternate spelling" }
+    Nested<::B>::method(); // { dg-error "11: error: '<::' cannot begin|11: note: '<:' is an alternate" }
   }
 };
 
 template <int N> struct Foo2 {};
-template struct Foo2<::B>;  // { dg-error "cannot begin|alternate spelling|type/value mismatch|expected a constant" }
+template struct Foo2<::B>;  // { dg-error "21: error: '<::' cannot begin|21: note: '<:' is an alternate|25: error: type/value mismatch|25: error:   expected a constant" }
 
 int value = 0;
 
@@ -32,22 +33,28 @@ void func(void)
 {
   Foo<::B> f; // { dg-error "cannot begin|alternate spelling" }
   f.Foo<B>::method();
-  f.Foo<::B>::method(); // { dg-error "cannot begin|alternate spelling" }
+  f.Foo<::B>::method(); // { dg-error "8: error|8: note" }
 
   // Check cases where we the token sequence is the correct one, but there
   //  was no digraph or whitespaces in the middle, so we should not emit
   //  the special error message.
   Foo<: :B> k2;     // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" }
   Foo[:B> k1;       // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" } 
-// { dg-error "" "" { target *-*-* } 40 }
-// { dg-error "" "" { target *-*-* } 41 }
-
+// { dg-error "6: error: missing template arguments before" "" { target *-*-* } { 41 } }
+// { dg-error "9: error: expected primary-expression before ':' token" "" { target *-*-* } 41 }
+// { dg-error "9: error: expected '\]' before ':' token" "" { target *-*-* } 41 }
+// { dg-error "9: error: expected ';' before ':' token" "" { target *-*-* } 41 }
+// { dg-error "6: error: missing template arguments before" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected primary-expression before ':' token" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected '\]' before ':' token" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected ';' before ':' token" "" { target *-*-* } 42 }
+//
   int Foo[2];
   Foo[::value] = 0;
 }
 
-template struct Foo<::B>; // { dg-error "cannot begin|alternate spelling" }
+template struct Foo<::B>; // { dg-error "20: error: '<::' cannot begin|20: note: '<:' is an alternate" }
 
 // On the first error message, an additional note about the use of 
 //  -fpermissive should be present
-// { dg-error "-fpermissive" "-fpermissive" { target *-*-* } 18 }
+// { dg-error "17: note: \\(if you use '-fpermissive' G\\+\\+ will accept your code\\)" "-fpermissive" { target *-*-* } 19 }
diff --git a/gcc/testsuite/g++.dg/parse/error12.C b/gcc/testsuite/g++.dg/parse/error12.C
index ea04fd0..b002588 100644
--- a/gcc/testsuite/g++.dg/parse/error12.C
+++ b/gcc/testsuite/g++.dg/parse/error12.C
@@ -1,7 +1,7 @@
 // { dg-do compile }
 // Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
 // Make sure the error about '<:' can be turned into a warning
-// { dg-options "-fpermissive" }
+// { dg-options "-fpermissive -fshow-column" }
 
 struct B;
 
@@ -9,4 +9,5 @@ template <class A>
 struct Foo {};
 
 Foo<::B> foo;   // { dg-bogus "error" "error in place of warning" }
-// { dg-error "" "" { target *-*-* } 11 }
+// { dg-error "4: warning: '<::' cannot begin a template-argument list" "warning <::" { target *-*-* } 11 }
+// { dg-error "4: note: '<:' is an alternate spelling for '.'. Insert whitespace between '<' and '::'" "note <:" { target *-*-* } 11 }
diff --git a/gcc/testsuite/g++.dg/parse/error13.C b/gcc/testsuite/g++.dg/parse/error13.C
index 15642e3..94ddae8 100644
--- a/gcc/testsuite/g++.dg/parse/error13.C
+++ b/gcc/testsuite/g++.dg/parse/error13.C
@@ -1,13 +1,14 @@
+// { dg-options "-fshow-column" }
 // PR c++/13975
 
-public: // { dg-error "" }
+public: // { dg-error "1: error: expected unqualified-id before 'public'" }
 
 int i;
 
-protected: // { dg-error "" }
+protected: // { dg-error "1: error: expected unqualified-id before 'protected'" }
 
 int j;
 
-private: // { dg-error "" }
+private: // { dg-error "1: error: expected unqualified-id before 'private'" }
 
 int k;
diff --git a/gcc/testsuite/g++.dg/parse/error14.C b/gcc/testsuite/g++.dg/parse/error14.C
index 4b23045..906b98f 100644
--- a/gcc/testsuite/g++.dg/parse/error14.C
+++ b/gcc/testsuite/g++.dg/parse/error14.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column" }
 // PR c++/13970
 
 struct X
@@ -18,5 +19,5 @@ struct X
         Zinc<int>( //);
 		  //    }
 
-}; // { dg-error "" }
+}; // { dg-error "2: error: expected '.' at end of input|1: error: expected primary-expression before '.' token|1: error: expected ';' before '.' token|1: error: expected unqualified-id at end of input" }
 
diff --git a/gcc/testsuite/g++.dg/parse/error15.C b/gcc/testsuite/g++.dg/parse/error15.C
index b343970..b65175c 100644
--- a/gcc/testsuite/g++.dg/parse/error15.C
+++ b/gcc/testsuite/g++.dg/parse/error15.C
@@ -1,5 +1,6 @@
 // { dg-do compile }
 // Contributed by Volker Reichelt <reichelt at gcc dot gnu dot org> 
+// { dg-options "-fshow-column" }
 // PR c++/14008: Improve diagnostic on invalid types in declarators.
 
 namespace N
@@ -9,29 +10,29 @@ namespace N
   int K;
 }
 
-N::A f2;              // { dg-error "without an argument list" }
-N::INVALID f3;        // { dg-error "in namespace 'N' does not name a type" }
-N::C::INVALID f4;     // { dg-error "in class 'N::C' does not name a type" }
-N::K f6;              // { dg-error "in namespace 'N' does not name a type" }
-typename N::A f7;     // { dg-error "without an argument list|outside of template" }
+N::A f2;              // { dg-error "4: error: invalid use of template-name 'N::A' without an argument list" }
+N::INVALID f3;        // { dg-error "4: error: 'INVALID' in namespace 'N' does not name a type" }
+N::C::INVALID f4;     // { dg-error "7: error: 'INVALID' in class 'N::C' does not name a type" }
+N::K f6;              // { dg-error "4: error: 'K' in namespace 'N' does not name a type" }
+typename N::A f7;     // { dg-error "1: error: using 'typename' outside of template|13: error: invalid use of template-name 'N::A' without an argument list|17: error: invalid type in declaration before ';' token" }
 
 struct B
 {
-  N::A f2;            // { dg-error "without an argument list" }
-  N::INVALID f3;      // { dg-error "in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "in namespace 'N' does not name a type" }
-  typename N::A f7;   // { dg-error "without an argument list|outside of template" }
+  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  typename N::A f7;   // { dg-error "3: error: using 'typename' outside of template|15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
 template <int>
 struct C
 {
-  N::A f2;            // { dg-error "without an argument list" }
-  N::INVALID f3;      // { dg-error "in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "in namespace 'N' does not name a type" }
-  typename N::A f7;   // { dg-error "without an argument list" }
+  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  typename N::A f7;   // { dg-error "15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
-// { dg-bogus "" "bogus excess errors in declaration" { xfail *-*-* } 16 }
+// { dg-bogus "bogus excess errors in declaration" "bogus excess errors in declaration" { xfail *-*-* } 17 }
diff --git a/gcc/testsuite/g++.dg/parse/error16.C b/gcc/testsuite/g++.dg/parse/error16.C
index 3dc58ad..ddc302c 100644
--- a/gcc/testsuite/g++.dg/parse/error16.C
+++ b/gcc/testsuite/g++.dg/parse/error16.C
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 // PR c++/16964
 
 struct A
 {
-  struct B {}; // { dg-error "previous" }
+  struct B {}; // { dg-error "12: error: previous definition of 'struct A::B'" }
 };
 
-struct A::B{}; // { dg-error "redefinition" }
+struct A::B{}; // { dg-error "11: error: redefinition of 'struct A::B'" }
diff --git a/gcc/testsuite/g++.dg/parse/error17.C b/gcc/testsuite/g++.dg/parse/error17.C
index 2a8f3f8..0e05217 100644
--- a/gcc/testsuite/g++.dg/parse/error17.C
+++ b/gcc/testsuite/g++.dg/parse/error17.C
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 // PR c++/16965
 
 template <typename T> struct B { 
-  static int Bar(T); // { dg-error "" }
+  static int Bar(T); // { dg-error "19: error: candidates are: |19: error:  " }
 }; 
 struct D : B<int>, B<char> {}; 
  
-int i2 = D::Bar(2); // { dg-error "" }
+int i2 = D::Bar(2); // { dg-error "13: error: reference to 'Bar' is ambiguous|10: error: reference to 'Bar' is ambiguous" }
diff --git a/gcc/testsuite/g++.dg/parse/error18.C b/gcc/testsuite/g++.dg/parse/error18.C
index 363aae9..926af11 100644
--- a/gcc/testsuite/g++.dg/parse/error18.C
+++ b/gcc/testsuite/g++.dg/parse/error18.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column" }
 // PR c++/16002
 
 void f()
 {
-  double Q *= 5.0; // { dg-error "initializer" }
+  double Q *= 5.0; // { dg-error "12: error: expected initializer before '..' token" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error19.C b/gcc/testsuite/g++.dg/parse/error19.C
index 24a66af..b22156a 100644
--- a/gcc/testsuite/g++.dg/parse/error19.C
+++ b/gcc/testsuite/g++.dg/parse/error19.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -fmessage-length=0   -ansi -pedantic-errors -Wno-long-long " }
 // PR C++/17867
 
 struct A
-{  // { dg-error "candidate" }
+{  // { dg-error "1: note: candidates are:" }
   A(int);
 };
 
@@ -9,5 +10,5 @@ const A& foo();
 
 void bar()
 {
-  foo()=A(0); // { dg-error "A" }
+  foo()=A(0); // { dg-error "12: error: no match for 'operator='" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/error2.C b/gcc/testsuite/g++.dg/parse/error2.C
index 8dd1e9d..075dcc2 100644
--- a/gcc/testsuite/g++.dg/parse/error2.C
+++ b/gcc/testsuite/g++.dg/parse/error2.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }
 // Properly print CALL_EXPRs while dumping expressions
 
 double g;
@@ -7,4 +8,8 @@ int func(double);
 template <int>
 struct Foo {};
 
-Foo<func(g)> f; // { dg-error "" "func(g)" }
+Foo<func(g)> f; // { dg-error "5: error: 'int func.double.' cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "10: error: 'g' cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "11: error: a function call cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "12: error: template argument 1 is invalid" "" { target *-*-* } { 11 } }
+// { dg-error "15: error: invalid type in declaration before ';' token" "" { target *-*-* } { 11 } }
diff --git a/gcc/testsuite/g++.dg/parse/error20.C b/gcc/testsuite/g++.dg/parse/error20.C
index ee7390a..9564fab 100644
--- a/gcc/testsuite/g++.dg/parse/error20.C
+++ b/gcc/testsuite/g++.dg/parse/error20.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/17821
 
 struct A {
@@ -11,7 +12,7 @@ struct C {
 };
 int main() {
   C c;
-  A(c.p.i); // { dg-error "member.*non-class" }
+  A(c.p.i); // { dg-error "9: error: request for member 'i' in 'c.C::p', which is of non-class type 'B" }
   return 0;
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error21.C b/gcc/testsuite/g++.dg/parse/error21.C
index 6e24ae2..f60bf2b 100644
--- a/gcc/testsuite/g++.dg/parse/error21.C
+++ b/gcc/testsuite/g++.dg/parse/error21.C
@@ -1,5 +1,5 @@
 // PR c++/17393
-// { dg-options "-Wall" }
+// { dg-options "-Wall -fshow-column" }
 
 struct A { };
 
@@ -7,6 +7,6 @@ void foo()
 {
   // Check that we do not complain about an unused
   // compiler-generated variable.
-  A& = a; // { dg-error "token|declarator|not declared" }
+  A& = a; // { dg-error "6: error: expected unqualified-id before '=' token|8: error: 'a' was not declared in this scope" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error22.C b/gcc/testsuite/g++.dg/parse/error22.C
index da3a62f..3014121 100644
--- a/gcc/testsuite/g++.dg/parse/error22.C
+++ b/gcc/testsuite/g++.dg/parse/error22.C
@@ -1,5 +1,6 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/15786
 
 struct A {
-  void foo(bar* p); /* { dg-error "declared" } */
+  void foo(bar* p); /* { dg-error "12: error: 'bar' has not been declared" } */
 };
diff --git a/gcc/testsuite/g++.dg/parse/error23.C b/gcc/testsuite/g++.dg/parse/error23.C
index 7d6fda2..21b2434 100644
--- a/gcc/testsuite/g++.dg/parse/error23.C
+++ b/gcc/testsuite/g++.dg/parse/error23.C
@@ -1,7 +1,9 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/19149
 
 struct QChar {
   QChar( char c );
   QChar( const QChar& c );
-  static const ; // { dg-error "" }
+  //following column number is not accurate enough but will make it for now
+  static const ; // { dg-error "10: error: declaration does not declare anything" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error24.C b/gcc/testsuite/g++.dg/parse/error24.C
index c072250..e341c34 100644
--- a/gcc/testsuite/g++.dg/parse/error24.C
+++ b/gcc/testsuite/g++.dg/parse/error24.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/19395
 
 struct A {
-  typedef int ::X; // { dg-error "" }
+  typedef int ::X; // { dg-error "17: error: typedef name may not be a nested-name-specifier" }
 };
 
 
diff --git a/gcc/testsuite/g++.dg/parse/error25.C b/gcc/testsuite/g++.dg/parse/error25.C
index 360b40f..b5cb57e 100644
--- a/gcc/testsuite/g++.dg/parse/error25.C
+++ b/gcc/testsuite/g++.dg/parse/error25.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // Origin: Steven Bosscher <steven at gcc dot gnu dot org>
 // PR c++/17401: ICE with invalid pure specifier
 
@@ -8,10 +9,10 @@
 class foo
 {
   virtual void bar1 () = 0;
-  virtual void bar2 () = __null;  // { dg-error "invalid pure specifier" }
-  virtual void bar3 () = 4;       // { dg-error "invalid pure specifier" }
-  virtual void bar4 () = A::f;    // { dg-error "invalid pure specifier" }
-  virtual void bar5 () = 0l;      // { dg-error "invalid pure specifier" }
-  virtual void bar6 () = 00;      // { dg-error "invalid pure specifier" }
-  virtual void bar7 () = 0x0;     // { dg-error "invalid pure specifier" }
+  virtual void bar2 () = __null;  // { dg-error "32: error: invalid pure specifier" }
+  virtual void bar3 () = 4;       // { dg-error "27: error: invalid pure specifier" }
+  virtual void bar4 () = A::f;    // { dg-error "27: error: invalid pure specifier" }
+  virtual void bar5 () = 0l;      // { dg-error "28: error: invalid pure specifier" }
+  virtual void bar6 () = 00;      // { dg-error "28: error: invalid pure specifier" }
+  virtual void bar7 () = 0x0;     // { dg-error "29: error: invalid pure specifier" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error26.C b/gcc/testsuite/g++.dg/parse/error26.C
index 6e2b897..81f7ba6 100644
--- a/gcc/testsuite/g++.dg/parse/error26.C
+++ b/gcc/testsuite/g++.dg/parse/error26.C
@@ -1,12 +1,12 @@
 // PR c++/20148
-// { dg-options "" }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 
 void foo()
 {
-  if (({int c[2];})) ; // { dg-error "\{\.\.\.\}" }
+  if (({int c[2];})) ; // { dg-error "7: error: ISO C.. forbids|20: error: could not convert" }
 }
 
 void bar()
 {
-  if (({})); // { dg-error "\{\.\.\.\}" }
+  if (({})); // { dg-error "7: error: ISO C.. forbids|11: error: could not convert" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/error27.C b/gcc/testsuite/g++.dg/parse/error27.C
index f52d3ce..f1fd537 100644
--- a/gcc/testsuite/g++.dg/parse/error27.C
+++ b/gcc/testsuite/g++.dg/parse/error27.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/20152
 
-struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "previous definition" }
-struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "previous definition" }
-struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "" }
-struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "" }
+struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "24: error: previous definition of 'struct KrSelectionMode'" }
+struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "52: error: previous definition of 'struct KrKDESelectionMode'" }
+struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "8: error: redefinition of 'struct KrSelectionMode'" }
+struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "8: error: redefinition of 'struct KrKDESelectionMode'" }
 KrKDESelectionMode krKDESelectionMode;
diff --git a/gcc/testsuite/g++.dg/parse/error28.C b/gcc/testsuite/g++.dg/parse/error28.C
index 046cc50..fd202a1 100644
--- a/gcc/testsuite/g++.dg/parse/error28.C
+++ b/gcc/testsuite/g++.dg/parse/error28.C
@@ -1,10 +1,11 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/21908
 
 struct virt { virt () {} virt (int i) {} };
-struct der : public virtual virt { // { dg-error "der" }
-  der (int i) : virt(i) {} // { dg-error "der" }
+struct der : public virtual virt { // { dg-error "34: note:                 der::der" }
+  der (int i) : virt(i) {} // { dg-error "13: note: candidates are: der" }
 };
 struct top : public der { 
-  // { dg-error "der\\(\\)" "" { target *-*-* } 9 } 
   top () {} // { dg-bogus "der\\(const" }
 };
+// { dg-error "10: error: no matching function for call to 'der" "" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/parse/error29.C b/gcc/testsuite/g++.dg/parse/error29.C
index b50b275..fcd091b 100644
--- a/gcc/testsuite/g++.dg/parse/error29.C
+++ b/gcc/testsuite/g++.dg/parse/error29.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/25637
 
 struct A { 
@@ -6,7 +7,7 @@ struct A {
   void operator delete(void *);
 };
 struct B { 
-  friend void A::foo() {} // { dg-error "define" }
-  friend void A::operator delete(void*) {} // { dg-error "define" }
-  friend A::A() {} // { dg-error "define" }
+  friend void A::foo() {} // { dg-error "22: error: cannot define member function 'A::foo' within 'B'" }
+  friend void A::operator delete(void*) {} // { dg-error "39: error: cannot define member function 'A::operator delete' within 'B'" }
+  friend A::A() {} // { dg-error "15: error: cannot define member function 'A::A' within 'B'" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error3.C b/gcc/testsuite/g++.dg/parse/error3.C
index a052346..1f337e9 100644
--- a/gcc/testsuite/g++.dg/parse/error3.C
+++ b/gcc/testsuite/g++.dg/parse/error3.C
@@ -1,6 +1,19 @@
+// { dg-options "-fshow-column" }
 // PR c++/10779
 
 static void InstantiateConstraint(const float&, unsigned,
-                                  void(*AddFunction)(const TYPE&,bool&, // { dg-error "" }
+                                  void(*AddFunction)(const TYPE&,bool&,
                                                      char*, char*,
-                                                     unsigned*)); // { dg-error "" }
+                                                     unsigned*));
+// { dg-error "64: error: expected ',' or '...' before '&' token" "" { target *-*-* }  { 5 } }
+
+/// in the coming test, the column information is broken as it points to
+//  the end of the declaration instead of pointing to the begining of the
+//  'TYPE' identifier. This is due to the warning being generated by the
+//  declaration groking code (gcc/cp/decl.c) and not the parser. So in that
+//  code, the exact token location information is lost as the declaration
+//  groking code manipulates TREEs only. The token location used is then
+//  the global one that is not accurate enough. Anyway, let's say it is
+//  good enough for now, until we find a way to propagate token location to
+//  code paths that manipulate TREEs only.
+// { dg-error "64: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 7 } }
diff --git a/gcc/testsuite/g++.dg/parse/error30.C b/gcc/testsuite/g++.dg/parse/error30.C
index 734a255..5c52d1e 100644
--- a/gcc/testsuite/g++.dg/parse/error30.C
+++ b/gcc/testsuite/g++.dg/parse/error30.C
@@ -1,5 +1,6 @@
 // PR c++/30854
 // { dg-do compile }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 
 struct A
 {
@@ -7,5 +8,5 @@ struct A
   A(int);
 };
 
-A a = -A();	// { dg-error "no match for.*operator-.*in.*-A\\(\\)" }
-A b = -A(5);	// { dg-error "no match for.*operator-.*in.*-A\\(5\\)" }
+A a = -A();	// { dg-error "10: error: no match for.*operator-.*in.*-A\\(\\)" }
+A b = -A(5);	// { dg-error "11: error: no match for.*operator-.*in.*-A\\(5\\)" }
diff --git a/gcc/testsuite/g++.dg/parse/error31.C b/gcc/testsuite/g++.dg/parse/error31.C
index 5264f44..d354cc3 100644
--- a/gcc/testsuite/g++.dg/parse/error31.C
+++ b/gcc/testsuite/g++.dg/parse/error31.C
@@ -1,10 +1,12 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/32190
 
 template<typename T> class foo{ };
 
 int main() {
     foo<int> i;
-    foo<foo<int> j; // { dg-error "template argument" }
+    // this column number is not accurate yet, but that will make it for now.
+    foo<foo<int> j; // { dg-error "18: error: template argument 1 is invalid" }
     int k;
     int l;
     foo<int> m;
diff --git a/gcc/testsuite/g++.dg/parse/error4.C b/gcc/testsuite/g++.dg/parse/error4.C
index aa1bfad..790e5c9 100644
--- a/gcc/testsuite/g++.dg/parse/error4.C
+++ b/gcc/testsuite/g++.dg/parse/error4.C
@@ -1,7 +1,10 @@
 // PR c++/12160
+// { dg-options "-fshow-column" }
 
-struct X { 
-  virtual void f(int, 
-		 itn,        // { dg-error "declared" }
+struct X {
+  virtual void f(int,
+		 itn,
 		 int);
-}; 
+};
+
+// { dg-error "4: error: 'itn' has not been declared" "" { target *-*-* } { 6 } }
diff --git a/gcc/testsuite/g++.dg/parse/error5.C b/gcc/testsuite/g++.dg/parse/error5.C
index 81356ce..8c9a039 100644
--- a/gcc/testsuite/g++.dg/parse/error5.C
+++ b/gcc/testsuite/g++.dg/parse/error5.C
@@ -1,4 +1,19 @@
 // PR c++/13269
+// { dg-options "-fshow-column" }
 
-class Foo { int foo() return 0; } }; // { dg-error "" }
+class Foo { int foo() return 0; } };
+
+// { dg-error "30: error: expected identifier before numeric constant" "" { target *-*-* } { 4 } }
+
+// { dg-error "23: error: named return values are no longer supported" "" { target *-*-* } { 4 } }
+
+// the column number info of this error output is still wrong because the error
+// message has been generated by cp_parser_error() which does not
+// necessarily allow accurate column number display. At some point, we will
+// need make cp_parser_error() report more accurate column numbers.
+// { dg-error "30: error: expected '\{' at end of input" "" { target *-*-* } { 4 } }
+
+// { dg-error "35: error: expected unqualified-id before '\}' token" "" {target *-*-*  } { 4 } }
+
+// { dg-error "35: error: expected declaration before '\}' token" "" {target *-*-*  } { 4 } }
 
diff --git a/gcc/testsuite/g++.dg/parse/error6.C b/gcc/testsuite/g++.dg/parse/error6.C
index 3a16669..cd1b6b8 100644
--- a/gcc/testsuite/g++.dg/parse/error6.C
+++ b/gcc/testsuite/g++.dg/parse/error6.C
@@ -1,6 +1,11 @@
 // PR c++/10603
+// { dg-options "-fshow-column" }
 
-int f(int not) { // { dg-error "!" }
-  return 1-not; // { dg-error "" }
+int f(int not) {
+  return 1-not;
 } 
 
+// { dg-error "11: error: expected ',' or '...' before '!' token" "" { target *-*-* } { 4 } }
+
+// { dg-error "15: error: expected primary\\-expression before ';' token" "" { target *-*-* }  { 5 } }
+
diff --git a/gcc/testsuite/g++.dg/parse/error7.C b/gcc/testsuite/g++.dg/parse/error7.C
index 50e7f84..f71c9aa 100644
--- a/gcc/testsuite/g++.dg/parse/error7.C
+++ b/gcc/testsuite/g++.dg/parse/error7.C
@@ -1,4 +1,7 @@
 // PR c++/12827
+// { dg-options "-fshow-column" }
 
 void f(int x
-       int y); // { dg-error "," }
+       int y);
+
+// { dg-error "8: error: expected ',' or '...' before 'int'" "" { target *-*-* } { 5 } }
diff --git a/gcc/testsuite/g++.dg/parse/error8.C b/gcc/testsuite/g++.dg/parse/error8.C
index 125f2e4..a399cfe 100644
--- a/gcc/testsuite/g++.dg/parse/error8.C
+++ b/gcc/testsuite/g++.dg/parse/error8.C
@@ -1,4 +1,10 @@
 // PR c++/13438
+// {  dg-options "-fshow-column" }
 
-struct A { friend typename struct B; };  // { dg-error "" }
-  
+struct A { friend typename struct B; };
+
+
+// { dg-error "19: error: using 'typename' outside of template" "" { target *-*-* } { 4 } }
+// { dg-error "28: error: expected nested-name-specifier before 'struct'" "" { target *-*-* } { 4 } }
+// { dg-error "35: error: multiple types in one declaration" "" { target *-*-* } { 4 } }
+// { dg-error "12: error: friend declaration does not name a class or function" "" { target *-*-* } { 4 } }
diff --git a/gcc/testsuite/g++.dg/parse/error9.C b/gcc/testsuite/g++.dg/parse/error9.C
index aa9109f..c1be697 100644
--- a/gcc/testsuite/g++.dg/parse/error9.C
+++ b/gcc/testsuite/g++.dg/parse/error9.C
@@ -1,5 +1,9 @@
 // PR c++/12613
-// { dg-options "" }
+// { dg-options "-fshow-column" }
 
 enum { FOO = 1, BAR = 2 };
-int a[] = { FOO: 1, BAR: 2 }; // { dg-error "" }
+int a[] = { FOO: 1, BAR: 2 };
+
+// the following 2 column locations are still not accurate enough
+// { dg-error "28: error: name 'FOO' used in a GNU-style designated initializer for an array" "" { target *-*-* }  { 5 } }
+// { dg-error "28: error: name 'BAR' used in a GNU-style designated initializer for an array" "" { target *-*-* }  { 5 } }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
index 42a21fc..7fe07a2 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
@@ -1,8 +1,9 @@
 // { dg-do assemble  }
+// { dg-options "-fshow-column" }
 
 struct A { // { dg-error "" } forward declaration
-  friend struct B : A {		// { dg-error "" } 
+  friend struct B : A {		// { dg-error "invalid use of incomplete type 'struct A'" }
     int x;
-  };	// { dg-error "" } class definition cannot be a friend
+  };	// { dg-error "class definition may not be declared a friend" ""  { target *-*-* } { 5 } }
   int y;
 };
diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
index c188824..7ca5b73 100644
--- a/gcc/testsuite/lib/g++.exp
+++ b/gcc/testsuite/lib/g++.exp
@@ -273,7 +273,6 @@ proc g++_target_compile { source dest type options } {
     }
 
     lappend options "additional_flags=[libio_include_flags]"
-    lappend options "additional_flags=-fno-show-column"
     lappend options "compiler=$GXX_UNDER_TEST"
 
     set options [concat $gpp_compile_options $options]

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate  column numbers
  2008-06-26 14:24       ` Manuel López-Ibáñez
@ 2008-06-26 19:08         ` Dodji Seketeli
  0 siblings, 0 replies; 12+ messages in thread
From: Dodji Seketeli @ 2008-06-26 19:08 UTC (permalink / raw)
  To: Manuel López-Ibáñez; +Cc: gcc-patches, tromey, Janis Johnson

Manuel López-Ibáñez a écrit :

[...]

> 
> On the one hand, if this goes in, it is going to be difficult to
> notice it and change it afterwards. On the other hand, I understand
> that implementing a column parameter for the various dg-* things may
> be difficult. DejaGNU is not the easiest or enjoyable part of GCC to
> hack. After all, we are still using the "dg-error "error:" hack
> everywhere except in the C testsuite.

:-)

> 
> Anyway, my opinion doesn't matter since I can't approve patches.
> Maintainers should voice their preference here. At the minimum, if
> this goes in like this, you could open a PR about the missing
> "column-number" parameter to dg-* and point to this testcase, so if it
> ever gets fixed, the testcase can be updated.
>

Yes, I like that idea. If it goes in, I will open the relevant PR.

> BTW, if you plan to keep hacking on column numbers. I have an
> experimental patch to add caret diagnostics that may help you to
> pin-point where a location is actually pointing to.

Yes, I plan to be working on this for a while. Maybe you could open an 
enhancement PR and file your patch there ?

Thanks,

Dodji.

^ permalink raw reply	[flat|nested] 12+ messages in thread

* [patch] PR 31754/C++ - make -fshow-column produce more accurate column  numbers
  2008-06-26 18:39     ` Dodji Seketeli
@ 2008-07-02 10:37       ` Dodji Seketeli
  2008-07-10  4:33         ` Jason Merrill
  0 siblings, 1 reply; 12+ messages in thread
From: Dodji Seketeli @ 2008-07-02 10:37 UTC (permalink / raw)
  To: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 738 bytes --]

Hello,

I have not heard anything from the patch I sent earlier at 
http://gcc.gnu.org/ml/gcc-patches/2008-06/msg01677.html.

So I went forward and wrote a second patch that stacks on top of that 
first one I sent earlier.

The second patch goes forward in making all the calls to error() in 
gcc/cp/parser.c carry somewhat more precise location information. That 
eventually produces error message with more accurate column information, 
  when the parsed tokens context is still available to the parser.

As usual, the patch also updates some relevant tests of the testsuite to 
   catch future regressions that might happen around this column number 
thing.

I have also refreshed the patches against "current" trunk.

Cheers,

Dodji.

[-- Attachment #2: gcc-error-location-2008-06-30-gcc-patch.txt --]
[-- Type: text/plain, Size: 131138 bytes --]

gcc/cp/ChangeLog:
2008-06-30 Dodji Seketeli <dseketel@redhat.com>

	PR c/31754
	* pt.c, semantic.c:
	* semantic.c (qualified_name_lookup_error, finish_id_expression):
	add a location_t parameter so that
	error message can have a more accurate location.
	* cp-tree.h: updated prototype
	* pt.c (tsubst_qualified_id): use location in error messages.
	* parser.c (cp_parser_postfix_expression,
	cp_parser_objc_statement, cp_parser_trait_expr,
	cp_parser_token_is_class_key,
	cp_parser_uncommitted_to_tentative_parse_p,
	cp_parser_check_for_invalid_template_id, cp_parser_is_string_literal,
	cp_parser_error, cp_parser_name_lookup_error,
	cp_parser_simulate_error, cp_parser_check_decl_spec,
	cp_parser_check_decl_spec, cp_parser_non_integral_constant_expression,
	cp_parser_diagnose_invalid_type_name,
	cp_parser_parse_and_diagnose_invalid_type_name,
	cp_parser_require_pragma_eol, cp_parser_make_typename_type,
	cp_parser_string_literal, cp_parser_primary_expression,
	cp_parser_primary_expression, cp_parser_unqualified_id,
	cp_parser_nested_name_specifier_opt, cp_parser_postfix_expression,
	cp_parser_postfix_dot_deref_expression, cp_parser_new_expression,
	cp_parser_direct_new_declarator, cp_parser_builtin_offsetof,
	cp_parser_label_for_labeled_statement, cp_parser_statement_seq_opt,
	cp_parser_jump_statement, cp_parser_block_declaration,
	cp_parser_simple_declaration, cp_parser_decl_specifier_seq,
	cp_parser_function_specifier_opt, cp_parser_decltype,
	cp_parser_mem_initializer_list, cp_parser_mem_initializer,
	cp_parser_mem_initializer_id, cp_parser_template_parameter,
	cp_parser_type_parameter, cp_parser_template_id, cp_parser_template_name,
	cp_parser_template_argument): likewise.

gcc/testsuite/ChangeLog:
2008-06-30 Dodji Seketeli <dseketel@redhat.com>

	* g.dg/parse/constructor1.C, g.dg/parse/error*.C: update these
	  tests to make them catch column number regressions. Make these tests
	  run with the -fshow-column option.
	* g.dg/parse/error-column.C: new column number test.


diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index d090d8f..afea188 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4632,13 +4632,15 @@ extern void finish_template_decl		(tree);
 extern tree finish_template_type		(tree, tree, int);
 extern tree finish_base_specifier		(tree, tree, bool);
 extern void finish_member_declaration		(tree);
-extern void qualified_name_lookup_error		(tree, tree, tree);
+extern void qualified_name_lookup_error		(tree, tree, tree,
+						 location_t);
 extern void check_template_keyword		(tree);
 extern tree finish_id_expression		(tree, tree, tree,
 						 cp_id_kind *,
 						 bool, bool, bool *,
 						 bool, bool, bool, bool,
-						 const char **);
+						 const char **,
+                                                 location_t);
 extern tree finish_typeof			(tree);
 extern tree finish_offsetof			(tree);
 extern void finish_decl_cleanup			(tree, tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 7d530f5..184b9ec 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1585,7 +1585,7 @@ static tree cp_parser_postfix_expression
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
-  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
+  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
 static tree cp_parser_parenthesized_expression_list
   (cp_parser *, bool, bool, bool, bool *);
 static void cp_parser_pseudo_destructor_name
@@ -1894,15 +1894,15 @@ static tree cp_parser_objc_statement
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
-  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
+  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t);
 static tree cp_parser_lookup_name_simple
-  (cp_parser *, tree);
+  (cp_parser *, tree, location_t);
 static tree cp_parser_maybe_treat_template_as_class
   (tree, bool);
 static bool cp_parser_check_declarator_template_parameters
-  (cp_parser *, cp_declarator *);
+  (cp_parser *, cp_declarator *, location_t);
 static bool cp_parser_check_template_parameters
-  (cp_parser *, unsigned);
+  (cp_parser *, unsigned, location_t);
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
@@ -1938,7 +1938,7 @@ static tree cp_parser_trait_expr
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
-  (cp_parser *, cp_decl_specifier_seq *, enum rid);
+  (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
 static void cp_parser_set_decl_spec_type
   (cp_decl_specifier_seq *, tree, bool);
 static bool cp_parser_friend_p
@@ -1960,7 +1960,7 @@ static enum tag_types cp_parser_token_is_class_key
 static void cp_parser_check_class_key
   (enum tag_types, tree type);
 static void cp_parser_check_access_in_redeclaration
-  (tree type);
+  (tree type, location_t location);
 static bool cp_parser_optional_template_keyword
   (cp_parser *);
 static void cp_parser_pre_parsed_nested_name_specifier
@@ -1982,7 +1982,7 @@ static bool cp_parser_uncommitted_to_tentative_parse_p
 static void cp_parser_error
   (cp_parser *, const char *);
 static void cp_parser_name_lookup_error
-  (cp_parser *, tree, tree, const char *);
+  (cp_parser *, tree, tree, const char *, location_t);
 static bool cp_parser_simulate_error
   (cp_parser *);
 static bool cp_parser_check_type_definition
@@ -1994,7 +1994,7 @@ static void cp_parser_check_for_invalid_template_id
 static bool cp_parser_non_integral_constant_expression
   (cp_parser *, const char *);
 static void cp_parser_diagnose_invalid_type_name
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t);
 static bool cp_parser_parse_and_diagnose_invalid_type_name
   (cp_parser *);
 static int cp_parser_skip_to_closing_parenthesis
@@ -2020,7 +2020,7 @@ static bool cp_parser_is_string_literal
 static bool cp_parser_is_keyword
   (cp_token *, enum rid);
 static tree cp_parser_make_typename_type
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t location);
 static cp_declarator * cp_parser_make_indirect_declarator
   (enum tree_code, tree, cp_cv_quals, cp_declarator *);
 
@@ -2069,7 +2069,7 @@ cp_parser_error (cp_parser* parser, const char* message)
 
       if (token->type == CPP_PRAGMA)
 	{
-	  error ("%<#pragma%> is not allowed here");
+	  error ("%H%<#pragma%> is not allowed here", &token->location);
 	  cp_parser_skip_to_pragma_eol (parser, token);
 	  return;
 	}
@@ -2092,33 +2092,34 @@ static void
 cp_parser_name_lookup_error (cp_parser* parser,
 			     tree name,
 			     tree decl,
-			     const char* desired)
+			     const char* desired,
+			     location_t location)
 {
   /* If name lookup completely failed, tell the user that NAME was not
      declared.  */
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-	error ("%<%E::%E%> has not been declared",
-	       parser->scope, name);
+	error ("%H%<%E::%E%> has not been declared",
+	       &location, parser->scope, name);
       else if (parser->scope == global_namespace)
-	error ("%<::%E%> has not been declared", name);
+	error ("%H%<::%E%> has not been declared", &location, name);
       else if (parser->object_scope
 	       && !CLASS_TYPE_P (parser->object_scope))
-	error ("request for member %qE in non-class type %qT",
-	       name, parser->object_scope);
+	error ("%Hrequest for member %qE in non-class type %qT",
+	       &location, name, parser->object_scope);
       else if (parser->object_scope)
-	error ("%<%T::%E%> has not been declared",
-	       parser->object_scope, name);
+	error ("%H%<%T::%E%> has not been declared",
+	       &location, parser->object_scope, name);
       else
-	error ("%qE has not been declared", name);
+	error ("%H%qE has not been declared", &location, name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("%<%E::%E%> %s", parser->scope, name, desired);
+    error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
   else if (parser->scope == global_namespace)
-    error ("%<::%E%> %s", name, desired);
+    error ("%H%<::%E%> %s", &location, name, desired);
   else
-    error ("%qE %s", name, desired);
+    error ("%H%qE %s", &location, name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -2139,7 +2140,8 @@ cp_parser_simulate_error (cp_parser* parser)
 /* Check for repeated decl-specifiers.  */
 
 static void
-cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
+cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
+			   location_t location)
 {
   cp_decl_spec ds;
 
@@ -2152,10 +2154,11 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
       if (ds == ds_long)
 	{
 	  if (count > 2)
-	    error ("%<long long long%> is too long for GCC");
+	    error ("%H%<long long long%> is too long for GCC", &location);
 	  else if (pedantic && !in_system_header && warn_long_long
                    && cxx_dialect == cxx98)
-	    pedwarn ("ISO C++ 1998 does not support %<long long%>");
+	    pedwarn ("%HISO C++ 1998 does not support %<long long%>",
+		     &location);
 	}
       else if (count > 1)
 	{
@@ -2175,7 +2178,7 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
 	    "__complex",
 	    "__thread"
 	  };
-	  error ("duplicate %qs", decl_spec_names[(int)ds]);
+	  error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
 	}
     }
 }
@@ -2291,13 +2294,15 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
    in duplicate error messages.)  */
 
 static void
-cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
+cp_parser_diagnose_invalid_type_name (cp_parser *parser,
+				      tree scope, tree id,
+				      location_t id_location)
 {
   tree decl, old_scope;
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
-  decl = cp_parser_lookup_name_simple (parser, id);
+  decl = cp_parser_lookup_name_simple (parser, id, id_location);
   parser->scope = old_scope;
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
@@ -2382,6 +2387,7 @@ static bool
 cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
 {
   tree id;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   cp_parser_parse_tentatively (parser);
   id = cp_parser_id_expression (parser,
@@ -2405,7 +2411,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
-  cp_parser_diagnose_invalid_type_name (parser, parser->scope, id);
+  cp_parser_diagnose_invalid_type_name (parser, parser->scope,
+					id, token->location);
   /* Skip to the end of the declaration; there's no point in
      trying to process it.  */
   cp_parser_skip_to_end_of_block_or_statement (parser);
@@ -2693,7 +2700,8 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok)
    using cp_parser_diagnose_invalid_type_name.  */
 
 static tree
-cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
+cp_parser_make_typename_type (cp_parser *parser, tree scope,
+			      tree id, location_t id_location)
 {
   tree result;
   if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -2701,7 +2709,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
       result = make_typename_type (scope, id, typename_type,
 				   /*complain=*/tf_none);
       if (result == error_mark_node)
-	cp_parser_diagnose_invalid_type_name (parser, scope, id);
+	cp_parser_diagnose_invalid_type_name (parser, scope, id, id_location);
       return result;
     }
   return make_typename_type (scope, id, typename_type, tf_error);
@@ -2919,7 +2927,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
 	      if (type == CPP_STRING)
 		type = tok->type;
 	      else if (tok->type != CPP_STRING)
-		error ("unsupported non-standard concatenation of string literals");
+		error ("%Hunsupported non-standard concatenation "
+                       "of string literals", &tok->location);
 	    }
 
 	  obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -3098,7 +3107,7 @@ cp_parser_primary_expression (cp_parser *parser,
 			      bool template_arg_p,
 			      cp_id_kind *idk)
 {
-  cp_token *token;
+  cp_token *token = NULL;
 
   /* Assume the primary expression is not an id-expression.  */
   *idk = CP_ID_KIND_NONE;
@@ -3196,7 +3205,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  {
 	    /* Statement-expressions are not allowed by the standard.  */
 	    if (pedantic)
-	      pedwarn ("ISO C++ forbids braced-groups within expressions");
+	      pedwarn ("%HISO C++ forbids braced-groups within expressions",
+		       &token->location);
 
 	    /* And they're not allowed outside of a function-body; you
 	       cannot, for example, write:
@@ -3207,8 +3217,9 @@ cp_parser_primary_expression (cp_parser *parser,
 	    if (!parser->in_function_body
 		|| parser->in_template_argument_list_p)
 	      {
-		error ("statement-expressions are not allowed outside "
-		       "functions nor in template-argument lists");
+		error ("%Hstatement-expressions are not allowed outside "
+		       "functions nor in template-argument lists",
+		       &token->location);
 		cp_parser_skip_to_end_of_block_or_statement (parser);
 		expr = error_mark_node;
 	      }
@@ -3265,7 +3276,8 @@ cp_parser_primary_expression (cp_parser *parser,
 	  cp_lexer_consume_token (parser->lexer);
 	  if (parser->local_variables_forbidden_p)
 	    {
-	      error ("%<this%> may not be used in this context");
+	      error ("%H%<this%> may not be used in this context",
+                     &token->location);
 	      return error_mark_node;
 	    }
 	  /* Pointers cannot appear in constant-expressions.  */
@@ -3365,6 +3377,7 @@ cp_parser_primary_expression (cp_parser *parser,
 	const char *error_msg;
 	bool template_p;
 	bool done;
+	cp_token *id_expr_token;
 
       id_expression:
 	/* Parse the id-expression.  */
@@ -3377,6 +3390,7 @@ cp_parser_primary_expression (cp_parser *parser,
 				     /*optional_p=*/false);
 	if (id_expression == error_mark_node)
 	  return error_mark_node;
+	id_expr_token = token;
 	token = cp_lexer_peek_token (parser->lexer);
 	done = (token->type != CPP_OPEN_SQUARE
 		&& token->type != CPP_OPEN_PAREN
@@ -3400,7 +3414,8 @@ cp_parser_primary_expression (cp_parser *parser,
 					  template_p,
 					  /*is_namespace=*/false,
 					  /*check_dependency=*/true,
-					  &ambiguous_decls);
+					  &ambiguous_decls,
+					  id_expr_token->location);
 	    /* If the lookup was ambiguous, an error will already have
 	       been issued.  */
 	    if (ambiguous_decls)
@@ -3447,8 +3462,8 @@ cp_parser_primary_expression (cp_parser *parser,
 		decl = check_for_out_of_scope_variable (decl);
 		if (local_variable_p (decl))
 		  {
-		    error ("local variable %qD may not appear in this context",
-			   decl);
+		    error ("%Hlocal variable %qD may not appear in this context",
+			   &id_expr_token->location, decl);
 		    return error_mark_node;
 		  }
 	      }
@@ -3462,7 +3477,8 @@ cp_parser_primary_expression (cp_parser *parser,
 		 &parser->non_integral_constant_expression_p,
 		 template_p, done, address_p,
 		 template_arg_p,
-		 &error_msg));
+		 &error_msg,
+                 id_expr_token->location));
 	if (error_msg)
 	  cp_parser_error (parser, error_msg);
 	return decl;
@@ -3746,7 +3762,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	      error ("scope %qT before %<~%> is not a class-name", scope);
+	      error ("%Hscope %qT before %<~%> is not a class-name",
+		     &token->location, scope);
 	    cp_parser_simulate_error (parser);
 	    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
 	      cp_lexer_consume_token (parser->lexer);
@@ -3847,8 +3864,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	if (declarator_p && scope && !check_dtor_name (scope, type_decl))
 	  {
 	    if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	      error ("declaration of %<~%T%> as member of %qT",
-		     type_decl, scope);
+	      error ("%Hdeclaration of %<~%T%> as member of %qT",
+		     &token->location, type_decl, scope);
 	    cp_parser_simulate_error (parser);
 	    return error_mark_node;
 	  }
@@ -3861,8 +3878,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 	    && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
 	    && !DECL_SELF_REFERENCE_P (type_decl)
 	    && !cp_parser_uncommitted_to_tentative_parse_p (parser))
-	  error ("typedef-name %qD used as destructor declarator",
-		 type_decl);
+	  error ("%Htypedef-name %qD used as destructor declarator",
+		 &token->location, type_decl);
 
 	return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
@@ -4066,20 +4083,23 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
 						    /*is_template=*/false,
 						    /*is_namespace=*/false,
 						    /*check_dependency=*/true,
-						    &ambiguous_decls);
+						    &ambiguous_decls,
+						    token->location);
 		      if (TREE_CODE (decl) == TEMPLATE_DECL)
-			error ("%qD used without template parameters", decl);
+			error ("%H%qD used without template parameters",
+			       &token->location, decl);
 		      else if (ambiguous_decls)
 			{
-			  error ("reference to %qD is ambiguous",
-				 token->u.value);
+			  error ("%Hreference to %qD is ambiguous",
+				 &token->location, token->u.value);
 			  print_candidates (ambiguous_decls);
 			  decl = error_mark_node;
 			}
 		      else
 			cp_parser_name_lookup_error
 			  (parser, token->u.value, decl,
-			   "is not a class or namespace");
+			   "is not a class or namespace",
+			   token->location);
 		    }
 		  parser->scope = error_mark_node;
 		  error_p = true;
@@ -4731,7 +4751,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 	  postfix_expression
 	    = cp_parser_postfix_dot_deref_expression (parser, token->type,
 						      postfix_expression,
-						      false, &idk);
+						      false, &idk,
+						      token->location);
 
           is_member_access = true;
 	  break;
@@ -4845,7 +4866,8 @@ static tree
 cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 					enum cpp_ttype token_type,
 					tree postfix_expression,
-					bool for_offsetof, cp_id_kind *idk)
+					bool for_offsetof, cp_id_kind *idk,
+					location_t location)
 {
   tree name;
   bool dependent_p;
@@ -4877,7 +4899,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
 	{
-	  error ("%qE does not have class type", postfix_expression);
+	  error ("%H%qE does not have class type", &location, postfix_expression);
 	  scope = NULL_TREE;
 	}
       else
@@ -4933,6 +4955,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 ordinary class member access expression, rather than a
 	 pseudo-destructor-name.  */
       bool template_p;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
       /* Parse the id-expression.  */
       name = (cp_parser_id_expression
 	      (parser,
@@ -4960,7 +4983,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 	 TYPE_DECL here.  That is invalid code.  */
       if (TREE_CODE (name) == TYPE_DECL)
 	{
-	  error ("invalid use of %qD", name);
+	  error ("%Hinvalid use of %qD", &token->location, name);
 	  postfix_expression = error_mark_node;
 	}
       else
@@ -5514,18 +5537,21 @@ cp_parser_new_expression (cp_parser* parser)
      type-id.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
+      cp_token *token;
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the type-id.  */
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      token = cp_lexer_peek_token (parser->lexer);
       /* There should not be a direct-new-declarator in this production,
 	 but GCC used to allowed this, so we check and emit a sensible error
 	 message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
 	{
-	  error ("array bound forbidden after parenthesized type-id");
+	  error ("%Harray bound forbidden after parenthesized type-id",
+		 &token->location);
 	  inform ("try removing the parentheses around the type-id");
 	  cp_parser_direct_new_declarator (parser);
 	}
@@ -5702,6 +5728,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       /* The first expression is not required to be constant.  */
       if (!declarator)
 	{
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
 	  expression = cp_parser_expression (parser, /*cast_p=*/false);
 	  /* The standard requires that the expression have integral
 	     type.  DR 74 adds enumeration types.  We believe that the
@@ -5717,8 +5744,8 @@ cp_parser_direct_new_declarator (cp_parser* parser)
 					      /*complain=*/true);
 	      if (!expression)
 		{
-		  error ("expression in new-declarator must have integral "
-			 "or enumeration type");
+		  error ("%Hexpression in new-declarator must have integral "
+			 "or enumeration type", &token->location);
 		  expression = error_mark_node;
 		}
 	    }
@@ -6445,6 +6472,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   int save_ice_p, save_non_ice_p;
   tree type, expr;
   cp_id_kind dummy;
+  cp_token *token;
 
   /* We're about to accept non-integral-constant things, but will
      definitely yield an integral constant expression.  Save and
@@ -6460,6 +6488,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
   cp_parser_require (parser, CPP_COMMA, "%<,%>");
+  token = cp_lexer_peek_token (parser->lexer);
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
   expr = build_static_cast (build_pointer_type (type), null_pointer_node,
@@ -6467,10 +6496,10 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 
   /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
   expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
-						 true, &dummy);
+						 true, &dummy, token->location);
   while (true)
     {
-      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
       switch (token->type)
 	{
 	case CPP_OPEN_SQUARE:
@@ -6482,7 +6511,8 @@ cp_parser_builtin_offsetof (cp_parser *parser)
 	  /* offsetof-member-designator "." identifier */
 	  cp_lexer_consume_token (parser->lexer);
 	  expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
-							 true, &dummy);
+							 true, &dummy,
+							 token->location);
 	  break;
 
 	case CPP_CLOSE_PAREN:
@@ -6844,7 +6874,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
 	if (parser->in_switch_statement_p)
 	  finish_case_label (expr, expr_hi);
 	else
-	  error ("case label %qE not within a switch statement", expr);
+	  error ("%Hcase label %qE not within a switch statement",
+		 &token->location, expr);
       }
       break;
 
@@ -6855,7 +6886,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
       if (parser->in_switch_statement_p)
 	finish_case_label (NULL_TREE, NULL_TREE);
       else
-	error ("case label not within a switch statement");
+	error ("%Hcase label not within a switch statement", &token->location);
       break;
 
     default:
@@ -6973,7 +7004,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
 	  else
 	    {
 	      token = cp_lexer_consume_token (parser->lexer);
-	      error ("%<else%> without a previous %<if%>");
+	      error ("%H%<else%> without a previous %<if%>", &token->location);
 	    }
 	}
 
@@ -7457,7 +7488,7 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (in_statement)
 	{
 	case 0:
-	  error ("break statement not within loop or switch");
+	  error ("%Hbreak statement not within loop or switch", &token->location);
 	  break;
 	default:
 	  gcc_assert ((in_statement & IN_SWITCH_STMT)
@@ -7465,10 +7496,10 @@ cp_parser_jump_statement (cp_parser* parser)
 	  statement = finish_break_stmt ();
 	  break;
 	case IN_OMP_BLOCK:
-	  error ("invalid exit from OpenMP structured block");
+	  error ("%Hinvalid exit from OpenMP structured block", &token->location);
 	  break;
 	case IN_OMP_FOR:
-	  error ("break statement used with OpenMP for loop");
+	  error ("%Hbreak statement used with OpenMP for loop", &token->location);
 	  break;
 	}
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
@@ -7478,14 +7509,14 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
 	{
 	case 0:
-	  error ("continue statement not within a loop");
+	  error ("%Hcontinue statement not within a loop", &token->location);
 	  break;
 	case IN_ITERATION_STMT:
 	case IN_OMP_FOR:
 	  statement = finish_continue_stmt ();
 	  break;
 	case IN_OMP_BLOCK:
-	  error ("invalid exit from OpenMP structured block");
+	  error ("%Hinvalid exit from OpenMP structured block", &token->location);
 	  break;
 	default:
 	  gcc_unreachable ();
@@ -7516,7 +7547,7 @@ cp_parser_jump_statement (cp_parser* parser)
 	{
 	  /* Issue a warning about this use of a GNU extension.  */
 	  if (pedantic)
-	    pedwarn ("ISO C++ forbids computed gotos");
+	    pedwarn ("%HISO C++ forbids computed gotos", &token->location);
 	  /* Consume the '*' token.  */
 	  cp_lexer_consume_token (parser->lexer);
 	  /* Parse the dependent expression.  */
@@ -7877,7 +7908,7 @@ cp_parser_block_declaration (cp_parser *parser,
   else if (token1->keyword == RID_LABEL)
     {
       cp_lexer_consume_token (parser->lexer);
-      error ("%<__label__%> not at the beginning of a block");
+      error ("%H%<__label__%> not at the beginning of a block", &token1->location);
       cp_parser_skip_to_end_of_statement (parser);
       /* If the next token is now a `;', consume it.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -8010,7 +8041,11 @@ cp_parser_simple_declaration (cp_parser* parser,
 
 	     which is erroneous.  */
 	  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-	    error ("mixing declarations and function-definitions is forbidden");
+	    {
+	      cp_token *token = cp_lexer_peek_token (parser->lexer);
+	      error ("%Hmixing declarations and function-definitions is forbidden",
+		     &token->location);
+	    }
 	  /* Otherwise, we're done with the list of declarators.  */
 	  else
 	    {
@@ -8106,6 +8141,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 			      int* declares_class_or_enum)
 {
   bool constructor_possible_p = !parser->in_declarator_p;
+  cp_token *start_token = NULL;
 
   /* Clear DECL_SPECS.  */
   clear_decl_specs (decl_specs);
@@ -8122,6 +8158,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
+
+      /* Save the first token of the decl spec list for error
+         reporting.  */
+      if (!start_token)
+	start_token = token;
       /* Handle attributes.  */
       if (token->keyword == RID_ATTRIBUTE)
 	{
@@ -8198,15 +8239,17 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
                  we're complaining about C++0x compatibility.  */
               warning 
                 (OPT_Wc__0x_compat, 
-                 "%<auto%> will change meaning in C++0x; please remove it");
+                 "%H%<auto%> will change meaning in C++0x; please remove it",
+		 &token->location);
 
               /* Set the storage class anyway.  */
-              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO);
+              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
+					   token->location);
             }
           else 
             /* We do not yet support the use of `auto' as a
                type-specifier.  */
-            error ("C++0x %<auto%> specifier not supported");
+            error ("%HC++0x %<auto%> specifier not supported", &token->location);
           break;
 
 	case RID_REGISTER:
@@ -8215,7 +8258,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 	case RID_MUTABLE:
 	  /* Consume the token.  */
 	  cp_lexer_consume_token (parser->lexer);
-          cp_parser_set_storage_class (parser, decl_specs, token->keyword);
+          cp_parser_set_storage_class (parser, decl_specs, token->keyword,
+				       token->location);
 	  break;
 	case RID_THREAD:
 	  /* Consume the token.  */
@@ -8251,7 +8295,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 					/*is_declaration=*/true,
 					&decl_spec_declares_class_or_enum,
 					&is_cv_qualifier);
-
 	  *declares_class_or_enum |= decl_spec_declares_class_or_enum;
 
 	  /* If this type-specifier referenced a user-defined type
@@ -8311,12 +8354,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
-  cp_parser_check_decl_spec (decl_specs);
+  cp_parser_check_decl_spec (decl_specs, start_token->location);
 
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
-    error ("class definition may not be declared a friend");
+    error ("%Hclass definition may not be declared a friend",
+	    &start_token->location);
 }
 
 /* Parse an (optional) storage-class-specifier.
@@ -8372,7 +8416,8 @@ static tree
 cp_parser_function_specifier_opt (cp_parser* parser,
 				  cp_decl_specifier_seq *decl_specs)
 {
-  switch (cp_lexer_peek_token (parser->lexer)->keyword)
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  switch (token->keyword)
     {
     case RID_INLINE:
       if (decl_specs)
@@ -8384,7 +8429,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
 
 	 A member function template shall not be virtual.  */
       if (PROCESSING_REAL_TEMPLATE_DECL_P ())
-	error ("templates may not be %<virtual%>");
+	error ("%Htemplates may not be %<virtual%>", &token->location);
       else if (decl_specs)
 	++decl_specs->specs[(int) ds_virtual];
       break;
@@ -8538,6 +8583,7 @@ cp_parser_decltype (cp_parser *parser)
   const char *saved_message;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
+  cp_token *id_expr_start_token;
 
   /* Look for the `decltype' token.  */
   if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
@@ -8567,6 +8613,7 @@ cp_parser_decltype (cp_parser *parser)
     return error_mark_node;
   
   /* First, try parsing an id-expression.  */
+  id_expr_start_token = cp_lexer_peek_token (parser->lexer);
   cp_parser_parse_tentatively (parser);
   expr = cp_parser_id_expression (parser,
                                   /*template_keyword_p=*/false,
@@ -8589,7 +8636,8 @@ cp_parser_decltype (cp_parser *parser)
 				      /*is_template=*/false,
 				      /*is_namespace=*/false,
 				      /*check_dependency=*/true,
-				      /*ambiguous_decls=*/NULL);
+				      /*ambiguous_decls=*/NULL,
+				      id_expr_start_token->location);
 
       if (expr
           && expr != error_mark_node
@@ -8609,7 +8657,8 @@ cp_parser_decltype (cp_parser *parser)
                    /*done=*/true,
                    /*address_p=*/false,
                    /*template_arg_p=*/false,
-                   &error_msg));
+                   &error_msg,
+		   id_expr_start_token->location));
 
           if (expr == error_mark_node)
             /* We found an id-expression, but it was something that we
@@ -8852,17 +8901,20 @@ static void
 cp_parser_mem_initializer_list (cp_parser* parser)
 {
   tree mem_initializer_list = NULL_TREE;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Let the semantic analysis code know that we are starting the
      mem-initializer-list.  */
   if (!DECL_CONSTRUCTOR_P (current_function_decl))
-    error ("only constructors take base initializers");
+    error ("%Honly constructors take base initializers",
+	   &token->location);
 
   /* Loop through the list.  */
   while (true)
     {
       tree mem_initializer;
 
+      token = cp_lexer_peek_token (parser->lexer);
       /* Parse the mem-initializer.  */
       mem_initializer = cp_parser_mem_initializer (parser);
       /* If the next token is a `...', we're expanding member initializers. */
@@ -8876,8 +8928,8 @@ cp_parser_mem_initializer_list (cp_parser* parser)
           if (mem_initializer != error_mark_node
               && !TYPE_P (TREE_PURPOSE (mem_initializer)))
             {
-              error ("cannot expand initializer for member %<%D%>", 
-                     TREE_PURPOSE (mem_initializer));
+              error ("%Hcannot expand initializer for member %<%D%>",
+                     &token->location, TREE_PURPOSE (mem_initializer));
               mem_initializer = error_mark_node;
             }
 
@@ -8924,11 +8976,13 @@ cp_parser_mem_initializer (cp_parser* parser)
   tree mem_initializer_id;
   tree expression_list;
   tree member;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
-      permerror ("anachronistic old-style base class initializer");
+      permerror ("%Hanachronistic old-style base class initializer",
+                 &token->location);
       mem_initializer_id = NULL_TREE;
     }
   else
@@ -8970,11 +9024,14 @@ cp_parser_mem_initializer_id (cp_parser* parser)
   bool template_p = false;
   tree id;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* `typename' is not allowed in this context ([temp.res]).  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
-      error ("keyword %<typename%> not allowed in this context (a qualified "
-	     "member initializer is implicitly a type)");
+      error ("%Hkeyword %<typename%> not allowed in this context (a qualified "
+	     "member initializer is implicitly a type)",
+	     &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the optional `::' operator.  */
@@ -9491,6 +9548,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	 appropriate diagnostic here.  */
 
       /* Consume the `='.  */
+      cp_token *start_token = cp_lexer_peek_token (parser->lexer);
       cp_lexer_consume_token (parser->lexer);
       
       /* Find the name of the parameter pack.  */     
@@ -9499,10 +9557,11 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 	id_declarator = id_declarator->declarator;
       
       if (id_declarator && id_declarator->kind == cdk_id)
-	error ("template parameter pack %qD cannot have a default argument",
-	       id_declarator->u.id.unqualified_name);
+	error ("%Htemplate parameter pack %qD cannot have a default argument",
+	       &start_token->location, id_declarator->u.id.unqualified_name);
       else
-	error ("template parameter pack cannot have a default argument");
+	error ("%Htemplate parameter pack cannot have a default argument",
+	       &start_token->location);
       
       /* Parse the default argument, but throw away the result.  */
       cp_parser_default_argument (parser, /*template_parm_p=*/true);
@@ -9596,10 +9655,11 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("template parameter pack %qD cannot have a default argument", 
-                         identifier);
+                  error ("%Htemplate parameter pack %qD cannot have a "
+			 "default argument", &token->location, identifier);
                 else
-                  error ("template parameter packs cannot have default arguments");
+                  error ("%Htemplate parameter packs cannot have "
+			 "default arguments", &token->location);
                 default_argument = NULL_TREE;
               }
 	    pop_deferring_access_checks ();
@@ -9667,6 +9727,9 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 	    cp_lexer_consume_token (parser->lexer);
 	    /* Parse the id-expression.  */
 	    push_deferring_access_checks (dk_no_deferred);
+	    /* save token before parsing the id-expression, for error
+	       reporting */
+	    token = cp_lexer_peek_token (parser->lexer);
 	    default_argument
 	      = cp_parser_id_expression (parser,
 					 /*template_keyword_p=*/false,
@@ -9687,7 +9750,8 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 					 /*is_template=*/is_template,
 					 /*is_namespace=*/false,
 					 /*check_dependency=*/true,
-					 /*ambiguous_decls=*/NULL);
+					 /*ambiguous_decls=*/NULL,
+					 token->location);
 	    /* See if the default argument is valid.  */
 	    default_argument
 	      = check_template_template_default_arg (default_argument);
@@ -9697,10 +9761,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("template parameter pack %qD cannot have a default argument", 
-                         identifier);
+                  error ("%Htemplate parameter pack %qD cannot "
+			 "have a default argument",
+			 &token->location, identifier);
                 else
-                  error ("template parameter packs cannot have default arguments");
+                  error ("%Htemplate parameter packs cannot "
+			 "have default arguments",
+			 &token->location);
                 default_argument = NULL_TREE;
               }
 	    pop_deferring_access_checks ();
@@ -9749,7 +9816,7 @@ cp_parser_template_id (cp_parser *parser,
   cp_token_position start_of_id = 0;
   deferred_access_check *chk;
   VEC (deferred_access_check,gc) *access_check;
-  cp_token *next_token, *next_token_2;
+  cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
   bool is_identifier;
 
   /* If the next token corresponds to a template-id, there is no need
@@ -9797,6 +9864,7 @@ cp_parser_template_id (cp_parser *parser,
 
   /* Parse the template-name.  */
   is_identifier = false;
+  token = cp_lexer_peek_token (parser->lexer);
   template = cp_parser_template_name (parser, template_keyword_p,
 				      check_dependency_p,
 				      is_declaration,
@@ -9823,6 +9891,7 @@ cp_parser_template_id (cp_parser *parser,
       /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
 	 CPP_LESS.  */
       cp_lexer_consume_token (parser->lexer);
+
       /* Parse the arguments.  */
       arguments = cp_parser_enclosed_template_argument_list (parser);
       if (!cp_parser_parse_definitely (parser))
@@ -9837,15 +9906,18 @@ cp_parser_template_id (cp_parser *parser,
 	}
       /* Otherwise, emit an error about the invalid digraph, but continue
 	 parsing because we got our argument list.  */
-      permerror ("%<<::%> cannot begin a template-argument list");
-      inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
-	      "between %<<%> and %<::%>");
+      permerror ("%H%<<::%> cannot begin a template-argument list",
+		 &next_token->location);
+      inform ("%H%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
+	      "between %<<%> and %<::%>",
+	      &next_token->location);
       if (!flag_permissive)
 	{
 	  static bool hint;
 	  if (!hint)
 	    {
-	      inform ("(if you use %<-fpermissive%> G++ will accept your code)");
+	      inform ("%H(if you use %<-fpermissive%> G++ will accept your code)",
+                      &next_token->location);
 	      hint = true;
 	    }
 	}
@@ -9918,7 +9990,8 @@ cp_parser_template_id (cp_parser *parser,
 	 user, as opposed to simply marking the tentative parse as
 	 failed?  */
       if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
-	error ("parse error in template argument list");
+	error ("%Hparse error in template argument list",
+	       &token->location);
     }
 
   pop_deferring_access_checks ();
@@ -9972,6 +10045,7 @@ cp_parser_template_name (cp_parser* parser,
   tree identifier;
   tree decl;
   tree fns;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* If the next token is `operator', then we have either an
      operator-function-id or a conversion-function-id.  */
@@ -10031,7 +10105,8 @@ cp_parser_template_name (cp_parser* parser,
 	  cp_token_position start = 0;
 
 	  /* Explain what went wrong.  */
-	  error ("non-template %qD used as template", identifier);
+	  error ("%Hnon-template %qD used as template",
+		 &token->location, identifier);
 	  inform ("use %<%T::template %D%> to indicate that it is a template",
 		  parser->scope, identifier);
 	  /* If parsing tentatively, find the location of the "<" token.  */
@@ -10075,7 +10150,8 @@ cp_parser_template_name (cp_parser* parser,
 				/*is_template=*/false,
 				/*is_namespace=*/false,
 				check_dependency_p,
-				/*ambiguous_decls=*/NULL);
+				/*ambiguous_decls=*/NULL,
+				token->location);
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
@@ -10221,7 +10297,7 @@ cp_parser_template_argument (cp_parser* parser)
   bool template_p;
   bool address_p;
   bool maybe_type_id = false;
-  cp_token *token;
+  cp_token *token = NULL, *argument_start_token = NULL;
   cp_id_kind idk;
 
   /* There's really no way to know what we're looking at, so we just
@@ -10268,6 +10344,7 @@ cp_parser_template_argument (cp_parser* parser)
   /* We're still not sure what the argument will be.  */
   cp_parser_parse_tentatively (parser);
   /* Try a template.  */
+  argument_start_token = cp_lexer_peek_token (parser->lexer);
   argument = cp_parser_id_expression (parser,
 				      /*template_keyword_p=*/false,
 				      /*check_dependency_p=*/true,
@@ -10290,7 +10367,8 @@ cp_parser_template_argument (cp_parser* parser)
 					  /*is_template=*/template_p,
 					  /*is_namespace=*/false,
 					  /*check_dependency=*/true,
-					  /*ambiguous_decls=*/NULL);
+					  /*ambiguous_decls=*/NULL,
+					  argument_start_token->location);
       if (TREE_CODE (argument) != TEMPLATE_DECL
 	  && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
 	cp_parser_error (parser, "expected template-name");
@@ -10542,6 +10620,8 @@ static void
 cp_parser_explicit_specialization (cp_parser* parser)
 {
   bool need_lang_pop;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `template' keyword.  */
   cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Look for the `<'.  */
@@ -10556,7 +10636,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
      linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template specialization with C linkage");
+      error ("%Htemplate specialization with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
 	 front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -10881,7 +10961,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
           cp_lexer_consume_token (parser->lexer);
           /* We do not yet support the use of `auto' as a
              type-specifier.  */
-          error ("C++0x %<auto%> specifier not supported");
+          error ("%HC++0x %<auto%> specifier not supported", &token->location);
         }
       break;
 
@@ -11094,12 +11174,13 @@ cp_parser_nonclass_name (cp_parser* parser)
   tree type_decl;
   tree identifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
     return error_mark_node;
 
   /* Look up the type-name.  */
-  type_decl = cp_parser_lookup_name_simple (parser, identifier);
+  type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
 
   if (TREE_CODE (type_decl) != TYPE_DECL
       && (objc_is_id (identifier) || objc_is_class_name (identifier)))
@@ -11116,7 +11197,7 @@ cp_parser_nonclass_name (cp_parser* parser)
     {
       if (!cp_parser_simulate_error (parser))
 	cp_parser_name_lookup_error (parser, identifier, type_decl,
-				     "is not a type");
+				     "is not a type", token->location);
       return error_mark_node;
     }
   /* Remember that the name was used in the definition of the
@@ -11165,6 +11246,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
   tree identifier;
   tree type = NULL_TREE;
   tree attributes = NULL_TREE;
+  cp_token *token = NULL;
 
   /* See if we're looking at the `enum' keyword.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM))
@@ -11234,6 +11316,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (!template_p)
 	cp_parser_parse_tentatively (parser);
       /* Parse the template-id.  */
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_template_id (parser, template_p,
 				    /*check_dependency_p=*/true,
 				    is_declaration);
@@ -11255,6 +11338,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
   if (!type)
     {
+      token = cp_lexer_peek_token (parser->lexer);
       identifier = cp_parser_identifier (parser);
 
       if (identifier == error_mark_node)
@@ -11267,7 +11351,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (tag_type == typename_type
 	  && TREE_CODE (parser->scope) != NAMESPACE_DECL)
 	return cp_parser_make_typename_type (parser, parser->scope,
-					     identifier);
+					     identifier,
+					     token->location);
       /* Look up a qualified name in the usual way.  */
       if (parser->scope)
 	{
@@ -11279,7 +11364,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 					/*is_template=*/false,
 					/*is_namespace=*/false,
 					/*check_dependency=*/true,
-					&ambiguous_decls);
+					&ambiguous_decls,
+					token->location);
 
 	  /* If the lookup was ambiguous, an error will already have been
 	     issued.  */
@@ -11315,7 +11401,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	    {
 	      cp_parser_diagnose_invalid_type_name (parser,
 						    parser->scope,
-						    identifier);
+						    identifier,
+						    token->location);
 	      return error_mark_node;
 	    }
 
@@ -11415,7 +11502,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 	  /* An unqualified name was used to reference this type, so
 	     there were no qualifying templates.  */
 	  if (!cp_parser_check_template_parameters (parser,
-						    /*num_templates=*/0))
+						    /*num_templates=*/0,
+						    token->location))
 	    return error_mark_node;
 	  type = xref_tag (tag_type, identifier, ts, template_p);
 	}
@@ -11618,6 +11706,8 @@ cp_parser_namespace_name (cp_parser* parser)
   tree identifier;
   tree namespace_decl;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Get the name of the namespace.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
@@ -11646,13 +11736,14 @@ cp_parser_namespace_name (cp_parser* parser)
 					  /*is_template=*/false,
 					  /*is_namespace=*/true,
 					  /*check_dependency=*/true,
-					  /*ambiguous_decls=*/NULL);
+					  /*ambiguous_decls=*/NULL,
+					  token->location);
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
     {
       if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-	error ("%qD is not a namespace-name", identifier);
+	error ("%H%qD is not a namespace-name", &token->location, identifier);
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
@@ -11767,6 +11858,8 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   tree identifier;
   tree namespace_specifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the identifier.  */
@@ -11777,7 +11870,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
       && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) 
     {
-      error ("%<namespace%> definition is not allowed here");
+      error ("%H%<namespace%> definition is not allowed here", &token->location);
       /* Skip the definition.  */
       cp_lexer_consume_token (parser->lexer);
       if (cp_parser_skip_to_closing_brace (parser))
@@ -11892,6 +11985,7 @@ cp_parser_using_declaration (cp_parser* parser,
        cp_parser_parse_definitely will be false, as required.  */
     return cp_parser_parse_definitely (parser);
 
+  token = cp_lexer_peek_token (parser->lexer);
   /* Parse the unqualified-id.  */
   identifier = cp_parser_unqualified_id (parser,
 					 /*template_keyword_p=*/false,
@@ -11916,7 +12010,8 @@ cp_parser_using_declaration (cp_parser* parser,
     /* [namespace.udecl]
 
        A using declaration shall not name a template-id.  */
-    error ("a template-id may not appear in a using-declaration");
+    error ("%Ha template-id may not appear in a using-declaration",
+            &token->location);
   else
     {
       if (at_class_scope_p ())
@@ -11932,9 +12027,13 @@ cp_parser_using_declaration (cp_parser* parser,
 	}
       else
 	{
-	  decl = cp_parser_lookup_name_simple (parser, identifier);
+	  decl = cp_parser_lookup_name_simple (parser,
+					       identifier,
+					       token->location);
 	  if (decl == error_mark_node)
-	    cp_parser_name_lookup_error (parser, identifier, decl, NULL);
+	    cp_parser_name_lookup_error (parser, identifier,
+					 decl, NULL,
+					 token->location);
 	  else if (check_for_bare_parameter_packs (decl))
 	    return false;
 	  else if (!at_namespace_scope_p ())
@@ -12184,7 +12283,8 @@ cp_parser_init_declarator (cp_parser* parser,
 			   int declares_class_or_enum,
 			   bool* function_definition_p)
 {
-  cp_token *token;
+  cp_token *token = NULL, *asm_spec_start_token = NULL,
+           *attributes_start_token = NULL;
   cp_declarator *declarator;
   tree prefix_attributes;
   tree attributes;
@@ -12218,6 +12318,7 @@ cp_parser_init_declarator (cp_parser* parser,
   resume_deferring_access_checks ();
 
   /* Parse the declarator.  */
+  token = cp_lexer_peek_token (parser->lexer);
   declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
 			    &ctor_dtor_or_conv_p,
@@ -12232,7 +12333,8 @@ cp_parser_init_declarator (cp_parser* parser,
     return error_mark_node;
 
   /* Check that the number of template-parameter-lists is OK.  */
-  if (!cp_parser_check_declarator_template_parameters (parser, declarator))
+  if (!cp_parser_check_declarator_template_parameters (parser, declarator,
+						       token->location))
     return error_mark_node;
 
   if (declares_class_or_enum & 2)
@@ -12249,8 +12351,10 @@ cp_parser_init_declarator (cp_parser* parser,
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       /* Look for an asm-specification.  */
+      asm_spec_start_token = cp_lexer_peek_token (parser->lexer);
       asm_specification = cp_parser_asm_specification_opt (parser);
       /* And attributes.  */
+      attributes_start_token = cp_lexer_peek_token (parser->lexer);
       attributes = cp_parser_attributes_opt (parser);
     }
   else
@@ -12278,9 +12382,12 @@ cp_parser_init_declarator (cp_parser* parser,
 	  /* Neither attributes nor an asm-specification are allowed
 	     on a function-definition.  */
 	  if (asm_specification)
-	    error ("an asm-specification is not allowed on a function-definition");
+	    error ("%Han asm-specification is not allowed "
+		   "on a function-definition",
+		   &asm_spec_start_token->location);
 	  if (attributes)
-	    error ("attributes are not allowed on a function-definition");
+	    error ("%Hattributes are not allowed on a function-definition",
+		   &attributes_start_token->location);
 	  /* This is a function-definition.  */
 	  *function_definition_p = true;
 
@@ -12405,6 +12512,7 @@ cp_parser_init_declarator (cp_parser* parser,
     {
       if (function_declarator_p (declarator))
 	{
+	  cp_token *initializer_start_token = cp_lexer_peek_token (parser->lexer);
 	   if (initialization_kind == CPP_EQ)
 	     initializer = cp_parser_pure_specifier (parser);
 	   else
@@ -12413,7 +12521,8 @@ cp_parser_init_declarator (cp_parser* parser,
 		  know what the user intended, so just silently
 		  consume the initializer.  */
 	       if (decl != error_mark_node)
-		 error ("initializer provided for function");
+		 error ("%Hinitializer provided for function",
+			&initializer_start_token->location);
 	       cp_parser_skip_to_closing_parenthesis (parser,
 						      /*recovering=*/true,
 						      /*or_comma=*/false,
@@ -12814,7 +12923,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 		 in function scopes.  */
 	      else if (!parser->in_function_body)
 		{
-		  error ("array bound is not an integer constant");
+		  error ("%Harray bound is not an integer constant",
+			 &token->location);
 		  bounds = error_mark_node;
 		}
 	    }
@@ -12836,6 +12946,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 	  special_function_kind sfk;
 	  bool abstract_ok;
           bool pack_expansion_p = false;
+	  cp_token *declarator_id_start_token;
 
 	  /* Parse a declarator-id */
 	  abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
@@ -12854,6 +12965,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                 }
             }
 
+	  declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
 	  unqualified_name
 	    = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
 	  qualifying_scope = parser->scope;
@@ -12923,7 +13035,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 					    /*only_current_p=*/false);
 	      /* If that failed, the declarator is invalid.  */
 	      if (TREE_CODE (type) == TYPENAME_TYPE)
-		error ("%<%T::%E%> is not a type",
+		error ("%H%<%T::%E%> is not a type",
+		       &declarator_id_start_token->location,
 		       TYPE_CONTEXT (qualifying_scope),
 		       TYPE_IDENTIFIER (qualifying_scope));
 	      qualifying_scope = type;
@@ -12949,7 +13062,8 @@ cp_parser_direct_declarator (cp_parser* parser,
 		      if (qualifying_scope
 			  && CLASSTYPE_USE_TEMPLATE (name_type))
 			{
-			  error ("invalid use of constructor as a template");
+			  error ("%Hinvalid use of constructor as a template",
+				 &declarator_id_start_token->location);
 			  inform ("use %<%T::%D%> instead of %<%T::%D%> to "
 				  "name the constructor in a qualified name",
 				  class_type,
@@ -13108,6 +13222,7 @@ cp_parser_ptr_operator (cp_parser* parser,
       cp_parser_global_scope_opt (parser,
 				  /*current_scope_valid_p=*/false);
       /* Look for the nested-name specifier.  */
+      token = cp_lexer_peek_token (parser->lexer);
       cp_parser_nested_name_specifier (parser,
 				       /*typename_keyword_p=*/false,
 				       /*check_dependency_p=*/true,
@@ -13122,7 +13237,7 @@ cp_parser_ptr_operator (cp_parser* parser,
 	  code = INDIRECT_REF;
 
 	  if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-	    error ("%qD is a namespace", parser->scope);
+	    error ("%H%qD is a namespace", &token->location, parser->scope);
 	  else
 	    {
 	      /* The type of which the member is a member is given by the
@@ -13197,7 +13312,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 
       if (cv_quals & cv_qualifier)
 	{
-	  error ("duplicate cv-qualifier");
+	  error ("%Hduplicate cv-qualifier", &token->location);
 	  cp_lexer_purge_token (parser->lexer);
 	}
       else
@@ -13307,6 +13422,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 {
   bool seen_type_specifier = false;
   cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
+  cp_token *start_token = NULL;
 
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
@@ -13326,6 +13442,11 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 	  continue;
 	}
 
+      /* record the token of the beginning of the type specifier seq,
+         for error reporting purposes*/
+     if (!start_token)
+       start_token = cp_lexer_peek_token (parser->lexer);
+
       /* Look for the type-specifier.  */
       type_specifier = cp_parser_type_specifier (parser,
 						 flags,
@@ -13369,7 +13490,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 	flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
 
-  cp_parser_check_decl_spec (type_specifier_seq);
+  cp_parser_check_decl_spec (type_specifier_seq, start_token->location);
 }
 
 /* Parse a parameter-declaration-clause.
@@ -13596,7 +13717,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
   cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
   tree default_argument;
-  cp_token *token;
+  cp_token *token = NULL, *declarator_token_start = NULL;
   const char *saved_message;
 
   /* In a template parameter, `>' is not an operator.
@@ -13665,6 +13786,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	  && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
 	cp_parser_commit_to_tentative_parse (parser);
       /* Parse the declarator.  */
+      declarator_token_start = token;
       declarator = cp_parser_declarator (parser,
 					 CP_PARSER_DECLARATOR_EITHER,
 					 /*ctor_dtor_or_conv_p=*/NULL,
@@ -13823,7 +13945,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 		  /* If we run out of tokens, issue an error message.  */
 		case CPP_EOF:
 		case CPP_PRAGMA_EOL:
-		  error ("file ends in default argument");
+		  error ("%Hfile ends in default argument", &token->location);
 		  done = true;
 		  break;
 
@@ -13860,8 +13982,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
       /* Outside of a class definition, we can just parse the
 	 assignment-expression.  */
       else
-        default_argument 
-          = cp_parser_default_argument (parser, template_parm_p);
+	{
+	  token = cp_lexer_peek_token (parser->lexer);
+	  default_argument 
+	    = cp_parser_default_argument (parser, template_parm_p);
+	}
 
       if (!parser->default_arg_ok_p)
 	{
@@ -13869,7 +13994,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	    warning (0, "deprecated use of default argument for parameter of non-function");
 	  else
 	    {
-	      error ("default arguments are only permitted for function parameters");
+	      error ("%Hdefault arguments are only "
+		     "permitted for function parameters",
+		     &token->location);
 	      default_argument = NULL_TREE;
 	    }
 	}
@@ -13885,11 +14012,12 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	    id_declarator = id_declarator->declarator;
 	  
 	  if (id_declarator && id_declarator->kind == cdk_id)
-	    error ("%sparameter pack %qD cannot have a default argument",
+	    error ("%H%sparameter pack %qD cannot have a default argument",
+		   &declarator_token_start->location,
 		   kind, id_declarator->u.id.unqualified_name);
 	  else
-	    error ("%sparameter pack cannot have a default argument",
-		   kind);
+	    error ("%H%sparameter pack cannot have a default argument",
+		   &declarator_token_start->location, kind);
 	  
 	  default_argument = NULL_TREE;
 	}
@@ -14279,10 +14407,12 @@ cp_parser_class_name (cp_parser *parser,
 					/*is_template=*/false,
 					/*is_namespace=*/false,
 					check_dependency_p,
-					&ambiguous_decls);
+					&ambiguous_decls,
+					identifier_token->location);
 	  if (ambiguous_decls)
 	    {
-	      error ("reference to %qD is ambiguous", identifier);
+	      error ("%Hreference to %qD is ambiguous",
+		     &identifier_token->location, identifier);
 	      print_candidates (ambiguous_decls);
 	      if (cp_parser_parsing_tentatively (parser))
 		{
@@ -14573,7 +14703,7 @@ cp_parser_class_head (cp_parser* parser,
   bool invalid_explicit_specialization_p = false;
   tree pushed_scope = NULL_TREE;
   unsigned num_templates;
-
+  cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL;
   /* Assume no nested-name-specifier will be present.  */
   *nested_name_specifier_p = false;
   /* Assume no template parameter lists will be used in defining the
@@ -14606,6 +14736,7 @@ cp_parser_class_head (cp_parser* parser,
 
   /* Determine the name of the class.  Begin by looking for an
      optional nested-name-specifier.  */
+  nested_name_specifier_token_start = cp_lexer_peek_token (parser->lexer);
   nested_name_specifier
     = cp_parser_nested_name_specifier_opt (parser,
 					   /*typename_keyword_p=*/false,
@@ -14616,6 +14747,7 @@ cp_parser_class_head (cp_parser* parser,
      identifier.  */
   if (nested_name_specifier)
     {
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       /* Although the grammar says `identifier', it really means
 	 `class-name' or `template-name'.  You are only allowed to
 	 define a class that has already been declared with this
@@ -14679,6 +14811,7 @@ cp_parser_class_head (cp_parser* parser,
 	 an identifier, or nothing at all.  */
       cp_parser_parse_tentatively (parser);
       /* Check for a template-id.  */
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       id = cp_parser_template_id (parser,
 				  /*template_keyword_p=*/false,
 				  /*check_dependency_p=*/true,
@@ -14730,7 +14863,8 @@ cp_parser_class_head (cp_parser* parser,
       /* Reject typedef-names in class heads.  */
       if (!DECL_IMPLICIT_TYPEDEF_P (type))
 	{
-	  error ("invalid class name in declaration of %qD", type);
+	  error ("%Hinvalid class name in declaration of %qD",
+		 &type_start_token->location, type);
 	  type = NULL_TREE;
 	  goto done;
 	}
@@ -14742,10 +14876,13 @@ cp_parser_class_head (cp_parser* parser,
       if (scope && !is_ancestor (scope, nested_name_specifier))
 	{
 	  if (at_namespace_scope_p ())
-	    error ("declaration of %qD in namespace %qD which does not "
-		   "enclose %qD", type, scope, nested_name_specifier);
+	    error ("%Hdeclaration of %qD in namespace %qD which does not "
+		   "enclose %qD",
+		   &type_start_token->location,
+		   type, scope, nested_name_specifier);
 	  else
-	    error ("declaration of %qD in %qD which does not enclose %qD",
+	    error ("%Hdeclaration of %qD in %qD which does not enclose %qD",
+		   &type_start_token->location,
 		   type, scope, nested_name_specifier);
 	  type = NULL_TREE;
 	  goto done;
@@ -14758,7 +14895,8 @@ cp_parser_class_head (cp_parser* parser,
 	 class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
 	{
-	  permerror ("extra qualification not allowed");
+	  permerror ("%Hextra qualification not allowed",
+		     &nested_name_specifier_token_start->location);
 	  nested_name_specifier = NULL_TREE;
 	  num_templates = 0;
 	}
@@ -14769,7 +14907,8 @@ cp_parser_class_head (cp_parser* parser,
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
-      error ("an explicit specialization must be preceded by %<template <>%>");
+      error ("%Han explicit specialization must be preceded by %<template <>%>",
+	     &type_start_token->location);
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
 	 cp_parser_explicit_specialization.  */
@@ -14781,7 +14920,8 @@ cp_parser_class_head (cp_parser* parser,
      use "goto done;" to return.  */
   /* Make sure that the right number of template parameters were
      present.  */
-  if (!cp_parser_check_template_parameters (parser, num_templates))
+  if (!cp_parser_check_template_parameters (parser, num_templates,
+					    type_start_token->location))
     {
       /* If something went wrong, there is no point in even trying to
 	 process the class-definition.  */
@@ -14796,7 +14936,8 @@ cp_parser_class_head (cp_parser* parser,
 	  && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0))
 	      || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD))
 	{
-	  error ("function template %qD redeclared as a class template", id);
+	  error ("%Hfunction template %qD redeclared as a class template",
+		 &type_start_token->location, id);
 	  type = error_mark_node;
 	}
       else
@@ -14877,8 +15018,10 @@ cp_parser_class_head (cp_parser* parser,
      that's an error.  */
   if (type != error_mark_node && COMPLETE_TYPE_P (type))
     {
-      error ("redefinition of %q#T", type);
-      error ("previous definition of %q+#T", type);
+      error ("%Hredefinition of %q#T",
+	     &type_start_token->location, type);
+      error ("%Hprevious definition of %q+#T",
+	     &type_start_token->location, type);
       type = NULL_TREE;
       goto done;
     }
@@ -15033,7 +15176,9 @@ cp_parser_member_declaration (cp_parser* parser)
   tree decl;
   int declares_class_or_enum;
   bool friend_p;
-  cp_token *token;
+  cp_token *token = NULL;
+  cp_token *decl_spec_token_start = NULL;
+  cp_token *initializer_token_start = NULL;
   int saved_pedantic;
 
   /* Check for the `__extension__' keyword.  */
@@ -15097,6 +15242,7 @@ cp_parser_member_declaration (cp_parser* parser)
     return;
 
   /* Parse the decl-specifier-seq.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -15142,7 +15288,8 @@ cp_parser_member_declaration (cp_parser* parser)
 	      /* If the `friend' keyword was present, the friend must
 		 be introduced with a class-key.  */
 	       if (!declares_class_or_enum)
-		 error ("a class-key must be used when declaring a friend");
+		 error ("%Ha class-key must be used when declaring a friend",
+                        &decl_spec_token_start->location);
 	       /* In this case:
 
 		    template <typename T> struct A {
@@ -15156,8 +15303,8 @@ cp_parser_member_declaration (cp_parser* parser)
 		   && TYPE_P (decl_specifiers.type))
 		 type = decl_specifiers.type;
 	       if (!type || !TYPE_P (type))
-		 error ("friend declaration does not name a class or "
-			"function");
+		 error ("%Hfriend declaration does not name a class or "
+			"function", &decl_spec_token_start->location);
 	       else
 		 make_friend_class (current_class_type, type,
 				    /*complain=*/true);
@@ -15180,7 +15327,9 @@ cp_parser_member_declaration (cp_parser* parser)
 	      finish_member_declaration (decl);
 	    }
 	  else
-	    cp_parser_check_access_in_redeclaration (TYPE_NAME (type));
+	    cp_parser_check_access_in_redeclaration
+					      (TYPE_NAME (type),
+					       decl_spec_token_start->location);
 	}
     }
   else
@@ -15308,6 +15457,7 @@ cp_parser_member_declaration (cp_parser* parser)
 		     for a pure-specifier; otherwise, we look for a
 		     constant-initializer.  When we call `grokfield', it will
 		     perform more stringent semantics checks.  */
+		  initializer_token_start = cp_lexer_peek_token (parser->lexer);
 		  if (function_declarator_p (declarator))
 		    initializer = cp_parser_pure_specifier (parser);
 		  else
@@ -15332,7 +15482,8 @@ cp_parser_member_declaration (cp_parser* parser)
 		     standard, since a pure function may be defined
 		     outside of the class-specifier.  */
 		  if (initializer)
-		    error ("pure-specifier on function-definition");
+		    error ("%Hpure-specifier on function-definition",
+			   &initializer_token_start->location);
 		  decl = cp_parser_save_member_function_body (parser,
 							      &decl_specifiers,
 							      declarator,
@@ -15423,7 +15574,7 @@ cp_parser_pure_specifier (cp_parser* parser)
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
-      error ("templates may not be %<virtual%>");
+      error ("%Htemplates may not be %<virtual%>", &token->location);
       return error_mark_node;
     }
 
@@ -15625,11 +15776,14 @@ cp_parser_base_specifier (cp_parser* parser)
      as base classes.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
+      token = cp_lexer_peek_token (parser->lexer);
       if (!processing_template_decl)
-	error ("keyword %<typename%> not allowed outside of templates");
+	error ("%Hkeyword %<typename%> not allowed outside of templates",
+	       &token->location);
       else
-	error ("keyword %<typename%> not allowed in this context "
-	       "(the base class is implicitly a type)");
+	error ("%Hkeyword %<typename%> not allowed in this context "
+	       "(the base class is implicitly a type)",
+	       &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
 
@@ -16330,7 +16484,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 		       bool is_template,
 		       bool is_namespace,
 		       bool check_dependency,
-		       tree *ambiguous_decls)
+		       tree *ambiguous_decls,
+		       location_t name_location)
 {
   int flags = 0;
   tree decl;
@@ -16511,7 +16666,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
 	 cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
 	{
-	  error ("reference to %qD is ambiguous", name);
+	  error ("%Hreference to %qD is ambiguous",
+		 &name_location, name);
 	  print_candidates (decl);
 	}
       return error_mark_node;
@@ -16541,14 +16697,15 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
    IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE.  */
 
 static tree
-cp_parser_lookup_name_simple (cp_parser* parser, tree name)
+cp_parser_lookup_name_simple (cp_parser* parser, tree name, location_t location)
 {
   return cp_parser_lookup_name (parser, name,
 				none_type,
 				/*is_template=*/false,
 				/*is_namespace=*/false,
 				/*check_dependency=*/true,
-				/*ambiguous_decls=*/NULL);
+				/*ambiguous_decls=*/NULL,
+				location);
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
@@ -16601,7 +16758,8 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
 
 static bool
 cp_parser_check_declarator_template_parameters (cp_parser* parser,
-						cp_declarator *declarator)
+						cp_declarator *declarator,
+						location_t declarator_location)
 {
   unsigned num_templates;
 
@@ -16651,7 +16809,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 	++num_templates;
 
       return cp_parser_check_template_parameters (parser,
-						  num_templates);
+						  num_templates,
+						  declarator_location);
 
     case cdk_function:
     case cdk_array:
@@ -16659,7 +16818,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
     case cdk_reference:
     case cdk_ptrmem:
       return (cp_parser_check_declarator_template_parameters
-	      (parser, declarator->declarator));
+	      (parser, declarator->declarator, declarator_location));
 
     case cdk_error:
       return true;
@@ -16676,7 +16835,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
-				     unsigned num_templates)
+				     unsigned num_templates,
+				     location_t location)
 {
   /* If there are more template classes than parameter lists, we have
      something like:
@@ -16684,7 +16844,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      error ("too few template-parameter-lists");
+      error ("%Htoo few template-parameter-lists", &location);
       return false;
     }
   /* If there are the same number of template classes and parameter
@@ -16699,7 +16859,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
      something like:
 
      template <class T> template <class U> void S::f();  */
-  error ("too many template-parameter-lists");
+  error ("%Htoo many template-parameter-lists", &location);
   return false;
 }
 
@@ -16957,12 +17117,14 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   bool saved_in_unbraced_linkage_specification_p;
   bool saved_in_function_body;
   unsigned saved_num_template_parameter_lists;
+  cp_token *token;
 
   saved_in_function_body = parser->in_function_body;
   parser->in_function_body = true;
   /* If the next token is `return', then the code may be trying to
      make use of the "named return value" extension that G++ used to
      support.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_RETURN))
     {
       /* Consume the `return' keyword.  */
@@ -16971,7 +17133,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
 	 returned.  */
       cp_parser_identifier (parser);
       /* Issue an error message.  */
-      error ("named return values are no longer supported");
+      error ("%Hnamed return values are no longer supported",
+	     &token->location);
       /* Skip tokens until we reach the start of the function body.  */
       while (true)
 	{
@@ -17030,8 +17193,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
+  cp_token *token;
 
   /* Look for the `template' keyword.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
     return;
 
@@ -17043,7 +17208,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* 14.5.2.2 [temp.mem]
 
          A local class shall not have member templates.  */
-      error ("invalid declaration of member template in local class");
+      error ("%Hinvalid declaration of member template in local class",
+	     &token->location);
       cp_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
@@ -17052,7 +17218,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
      A template ... shall not have C linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template with C linkage");
+      error ("%Htemplate with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
 	 front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -17099,6 +17265,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* There are no access checks when parsing a template, as we do not
 	 know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_single_declaration (parser,
 					   checks,
 					   member_p,
@@ -17111,7 +17278,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       if (member_p && !friend_p && decl)
 	{
 	  if (TREE_CODE (decl) == TYPE_DECL)
-	    cp_parser_check_access_in_redeclaration (decl);
+	    cp_parser_check_access_in_redeclaration (decl, token->location);
 
 	  decl = finish_member_template_decl (decl);
 	}
@@ -17175,6 +17342,7 @@ cp_parser_single_declaration (cp_parser* parser,
   tree decl = NULL_TREE;
   cp_decl_specifier_seq decl_specifiers;
   bool function_definition_p = false;
+  cp_token *decl_spec_token_start;
 
   /* This function is only used when processing a template
      declaration.  */
@@ -17186,6 +17354,7 @@ cp_parser_single_declaration (cp_parser* parser,
 
   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
      alternative.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -17196,7 +17365,8 @@ cp_parser_single_declaration (cp_parser* parser,
   /* There are no template typedefs.  */
   if (decl_specifiers.specs[(int) ds_typedef])
     {
-      error ("template declaration of %qs", "typedef");
+      error ("%Htemplate declaration of %qs",
+	     &decl_spec_token_start->location, "typedef");
       decl = error_mark_node;
     }
 
@@ -17259,7 +17429,8 @@ cp_parser_single_declaration (cp_parser* parser,
         && explicit_specialization_p
         && decl_specifiers.storage_class != sc_none)
       {
-        error ("explicit template specialization cannot have a storage class");
+        error ("%Hexplicit template specialization cannot have a storage class",
+	       &decl_spec_token_start->location);
         decl = error_mark_node;
       }
     }
@@ -17461,9 +17632,9 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
 	    is a typo for '>'. Emit an error message and continue.
 	    Same deal about the token location, but here we can get it
 	    right by consuming the '>>' before issuing the diagnostic.  */
-	  cp_lexer_consume_token (parser->lexer);
-	  error ("spurious %<>>%>, use %<>%> to terminate "
-		 "a template argument list");
+	  cp_token *token = cp_lexer_consume_token (parser->lexer);
+	  error ("%Hspurious %<>>%>, use %<>%> to terminate "
+		 "a template argument list", &token->location);
 	}
     }
   else
@@ -17784,14 +17955,15 @@ cp_parser_declares_only_class_p (cp_parser *parser)
 static void
 cp_parser_set_storage_class (cp_parser *parser,
 			     cp_decl_specifier_seq *decl_specs,
-			     enum rid keyword)
+			     enum rid keyword,
+			     location_t location)
 {
   cp_storage_class storage_class;
 
   if (parser->in_unbraced_linkage_specification_p)
     {
-      error ("invalid use of %qD in linkage specification",
-	     ridpointers[keyword]);
+      error ("%Hinvalid use of %qD in linkage specification",
+	     &location, ridpointers[keyword]);
       return;
     }
   else if (decl_specs->storage_class != sc_none)
@@ -17803,7 +17975,7 @@ cp_parser_set_storage_class (cp_parser *parser,
   if ((keyword == RID_EXTERN || keyword == RID_STATIC)
       && decl_specs->specs[(int) ds_thread])
     {
-      error ("%<__thread%> before %qD", ridpointers[keyword]);
+      error ("%H%<__thread%> before %qD", &location, ridpointers[keyword]);
       decl_specs->specs[(int) ds_thread] = 0;
     }
 
@@ -18133,7 +18305,7 @@ cp_parser_check_class_key (enum tag_types class_key, tree type)
    [class.mem/1].  */
 
 static void
-cp_parser_check_access_in_redeclaration (tree decl)
+cp_parser_check_access_in_redeclaration (tree decl, location_t location)
 {
   if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl)))
     return;
@@ -18142,7 +18314,7 @@ cp_parser_check_access_in_redeclaration (tree decl)
        != (current_access_specifier == access_private_node))
       || (TREE_PROTECTED (decl)
 	  != (current_access_specifier == access_protected_node)))
-    error ("%qD redeclared with different access", decl);
+    error ("%H%qD redeclared with different access", &location, decl);
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
@@ -18159,8 +18331,9 @@ cp_parser_optional_template_keyword (cp_parser *parser)
 	 template and what is not.  */
       if (!processing_template_decl)
 	{
-	  error ("%<template%> (as a disambiguator) is only allowed "
-		 "within templates");
+	  cp_token *token = cp_lexer_peek_token (parser->lexer);
+	  error ("%H%<template%> (as a disambiguator) is only allowed "
+		 "within templates", &token->location);
 	  /* If this part of the token stream is rescanned, the same
 	     error message would be generated.  So, we purge the token
 	     from the stream.  */
@@ -18412,7 +18585,8 @@ cp_parser_objc_expression (cp_parser* parser)
 	  break;
 	}
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -18545,15 +18719,18 @@ static tree
 cp_parser_objc_encode_expression (cp_parser* parser)
 {
   tree type;
+  cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  token = cp_lexer_peek_token (parser->lexer);
   type = complete_type (cp_parser_type_id (parser));
   cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   if (!type)
     {
-      error ("%<@encode%> must specify a type as an argument");
+      error ("%H%<@encode%> must specify a type as an argument",
+	     &token->location);
       return error_mark_node;
     }
 
@@ -18868,7 +19045,7 @@ cp_parser_objc_selector (cp_parser* parser)
 
   if (!cp_parser_objc_selector_p (token->type))
     {
-      error ("invalid Objective-C++ selector name");
+      error ("%Hinvalid Objective-C++ selector name", &token->location);
       return error_mark_node;
     }
 
@@ -19198,7 +19375,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
     {
-      error ("identifier expected after %<@protocol%>");
+      tok = cp_lexer_peek_token (parser->lexer);
+      error ("%Hidentifier expected after %<@protocol%>", &tok->location);
       goto finish;
     }
 
@@ -19334,7 +19512,8 @@ cp_parser_objc_declaration (cp_parser* parser)
       cp_parser_objc_end_implementation (parser);
       break;
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 }
@@ -19465,7 +19644,8 @@ cp_parser_objc_statement (cp_parser * parser) {
     case RID_AT_THROW:
       return cp_parser_objc_throw_statement (parser);
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+	     &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -19549,14 +19729,15 @@ cp_parser_omp_clause_name (cp_parser *parser)
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
-check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+check_no_duplicate_clause (tree clauses, enum tree_code code,
+			   const char *name, location_t location)
 {
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
-	error ("too many %qs clauses", name);
+	error ("%Htoo many %qs clauses", &location, name);
 	break;
       }
 }
@@ -19579,10 +19760,12 @@ static tree
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 				tree list)
 {
+  cp_token *token;
   while (1)
     {
       tree name, decl;
 
+      token = cp_lexer_peek_token (parser->lexer);
       name = cp_parser_id_expression (parser, /*template_p=*/false,
 				      /*check_dependency_p=*/true,
 				      /*template_p=*/NULL,
@@ -19591,9 +19774,9 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       if (name == error_mark_node)
 	goto skip_comma;
 
-      decl = cp_parser_lookup_name_simple (parser, name);
+      decl = cp_parser_lookup_name_simple (parser, name, token->location);
       if (decl == error_mark_node)
-	cp_parser_name_lookup_error (parser, name, decl, NULL);
+	cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
       else if (kind != 0)
 	{
 	  tree u = build_omp_clause (kind);
@@ -19643,7 +19826,7 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
    collapse ( constant-expression ) */
 
 static tree
-cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
+cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location)
 {
   tree c, num;
   location_t loc;
@@ -19668,11 +19851,12 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
       || (n = tree_low_cst (num, 0)) <= 0
       || (int) n != n)
     {
-      error ("%Hcollapse argument needs positive constant integer expression", &loc);
+      error ("%Hcollapse argument needs positive constant integer expression",
+	     &loc);
       return list;
     }
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse");
+  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
   c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
@@ -19684,7 +19868,7 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list)
    default ( shared | none ) */
 
 static tree
-cp_parser_omp_clause_default (cp_parser *parser, tree list)
+cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
 {
   enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
   tree c;
@@ -19730,7 +19914,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
   if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
     return list;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
   c = build_omp_clause (OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
@@ -19742,7 +19926,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
    if ( expression ) */
 
 static tree
-cp_parser_omp_clause_if (cp_parser *parser, tree list)
+cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
 {
   tree t, c;
 
@@ -19757,7 +19941,7 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
 
   c = build_omp_clause (OMP_CLAUSE_IF);
   OMP_CLAUSE_IF_EXPR (c) = t;
@@ -19770,11 +19954,12 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
    nowait */
 
 static tree
-cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED,
+			     tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait", location);
 
   c = build_omp_clause (OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -19785,7 +19970,8 @@ cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
    num_threads ( expression ) */
 
 static tree
-cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
+cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
+				  location_t location)
 {
   tree t, c;
 
@@ -19800,7 +19986,8 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
 					   /*or_comma=*/false,
 					   /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
+			     "num_threads", location);
 
   c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
   OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
@@ -19813,11 +20000,13 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
    ordered */
 
 static tree
-cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
+			      tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED,
+			     "ordered", location);
 
   c = build_omp_clause (OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -19894,7 +20083,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
      static | dynamic | guided | runtime | auto  */
 
 static tree
-cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
+cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location)
 {
   tree c, t;
 
@@ -19942,18 +20131,20 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
     {
+      cp_token *token;
       cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       t = cp_parser_assignment_expression (parser, false);
 
       if (t == error_mark_node)
 	goto resync_fail;
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-	error ("schedule %<runtime%> does not take "
-	       "a %<chunk_size%> parameter");
+	error ("%Hschedule %<runtime%> does not take "
+	       "a %<chunk_size%> parameter", &token->location);
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
-	error ("schedule %<auto%> does not take "
-	       "a %<chunk_size%> parameter");
+	error ("%Hschedule %<auto%> does not take "
+	       "a %<chunk_size%> parameter", &token->location);
       else
 	OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
@@ -19963,7 +20154,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
   else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<,%> or %<)%>"))
     goto resync_fail;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
@@ -19980,11 +20171,12 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
    untied */
 
 static tree
-cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED,
+			     tree list, location_t location)
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied");
+  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
 
   c = build_omp_clause (OMP_CLAUSE_UNTIED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -20001,6 +20193,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 {
   tree clauses = NULL;
   bool first = true;
+  cp_token *token = NULL;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
@@ -20011,13 +20204,15 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
       if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
 	cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       c_kind = cp_parser_omp_clause_name (parser);
       first = false;
 
       switch (c_kind)
 	{
 	case PRAGMA_OMP_CLAUSE_COLLAPSE:
-	  clauses = cp_parser_omp_clause_collapse (parser, clauses);
+	  clauses = cp_parser_omp_clause_collapse (parser, clauses,
+						   token->location);
 	  c_name = "collapse";
 	  break;
 	case PRAGMA_OMP_CLAUSE_COPYIN:
@@ -20030,7 +20225,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "copyprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_DEFAULT:
-	  clauses = cp_parser_omp_clause_default (parser, clauses);
+	  clauses = cp_parser_omp_clause_default (parser, clauses,
+						  token->location);
 	  c_name = "default";
 	  break;
 	case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
@@ -20039,7 +20235,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "firstprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_IF:
-	  clauses = cp_parser_omp_clause_if (parser, clauses);
+	  clauses = cp_parser_omp_clause_if (parser, clauses, token->location);
 	  c_name = "if";
 	  break;
 	case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -20048,15 +20244,17 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "lastprivate";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NOWAIT:
-	  clauses = cp_parser_omp_clause_nowait (parser, clauses);
+	  clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
 	  c_name = "nowait";
 	  break;
 	case PRAGMA_OMP_CLAUSE_NUM_THREADS:
-	  clauses = cp_parser_omp_clause_num_threads (parser, clauses);
+	  clauses = cp_parser_omp_clause_num_threads (parser, clauses,
+						      token->location);
 	  c_name = "num_threads";
 	  break;
 	case PRAGMA_OMP_CLAUSE_ORDERED:
-	  clauses = cp_parser_omp_clause_ordered (parser, clauses);
+	  clauses = cp_parser_omp_clause_ordered (parser, clauses,
+						  token->location);
 	  c_name = "ordered";
 	  break;
 	case PRAGMA_OMP_CLAUSE_PRIVATE:
@@ -20069,7 +20267,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "reduction";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SCHEDULE:
-	  clauses = cp_parser_omp_clause_schedule (parser, clauses);
+	  clauses = cp_parser_omp_clause_schedule (parser, clauses,
+						   token->location);
 	  c_name = "schedule";
 	  break;
 	case PRAGMA_OMP_CLAUSE_SHARED:
@@ -20078,7 +20277,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  c_name = "shared";
 	  break;
 	case PRAGMA_OMP_CLAUSE_UNTIED:
-	  clauses = cp_parser_omp_clause_untied (parser, clauses);
+	  clauses = cp_parser_omp_clause_untied (parser, clauses,
+						 token->location);
 	  c_name = "nowait";
 	  break;
 	default:
@@ -20091,7 +20291,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
 	  /* Remove the invalid clause(s) from the list to avoid
 	     confusing the rest of the compiler.  */
 	  clauses = prev;
-	  error ("%qs is not valid for %qs", c_name, where);
+	  error ("%H%qs is not valid for %qs", &token->location, c_name, where);
 	}
     }
  saw_error:
@@ -21177,10 +21377,11 @@ cp_parser_initial_pragma (cp_token *first_token)
 
       cp_lexer_get_preprocessor_token (NULL, first_token);
       if (first_token->type != CPP_PRAGMA_EOL)
-	error ("junk at end of %<#pragma GCC pch_preprocess%>");
+	error ("%Hjunk at end of %<#pragma GCC pch_preprocess%>",
+               &first_token->location);
     }
   else
-    error ("expected string literal");
+    error ("%Hexpected string literal", &first_token->location);
 
   /* Skip to the end of the pragma.  */
   while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
@@ -21213,7 +21414,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
   switch (id)
     {
     case PRAGMA_GCC_PCH_PREPROCESS:
-      error ("%<#pragma GCC pch_preprocess%> must be first");
+      error ("%H%<#pragma GCC pch_preprocess%> must be first",
+             &pragma_tok->location);
       break;
 
     case PRAGMA_OMP_BARRIER:
@@ -21223,8 +21425,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_barrier (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp barrier%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp barrier%> may only be "
+		 "used in compound statements", &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
@@ -21238,8 +21440,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_flush (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp flush%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp flush%> may only be "
+		 "used in compound statements", &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
@@ -21280,8 +21482,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
       return true;
 
     case PRAGMA_OMP_SECTION:
-      error ("%<#pragma omp section%> may only be used in "
-	     "%<#pragma omp sections%> construct");
+      error ("%H%<#pragma omp section%> may only be used in "
+	     "%<#pragma omp sections%> construct", &pragma_tok->location);
       break;
 
     default:
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f24b6ff..f95ae07 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -9750,7 +9750,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
       if (complain & tf_error)
 	qualified_name_lookup_error (scope,
 				     TREE_OPERAND (qualified_id, 1),
-				     expr);
+				     expr, input_location);
       return error_mark_node;
     }
 
@@ -9759,7 +9759,7 @@ tsubst_qualified_id (tree qualified_id, tree args,
 
   if (expr == error_mark_node && complain & tf_error)
     qualified_name_lookup_error (scope, TREE_OPERAND (qualified_id, 1),
-				 expr);
+				 expr, input_location);
   else if (TYPE_P (scope))
     {
       expr = (adjust_result_of_qualified_name_lookup
@@ -10491,7 +10491,7 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
 					  /*is_type_p=*/false,
 					  /*complain=*/false);
 	    if (decl == error_mark_node || TREE_CODE (decl) == TREE_LIST)
-	      qualified_name_lookup_error (scope, name, decl);
+	      qualified_name_lookup_error (scope, name, decl, input_location);
 	    else
 	      do_local_using_decl (decl, scope, name);
 	  }
@@ -10938,7 +10938,8 @@ tsubst_copy_and_build (tree t,
 				     /*done=*/true,
 				     /*address_p=*/false,
 				     /*template_arg_p=*/false,
-				     &error_msg);
+				     &error_msg,
+				     input_location);
 	if (error_msg)
 	  error (error_msg);
 	if (!function_p && TREE_CODE (decl) == IDENTIFIER_NODE)
@@ -11467,7 +11468,8 @@ tsubst_copy_and_build (tree t,
 	      }
 	    else
 	      {
-		qualified_name_lookup_error (object_type, tmpl, member);
+		qualified_name_lookup_error (object_type, tmpl, member,
+					     input_location);
 		return error_mark_node;
 	      }
 	  }
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2400aeb..4ac585b 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2482,29 +2482,33 @@ finish_base_specifier (tree base, tree access, bool virtual_p)
 }
 
 /* Issue a diagnostic that NAME cannot be found in SCOPE.  DECL is
-   what we found when we tried to do the lookup.  */
+   what we found when we tried to do the lookup.
+   LOCATION is the location of the NAME identifier;
+   The location is used in the error message*/
 
 void
-qualified_name_lookup_error (tree scope, tree name, tree decl)
+qualified_name_lookup_error (tree scope, tree name,
+			     tree decl, location_t location)
 {
   if (scope == error_mark_node)
     ; /* We already complained.  */
   else if (TYPE_P (scope))
     {
       if (!COMPLETE_TYPE_P (scope))
-	error ("incomplete type %qT used in nested name specifier", scope);
+	error ("%Hincomplete type %qT used in nested name specifier",
+	       &location, scope);
       else if (TREE_CODE (decl) == TREE_LIST)
 	{
-	  error ("reference to %<%T::%D%> is ambiguous", scope, name);
+	  error ("%Hreference to %<%T::%D%> is ambiguous", &location, scope, name);
 	  print_candidates (decl);
 	}
       else
-	error ("%qD is not a member of %qT", name, scope);
+	error ("%H%qD is not a member of %qT", &location, name, scope);
     }
   else if (scope != global_namespace)
-    error ("%qD is not a member of %qD", name, scope);
+    error ("%H%qD is not a member of %qD", &location, name, scope);
   else
-    error ("%<::%D%> has not been declared", name);
+    error ("%H%<::%D%> has not been declared", &location, name);
 }
 
 /* If FNS is a member function, a set of member functions, or a
@@ -2569,7 +2573,6 @@ baselink_for_fns (tree fns)
    the use of "this" explicit.
 
    Upon return, *IDK will be filled in appropriately.  */
-
 tree
 finish_id_expression (tree id_expression,
 		      tree decl,
@@ -2582,7 +2585,8 @@ finish_id_expression (tree id_expression,
 		      bool done,
 		      bool address_p,
 		      bool template_arg_p,
-		      const char **error_msg)
+		      const char **error_msg,
+		      location_t location)
 {
   /* Initialize the output parameters.  */
   *idk = CP_ID_KIND_NONE;
@@ -2612,7 +2616,7 @@ finish_id_expression (tree id_expression,
 	      /* If the qualifying type is non-dependent (and the name
 		 does not name a conversion operator to a dependent
 		 type), issue an error.  */
-	      qualified_name_lookup_error (scope, id_expression, decl);
+	      qualified_name_lookup_error (scope, id_expression, decl, location);
 	      return error_mark_node;
 	    }
 	  else if (!scope)
diff --git a/gcc/testsuite/g++.dg/parse/constructor1.C b/gcc/testsuite/g++.dg/parse/constructor1.C
index 3011862..8f222f8 100644
--- a/gcc/testsuite/g++.dg/parse/constructor1.C
+++ b/gcc/testsuite/g++.dg/parse/constructor1.C
@@ -1,4 +1,7 @@
+// { dg-do compile }
+// { dg-options "-fshow-column" }
+
 ACE_Process_Descriptor::ACE_Process_Descriptor () : // { dg-error "" }
-  process_ (0)
+  process_ (0) // { dg-error "3: error: only constructors take base initializers" }
 {
 }
diff --git a/gcc/testsuite/g++.dg/parse/error-column.C b/gcc/testsuite/g++.dg/parse/error-column.C
new file mode 100644
index 0000000..812a499
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/error-column.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// Make sure column information is correctly shown in error reporting
+// { dg-options "-fshow-column" }
+
+
+void foo ()
+{
+  cout << "blah"; // { dg-error "3: error: 'cout'" }
+}
diff --git a/gcc/testsuite/g++.dg/parse/error1.C b/gcc/testsuite/g++.dg/parse/error1.C
index 8756df6..60e7d65 100644
--- a/gcc/testsuite/g++.dg/parse/error1.C
+++ b/gcc/testsuite/g++.dg/parse/error1.C
@@ -1,6 +1,7 @@
+// { dg-options "-fshow-column" }
 struct INCOMPLETE;
 template <int> struct X {
     static INCOMPLETE value;
 };
-template <> INCOMPLETE X<1>::value = 0; // { dg-error "" }
+template <> INCOMPLETE X<1>::value = 0; // { dg-error "30: error: variable 'INCOMPLETE X<1>::value' has initializer but incomplete type" }
 
diff --git a/gcc/testsuite/g++.dg/parse/error10.C b/gcc/testsuite/g++.dg/parse/error10.C
index 242c421..6e46922 100644
--- a/gcc/testsuite/g++.dg/parse/error10.C
+++ b/gcc/testsuite/g++.dg/parse/error10.C
@@ -1,5 +1,5 @@
 // PR c++/3478
-// { dg-options "" }
+// { dg-options "-fshow-column" }
 
 template <typename> struct A
 {
@@ -11,5 +11,9 @@ template <typename T> void foo()
   enum          A<void>::E e1;
   typename      A<T>::E    e2;
   enum          A<T>::E    e3;
-  enum typename A<T>::E    e4; // { dg-error "" }
+  enum typename A<T>::E    e4;
 }
+
+// Here, columns nums are not very accurate either. Still acceptable though
+// { dg-error "30: error: invalid type in declaration before ';' token" "" { target *-*-* } { 14 } }
+// { dg-error "30: error: two or more data types in declaration of 'e4'" "" { target *-*-* } { 14 } }
diff --git a/gcc/testsuite/g++.dg/parse/error11.C b/gcc/testsuite/g++.dg/parse/error11.C
index 0a8e2e4..f7093a8 100644
--- a/gcc/testsuite/g++.dg/parse/error11.C
+++ b/gcc/testsuite/g++.dg/parse/error11.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }"
 // Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
 // Try to find out when the digraph '<:' is used as a mistake, and parse it
 //  correctly to avoid cascaded errors.
@@ -15,16 +16,16 @@ struct Foo
   };
 
   void method(void) {
-    typename Foo<::B>::template Nested<::B> n; // { dg-error "cannot begin|alternate spelling" }
+    typename Foo<::B>::template Nested<::B> n; // { dg-error "17: error: '<::' cannot begin|17: note: '<:' is an alternate spelling|39: error: '<::' cannot begin|39: note: '<:' is an alternate" }
     n.template Nested<B>::method();
-    n.template Nested<::B>::method();  // { dg-error "cannot begin|alternate spelling" }
+    n.template Nested<::B>::method();  // { dg-error "22: error: '<::' cannot begin|22: note: '<:' is an alternate" }
     Nested<B>::method();
-    Nested<::B>::method(); // { dg-error "cannot begin|alternate spelling" }
+    Nested<::B>::method(); // { dg-error "11: error: '<::' cannot begin|11: note: '<:' is an alternate" }
   }
 };
 
 template <int N> struct Foo2 {};
-template struct Foo2<::B>;  // { dg-error "cannot begin|alternate spelling|type/value mismatch|expected a constant" }
+template struct Foo2<::B>;  // { dg-error "21: error: '<::' cannot begin|21: note: '<:' is an alternate|25: error: type/value mismatch|25: error:   expected a constant" }
 
 int value = 0;
 
@@ -32,22 +33,28 @@ void func(void)
 {
   Foo<::B> f; // { dg-error "cannot begin|alternate spelling" }
   f.Foo<B>::method();
-  f.Foo<::B>::method(); // { dg-error "cannot begin|alternate spelling" }
+  f.Foo<::B>::method(); // { dg-error "8: error|8: note" }
 
   // Check cases where we the token sequence is the correct one, but there
   //  was no digraph or whitespaces in the middle, so we should not emit
   //  the special error message.
   Foo<: :B> k2;     // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" }
   Foo[:B> k1;       // { dg-bogus "cannot begin|alternate spelling" "smart error should not be triggered here" } 
-// { dg-error "" "" { target *-*-* } 40 }
-// { dg-error "" "" { target *-*-* } 41 }
-
+// { dg-error "6: error: missing template arguments before" "" { target *-*-* } { 41 } }
+// { dg-error "9: error: expected primary-expression before ':' token" "" { target *-*-* } 41 }
+// { dg-error "9: error: expected '\]' before ':' token" "" { target *-*-* } 41 }
+// { dg-error "9: error: expected ';' before ':' token" "" { target *-*-* } 41 }
+// { dg-error "6: error: missing template arguments before" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected primary-expression before ':' token" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected '\]' before ':' token" "" { target *-*-* } 42 }
+// { dg-error "7: error: expected ';' before ':' token" "" { target *-*-* } 42 }
+//
   int Foo[2];
   Foo[::value] = 0;
 }
 
-template struct Foo<::B>; // { dg-error "cannot begin|alternate spelling" }
+template struct Foo<::B>; // { dg-error "20: error: '<::' cannot begin|20: note: '<:' is an alternate" }
 
 // On the first error message, an additional note about the use of 
 //  -fpermissive should be present
-// { dg-error "-fpermissive" "-fpermissive" { target *-*-* } 18 }
+// { dg-error "17: note: \\(if you use '-fpermissive' G\\+\\+ will accept your code\\)" "-fpermissive" { target *-*-* } 19 }
diff --git a/gcc/testsuite/g++.dg/parse/error12.C b/gcc/testsuite/g++.dg/parse/error12.C
index ea04fd0..b002588 100644
--- a/gcc/testsuite/g++.dg/parse/error12.C
+++ b/gcc/testsuite/g++.dg/parse/error12.C
@@ -1,7 +1,7 @@
 // { dg-do compile }
 // Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
 // Make sure the error about '<:' can be turned into a warning
-// { dg-options "-fpermissive" }
+// { dg-options "-fpermissive -fshow-column" }
 
 struct B;
 
@@ -9,4 +9,5 @@ template <class A>
 struct Foo {};
 
 Foo<::B> foo;   // { dg-bogus "error" "error in place of warning" }
-// { dg-error "" "" { target *-*-* } 11 }
+// { dg-error "4: warning: '<::' cannot begin a template-argument list" "warning <::" { target *-*-* } 11 }
+// { dg-error "4: note: '<:' is an alternate spelling for '.'. Insert whitespace between '<' and '::'" "note <:" { target *-*-* } 11 }
diff --git a/gcc/testsuite/g++.dg/parse/error13.C b/gcc/testsuite/g++.dg/parse/error13.C
index 15642e3..94ddae8 100644
--- a/gcc/testsuite/g++.dg/parse/error13.C
+++ b/gcc/testsuite/g++.dg/parse/error13.C
@@ -1,13 +1,14 @@
+// { dg-options "-fshow-column" }
 // PR c++/13975
 
-public: // { dg-error "" }
+public: // { dg-error "1: error: expected unqualified-id before 'public'" }
 
 int i;
 
-protected: // { dg-error "" }
+protected: // { dg-error "1: error: expected unqualified-id before 'protected'" }
 
 int j;
 
-private: // { dg-error "" }
+private: // { dg-error "1: error: expected unqualified-id before 'private'" }
 
 int k;
diff --git a/gcc/testsuite/g++.dg/parse/error14.C b/gcc/testsuite/g++.dg/parse/error14.C
index 4b23045..906b98f 100644
--- a/gcc/testsuite/g++.dg/parse/error14.C
+++ b/gcc/testsuite/g++.dg/parse/error14.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column" }
 // PR c++/13970
 
 struct X
@@ -18,5 +19,5 @@ struct X
         Zinc<int>( //);
 		  //    }
 
-}; // { dg-error "" }
+}; // { dg-error "2: error: expected '.' at end of input|1: error: expected primary-expression before '.' token|1: error: expected ';' before '.' token|1: error: expected unqualified-id at end of input" }
 
diff --git a/gcc/testsuite/g++.dg/parse/error15.C b/gcc/testsuite/g++.dg/parse/error15.C
index b343970..b65175c 100644
--- a/gcc/testsuite/g++.dg/parse/error15.C
+++ b/gcc/testsuite/g++.dg/parse/error15.C
@@ -1,5 +1,6 @@
 // { dg-do compile }
 // Contributed by Volker Reichelt <reichelt at gcc dot gnu dot org> 
+// { dg-options "-fshow-column" }
 // PR c++/14008: Improve diagnostic on invalid types in declarators.
 
 namespace N
@@ -9,29 +10,29 @@ namespace N
   int K;
 }
 
-N::A f2;              // { dg-error "without an argument list" }
-N::INVALID f3;        // { dg-error "in namespace 'N' does not name a type" }
-N::C::INVALID f4;     // { dg-error "in class 'N::C' does not name a type" }
-N::K f6;              // { dg-error "in namespace 'N' does not name a type" }
-typename N::A f7;     // { dg-error "without an argument list|outside of template" }
+N::A f2;              // { dg-error "4: error: invalid use of template-name 'N::A' without an argument list" }
+N::INVALID f3;        // { dg-error "4: error: 'INVALID' in namespace 'N' does not name a type" }
+N::C::INVALID f4;     // { dg-error "7: error: 'INVALID' in class 'N::C' does not name a type" }
+N::K f6;              // { dg-error "4: error: 'K' in namespace 'N' does not name a type" }
+typename N::A f7;     // { dg-error "1: error: using 'typename' outside of template|13: error: invalid use of template-name 'N::A' without an argument list|17: error: invalid type in declaration before ';' token" }
 
 struct B
 {
-  N::A f2;            // { dg-error "without an argument list" }
-  N::INVALID f3;      // { dg-error "in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "in namespace 'N' does not name a type" }
-  typename N::A f7;   // { dg-error "without an argument list|outside of template" }
+  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  typename N::A f7;   // { dg-error "3: error: using 'typename' outside of template|15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
 template <int>
 struct C
 {
-  N::A f2;            // { dg-error "without an argument list" }
-  N::INVALID f3;      // { dg-error "in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "in namespace 'N' does not name a type" }
-  typename N::A f7;   // { dg-error "without an argument list" }
+  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  typename N::A f7;   // { dg-error "15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
-// { dg-bogus "" "bogus excess errors in declaration" { xfail *-*-* } 16 }
+// { dg-bogus "bogus excess errors in declaration" "bogus excess errors in declaration" { xfail *-*-* } 17 }
diff --git a/gcc/testsuite/g++.dg/parse/error16.C b/gcc/testsuite/g++.dg/parse/error16.C
index 3dc58ad..ddc302c 100644
--- a/gcc/testsuite/g++.dg/parse/error16.C
+++ b/gcc/testsuite/g++.dg/parse/error16.C
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 // PR c++/16964
 
 struct A
 {
-  struct B {}; // { dg-error "previous" }
+  struct B {}; // { dg-error "12: error: previous definition of 'struct A::B'" }
 };
 
-struct A::B{}; // { dg-error "redefinition" }
+struct A::B{}; // { dg-error "11: error: redefinition of 'struct A::B'" }
diff --git a/gcc/testsuite/g++.dg/parse/error17.C b/gcc/testsuite/g++.dg/parse/error17.C
index 2a8f3f8..0e05217 100644
--- a/gcc/testsuite/g++.dg/parse/error17.C
+++ b/gcc/testsuite/g++.dg/parse/error17.C
@@ -1,8 +1,9 @@
+// { dg-options "-fshow-column" }
 // PR c++/16965
 
 template <typename T> struct B { 
-  static int Bar(T); // { dg-error "" }
+  static int Bar(T); // { dg-error "19: error: candidates are: |19: error:  " }
 }; 
 struct D : B<int>, B<char> {}; 
  
-int i2 = D::Bar(2); // { dg-error "" }
+int i2 = D::Bar(2); // { dg-error "13: error: reference to 'Bar' is ambiguous|10: error: reference to 'Bar' is ambiguous" }
diff --git a/gcc/testsuite/g++.dg/parse/error18.C b/gcc/testsuite/g++.dg/parse/error18.C
index 363aae9..926af11 100644
--- a/gcc/testsuite/g++.dg/parse/error18.C
+++ b/gcc/testsuite/g++.dg/parse/error18.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column" }
 // PR c++/16002
 
 void f()
 {
-  double Q *= 5.0; // { dg-error "initializer" }
+  double Q *= 5.0; // { dg-error "12: error: expected initializer before '..' token" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error19.C b/gcc/testsuite/g++.dg/parse/error19.C
index 24a66af..b22156a 100644
--- a/gcc/testsuite/g++.dg/parse/error19.C
+++ b/gcc/testsuite/g++.dg/parse/error19.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -fmessage-length=0   -ansi -pedantic-errors -Wno-long-long " }
 // PR C++/17867
 
 struct A
-{  // { dg-error "candidate" }
+{  // { dg-error "1: note: candidates are:" }
   A(int);
 };
 
@@ -9,5 +10,5 @@ const A& foo();
 
 void bar()
 {
-  foo()=A(0); // { dg-error "A" }
+  foo()=A(0); // { dg-error "12: error: no match for 'operator='" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/error2.C b/gcc/testsuite/g++.dg/parse/error2.C
index 8dd1e9d..075dcc2 100644
--- a/gcc/testsuite/g++.dg/parse/error2.C
+++ b/gcc/testsuite/g++.dg/parse/error2.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }
 // Properly print CALL_EXPRs while dumping expressions
 
 double g;
@@ -7,4 +8,8 @@ int func(double);
 template <int>
 struct Foo {};
 
-Foo<func(g)> f; // { dg-error "" "func(g)" }
+Foo<func(g)> f; // { dg-error "5: error: 'int func.double.' cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "10: error: 'g' cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "11: error: a function call cannot appear in a constant-expression" "" { target *-*-* } { 11 } }
+// { dg-error "12: error: template argument 1 is invalid" "" { target *-*-* } { 11 } }
+// { dg-error "15: error: invalid type in declaration before ';' token" "" { target *-*-* } { 11 } }
diff --git a/gcc/testsuite/g++.dg/parse/error20.C b/gcc/testsuite/g++.dg/parse/error20.C
index ee7390a..9564fab 100644
--- a/gcc/testsuite/g++.dg/parse/error20.C
+++ b/gcc/testsuite/g++.dg/parse/error20.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/17821
 
 struct A {
@@ -11,7 +12,7 @@ struct C {
 };
 int main() {
   C c;
-  A(c.p.i); // { dg-error "member.*non-class" }
+  A(c.p.i); // { dg-error "9: error: request for member 'i' in 'c.C::p', which is of non-class type 'B" }
   return 0;
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error21.C b/gcc/testsuite/g++.dg/parse/error21.C
index 6e24ae2..f60bf2b 100644
--- a/gcc/testsuite/g++.dg/parse/error21.C
+++ b/gcc/testsuite/g++.dg/parse/error21.C
@@ -1,5 +1,5 @@
 // PR c++/17393
-// { dg-options "-Wall" }
+// { dg-options "-Wall -fshow-column" }
 
 struct A { };
 
@@ -7,6 +7,6 @@ void foo()
 {
   // Check that we do not complain about an unused
   // compiler-generated variable.
-  A& = a; // { dg-error "token|declarator|not declared" }
+  A& = a; // { dg-error "6: error: expected unqualified-id before '=' token|8: error: 'a' was not declared in this scope" }
 }
 
diff --git a/gcc/testsuite/g++.dg/parse/error22.C b/gcc/testsuite/g++.dg/parse/error22.C
index da3a62f..3014121 100644
--- a/gcc/testsuite/g++.dg/parse/error22.C
+++ b/gcc/testsuite/g++.dg/parse/error22.C
@@ -1,5 +1,6 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/15786
 
 struct A {
-  void foo(bar* p); /* { dg-error "declared" } */
+  void foo(bar* p); /* { dg-error "12: error: 'bar' has not been declared" } */
 };
diff --git a/gcc/testsuite/g++.dg/parse/error23.C b/gcc/testsuite/g++.dg/parse/error23.C
index 7d6fda2..21b2434 100644
--- a/gcc/testsuite/g++.dg/parse/error23.C
+++ b/gcc/testsuite/g++.dg/parse/error23.C
@@ -1,7 +1,9 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/19149
 
 struct QChar {
   QChar( char c );
   QChar( const QChar& c );
-  static const ; // { dg-error "" }
+  //following column number is not accurate enough but will make it for now
+  static const ; // { dg-error "10: error: declaration does not declare anything" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error24.C b/gcc/testsuite/g++.dg/parse/error24.C
index c072250..e341c34 100644
--- a/gcc/testsuite/g++.dg/parse/error24.C
+++ b/gcc/testsuite/g++.dg/parse/error24.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/19395
 
 struct A {
-  typedef int ::X; // { dg-error "" }
+  typedef int ::X; // { dg-error "17: error: typedef name may not be a nested-name-specifier" }
 };
 
 
diff --git a/gcc/testsuite/g++.dg/parse/error25.C b/gcc/testsuite/g++.dg/parse/error25.C
index 360b40f..b5cb57e 100644
--- a/gcc/testsuite/g++.dg/parse/error25.C
+++ b/gcc/testsuite/g++.dg/parse/error25.C
@@ -1,4 +1,5 @@
 // { dg-do compile }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // Origin: Steven Bosscher <steven at gcc dot gnu dot org>
 // PR c++/17401: ICE with invalid pure specifier
 
@@ -8,10 +9,10 @@
 class foo
 {
   virtual void bar1 () = 0;
-  virtual void bar2 () = __null;  // { dg-error "invalid pure specifier" }
-  virtual void bar3 () = 4;       // { dg-error "invalid pure specifier" }
-  virtual void bar4 () = A::f;    // { dg-error "invalid pure specifier" }
-  virtual void bar5 () = 0l;      // { dg-error "invalid pure specifier" }
-  virtual void bar6 () = 00;      // { dg-error "invalid pure specifier" }
-  virtual void bar7 () = 0x0;     // { dg-error "invalid pure specifier" }
+  virtual void bar2 () = __null;  // { dg-error "32: error: invalid pure specifier" }
+  virtual void bar3 () = 4;       // { dg-error "27: error: invalid pure specifier" }
+  virtual void bar4 () = A::f;    // { dg-error "27: error: invalid pure specifier" }
+  virtual void bar5 () = 0l;      // { dg-error "28: error: invalid pure specifier" }
+  virtual void bar6 () = 00;      // { dg-error "28: error: invalid pure specifier" }
+  virtual void bar7 () = 0x0;     // { dg-error "29: error: invalid pure specifier" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error26.C b/gcc/testsuite/g++.dg/parse/error26.C
index 6e2b897..81f7ba6 100644
--- a/gcc/testsuite/g++.dg/parse/error26.C
+++ b/gcc/testsuite/g++.dg/parse/error26.C
@@ -1,12 +1,12 @@
 // PR c++/20148
-// { dg-options "" }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 
 void foo()
 {
-  if (({int c[2];})) ; // { dg-error "\{\.\.\.\}" }
+  if (({int c[2];})) ; // { dg-error "7: error: ISO C.. forbids|20: error: could not convert" }
 }
 
 void bar()
 {
-  if (({})); // { dg-error "\{\.\.\.\}" }
+  if (({})); // { dg-error "7: error: ISO C.. forbids|11: error: could not convert" }
 }
diff --git a/gcc/testsuite/g++.dg/parse/error27.C b/gcc/testsuite/g++.dg/parse/error27.C
index f52d3ce..f1fd537 100644
--- a/gcc/testsuite/g++.dg/parse/error27.C
+++ b/gcc/testsuite/g++.dg/parse/error27.C
@@ -1,7 +1,8 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/20152
 
-struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "previous definition" }
-struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "previous definition" }
-struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "" }
-struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "" }
+struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "24: error: previous definition of 'struct KrSelectionMode'" }
+struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "52: error: previous definition of 'struct KrKDESelectionMode'" }
+struct KrSelectionMode {  virtual void init() = 0; }; // { dg-error "8: error: redefinition of 'struct KrSelectionMode'" }
+struct KrKDESelectionMode : public KrSelectionMode { void init() { } }; // { dg-error "8: error: redefinition of 'struct KrKDESelectionMode'" }
 KrKDESelectionMode krKDESelectionMode;
diff --git a/gcc/testsuite/g++.dg/parse/error28.C b/gcc/testsuite/g++.dg/parse/error28.C
index 046cc50..fd202a1 100644
--- a/gcc/testsuite/g++.dg/parse/error28.C
+++ b/gcc/testsuite/g++.dg/parse/error28.C
@@ -1,10 +1,11 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/21908
 
 struct virt { virt () {} virt (int i) {} };
-struct der : public virtual virt { // { dg-error "der" }
-  der (int i) : virt(i) {} // { dg-error "der" }
+struct der : public virtual virt { // { dg-error "34: note:                 der::der" }
+  der (int i) : virt(i) {} // { dg-error "13: note: candidates are: der" }
 };
 struct top : public der { 
-  // { dg-error "der\\(\\)" "" { target *-*-* } 9 } 
   top () {} // { dg-bogus "der\\(const" }
 };
+// { dg-error "10: error: no matching function for call to 'der" "" { target *-*-* } 9 }
diff --git a/gcc/testsuite/g++.dg/parse/error29.C b/gcc/testsuite/g++.dg/parse/error29.C
index b50b275..fcd091b 100644
--- a/gcc/testsuite/g++.dg/parse/error29.C
+++ b/gcc/testsuite/g++.dg/parse/error29.C
@@ -1,3 +1,4 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/25637
 
 struct A { 
@@ -6,7 +7,7 @@ struct A {
   void operator delete(void *);
 };
 struct B { 
-  friend void A::foo() {} // { dg-error "define" }
-  friend void A::operator delete(void*) {} // { dg-error "define" }
-  friend A::A() {} // { dg-error "define" }
+  friend void A::foo() {} // { dg-error "22: error: cannot define member function 'A::foo' within 'B'" }
+  friend void A::operator delete(void*) {} // { dg-error "39: error: cannot define member function 'A::operator delete' within 'B'" }
+  friend A::A() {} // { dg-error "15: error: cannot define member function 'A::A' within 'B'" }
 };
diff --git a/gcc/testsuite/g++.dg/parse/error3.C b/gcc/testsuite/g++.dg/parse/error3.C
index a052346..1f337e9 100644
--- a/gcc/testsuite/g++.dg/parse/error3.C
+++ b/gcc/testsuite/g++.dg/parse/error3.C
@@ -1,6 +1,19 @@
+// { dg-options "-fshow-column" }
 // PR c++/10779
 
 static void InstantiateConstraint(const float&, unsigned,
-                                  void(*AddFunction)(const TYPE&,bool&, // { dg-error "" }
+                                  void(*AddFunction)(const TYPE&,bool&,
                                                      char*, char*,
-                                                     unsigned*)); // { dg-error "" }
+                                                     unsigned*));
+// { dg-error "64: error: expected ',' or '...' before '&' token" "" { target *-*-* }  { 5 } }
+
+/// in the coming test, the column information is broken as it points to
+//  the end of the declaration instead of pointing to the begining of the
+//  'TYPE' identifier. This is due to the warning being generated by the
+//  declaration groking code (gcc/cp/decl.c) and not the parser. So in that
+//  code, the exact token location information is lost as the declaration
+//  groking code manipulates TREEs only. The token location used is then
+//  the global one that is not accurate enough. Anyway, let's say it is
+//  good enough for now, until we find a way to propagate token location to
+//  code paths that manipulate TREEs only.
+// { dg-error "64: error: ISO C\\+\\+ forbids declaration of 'TYPE' with no type" "" { target *-*-* } { 7 } }
diff --git a/gcc/testsuite/g++.dg/parse/error30.C b/gcc/testsuite/g++.dg/parse/error30.C
index 734a255..5c52d1e 100644
--- a/gcc/testsuite/g++.dg/parse/error30.C
+++ b/gcc/testsuite/g++.dg/parse/error30.C
@@ -1,5 +1,6 @@
 // PR c++/30854
 // { dg-do compile }
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 
 struct A
 {
@@ -7,5 +8,5 @@ struct A
   A(int);
 };
 
-A a = -A();	// { dg-error "no match for.*operator-.*in.*-A\\(\\)" }
-A b = -A(5);	// { dg-error "no match for.*operator-.*in.*-A\\(5\\)" }
+A a = -A();	// { dg-error "10: error: no match for.*operator-.*in.*-A\\(\\)" }
+A b = -A(5);	// { dg-error "11: error: no match for.*operator-.*in.*-A\\(5\\)" }
diff --git a/gcc/testsuite/g++.dg/parse/error31.C b/gcc/testsuite/g++.dg/parse/error31.C
index 5264f44..d354cc3 100644
--- a/gcc/testsuite/g++.dg/parse/error31.C
+++ b/gcc/testsuite/g++.dg/parse/error31.C
@@ -1,10 +1,12 @@
+// { dg-options "-fshow-column -ansi -pedantic-errors -Wno-long-long" }
 // PR c++/32190
 
 template<typename T> class foo{ };
 
 int main() {
     foo<int> i;
-    foo<foo<int> j; // { dg-error "template argument" }
+    // this column number is not accurate yet, but that will make it for now.
+    foo<foo<int> j; // { dg-error "18: error: template argument 1 is invalid" }
     int k;
     int l;
     foo<int> m;
diff --git a/gcc/testsuite/g++.dg/parse/error4.C b/gcc/testsuite/g++.dg/parse/error4.C
index aa1bfad..790e5c9 100644
--- a/gcc/testsuite/g++.dg/parse/error4.C
+++ b/gcc/testsuite/g++.dg/parse/error4.C
@@ -1,7 +1,10 @@
 // PR c++/12160
+// { dg-options "-fshow-column" }
 
-struct X { 
-  virtual void f(int, 
-		 itn,        // { dg-error "declared" }
+struct X {
+  virtual void f(int,
+		 itn,
 		 int);
-}; 
+};
+
+// { dg-error "4: error: 'itn' has not been declared" "" { target *-*-* } { 6 } }
diff --git a/gcc/testsuite/g++.dg/parse/error5.C b/gcc/testsuite/g++.dg/parse/error5.C
index 81356ce..8c9a039 100644
--- a/gcc/testsuite/g++.dg/parse/error5.C
+++ b/gcc/testsuite/g++.dg/parse/error5.C
@@ -1,4 +1,19 @@
 // PR c++/13269
+// { dg-options "-fshow-column" }
 
-class Foo { int foo() return 0; } }; // { dg-error "" }
+class Foo { int foo() return 0; } };
+
+// { dg-error "30: error: expected identifier before numeric constant" "" { target *-*-* } { 4 } }
+
+// { dg-error "23: error: named return values are no longer supported" "" { target *-*-* } { 4 } }
+
+// the column number info of this error output is still wrong because the error
+// message has been generated by cp_parser_error() which does not
+// necessarily allow accurate column number display. At some point, we will
+// need make cp_parser_error() report more accurate column numbers.
+// { dg-error "30: error: expected '\{' at end of input" "" { target *-*-* } { 4 } }
+
+// { dg-error "35: error: expected unqualified-id before '\}' token" "" {target *-*-*  } { 4 } }
+
+// { dg-error "35: error: expected declaration before '\}' token" "" {target *-*-*  } { 4 } }
 
diff --git a/gcc/testsuite/g++.dg/parse/error6.C b/gcc/testsuite/g++.dg/parse/error6.C
index 3a16669..cd1b6b8 100644
--- a/gcc/testsuite/g++.dg/parse/error6.C
+++ b/gcc/testsuite/g++.dg/parse/error6.C
@@ -1,6 +1,11 @@
 // PR c++/10603
+// { dg-options "-fshow-column" }
 
-int f(int not) { // { dg-error "!" }
-  return 1-not; // { dg-error "" }
+int f(int not) {
+  return 1-not;
 } 
 
+// { dg-error "11: error: expected ',' or '...' before '!' token" "" { target *-*-* } { 4 } }
+
+// { dg-error "15: error: expected primary\\-expression before ';' token" "" { target *-*-* }  { 5 } }
+
diff --git a/gcc/testsuite/g++.dg/parse/error7.C b/gcc/testsuite/g++.dg/parse/error7.C
index 50e7f84..f71c9aa 100644
--- a/gcc/testsuite/g++.dg/parse/error7.C
+++ b/gcc/testsuite/g++.dg/parse/error7.C
@@ -1,4 +1,7 @@
 // PR c++/12827
+// { dg-options "-fshow-column" }
 
 void f(int x
-       int y); // { dg-error "," }
+       int y);
+
+// { dg-error "8: error: expected ',' or '...' before 'int'" "" { target *-*-* } { 5 } }
diff --git a/gcc/testsuite/g++.dg/parse/error8.C b/gcc/testsuite/g++.dg/parse/error8.C
index 125f2e4..a399cfe 100644
--- a/gcc/testsuite/g++.dg/parse/error8.C
+++ b/gcc/testsuite/g++.dg/parse/error8.C
@@ -1,4 +1,10 @@
 // PR c++/13438
+// {  dg-options "-fshow-column" }
 
-struct A { friend typename struct B; };  // { dg-error "" }
-  
+struct A { friend typename struct B; };
+
+
+// { dg-error "19: error: using 'typename' outside of template" "" { target *-*-* } { 4 } }
+// { dg-error "28: error: expected nested-name-specifier before 'struct'" "" { target *-*-* } { 4 } }
+// { dg-error "35: error: multiple types in one declaration" "" { target *-*-* } { 4 } }
+// { dg-error "12: error: friend declaration does not name a class or function" "" { target *-*-* } { 4 } }
diff --git a/gcc/testsuite/g++.dg/parse/error9.C b/gcc/testsuite/g++.dg/parse/error9.C
index aa9109f..c1be697 100644
--- a/gcc/testsuite/g++.dg/parse/error9.C
+++ b/gcc/testsuite/g++.dg/parse/error9.C
@@ -1,5 +1,9 @@
 // PR c++/12613
-// { dg-options "" }
+// { dg-options "-fshow-column" }
 
 enum { FOO = 1, BAR = 2 };
-int a[] = { FOO: 1, BAR: 2 }; // { dg-error "" }
+int a[] = { FOO: 1, BAR: 2 };
+
+// the following 2 column locations are still not accurate enough
+// { dg-error "28: error: name 'FOO' used in a GNU-style designated initializer for an array" "" { target *-*-* }  { 5 } }
+// { dg-error "28: error: name 'BAR' used in a GNU-style designated initializer for an array" "" { target *-*-* }  { 5 } }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
index 42a21fc..7fe07a2 100644
--- a/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
+++ b/gcc/testsuite/g++.old-deja/g++.pt/niklas01a.C
@@ -1,8 +1,9 @@
 // { dg-do assemble  }
+// { dg-options "-fshow-column" }
 
 struct A { // { dg-error "" } forward declaration
-  friend struct B : A {		// { dg-error "" } 
+  friend struct B : A {		// { dg-error "invalid use of incomplete type 'struct A'" }
     int x;
-  };	// { dg-error "" } class definition cannot be a friend
+  };	// { dg-error "class definition may not be declared a friend" ""  { target *-*-* } { 5 } }
   int y;
 };
diff --git a/gcc/testsuite/lib/g++.exp b/gcc/testsuite/lib/g++.exp
index c188824..7ca5b73 100644
--- a/gcc/testsuite/lib/g++.exp
+++ b/gcc/testsuite/lib/g++.exp
@@ -273,7 +273,6 @@ proc g++_target_compile { source dest type options } {
     }
 
     lappend options "additional_flags=[libio_include_flags]"
-    lappend options "additional_flags=-fno-show-column"
     lappend options "compiler=$GXX_UNDER_TEST"
 
     set options [concat $gpp_compile_options $options]

[-- Attachment #3: gcc-error-location-2008-06-30-gcc-patch-2.txt --]
[-- Type: text/plain, Size: 24497 bytes --]

gcc/cp/ChangeLog:
2008-06-30 Dodji Seketeli <dseketel@redhat.com>

 	PR c++/31754
	* cp-tree.h (struct cp_decl_specifier_seq): add a location field. It
	carries the location of the primary type.
	* parser.c (cp_parser_check_type_definition): update documentation.
	(cp_parser_check_for_definition_in_return_type,
	cp_parser_check_for_invalid_template_id,
	cp_parser_set_decl_spec_type,
	cp_parser_check_for_definition_in_return_type,
	cp_parser_diagnose_invalid_type_name,
	cp_parser_new_expression, cp_parser_explicit_instantiation,
	cp_parser_type_specifier, cp_parser_simple_type_specifier,
	cp_parser_omp_for_loop, cp_parser_pragma): use location in error messages.

gcc/testsuite/ChangeLog:
2008-06-30 Dodji Seketeli <dseketel@redhat.com>

	* g++.dg/other/semicolon.C: Tighten this test, making it column aware.
	* g++.dg/parse/error15.C: update this because of more accurate column
	numbers in error reporting.
	* g++.old-deja/g++.brendan/crash16.C: Tighten the test, making it
	column aware.
	* g++.old-deja/g++.law/ctors5.C: Likewise.
	* g++.old-deja/g++.other/crash25.C: Likewise.

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index afea188..9cd84f3 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -3910,6 +3910,9 @@ typedef struct cp_decl_specifier_seq {
      reflected here.  This field will be a TYPE, unless a typedef-name
      was used, in which case it will be a TYPE_DECL.  */
   tree type;
+  /* The location of the primary type. Mainly used for error
+     reporting.  */
+  location_t type_location;
   /* The attributes, if any, provided with the specifier sequence.  */
   tree attributes;
   /* If non-NULL, a built-in type that the user attempted to redefine
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 184b9ec..c859bae 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1940,7 +1940,7 @@ static bool cp_parser_declares_only_class_p
 static void cp_parser_set_storage_class
   (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
 static void cp_parser_set_decl_spec_type
-  (cp_decl_specifier_seq *, tree, bool);
+  (cp_decl_specifier_seq *, tree, location_t, bool);
 static bool cp_parser_friend_p
   (const cp_decl_specifier_seq *);
 static cp_token *cp_parser_require
@@ -1988,9 +1988,9 @@ static bool cp_parser_simulate_error
 static bool cp_parser_check_type_definition
   (cp_parser *);
 static void cp_parser_check_for_definition_in_return_type
-  (cp_declarator *, tree);
+  (cp_declarator *, tree, location_t type_location);
 static void cp_parser_check_for_invalid_template_id
-  (cp_parser *, tree);
+  (cp_parser *, tree, location_t location);
 static bool cp_parser_non_integral_constant_expression
   (cp_parser *, const char *);
 static void cp_parser_diagnose_invalid_type_name
@@ -2204,11 +2204,12 @@ cp_parser_check_type_definition (cp_parser* parser)
 /* This function is called when the DECLARATOR is processed.  The TYPE
    was a type defined in the decl-specifiers.  If it is invalid to
    define a type in the decl-specifiers for DECLARATOR, an error is
-   issued.  */
+   issued. TYPE_LOCATION is the location of TYPE and is used
+   for error reporting.  */
 
 static void
 cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
-					       tree type)
+					       tree type, location_t type_location)
 {
   /* [dcl.fct] forbids type definitions in return types.
      Unfortunately, it's not easy to know whether or not we are
@@ -2221,31 +2222,32 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
   if (declarator
       && declarator->kind == cdk_function)
     {
-      error ("new types may not be defined in a return type");
-      inform ("(perhaps a semicolon is missing after the definition of %qT)",
-	      type);
+      error ("%Hnew types may not be defined in a return type", &type_location);
+      inform ("%H(perhaps a semicolon is missing after the definition of %qT)",
+	      &type_location, type);
     }
 }
 
 /* A type-specifier (TYPE) has been parsed which cannot be followed by
    "<" in any valid C++ program.  If the next token is indeed "<",
    issue a message warning the user about what appears to be an
-   invalid attempt to form a template-id.  */
+   invalid attempt to form a template-id. LOCATION is the location
+   of the type-specifier (TYPE) */
 
 static void
 cp_parser_check_for_invalid_template_id (cp_parser* parser,
-					 tree type)
+					 tree type, location_t location)
 {
   cp_token_position start = 0;
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
     {
       if (TYPE_P (type))
-	error ("%qT is not a template", type);
+	error ("%H%qT is not a template", &location, type);
       else if (TREE_CODE (type) == IDENTIFIER_NODE)
-	error ("%qE is not a template", type);
+	error ("%H%qE is not a template", &location, type);
       else
-	error ("invalid template-id");
+	error ("%Hinvalid template-id", &location);
       /* Remember the location of the invalid "<".  */
       if (cp_parser_uncommitted_to_tentative_parse_p (parser))
 	start = cp_lexer_token_position (parser->lexer, true);
@@ -2291,32 +2293,34 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
    qualifying scope (or NULL, if none) for ID.  This function commits
    to the current active tentative parse, if any.  (Otherwise, the
    problematic construct might be encountered again later, resulting
-   in duplicate error messages.)  */
+   in duplicate error messages.) LOCATION is the location of ID.  */
 
 static void
 cp_parser_diagnose_invalid_type_name (cp_parser *parser,
 				      tree scope, tree id,
-				      location_t id_location)
+				      location_t location)
 {
   tree decl, old_scope;
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
-  decl = cp_parser_lookup_name_simple (parser, id, id_location);
+  decl = cp_parser_lookup_name_simple (parser, id, location);
   parser->scope = old_scope;
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
-    error ("invalid use of template-name %qE without an argument list", decl);
+    error ("%Hinvalid use of template-name %qE without an argument list",
+           &location, decl);
   else if (TREE_CODE (id) == BIT_NOT_EXPR)
-    error ("invalid use of destructor %qD as a type", id);
+    error ("%Hinvalid use of destructor %qD as a type", &location, id);
   else if (TREE_CODE (decl) == TYPE_DECL)
     /* Something like 'unsigned A a;'  */
-    error ("invalid combination of multiple type-specifiers");
+    error ("%Hinvalid combination of multiple type-specifiers",
+           &location);
   else if (!parser->scope)
     {
       /* Issue an error message.  */
-      error ("%qE does not name a type", id);
+      error ("%H%qE does not name a type", &location, id);
       /* If we're in a template class, it's possible that the user was
 	 referring to a type from a base class.  For example:
 
@@ -2348,8 +2352,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
 		    if (TREE_CODE (field) == TYPE_DECL
 			&& DECL_NAME (field) == id)
 		      {
-			inform ("(perhaps %<typename %T::%E%> was intended)",
-				BINFO_TYPE (b), id);
+			inform ("%H(perhaps %<typename %T::%E%> was intended)",
+				&location, BINFO_TYPE (b), id);
 			break;
 		      }
 		  if (field)
@@ -2363,10 +2367,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
   else if (parser->scope != error_mark_node)
     {
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-	error ("%qE in namespace %qE does not name a type",
-	       id, parser->scope);
+	error ("%H%qE in namespace %qE does not name a type",
+	       &location, id, parser->scope);
       else if (TYPE_P (parser->scope))
-	error ("%qE in class %qT does not name a type", id, parser->scope);
+	error ("%H%qE in class %qT does not name a type",
+               &location, id, parser->scope);
       else
 	gcc_unreachable ();
     }
@@ -5552,7 +5557,8 @@ cp_parser_new_expression (cp_parser* parser)
 	{
 	  error ("%Harray bound forbidden after parenthesized type-id",
 		 &token->location);
-	  inform ("try removing the parentheses around the type-id");
+	  inform ("%Htry removing the parentheses around the type-id",
+		 &token->location);
 	  cp_parser_direct_new_declarator (parser);
 	}
       nelts = NULL_TREE;
@@ -10525,6 +10531,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   int declares_class_or_enum;
   cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
+  cp_token *token;
 
   /* Look for an (optional) storage-class-specifier or
      function-specifier.  */
@@ -10547,6 +10554,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
      control while processing explicit instantiation directives.  */
   push_deferring_access_checks (dk_no_check);
   /* Parse a decl-specifier-seq.  */
+  token = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
 				CP_PARSER_FLAGS_OPTIONAL,
 				&decl_specifiers,
@@ -10579,7 +10587,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
 				/*member_p=*/false);
       if (declares_class_or_enum & 2)
 	cp_parser_check_for_definition_in_return_type (declarator,
-						       decl_specifiers.type);
+						       decl_specifiers.type,
+						       decl_specifiers.type_location);
       if (declarator != cp_error_declarator)
 	{
 	  decl = grokdeclarator (declarator, &decl_specifiers,
@@ -10751,6 +10760,7 @@ cp_parser_type_specifier (cp_parser* parser,
 	  if (decl_specs)
 	    cp_parser_set_decl_spec_type (decl_specs,
 					  type_spec,
+					  token->location,
 					  /*user_defined_p=*/true);
 	  return type_spec;
 	}
@@ -10775,6 +10785,7 @@ cp_parser_type_specifier (cp_parser* parser,
 	  if (decl_specs)
 	    cp_parser_set_decl_spec_type (decl_specs,
 					  type_spec,
+					  token->location,
 					  /*user_defined_p=*/true);
 	  return type_spec;
 	}
@@ -10796,6 +10807,7 @@ cp_parser_type_specifier (cp_parser* parser,
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs,
 				      type_spec,
+				      token->location,
 				      /*user_defined_p=*/true);
       return type_spec;
 
@@ -10971,6 +10983,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
+				      token->location,
 				      /*user_defined_p=*/true);
 
       return type;
@@ -10986,6 +10999,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
       if (decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
+				      token->location,
 				      /*user_defined_p=*/true);
 
       return type;
@@ -11007,6 +11021,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 	      && token->keyword != RID_LONG))
 	cp_parser_set_decl_spec_type (decl_specs,
 				      type,
+				      token->location,
 				      /*user_defined=*/false);
       if (decl_specs)
 	decl_specs->any_specifiers_p = true;
@@ -11017,7 +11032,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       /* There is no valid C++ program where a non-template type is
 	 followed by a "<".  That usually indicates that the user thought
 	 that the type was a template.  */
-      cp_parser_check_for_invalid_template_id (parser, type);
+      cp_parser_check_for_invalid_template_id (parser, type, token->location);
 
       return TYPE_NAME (type);
     }
@@ -11046,6 +11061,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 						/*type_p=*/false,
 						/*is_declaration=*/false)
 	   != NULL_TREE);
+      token = cp_lexer_peek_token (parser->lexer);
       /* If we have seen a nested-name-specifier, and the next token
 	 is `template', then we are using the template-id production.  */
       if (parser->scope
@@ -11080,6 +11096,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 	type = NULL_TREE;
       if (type && decl_specs)
 	cp_parser_set_decl_spec_type (decl_specs, type,
+				      token->location,
 				      /*user_defined=*/true);
     }
 
@@ -11112,7 +11129,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 	  return qual_type;
 	}
 
-      cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+      cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type),
+					       token->location);
     }
 
   return type;
@@ -11534,7 +11552,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
   /* A "<" cannot follow an elaborated type specifier.  If that
      happens, the user was probably trying to form a template-id.  */
-  cp_parser_check_for_invalid_template_id (parser, type);
+  cp_parser_check_for_invalid_template_id (parser, type, token->location);
 
   return type;
 }
@@ -12339,7 +12357,8 @@ cp_parser_init_declarator (cp_parser* parser,
 
   if (declares_class_or_enum & 2)
     cp_parser_check_for_definition_in_return_type (declarator,
-						   decl_specifiers->type);
+						   decl_specifiers->type,
+						   decl_specifiers->type_location);
 
   /* Figure out what scope the entity declared by the DECLARATOR is
      located in.  `grokdeclarator' sometimes changes the scope, so
@@ -14777,6 +14796,7 @@ cp_parser_class_head (cp_parser* parser,
       if (!cp_parser_parse_definitely (parser))
 	{
 	  invalid_nested_name_p = true;
+	  type_start_token = cp_lexer_peek_token (parser->lexer);
 	  id = cp_parser_identifier (parser);
 	  if (id == error_mark_node)
 	    id = NULL_TREE;
@@ -14820,7 +14840,10 @@ cp_parser_class_head (cp_parser* parser,
       if (!cp_parser_parse_definitely (parser))
 	{
 	  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
-	    id = cp_parser_identifier (parser);
+	    {
+	      type_start_token = cp_lexer_peek_token (parser->lexer);
+	      id = cp_parser_identifier (parser);
+	    }
 	  else
 	    id = NULL_TREE;
 	}
@@ -14834,7 +14857,8 @@ cp_parser_class_head (cp_parser* parser,
   pop_deferring_access_checks ();
 
   if (id)
-    cp_parser_check_for_invalid_template_id (parser, id);
+    cp_parser_check_for_invalid_template_id (parser, id,
+					     type_start_token->location);
 
   /* If it's not a `:' or a `{' then we can't really be looking at a
      class-head, since a class-head only appears as part of a
@@ -15423,7 +15447,8 @@ cp_parser_member_declaration (cp_parser* parser)
 
 	      if (declares_class_or_enum & 2)
 		cp_parser_check_for_definition_in_return_type
-		  (declarator, decl_specifiers.type);
+					    (declarator, decl_specifiers.type,
+					     decl_specifiers.type_location);
 
 	      /* Look for an asm-specification.  */
 	      asm_specification = cp_parser_asm_specification_opt (parser);
@@ -18016,6 +18041,7 @@ cp_parser_set_storage_class (cp_parser *parser,
 static void
 cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
 			      tree type_spec,
+			      location_t location,
 			      bool user_defined_p)
 {
   decl_specs->any_specifiers_p = true;
@@ -18042,6 +18068,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
 	{
 	  decl_specs->type = type_spec;
 	  decl_specs->user_defined_type_p = false;
+	  decl_specs->type_location = location;
 	}
     }
   else if (decl_specs->type)
@@ -18051,6 +18078,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
       decl_specs->type = type_spec;
       decl_specs->user_defined_type_p = user_defined_p;
       decl_specs->redefined_builtin_type = NULL_TREE;
+      decl_specs->type_location = location;
     }
 }
 
@@ -20967,7 +20995,10 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
       else
 	{
 	  if (!collapse_err)
-	    error ("collapsed loops not perfectly nested");
+	    {
+	      location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+	      error ("%Hcollapsed loops not perfectly nested", &loc);
+	    }
 	  collapse_err = true;
 	  cp_parser_statement_seq_opt (parser, NULL);
 	  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
@@ -21455,8 +21486,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
 	  cp_parser_omp_taskwait (parser, pragma_tok);
 	  return false;
 	case pragma_stmt:
-	  error ("%<#pragma omp taskwait%> may only be "
-		 "used in compound statements");
+	  error ("%H%<#pragma omp taskwait%> may only be "
+		 "used in compound statements",
+		 &pragma_tok->location);
 	  break;
 	default:
 	  goto bad_stmt;
diff --git a/gcc/testsuite/g++.dg/other/semicolon.C b/gcc/testsuite/g++.dg/other/semicolon.C
index 6bc3d95..542d3b7 100644
--- a/gcc/testsuite/g++.dg/other/semicolon.C
+++ b/gcc/testsuite/g++.dg/other/semicolon.C
@@ -1,9 +1,10 @@
 // PR c++/18368
 // Origin: Chris Lattner <sabre@nondot.org>
 // { dg-do compile }
+// { dg-options "-fshow-column" }
 
 struct A
 {
-  struct B { int i; }
-  void foo();   // { dg-error "two or more|return type" }
-};              // { dg-error "semicolon is missing" "" { target *-*-* } 8 }
+  struct B { int i; } // { dg-error "3: error: new types may not be defined in a return type|note: \\(perhaps a semicolon is missing" }
+  void foo();   // { dg-error "12: error: two or more|return type" }
+};
diff --git a/gcc/testsuite/g++.dg/parse/error15.C b/gcc/testsuite/g++.dg/parse/error15.C
index b65175c..5903a58 100644
--- a/gcc/testsuite/g++.dg/parse/error15.C
+++ b/gcc/testsuite/g++.dg/parse/error15.C
@@ -10,28 +10,28 @@ namespace N
   int K;
 }
 
-N::A f2;              // { dg-error "4: error: invalid use of template-name 'N::A' without an argument list" }
-N::INVALID f3;        // { dg-error "4: error: 'INVALID' in namespace 'N' does not name a type" }
-N::C::INVALID f4;     // { dg-error "7: error: 'INVALID' in class 'N::C' does not name a type" }
-N::K f6;              // { dg-error "4: error: 'K' in namespace 'N' does not name a type" }
+N::A f2;              // { dg-error "1: error: invalid use of template-name 'N::A' without an argument list" }
+N::INVALID f3;        // { dg-error "1: error: 'INVALID' in namespace 'N' does not name a type" }
+N::C::INVALID f4;     // { dg-error "1: error: 'INVALID' in class 'N::C' does not name a type" }
+N::K f6;              // { dg-error "1: error: 'K' in namespace 'N' does not name a type" }
 typename N::A f7;     // { dg-error "1: error: using 'typename' outside of template|13: error: invalid use of template-name 'N::A' without an argument list|17: error: invalid type in declaration before ';' token" }
 
 struct B
 {
-  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
-  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  N::A f2;            // { dg-error "3: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "3: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "3: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "3: error: 'K' in namespace 'N' does not name a type" }
   typename N::A f7;   // { dg-error "3: error: using 'typename' outside of template|15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
 template <int>
 struct C
 {
-  N::A f2;            // { dg-error "6: error: invalid use of template-name 'N::A' without an argument list" }
-  N::INVALID f3;      // { dg-error "6: error: 'INVALID' in namespace 'N' does not name a type" }
-  N::C::INVALID f4;   // { dg-error "9: error: 'INVALID' in class 'N::C' does not name a type" }
-  N::K f6;            // { dg-error "6: error: 'K' in namespace 'N' does not name a type" }
+  N::A f2;            // { dg-error "3: error: invalid use of template-name 'N::A' without an argument list" }
+  N::INVALID f3;      // { dg-error "3: error: 'INVALID' in namespace 'N' does not name a type" }
+  N::C::INVALID f4;   // { dg-error "3: error: 'INVALID' in class 'N::C' does not name a type" }
+  N::K f6;            // { dg-error "3: error: 'K' in namespace 'N' does not name a type" }
   typename N::A f7;   // { dg-error "15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
diff --git a/gcc/testsuite/g++.dg/parse/non-templ2.C b/gcc/testsuite/g++.dg/parse/non-templ2.C
new file mode 100644
index 0000000..169006a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/non-templ2.C
@@ -0,0 +1,16 @@
+// Origin : Dodji Seketeli <dseketel@redhat.com>
+// { dg-do compile }
+// { dg-options "-fshow-column" }
+
+struct Outer {
+    struct Inner {int m;};
+};
+
+template <typename T>
+struct S {
+    T m;
+    static int sm;
+    class Outer::Inner<char> b0; // { dg-error "18: error: 'Inner' is not a template" }
+    class Outer<int>::Inner<char> b1; // { dg-error "11: error: 'Outer' is not a template|23: error: 'Outer::Inner' is not a template|35: error: declaration of 'Outer::Inner S<T>::b0"  }
+};
+
diff --git a/gcc/testsuite/g++.dg/parse/nontype2.C b/gcc/testsuite/g++.dg/parse/nontype2.C
new file mode 100644
index 0000000..8141443
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/nontype2.C
@@ -0,0 +1,13 @@
+// Origin: Dodji Seketeli <dseketel@redhat.com>
+// { dg-compile }
+// { dg-options "-fshow-column" }
+
+void
+foo ()
+{   
+    unsigned
+      A         // { dg-error "7: error: 'A' does not name a type" }
+         a;
+}
+
+
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C
index 7151eb1..ddcae3c 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash16.C
@@ -1,12 +1,14 @@
 // { dg-do compile }
+// { dg-options "-fshow-column" }
 // GROUPS passed old-abort
-class Graph {
+
+class Graph { // { dg-error "1: error: new types|1: note: \\(perhaps" }
 public:
       unsigned         char N;
-      Graph(void) {} // { dg-error "previously defined here" }
+      Graph(void) {} // { dg-error "17: error: 'Graph" }
 }
 
-Graph::Graph(void)    // { dg-error "return type|redefinition|semicolon" }
+Graph::Graph(void) // { dg-error "18: error: return type|18: error: redefinition" }
 {    N = 10;
 }
 
diff --git a/gcc/testsuite/g++.old-deja/g++.law/ctors5.C b/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
index 334b597..1f469cf 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/ctors5.C
@@ -1,11 +1,12 @@
 // { dg-do assemble  }
+// { dg-options "-fshow-column" }
 // GROUPS passed constructors
 // ctors file
 // Subject: bug in handling static const object of the enclosing class
 // Date: Tue, 1 Sep 92 10:38:44 EDT
 
 class X
-{ // { dg-error "X::X" } implicit constructor
+{ // { dg-error "1: note:                 X::X\\(const X&\\)" } implicit constructor
   private:
     int x;
   public:
@@ -13,21 +14,21 @@ class X
     X( int );
 };
 
-class Y
+class Y // { dg-error "1: error: new types may not be defined in a return type|1: note: \\(perhaps a semicolon is missing after the definition of 'Y'\\)" }
 {
   private:
     X xx;
   public:
     Y();
 }
-X::X( int xi ) // { dg-error "return type|X::X|semicolon" }
+X::X( int xi ) // { dg-error "14: error: return type specification for constructor invalid|14: note: candidates are: X::X\\(int\\)" }
 {
     x = xi;
 }
 
 const X X::x0( 0 );
 
-Y::Y() // { dg-error "no match" }
+Y::Y() // { dg-error "6: error: no matching function for call to 'X::X\\(\\)'" }
 {
     xx = X::x0;
 }
diff --git a/gcc/testsuite/g++.old-deja/g++.other/crash25.C b/gcc/testsuite/g++.old-deja/g++.other/crash25.C
index b8417e8..517bac2 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/crash25.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/crash25.C
@@ -1,16 +1,17 @@
 // { dg-do assemble  }
+// { dg-options "-fshow-column" }
 // Origin: Jakub Jelinek <jakub@redhat.com>
 
-class X {
+class X { // { dg-error "1: error: new types may not be defined in a return type|1: note: \\(perhaps a semicolon is missing after the definition of 'X'\\)" }
 public:
   X();
   virtual ~X();
 }
 
-X::x()	// { dg-error "return type|member function|semicolon" }
+X::x()	// { dg-error "6: error: no 'X X::x\\(\\)' member function declared in class 'X'" }
 {
 }
 
-X::~x()	// { dg-error "expected class-name" }
+X::~x()	// { dg-error "6: error: expected class-name before '\\(' token" }
 {				
 }

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate  column  numbers
  2008-07-02 10:37       ` Dodji Seketeli
@ 2008-07-10  4:33         ` Jason Merrill
  2008-07-10 13:49           ` Dodji Seketeli
  0 siblings, 1 reply; 12+ messages in thread
From: Jason Merrill @ 2008-07-10  4:33 UTC (permalink / raw)
  To: Dodji Seketeli; +Cc: gcc-patches

Dodji Seketeli wrote:
> +/// in the coming test, the column information is broken as it points to
> +//  the end of the declaration instead of pointing to the begining of the
> +//  'TYPE' identifier. This is due to the warning being generated by the
> +//  declaration groking code (gcc/cp/decl.c) and not the parser. So in that
> +//  code, the exact token location information is lost as the declaration
> +//  groking code manipulates TREEs only.

grokdeclarator takes a cp_declarator *, and cp_declarator has a 
location_t field.  The comment says "Currently only set for cdk_id", but 
surely that could change.

But that doesn't seem like a reason to hold up this patch; go ahead and 
check this in and fix that in another patch.

Jason

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [patch] PR 31754/C++ - make -fshow-column produce more accurate  column  numbers
  2008-07-10  4:33         ` Jason Merrill
@ 2008-07-10 13:49           ` Dodji Seketeli
  0 siblings, 0 replies; 12+ messages in thread
From: Dodji Seketeli @ 2008-07-10 13:49 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

Jason Merrill a écrit :
> Dodji Seketeli wrote:
>> +/// in the coming test, the column information is broken as it points to
>> +//  the end of the declaration instead of pointing to the begining of 
>> the
>> +//  'TYPE' identifier. This is due to the warning being generated by the
>> +//  declaration groking code (gcc/cp/decl.c) and not the parser. So 
>> in that
>> +//  code, the exact token location information is lost as the 
>> declaration
>> +//  groking code manipulates TREEs only.
> 
> grokdeclarator takes a cp_declarator *, and cp_declarator has a 
> location_t field.  The comment says "Currently only set for cdk_id", but 
> surely that could change.

Right. I will look into that.

> But that doesn't seem like a reason to hold up this patch; go ahead and 
> check this in and fix that in another patch.

Okay, thanks very much. I don't have the commit access to the 
repository, so I cannot commit.

Dodji.

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2008-07-10 13:03 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-06-20 10:29 [patch] PR 31754/C++ - make -fshow-column produce more accurate column numbers Dodji Seketeli
2008-06-25  2:01 ` Tom Tromey
2008-06-25  6:35   ` Manuel López-Ibáñez
2008-06-25 14:05     ` Tom Tromey
2008-06-26 14:10     ` Dodji Seketeli
2008-06-26 14:24       ` Manuel López-Ibáñez
2008-06-26 19:08         ` Dodji Seketeli
2008-06-26 13:58   ` Dodji Seketeli
2008-06-26 18:39     ` Dodji Seketeli
2008-07-02 10:37       ` Dodji Seketeli
2008-07-10  4:33         ` Jason Merrill
2008-07-10 13:49           ` Dodji Seketeli

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).