OSDN Git Service

PR c++/37877
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 85295eb..f497d66 100644 (file)
@@ -71,8 +71,6 @@ typedef struct cp_token GTY (())
   unsigned char flags;
   /* Identifier for the pragma.  */
   ENUM_BITFIELD (pragma_kind) pragma_kind : 6;
-  /* True if this token is from a system header.  */
-  BOOL_BITFIELD in_system_header : 1;
   /* True if this token is from a context where it is implicitly extern "C" */
   BOOL_BITFIELD implicit_extern_c : 1;
   /* True for a CPP_NAME token that is not a keyword (i.e., for which
@@ -97,7 +95,7 @@ DEF_VEC_ALLOC_P (cp_token_position,heap);
 
 static cp_token eof_token =
 {
-  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, false, 0, { NULL },
+  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, { NULL },
   0
 };
 
@@ -408,7 +406,6 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
                        lexer == NULL ? 0 : C_LEX_RAW_STRINGS);
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
-  token->in_system_header = in_system_header;
 
   /* On some systems, some header files are surrounded by an
      implicit extern "C" block.  Set a flag in the token if it
@@ -446,7 +443,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
 
               /* Clear out the C_RID_CODE so we don't warn about this
                  particular identifier-turned-keyword again.  */
-              C_RID_CODE (token->u.value) = RID_MAX;
+              C_SET_RID_CODE (token->u.value, RID_MAX);
             }
 
          token->ambiguous_p = false;
@@ -478,15 +475,13 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
     }
 }
 
-/* Update the globals input_location and in_system_header and the
-   input file stack from TOKEN.  */
+/* Update the globals input_location and the input file stack from TOKEN.  */
 static inline void
 cp_lexer_set_source_position_from_token (cp_token *token)
 {
   if (token->type != CPP_EOF)
     {
       input_location = token->location;
-      in_system_header = token->in_system_header;
     }
 }
 
@@ -529,6 +524,14 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
   return cp_lexer_peek_token (lexer)->keyword == keyword;
 }
 
+/* Return true if the next token is not the indicated KEYWORD.  */
+
+static inline bool
+cp_lexer_next_token_is_not_keyword (cp_lexer* lexer, enum rid keyword)
+{
+  return cp_lexer_peek_token (lexer)->keyword != keyword;
+}
+
 /* Return true if the next token is a keyword for a decl-specifier.  */
 
 static bool
@@ -556,6 +559,8 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
     case RID_TYPENAME:
       /* Simple type specifiers.  */
     case RID_CHAR:
+    case RID_CHAR16:
+    case RID_CHAR32:
     case RID_WCHAR:
     case RID_BOOL:
     case RID_SHORT:
@@ -789,6 +794,8 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
       break;
 
     case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
     case CPP_WSTRING:
       fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
       break;
@@ -846,7 +853,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
    VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
 
 static cp_declarator *make_call_declarator
-  (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree);
+  (cp_declarator *, tree, cp_cv_quals, tree, tree);
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
@@ -1006,9 +1013,10 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
 
 cp_declarator *
 make_call_declarator (cp_declarator *target,
-                     cp_parameter_declarator *parms,
+                     tree parms,
                      cp_cv_quals cv_qualifiers,
-                     tree exception_specification)
+                     tree exception_specification,
+                     tree late_return_type)
 {
   cp_declarator *declarator;
 
@@ -1017,6 +1025,7 @@ make_call_declarator (cp_declarator *target,
   declarator->u.function.parameters = parms;
   declarator->u.function.qualifiers = cv_qualifiers;
   declarator->u.function.exception_specification = exception_specification;
+  declarator->u.function.late_return_type = late_return_type;
   if (target)
     {
       declarator->parameter_pack_p = target->parameter_pack_p;
@@ -1365,7 +1374,7 @@ cp_parser_context_new (cp_parser_context* next)
 
   /* No errors have occurred yet in this context.  */
   context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
-  /* If this is not the bottomost context, copy information that we
+  /* If this is not the bottommost context, copy information that we
      need from the previous context.  */
   if (next)
     {
@@ -1574,14 +1583,14 @@ static tree cp_parser_nested_name_specifier_opt
   (cp_parser *, bool, bool, bool, bool);
 static tree cp_parser_nested_name_specifier
   (cp_parser *, bool, bool, bool, bool);
-static tree cp_parser_class_or_namespace_name
+static tree cp_parser_qualifying_entity
   (cp_parser *, bool, bool, bool, bool, bool);
 static tree cp_parser_postfix_expression
   (cp_parser *, bool, bool, bool);
 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
@@ -1607,7 +1616,7 @@ static tree cp_parser_delete_expression
 static tree cp_parser_cast_expression
   (cp_parser *, bool, bool);
 static tree cp_parser_binary_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, enum cp_parser_prec);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
 static tree cp_parser_assignment_expression
@@ -1719,15 +1728,17 @@ static enum tree_code cp_parser_ptr_operator
   (cp_parser *, tree *, cp_cv_quals *);
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
+static tree cp_parser_late_return_type_opt
+  (cp_parser *);
 static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
   (cp_parser *);
 static void cp_parser_type_specifier_seq
   (cp_parser *, bool, cp_decl_specifier_seq *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_clause
+static tree cp_parser_parameter_declaration_clause
   (cp_parser *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_list
+static tree cp_parser_parameter_declaration_list
   (cp_parser *, bool *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
   (cp_parser *, bool, bool *);
@@ -1739,6 +1750,8 @@ static tree cp_parser_initializer
   (cp_parser *, bool *, bool *);
 static tree cp_parser_initializer_clause
   (cp_parser *, bool *);
+static tree cp_parser_braced_list
+  (cp_parser*, bool*);
 static VEC(constructor_elt,gc) *cp_parser_initializer_list
   (cp_parser *, bool *);
 
@@ -1890,15 +1903,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
@@ -1934,9 +1947,9 @@ 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);
+  (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
@@ -1956,12 +1969,12 @@ 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
   (cp_parser *);
-static void cp_parser_cache_group
+static bool cp_parser_cache_group
   (cp_parser *, enum cpp_ttype, unsigned);
 static void cp_parser_parse_tentatively
   (cp_parser *);
@@ -1978,19 +1991,19 @@ 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
   (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
-  (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
@@ -2016,7 +2029,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 *);
 
@@ -2033,7 +2046,10 @@ cp_parser_parsing_tentatively (cp_parser* parser)
 static bool
 cp_parser_is_string_literal (cp_token* token)
 {
-  return (token->type == CPP_STRING || token->type == CPP_WSTRING);
+  return (token->type == CPP_STRING ||
+         token->type == CPP_STRING16 ||
+         token->type == CPP_STRING32 ||
+         token->type == CPP_WSTRING);
 }
 
 /* Returns nonzero if TOKEN is the indicated KEYWORD.  */
@@ -2062,7 +2078,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;
        }
@@ -2085,33 +2101,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
@@ -2132,7 +2149,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;
 
@@ -2145,10 +2163,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 (location, OPT_Wlong_long, 
+                    "ISO C++ 1998 does not support %<long long%>");
        }
       else if (count > 1)
        {
@@ -2168,7 +2187,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]);
        }
     }
 }
@@ -2183,9 +2202,9 @@ cp_parser_check_type_definition (cp_parser* parser)
   /* If types are forbidden here, issue a message.  */
   if (parser->type_definition_forbidden_message)
     {
-      /* Use `%s' to print the string in case there are any escape
-        characters in the message.  */
-      error ("%s", parser->type_definition_forbidden_message);
+      /* Don't use `%s' to print the string, because quotations (`%<', `%>')
+        in the message need to be interpreted.  */
+      error (parser->type_definition_forbidden_message);
       return false;
     }
   return true;
@@ -2194,11 +2213,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
@@ -2211,8 +2231,9 @@ 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)",
+      error ("%Hnew types may not be defined in a return type", &type_location);
+      inform (type_location, 
+             "(perhaps a semicolon is missing after the definition of %qT)",
              type);
     }
 }
@@ -2220,22 +2241,23 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
 /* 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);
@@ -2264,7 +2286,13 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
     {
       if (!parser->allow_non_integral_constant_expression_p)
        {
-         error ("%s cannot appear in a constant-expression", thing);
+         /* Don't use `%s' to print THING, because quotations (`%<', `%>')
+            in the message need to be interpreted.  */
+         char *message = concat (thing,
+                                 " cannot appear in a constant-expression",
+                                 NULL);
+         error (message);
+         free (message);
          return true;
        }
     }
@@ -2275,30 +2303,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)
+cp_parser_diagnose_invalid_type_name (cp_parser *parser,
+                                     tree scope, tree id,
+                                     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);
+  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:
 
@@ -2330,7 +2362,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
                    if (TREE_CODE (field) == TYPE_DECL
                        && DECL_NAME (field) == id)
                      {
-                       inform ("(perhaps %<typename %T::%E%> was intended)",
+                       inform (location, 
+                               "(perhaps %<typename %T::%E%> was intended)",
                                BINFO_TYPE (b), id);
                        break;
                      }
@@ -2345,10 +2378,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
   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 ();
     }
@@ -2369,6 +2403,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,
@@ -2392,7 +2427,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);
@@ -2545,7 +2581,7 @@ static void
 cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
 {
   /* Look for the trailing `;'.  */
-  if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
+  if (!cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"))
     {
       /* If there is additional (erroneous) input, skip to the end of
         the statement.  */
@@ -2680,7 +2716,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)
@@ -2688,7 +2725,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);
@@ -2861,11 +2898,11 @@ static tree
 cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
 {
   tree value;
-  bool wide = false;
   size_t count;
   struct obstack str_ob;
   cpp_string str, istr, *strs;
   cp_token *tok;
+  enum cpp_ttype type;
 
   tok = cp_lexer_peek_token (parser->lexer);
   if (!cp_parser_is_string_literal (tok))
@@ -2874,6 +2911,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
       return error_mark_node;
     }
 
+  type = tok->type;
+
   /* Try to avoid the overhead of creating and destroying an obstack
      for the common case of just one string.  */
   if (!cp_parser_is_string_literal
@@ -2884,8 +2923,6 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
       str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
       str.len = TREE_STRING_LENGTH (tok->u.value);
       count = 1;
-      if (tok->type == CPP_WSTRING)
-       wide = true;
 
       strs = &str;
     }
@@ -2900,8 +2937,15 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
          count++;
          str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
          str.len = TREE_STRING_LENGTH (tok->u.value);
-         if (tok->type == CPP_WSTRING)
-           wide = true;
+
+         if (type != tok->type)
+           {
+             if (type == CPP_STRING)
+               type = tok->type;
+             else if (tok->type != CPP_STRING)
+               error ("%Hunsupported non-standard concatenation "
+                       "of string literals", &tok->location);
+           }
 
          obstack_grow (&str_ob, &str, sizeof (cpp_string));
 
@@ -2912,19 +2956,35 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
       strs = (cpp_string *) obstack_finish (&str_ob);
     }
 
-  if (wide && !wide_ok)
+  if (type != CPP_STRING && !wide_ok)
     {
       cp_parser_error (parser, "a wide string is invalid in this context");
-      wide = false;
+      type = CPP_STRING;
     }
 
   if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
-      (parse_in, strs, count, &istr, wide))
+      (parse_in, strs, count, &istr, type))
     {
       value = build_string (istr.len, (const char *)istr.text);
       free (CONST_CAST (unsigned char *, istr.text));
 
-      TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
+      switch (type)
+       {
+       default:
+       case CPP_STRING:
+         TREE_TYPE (value) = char_array_type_node;
+         break;
+       case CPP_STRING16:
+         TREE_TYPE (value) = char16_array_type_node;
+         break;
+       case CPP_STRING32:
+         TREE_TYPE (value) = char32_array_type_node;
+         break;
+       case CPP_WSTRING:
+         TREE_TYPE (value) = wchar_array_type_node;
+         break;
+       }
+
       value = fix_string_type (value);
     }
   else
@@ -3063,7 +3123,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;
@@ -3079,6 +3139,8 @@ cp_parser_primary_expression (cp_parser *parser,
           string-literal
           boolean-literal  */
     case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
     case CPP_WCHAR:
     case CPP_NUMBER:
       token = cp_lexer_consume_token (parser->lexer);
@@ -3130,6 +3192,8 @@ cp_parser_primary_expression (cp_parser *parser,
       return token->u.value;
 
     case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
     case CPP_WSTRING:
       /* ??? Should wide strings be allowed when parser->translate_strings_p
         is false (i.e. in attributes)?  If not, we can kill the third
@@ -3156,8 +3220,8 @@ cp_parser_primary_expression (cp_parser *parser,
            && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
          {
            /* Statement-expressions are not allowed by the standard.  */
-           if (pedantic)
-             pedwarn ("ISO C++ forbids braced-groups within expressions");
+           pedwarn (token->location, OPT_pedantic, 
+                    "ISO C++ forbids braced-groups within expressions");
 
            /* And they're not allowed outside of a function-body; you
               cannot, for example, write:
@@ -3168,8 +3232,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;
              }
@@ -3199,7 +3264,7 @@ cp_parser_primary_expression (cp_parser *parser,
        parser->greater_than_is_operator_p
          = saved_greater_than_is_operator_p;
        /* Consume the `)'.  */
-       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
          cp_parser_skip_to_end_of_statement (parser);
 
        return expr;
@@ -3226,12 +3291,12 @@ 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.  */
-         if (cp_parser_non_integral_constant_expression (parser,
-                                                         "`this'"))
+         if (cp_parser_non_integral_constant_expression (parser, "%<this%>"))
            return error_mark_node;
          return finish_this_expr ();
 
@@ -3243,16 +3308,39 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_FUNCTION_NAME:
        case RID_PRETTY_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
-         /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
-            __func__ are the names of variables -- but they are
-            treated specially.  Therefore, they are handled here,
-            rather than relying on the generic id-expression logic
-            below.  Grammatically, these names are id-expressions.
+         {
+           const char *name;
 
-            Consume the token.  */
-         token = cp_lexer_consume_token (parser->lexer);
-         /* Look up the name.  */
-         return finish_fname (token->u.value);
+           /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
+              __func__ are the names of variables -- but they are
+              treated specially.  Therefore, they are handled here,
+              rather than relying on the generic id-expression logic
+              below.  Grammatically, these names are id-expressions.
+
+              Consume the token.  */
+           token = cp_lexer_consume_token (parser->lexer);
+
+           switch (token->keyword)
+             {
+             case RID_FUNCTION_NAME:
+               name = "%<__FUNCTION__%>";
+               break;
+             case RID_PRETTY_FUNCTION_NAME:
+               name = "%<__PRETTY_FUNCTION__%>";
+               break;
+             case RID_C99_FUNCTION_NAME:
+               name = "%<__func__%>";
+               break;
+             default:
+               gcc_unreachable ();
+             }
+
+           if (cp_parser_non_integral_constant_expression (parser, name))
+             return error_mark_node;
+
+           /* Look up the name.  */
+           return finish_fname (token->u.value);
+         }
 
        case RID_VA_ARG:
          {
@@ -3263,20 +3351,20 @@ cp_parser_primary_expression (cp_parser *parser,
               `va_arg'.  Consume the `__builtin_va_arg' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Look for the opening `('.  */
-           cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+           cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
            /* Now, parse the assignment-expression.  */
            expression = cp_parser_assignment_expression (parser,
                                                          /*cast_p=*/false);
            /* Look for the `,'.  */
-           cp_parser_require (parser, CPP_COMMA, "`,'");
+           cp_parser_require (parser, CPP_COMMA, "%<,%>");
            /* Parse the type-id.  */
            type = cp_parser_type_id (parser);
            /* Look for the closing `)'.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
            /* Using `va_arg' in a constant-expression is not
               allowed.  */
            if (cp_parser_non_integral_constant_expression (parser,
-                                                           "`va_arg'"))
+                                                           "%<va_arg%>"))
              return error_mark_node;
            return build_x_va_arg (expression, type);
          }
@@ -3327,6 +3415,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.  */
@@ -3339,6 +3428,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
@@ -3362,7 +3452,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)
@@ -3409,8 +3500,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;
                  }
              }
@@ -3424,7 +3515,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;
@@ -3708,7 +3800,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);
@@ -3809,8 +3902,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;
          }
@@ -3823,8 +3916,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));
       }
@@ -3866,10 +3959,16 @@ cp_parser_unqualified_id (cp_parser* parser,
 
 /* Parse an (optional) nested-name-specifier.
 
-   nested-name-specifier:
+   nested-name-specifier: [C++98]
      class-or-namespace-name :: nested-name-specifier [opt]
      class-or-namespace-name :: template nested-name-specifier [opt]
 
+   nested-name-specifier: [C++0x]
+     type-name ::
+     namespace-name ::
+     nested-name-specifier identifier ::
+     nested-name-specifier template [opt] simple-template-id ::
+
    PARSER->SCOPE should be set appropriately before this function is
    called.  TYPENAME_KEYWORD_P is TRUE if the `typename' keyword is in
    effect.  TYPE_P is TRUE if we non-type bindings should be ignored
@@ -3944,7 +4043,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
       else
        {
          /* If the next token is not an identifier, then it is
-            definitely not a class-or-namespace-name.  */
+            definitely not a type-name or namespace-name.  */
          if (token->type != CPP_NAME)
            break;
          /* If the following token is neither a `<' (to begin a
@@ -3984,14 +4083,14 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                                               /*only_current_p=*/false);
       /* Parse the qualifying entity.  */
       new_scope
-       = cp_parser_class_or_namespace_name (parser,
-                                            typename_keyword_p,
-                                            template_keyword_p,
-                                            check_dependency_p,
-                                            type_p,
-                                            is_declaration);
+       = cp_parser_qualifying_entity (parser,
+                                       typename_keyword_p,
+                                       template_keyword_p,
+                                       check_dependency_p,
+                                       type_p,
+                                       is_declaration);
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "`::'");
+      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
 
       /* If we found what we wanted, we keep going; otherwise, we're
         done.  */
@@ -4028,20 +4127,27 @@ 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");
+                        {
+                          const char* msg = "is not a class or namespace";
+                          if (cxx_dialect != cxx98)
+                            msg = "is not a class, namespace, or enumeration";
+                          cp_parser_name_lookup_error
+                            (parser, token->u.value, decl, msg,
+                            token->location);
+                        }
                    }
                  parser->scope = error_mark_node;
                  error_p = true;
@@ -4073,10 +4179,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
          && !(TREE_CODE (new_scope) == TYPENAME_TYPE
               && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
                   == TEMPLATE_ID_EXPR)))
-       pedwarn (TYPE_P (new_scope)
-                ? "%qT is not a template"
-                : "%qD is not a template",
-                new_scope);
+       permerror (input_location, TYPE_P (new_scope)
+                  ? "%qT is not a template"
+                  : "%qD is not a template",
+                  new_scope);
       /* If it is a class scope, try to complete it; we are about to
         be looking up names inside the class.  */
       if (TYPE_P (new_scope)
@@ -4160,11 +4266,11 @@ cp_parser_nested_name_specifier (cp_parser *parser,
   return scope;
 }
 
-/* Parse a class-or-namespace-name.
-
-   class-or-namespace-name:
-     class-name
-     namespace-name
+/* Parse the qualifying entity in a nested-name-specifier. For C++98,
+   this is either a class-name or a namespace-name (which corresponds
+   to the class-or-namespace-name production in the grammar). For
+   C++0x, it can also be a type-name that refers to an enumeration
+   type.
 
    TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect.
    TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect.
@@ -4178,18 +4284,19 @@ cp_parser_nested_name_specifier (cp_parser *parser,
    ERROR_MARK_NODE is returned.  */
 
 static tree
-cp_parser_class_or_namespace_name (cp_parser *parser,
-                                  bool typename_keyword_p,
-                                  bool template_keyword_p,
-                                  bool check_dependency_p,
-                                  bool type_p,
-                                  bool is_declaration)
+cp_parser_qualifying_entity (cp_parser *parser,
+                            bool typename_keyword_p,
+                            bool template_keyword_p,
+                            bool check_dependency_p,
+                            bool type_p,
+                            bool is_declaration)
 {
   tree saved_scope;
   tree saved_qualifying_scope;
   tree saved_object_scope;
   tree scope;
   bool only_class_p;
+  bool successful_parse_p;
 
   /* Before we try to parse the class-name, we must save away the
      current PARSER->SCOPE since cp_parser_class_name will destroy
@@ -4199,7 +4306,8 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
   saved_object_scope = parser->object_scope;
   /* Try for a class-name first.  If the SAVED_SCOPE is a type, then
      there is no need to look for a namespace-name.  */
-  only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope));
+  only_class_p = template_keyword_p 
+    || (saved_scope && TYPE_P (saved_scope) && cxx_dialect == cxx98);
   if (!only_class_p)
     cp_parser_parse_tentatively (parser);
   scope = cp_parser_class_name (parser,
@@ -4209,8 +4317,26 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
                                check_dependency_p,
                                /*class_head_p=*/false,
                                is_declaration);
+  successful_parse_p = only_class_p || cp_parser_parse_definitely (parser);
+  /* If that didn't work and we're in C++0x mode, try for a type-name.  */
+  if (!only_class_p 
+      && cxx_dialect != cxx98
+      && !successful_parse_p)
+    {
+      /* Restore the saved scope.  */
+      parser->scope = saved_scope;
+      parser->qualifying_scope = saved_qualifying_scope;
+      parser->object_scope = saved_object_scope;
+
+      /* Parse tentatively.  */
+      cp_parser_parse_tentatively (parser);
+     
+      /* Parse a typedef-name or enum-name.  */
+      scope = cp_parser_nonclass_name (parser);
+      successful_parse_p = cp_parser_parse_definitely (parser);
+    }
   /* If that didn't work, try for a namespace-name.  */
-  if (!only_class_p && !cp_parser_parse_definitely (parser))
+  if (!only_class_p && !successful_parse_p)
     {
       /* Restore the saved scope.  */
       parser->scope = saved_scope;
@@ -4307,18 +4433,18 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
          = "types may not be defined in casts";
 
        /* Look for the opening `<'.  */
-       cp_parser_require (parser, CPP_LESS, "`<'");
+       cp_parser_require (parser, CPP_LESS, "%<<%>");
        /* Parse the type to which we are casting.  */
        type = cp_parser_type_id (parser);
        /* Look for the closing `>'.  */
-       cp_parser_require (parser, CPP_GREATER, "`>'");
+       cp_parser_require (parser, CPP_GREATER, "%<>%>");
        /* Restore the old message.  */
        parser->type_definition_forbidden_message = saved_message;
 
        /* And the expression which is being cast.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        expression = cp_parser_expression (parser, /*cast_p=*/true);
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
        /* Only type conversions to integral or enumeration types
           can be used in constant-expressions.  */
@@ -4363,11 +4489,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
        /* Consume the `typeid' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Look for the `(' token.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Types cannot be defined in a `typeid' expression.  */
        saved_message = parser->type_definition_forbidden_message;
        parser->type_definition_forbidden_message
-         = "types may not be defined in a `typeid\' expression";
+         = "types may not be defined in a %<typeid%> expression";
        /* We can't be sure yet whether we're looking at a type-id or an
           expression.  */
        cp_parser_parse_tentatively (parser);
@@ -4379,7 +4505,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
        /* Look for the `)' token.  Otherwise, we can't be sure that
           we're not looking at an expression: consider `typeid (int
           (3))', for example.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
        /* If all went well, simply lookup the type-id.  */
        if (cp_parser_parse_definitely (parser))
          postfix_expression = get_typeid (type);
@@ -4393,13 +4519,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            /* Compute its typeid.  */
            postfix_expression = build_typeid (expression);
            /* Look for the `)' token.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
          }
        /* Restore the saved message.  */
        parser->type_definition_forbidden_message = saved_message;
        /* `typeid' may not appear in an integral constant expression.  */
        if (cp_parser_non_integral_constant_expression(parser,
-                                                      "`typeid' operator"))
+                                                      "%<typeid%> operator"))
          return error_mark_node;
       }
       break;
@@ -4454,9 +4580,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            type = cp_parser_type_id (parser);
            parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
            /* Look for the `)'.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
            /* Look for the `{'.  */
-           cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+           cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
            /* If things aren't going well, there's no need to
               keep going.  */
            if (!cp_parser_error_occurred (parser))
@@ -4469,7 +4595,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
                  cp_lexer_consume_token (parser->lexer);
                /* Look for the final `}'.  */
-               cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+               cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
              }
            /* If that worked, we're definitely looking at a
               compound-literal expression.  */
@@ -4477,8 +4603,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
              {
                /* Warn the user that a compound literal is not
                   allowed in standard C++.  */
-               if (pedantic)
-                 pedwarn ("ISO C++ forbids compound-literals");
+               pedwarn (input_location, OPT_pedantic, "ISO C++ forbids compound-literals");
                /* For simplicity, we disallow compound literals in
                   constant-expressions.  We could
                   allow compound literals of integer type, whose
@@ -4496,7 +4621,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                  }
                /* Form the representation of the compound-literal.  */
                postfix_expression
-                 = finish_compound_literal (type, initializer_list);
+                 = (finish_compound_literal
+                    (type, build_constructor (init_list_type_node,
+                                              initializer_list)));
                break;
              }
          }
@@ -4675,6 +4802,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                                    koenig_p,
                                    tf_warning_or_error);
 
+            if (warn_disallowed_functions)
+              warn_if_disallowed_function_p (postfix_expression);
+
            /* The POSTFIX_EXPRESSION is certainly no longer an id.  */
            idk = CP_ID_KIND_NONE;
          }
@@ -4693,7 +4823,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;
@@ -4775,7 +4906,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
     index = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* Look for the closing `]'.  */
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
 
   /* Build the ARRAY_REF.  */
   postfix_expression = grok_array_decl (postfix_expression, index);
@@ -4807,7 +4938,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;
@@ -4839,7 +4971,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
@@ -4895,6 +5027,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,
@@ -4922,7 +5055,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
@@ -4955,7 +5088,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
      constant-expressions.  */
   if (!for_offsetof
       && (cp_parser_non_integral_constant_expression
-         (parser, token_type == CPP_DEREF ? "'->'" : "`.'")))
+         (parser, token_type == CPP_DEREF ? "%<->%>" : "%<.%>")))
     postfix_expression = error_mark_node;
 
   return postfix_expression;
@@ -5003,7 +5136,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
   if (non_constant_p)
     *non_constant_p = false;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return error_mark_node;
 
   /* Within a parenthesized expression, a `>' token is always
@@ -5032,10 +5165,19 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
          }
        else
          {
+           bool expr_non_constant_p;
+
            /* Parse the next assignment-expression.  */
-           if (non_constant_p)
+           if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+             {
+               /* A braced-init-list.  */
+               maybe_warn_cpp0x ("extended initializer lists");
+               expr = cp_parser_braced_list (parser, &expr_non_constant_p);
+               if (non_constant_p && expr_non_constant_p)
+                 *non_constant_p = true;
+             }
+           else if (non_constant_p)
              {
-               bool expr_non_constant_p;
                expr = (cp_parser_constant_expression
                        (parser, /*allow_non_constant_p=*/true,
                         &expr_non_constant_p));
@@ -5083,7 +5225,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
        cp_lexer_consume_token (parser->lexer);
       }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     {
       int ending;
 
@@ -5145,7 +5287,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
                                            /*typename_keyword_p=*/false,
                                            /*check_dependency_p=*/true,
                                            /*type_p=*/false,
-                                           /*is_declaration=*/true)
+                                           /*is_declaration=*/false)
        != NULL_TREE);
   /* Now, if we saw a nested-name-specifier, we might be doing the
      second production.  */
@@ -5160,7 +5302,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
                             /*check_dependency_p=*/false,
                             /*is_declaration=*/true);
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "`::'");
+      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
     }
   /* If the next token is not a `~', then there might be some
      additional qualification.  */
@@ -5186,13 +5328,13 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
        return;
 
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "`::'");
+      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
     }
   else
     *scope = NULL_TREE;
 
   /* Look for the `~'.  */
-  cp_parser_require (parser, CPP_COMPL, "`~'");
+  cp_parser_require (parser, CPP_COMPL, "%<~%>");
   /* Look for the type-name again.  We are not responsible for
      checking that it matches the first type-name.  */
   *type = cp_parser_nonclass_name (parser);
@@ -5338,13 +5480,14 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
        {
          tree identifier;
          tree expression;
+         location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
          /* Consume the '&&' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Look for the identifier.  */
          identifier = cp_parser_identifier (parser);
          /* Create an expression representing the address.  */
-         expression = finish_label_address_expr (identifier);
+         expression = finish_label_address_expr (identifier, loc);
          if (cp_parser_non_integral_constant_expression (parser,
                                                "the address of a label"))
            expression = error_mark_node;
@@ -5368,13 +5511,13 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
       switch (unary_operator)
        {
        case INDIRECT_REF:
-         non_constant_p = "`*'";
+         non_constant_p = "%<*%>";
          expression = build_x_indirect_ref (cast_expression, "unary *",
                                              tf_warning_or_error);
          break;
 
        case ADDR_EXPR:
-         non_constant_p = "`&'";
+         non_constant_p = "%<&%>";
          /* Fall through.  */
        case BIT_NOT_EXPR:
          expression = build_x_unary_op (unary_operator, cast_expression,
@@ -5384,7 +5527,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
        case PREINCREMENT_EXPR:
        case PREDECREMENT_EXPR:
          non_constant_p = (unary_operator == PREINCREMENT_EXPR
-                           ? "`++'" : "`--'");
+                           ? "%<++%>" : "%<--%>");
          /* Fall through.  */
        case UNARY_PLUS_EXPR:
        case NEGATE_EXPR:
@@ -5462,7 +5605,7 @@ cp_parser_new_expression (cp_parser* parser)
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `new' operator.  */
-  cp_parser_require_keyword (parser, RID_NEW, "`new'");
+  cp_parser_require_keyword (parser, RID_NEW, "%<new%>");
   /* There's no easy way to tell a new-placement from the
      `( type-id )' construct.  */
   cp_parser_parse_tentatively (parser);
@@ -5476,19 +5619,23 @@ 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, "`)'");
+      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");
-         inform ("try removing the parentheses around the type-id");
+         error ("%Harray bound forbidden after parenthesized type-id",
+                &token->location);
+         inform (token->location, 
+                 "try removing the parentheses around the type-id");
          cp_parser_direct_new_declarator (parser);
        }
       nelts = NULL_TREE;
@@ -5497,15 +5644,16 @@ cp_parser_new_expression (cp_parser* parser)
   else
     type = cp_parser_new_type_id (parser, &nelts);
 
-  /* If the next token is a `(', then we have a new-initializer.  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+  /* If the next token is a `(' or '{', then we have a new-initializer.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+      || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     initializer = cp_parser_new_initializer (parser);
   else
     initializer = NULL_TREE;
 
   /* A new-expression may not appear in an integral constant
      expression.  */
-  if (cp_parser_non_integral_constant_expression (parser, "`new'"))
+  if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
     return error_mark_node;
 
   /* Create a representation of the new-expression.  */
@@ -5660,10 +5808,11 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       tree expression;
 
       /* Look for the opening `['.  */
-      cp_parser_require (parser, CPP_OPEN_SQUARE, "`['");
+      cp_parser_require (parser, CPP_OPEN_SQUARE, "%<[%>");
       /* 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
@@ -5679,8 +5828,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;
                }
            }
@@ -5692,7 +5841,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
                                           /*allow_non_constant=*/false,
                                           NULL);
       /* Look for the closing `]'.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
 
       /* Add this bound to the declarator.  */
       declarator = make_array_declarator (declarator, expression);
@@ -5710,6 +5859,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
 
    new-initializer:
      ( expression-list [opt] )
+     braced-init-list
 
    Returns a representation of the expression-list.  If there is no
    expression-list, VOID_ZERO_NODE is returned.  */
@@ -5719,9 +5869,18 @@ cp_parser_new_initializer (cp_parser* parser)
 {
   tree expression_list;
 
-  expression_list = (cp_parser_parenthesized_expression_list
-                    (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
-                     /*non_constant_p=*/NULL));
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      bool expr_non_constant_p;
+      maybe_warn_cpp0x ("extended initializer lists");
+      expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
+      expression_list = build_tree_list (NULL_TREE, expression_list);
+    }
+  else
+    expression_list = (cp_parser_parenthesized_expression_list
+                      (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+                       /*non_constant_p=*/NULL));
   if (!expression_list)
     expression_list = void_zero_node;
 
@@ -5749,14 +5908,14 @@ cp_parser_delete_expression (cp_parser* parser)
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `delete' keyword.  */
-  cp_parser_require_keyword (parser, RID_DELETE, "`delete'");
+  cp_parser_require_keyword (parser, RID_DELETE, "%<delete%>");
   /* See if the array syntax is in use.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
     {
       /* Consume the `[' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the `]' token.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
       /* Remember that this is the `[]' construct.  */
       array_p = true;
     }
@@ -5768,12 +5927,67 @@ cp_parser_delete_expression (cp_parser* parser)
 
   /* A delete-expression may not appear in an integral constant
      expression.  */
-  if (cp_parser_non_integral_constant_expression (parser, "`delete'"))
+  if (cp_parser_non_integral_constant_expression (parser, "%<delete%>"))
     return error_mark_node;
 
   return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
 }
 
+/* Returns true if TOKEN may start a cast-expression and false
+   otherwise.  */
+
+static bool
+cp_parser_token_starts_cast_expression (cp_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_COMMA:
+    case CPP_SEMICOLON:
+    case CPP_QUERY:
+    case CPP_COLON:
+    case CPP_CLOSE_SQUARE:
+    case CPP_CLOSE_PAREN:
+    case CPP_CLOSE_BRACE:
+    case CPP_DOT:
+    case CPP_DOT_STAR:
+    case CPP_DEREF:
+    case CPP_DEREF_STAR:
+    case CPP_DIV:
+    case CPP_MOD:
+    case CPP_LSHIFT:
+    case CPP_RSHIFT:
+    case CPP_LESS:
+    case CPP_GREATER:
+    case CPP_LESS_EQ:
+    case CPP_GREATER_EQ:
+    case CPP_EQ_EQ:
+    case CPP_NOT_EQ:
+    case CPP_EQ:
+    case CPP_MULT_EQ:
+    case CPP_DIV_EQ:
+    case CPP_MOD_EQ:
+    case CPP_PLUS_EQ:
+    case CPP_MINUS_EQ:
+    case CPP_RSHIFT_EQ:
+    case CPP_LSHIFT_EQ:
+    case CPP_AND_EQ:
+    case CPP_XOR_EQ:
+    case CPP_OR_EQ:
+    case CPP_XOR:
+    case CPP_OR:
+    case CPP_OR_OR:
+    case CPP_EOF:
+      return false;
+
+      /* '[' may start a primary-expression in obj-c++.  */
+    case CPP_OPEN_SQUARE:
+      return c_dialect_objc ();
+
+    default:
+      return true;
+    }
+}
+
 /* Parse a cast-expression.
 
    cast-expression:
@@ -5845,24 +6059,25 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
          /* Look for the type-id.  */
          type = cp_parser_type_id (parser);
          /* Look for the closing `)'.  */
-         cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+         cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
          parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
        }
 
       /* Restore the saved message.  */
       parser->type_definition_forbidden_message = saved_message;
 
-      /* If ok so far, parse the dependent expression. We cannot be
-        sure it is a cast. Consider `(T ())'.  It is a parenthesized
-        ctor of T, but looks like a cast to function returning T
-        without a dependent expression.  */
-      if (!cp_parser_error_occurred (parser))
-       expr = cp_parser_cast_expression (parser,
-                                         /*address_p=*/false,
-                                         /*cast_p=*/true);
-
-      if (cp_parser_parse_definitely (parser))
+      /* At this point this can only be either a cast or a
+        parenthesized ctor such as `(T ())' that looks like a cast to
+        function returning T.  */
+      if (!cp_parser_error_occurred (parser)
+         && cp_parser_token_starts_cast_expression (cp_lexer_peek_token
+                                                    (parser->lexer)))
        {
+         cp_parser_parse_definitely (parser);
+         expr = cp_parser_cast_expression (parser,
+                                           /*address_p=*/false,
+                                           /*cast_p=*/true);
+
          /* Warn about old-style casts, if so requested.  */
          if (warn_old_style_cast
              && !in_system_header
@@ -5883,6 +6098,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
          expr = build_c_cast (type, expr);
          return expr;
        }
+      else 
+        cp_parser_abort_tentative_parse (parser);
     }
 
   /* If we get here, then it's not a cast, so it must be a
@@ -5970,14 +6187,15 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
  : binops_by_token[token->type].prec)
 
 static tree
-cp_parser_binary_expression (cp_parser* parser, bool cast_p)
+cp_parser_binary_expression (cp_parser* parser, bool cast_p,
+                            enum cp_parser_prec prec)
 {
   cp_parser_expression_stack stack;
   cp_parser_expression_stack_entry *sp = &stack[0];
   tree lhs, rhs;
   cp_token *token;
   enum tree_code tree_type, lhs_type, rhs_type;
-  enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
+  enum cp_parser_prec new_prec, lookahead_prec;
   bool overloaded_p;
 
   /* Parse the first expression.  */
@@ -6068,6 +6286,13 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
        }
 
       overloaded_p = false;
+      /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
+        ERROR_MARK for everything that is not a binary expression.
+        This makes warn_about_parentheses miss some warnings that
+        involve unary operators.  For unary expressions we should
+        pass the correct tree_code unless the unary expression was
+        surrounded by parentheses.
+      */
       lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
                               &overloaded_p, tf_warning_or_error);
       lhs_type = tree_type;
@@ -6118,7 +6343,7 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
     expr = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* The next token should be a `:'.  */
-  cp_parser_require (parser, CPP_COLON, "`:'");
+  cp_parser_require (parser, CPP_COLON, "%<:%>");
   /* Parse the assignment-expression.  */
   assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false);
 
@@ -6154,7 +6379,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
   else
     {
       /* Parse the binary expressions (logical-or-expression).  */
-      expr = cp_parser_binary_expression (parser, cast_p);
+      expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR);
       /* If the next token is a `?' then we're actually looking at a
         conditional-expression.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
@@ -6169,10 +6394,14 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
            = cp_parser_assignment_operator_opt (parser);
          if (assignment_operator != ERROR_MARK)
            {
-             tree rhs;
+             bool non_constant_p;
 
              /* Parse the right-hand side of the assignment.  */
-             rhs = cp_parser_assignment_expression (parser, cast_p);
+             tree rhs = cp_parser_initializer_clause (parser, &non_constant_p);
+
+             if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
+               maybe_warn_cpp0x ("extended initializer lists");
+
              /* An assignment may not appear in a
                 constant-expression.  */
              if (cp_parser_non_integral_constant_expression (parser,
@@ -6213,7 +6442,7 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
   enum tree_code op;
   cp_token *token;
 
-  /* Peek at the next toen.  */
+  /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   switch (token->type)
@@ -6406,6 +6635,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
@@ -6416,11 +6646,12 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   /* Consume the "__builtin_offsetof" token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Consume the opening `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   /* Parse the type-id.  */
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
-  cp_parser_require (parser, CPP_COMMA, "`,'");
+  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,
@@ -6428,10 +6659,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:
@@ -6443,7 +6674,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:
@@ -6454,7 +6686,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
        default:
          /* Error.  We know the following require will fail, but
             that gives the proper error message.  */
-         cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+         cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
          cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
          expr = error_mark_node;
          goto failure;
@@ -6548,7 +6780,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
   /* Consume the token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
   type1 = cp_parser_type_id (parser);
 
@@ -6565,7 +6797,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 
   if (binary)
     {
-      cp_parser_require (parser, CPP_COMMA, "`,'");
+      cp_parser_require (parser, CPP_COMMA, "%<,%>");
  
       type2 = cp_parser_type_id (parser);
 
@@ -6581,7 +6813,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
                              /*initialized=*/0, /*attrlist=*/NULL);
     }
 
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   /* Complete the trait expression, which may mean either processing
      the trait expr now or saving it for template instantiation.  */
@@ -6805,7 +7037,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;
 
@@ -6816,7 +7049,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:
@@ -6826,7 +7059,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
     }
 
   /* Require the `:' token.  */
-  cp_parser_require (parser, CPP_COLON, "`:'");
+  cp_parser_require (parser, CPP_COLON, "%<:%>");
 }
 
 /* Parse an expression-statement.
@@ -6888,7 +7121,7 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   tree compound_stmt;
 
   /* Consume the `{'.  */
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
     return error_mark_node;
   /* Begin the compound-statement.  */
   compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
@@ -6900,7 +7133,7 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   /* Finish the compound-statement.  */
   finish_compound_stmt (compound_stmt);
   /* Consume the `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 
   return compound_stmt;
 }
@@ -6934,7 +7167,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);
            }
        }
 
@@ -6980,7 +7213,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
        tree condition;
 
        /* Look for the `('.  */
-       if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+       if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
          {
            cp_parser_skip_to_end_of_statement (parser);
            return error_mark_node;
@@ -6995,7 +7228,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        /* Look for the `)'.  */
-       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
          cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                                 /*consume_paren=*/true);
 
@@ -7010,7 +7243,18 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
            /* Parse the then-clause.  */
            in_statement = parser->in_statement;
            parser->in_statement |= IN_IF_STMT;
-           cp_parser_implicitly_scoped_statement (parser, &nested_if);
+           if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+             {
+               location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+               add_stmt (build_empty_stmt ());
+               cp_lexer_consume_token (parser->lexer);
+               if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
+                 warning_at (loc, OPT_Wempty_body, "suggest braces around "
+                             "empty body in an %<if%> statement");
+               nested_if = false;
+             }
+           else
+             cp_parser_implicitly_scoped_statement (parser, &nested_if);
            parser->in_statement = in_statement;
 
            finish_then_clause (statement);
@@ -7023,7 +7267,17 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
                cp_lexer_consume_token (parser->lexer);
                begin_else_clause (statement);
                /* Parse the else-clause.  */
-               cp_parser_implicitly_scoped_statement (parser, NULL);
+               if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+                 {
+                   warning_at (cp_lexer_peek_token (parser->lexer)->location,
+                               OPT_Wempty_body, "suggest braces around "
+                               "empty body in an %<else%> statement");
+                   add_stmt (build_empty_stmt ());
+                   cp_lexer_consume_token (parser->lexer);
+                 }
+               else
+                 cp_parser_implicitly_scoped_statement (parser, NULL);
+
                finish_else_clause (statement);
 
                /* If we are currently parsing a then-clause, then
@@ -7085,7 +7339,8 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
 
    condition:
      expression
-     type-specifier-seq declarator = assignment-expression
+     type-specifier-seq declarator = initializer-clause
+     type-specifier-seq declarator braced-init-list
 
    GNU Extension:
 
@@ -7131,31 +7386,47 @@ cp_parser_condition (cp_parser* parser)
       attributes = cp_parser_attributes_opt (parser);
       /* Parse the asm-specification.  */
       asm_specification = cp_parser_asm_specification_opt (parser);
-      /* If the next token is not an `=', then we might still be
+      /* If the next token is not an `=' or '{', then we might still be
         looking at an expression.  For example:
 
           if (A(a).x)
 
         looks like a decl-specifier-seq and a declarator -- but then
         there is no `=', so this is an expression.  */
-      cp_parser_require (parser, CPP_EQ, "`='");
-      /* If we did see an `=', then we are looking at a declaration
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
+         && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+       cp_parser_simulate_error (parser);
+       
+      /* If we did see an `=' or '{', then we are looking at a declaration
         for sure.  */
       if (cp_parser_parse_definitely (parser))
        {
          tree pushed_scope;
          bool non_constant_p;
+         bool flags = LOOKUP_ONLYCONVERTING;
 
          /* Create the declaration.  */
          decl = start_decl (declarator, &type_specifiers,
                             /*initialized_p=*/true,
                             attributes, /*prefix_attributes=*/NULL_TREE,
                             &pushed_scope);
-         /* Parse the assignment-expression.  */
-         initializer
-           = cp_parser_constant_expression (parser,
-                                            /*allow_non_constant_p=*/true,
-                                            &non_constant_p);
+
+         /* Parse the initializer.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+           {
+             initializer = cp_parser_braced_list (parser, &non_constant_p);
+             CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1;
+             flags = 0;
+           }
+         else
+           {
+             /* Consume the `='.  */
+             cp_parser_require (parser, CPP_EQ, "%<=%>");
+             initializer = cp_parser_initializer_clause (parser, &non_constant_p);
+           }
+         if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
+           maybe_warn_cpp0x ("extended initializer lists");
+
          if (!non_constant_p)
            initializer = fold_non_dependent_expr (initializer);
 
@@ -7163,7 +7434,7 @@ cp_parser_condition (cp_parser* parser)
          cp_finish_decl (decl,
                          initializer, !non_constant_p,
                          asm_specification,
-                         LOOKUP_ONLYCONVERTING);
+                         flags);
 
          if (pushed_scope)
            pop_scope (pushed_scope);
@@ -7180,48 +7451,6 @@ cp_parser_condition (cp_parser* parser)
   return cp_parser_expression (parser, /*cast_p=*/false);
 }
 
-/* We check for a ) immediately followed by ; with no whitespacing
-   between.  This is used to issue a warning for:
-
-     while (...);
-
-   and:
-
-     for (...);
-
-   as the semicolon is probably extraneous.
-
-   On parse errors, the next token might not be a ), so do nothing in
-   that case. */
-
-static void
-check_empty_body (cp_parser* parser, const char* type)
-{
-  cp_token *token;
-  cp_token *close_paren;
-  expanded_location close_loc;
-  expanded_location semi_loc;
-  
-  close_paren = cp_lexer_peek_token (parser->lexer);
-  if (close_paren->type != CPP_CLOSE_PAREN)
-    return;
-
-  close_loc = expand_location (close_paren->location);
-  token = cp_lexer_peek_nth_token (parser->lexer, 2);
-
-  if (token->type != CPP_SEMICOLON
-      || (token->flags & PREV_WHITE))
-    return;
-
-  semi_loc =  expand_location (token->location);
-  if (close_loc.line == semi_loc.line
-      && close_loc.column+1 == semi_loc.column)
-    warning (OPT_Wempty_body,
-            "suggest a space before %<;%> or explicit braces around empty "
-            "body in %<%s%> statement",
-            type);
-}
-
 /* Parse an iteration-statement.
 
    iteration-statement:
@@ -7260,13 +7489,12 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Begin the while-statement.  */
        statement = begin_while_stmt ();
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        finish_while_stmt_cond (condition, statement);
-       check_empty_body (parser, "while");
        /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
        /* Parse the dependent statement.  */
        parser->in_statement = IN_ITERATION_STMT;
        cp_parser_already_scoped_statement (parser);
@@ -7288,17 +7516,17 @@ cp_parser_iteration_statement (cp_parser* parser)
        parser->in_statement = in_statement;
        finish_do_body (statement);
        /* Look for the `while' keyword.  */
-       cp_parser_require_keyword (parser, RID_WHILE, "`while'");
+       cp_parser_require_keyword (parser, RID_WHILE, "%<while%>");
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Parse the expression.  */
        expression = cp_parser_expression (parser, /*cast_p=*/false);
        /* We're done with the do-statement.  */
        finish_do_stmt (expression, statement);
        /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
        /* Look for the `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       }
       break;
 
@@ -7310,7 +7538,7 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Begin the for-statement.  */
        statement = begin_for_stmt ();
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Parse the initialization.  */
        cp_parser_for_init_statement (parser);
        finish_for_init_stmt (statement);
@@ -7320,15 +7548,14 @@ cp_parser_iteration_statement (cp_parser* parser)
          condition = cp_parser_condition (parser);
        finish_for_cond (condition, statement);
        /* Look for the `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
        /* If there's an expression, process it.  */
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
          expression = cp_parser_expression (parser, /*cast_p=*/false);
        finish_for_expr (expression, statement);
-       check_empty_body (parser, "for");
        /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
        /* Parse the body of the for-statement.  */
        parser->in_statement = IN_ITERATION_STMT;
@@ -7387,6 +7614,7 @@ cp_parser_for_init_statement (cp_parser* parser)
      break ;
      continue ;
      return expression [opt] ;
+     return braced-init-list ;
      goto identifier ;
 
    GNU extension:
@@ -7418,7 +7646,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)
@@ -7426,10 +7654,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, "%<;%>");
@@ -7439,14 +7667,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 ();
@@ -7457,12 +7685,18 @@ cp_parser_jump_statement (cp_parser* parser)
     case RID_RETURN:
       {
        tree expr;
+       bool expr_non_constant_p;
 
-       /* If the next token is a `;', then there is no
-          expression.  */
-       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+         {
+           maybe_warn_cpp0x ("extended initializer lists");
+           expr = cp_parser_braced_list (parser, &expr_non_constant_p);
+         }
+       else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
          expr = cp_parser_expression (parser, /*cast_p=*/false);
        else
+         /* If the next token is a `;', then there is no
+            expression.  */
          expr = NULL_TREE;
        /* Build the return-statement.  */
        statement = finish_return_stmt (expr);
@@ -7476,8 +7710,7 @@ cp_parser_jump_statement (cp_parser* parser)
       if (cp_lexer_next_token_is (parser->lexer, CPP_MULT))
        {
          /* Issue a warning about this use of a GNU extension.  */
-         if (pedantic)
-           pedwarn ("ISO C++ forbids computed gotos");
+         pedwarn (token->location, OPT_pedantic, "ISO C++ forbids computed gotos");
          /* Consume the '*' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Parse the dependent expression.  */
@@ -7583,9 +7816,9 @@ cp_parser_already_scoped_statement (cp_parser* parser)
     {
       /* Avoid calling cp_parser_compound_statement, so that we
         don't create a new scope.  Do everything else by hand.  */
-      cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+      cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
       cp_parser_statement_seq_opt (parser, NULL_TREE);
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
     }
 }
 
@@ -7616,8 +7849,8 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
          /* A declaration consisting of a single semicolon is
             invalid.  Allow it unless we're being pedantic.  */
          cp_lexer_consume_token (parser->lexer);
-         if (pedantic && !in_system_header)
-           pedwarn ("extra %<;%>");
+         if (!in_system_header)
+           pedwarn (input_location, OPT_pedantic, "extra %<;%>");
          continue;
        }
 
@@ -7838,7 +8071,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))
@@ -7925,7 +8158,9 @@ cp_parser_simple_declaration (cp_parser* parser,
      is not a parenthesis, then we must be looking at a declaration.
      (After "int (" we might be looking at a functional cast.)  */
   if (decl_specifiers.any_specifiers_p
-      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
+      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)
+      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
+      && !cp_parser_error_occurred (parser))
     cp_parser_commit_to_tentative_parse (parser);
 
   /* Keep going until we hit the `;' at the end of the simple
@@ -7971,7 +8206,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
            {
@@ -8023,7 +8262,7 @@ cp_parser_simple_declaration (cp_parser* parser,
     }
 
   /* Consume the `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
  done:
   pop_deferring_access_checks ();
@@ -8067,6 +8306,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);
@@ -8083,6 +8323,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)
        {
@@ -8150,24 +8395,25 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
             GNU Extension:
               thread  */
        case RID_AUTO:
-          /* Consume the token.  */
-          cp_lexer_consume_token (parser->lexer);
-
           if (cxx_dialect == cxx98) 
             {
+             /* Consume the token.  */
+             cp_lexer_consume_token (parser->lexer);
+
               /* Complain about `auto' as a storage specifier, if
                  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");
+          else
+           /* C++0x auto type-specifier.  */
+           found_decl_spec = false;
           break;
 
        case RID_REGISTER:
@@ -8176,7 +8422,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.  */
@@ -8212,7 +8459,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
@@ -8272,12 +8518,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.
@@ -8333,7 +8580,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)
@@ -8345,7 +8593,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;
@@ -8375,7 +8623,7 @@ cp_parser_linkage_specification (cp_parser* parser)
   tree linkage;
 
   /* Look for the `extern' keyword.  */
-  cp_parser_require_keyword (parser, RID_EXTERN, "`extern'");
+  cp_parser_require_keyword (parser, RID_EXTERN, "%<extern%>");
 
   /* Look for the string-literal.  */
   linkage = cp_parser_string_literal (parser, false, false);
@@ -8405,7 +8653,7 @@ cp_parser_linkage_specification (cp_parser* parser)
       /* Parse the declarations.  */
       cp_parser_declaration_seq_opt (parser);
       /* Look for the closing `}'.  */
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
     }
   /* Otherwise, there's just one declaration.  */
   else
@@ -8446,7 +8694,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
 
   /* Look for the `static_assert' keyword.  */
   if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, 
-                                  "`static_assert'"))
+                                  "%<static_assert%>"))
     return;
 
   /*  We know we are in a static assertion; commit to any tentative
@@ -8455,7 +8703,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
     cp_parser_commit_to_tentative_parse (parser);
 
   /* Parse the `(' starting the static assertion condition.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
   /* Parse the constant-expression.  */
   condition = 
@@ -8464,7 +8712,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
                                    /*non_constant_p=*/NULL);
 
   /* Parse the separating `,'.  */
-  cp_parser_require (parser, CPP_COMMA, "`,'");
+  cp_parser_require (parser, CPP_COMMA, "%<,%>");
 
   /* Parse the string-literal message.  */
   message = cp_parser_string_literal (parser, 
@@ -8472,14 +8720,14 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
                                       /*wide_ok=*/true);
 
   /* A `)' completes the static assertion.  */
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, 
                                            /*recovering=*/true, 
                                            /*or_comma=*/false,
                                           /*consume_paren=*/true);
 
   /* A semicolon terminates the declaration.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
   /* Complete the static assertion, which may mean either processing 
      the static assert now or saving it for template instantiation.  */
@@ -8499,9 +8747,10 @@ 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'"))
+  if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
     return error_mark_node;
 
   /* Types cannot be defined in a `decltype' expression.  Save away the
@@ -8510,7 +8759,7 @@ cp_parser_decltype (cp_parser *parser)
 
   /* And create the new one.  */
   parser->type_definition_forbidden_message
-    = "types may not be defined in `decltype' expressions";
+    = "types may not be defined in %<decltype%> expressions";
 
   /* The restrictions on constant-expressions do not apply inside
      decltype expressions.  */
@@ -8524,10 +8773,11 @@ cp_parser_decltype (cp_parser *parser)
   ++skip_evaluation;
 
   /* Parse the opening `('.  */
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     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,
@@ -8550,7 +8800,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
@@ -8570,7 +8821,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
@@ -8641,7 +8893,7 @@ cp_parser_decltype (cp_parser *parser)
     }
   
   /* Parse to the closing `)'.  */
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     {
       cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                             /*consume_paren=*/true);
@@ -8670,7 +8922,7 @@ cp_parser_conversion_function_id (cp_parser* parser)
   tree pushed_scope = NULL_TREE;
 
   /* Look for the `operator' token.  */
-  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'"))
+  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%<operator%>"))
     return error_mark_node;
   /* When we parse the conversion-type-id, the current scope will be
      reset.  However, we need that information in able to look up the
@@ -8738,6 +8990,16 @@ cp_parser_conversion_type_id (cp_parser* parser)
                                    /*initialized=*/0, &attributes);
   if (attributes)
     cplus_decl_attributes (&type_specified, attributes, /*flags=*/0);
+
+  /* Don't give this error when parsing tentatively.  This happens to
+     work because we always parse this definitively once.  */
+  if (! cp_parser_uncommitted_to_tentative_parse_p (parser)
+      && type_uses_auto (type_specified))
+    {
+      error ("invalid use of %<auto%> in conversion operator");
+      return error_mark_node;
+    }
+
   return type_specified;
 }
 
@@ -8813,17 +9075,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. */
@@ -8837,8 +9102,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;
             }
 
@@ -8868,6 +9133,7 @@ cp_parser_mem_initializer_list (cp_parser* parser)
 
    mem-initializer:
      mem-initializer-id ( expression-list [opt] )
+     mem-initializer-id braced-init-list
 
    GNU extension:
 
@@ -8885,11 +9151,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");
+      permerror (token->location,
+                "anachronistic old-style base class initializer");
       mem_initializer_id = NULL_TREE;
     }
   else
@@ -8898,11 +9166,20 @@ cp_parser_mem_initializer (cp_parser* parser)
   if (member && !DECL_P (member))
     in_base_initializer = 1;
 
-  expression_list
-    = cp_parser_parenthesized_expression_list (parser, false,
-                                              /*cast_p=*/false,
-                                               /*allow_expansion_p=*/true,
-                                              /*non_constant_p=*/NULL);
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      bool expr_non_constant_p;
+      maybe_warn_cpp0x ("extended initializer lists");
+      expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
+      expression_list = build_tree_list (NULL_TREE, expression_list);
+    }
+  else
+    expression_list
+      = cp_parser_parenthesized_expression_list (parser, false,
+                                                /*cast_p=*/false,
+                                                /*allow_expansion_p=*/true,
+                                                /*non_constant_p=*/NULL);
   if (expression_list == error_mark_node)
     return error_mark_node;
   if (!expression_list)
@@ -8931,11 +9208,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.  */
@@ -9005,7 +9285,7 @@ static tree
 cp_parser_operator_function_id (cp_parser* parser)
 {
   /* Look for the `operator' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'"))
+  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%<operator%>"))
     return error_mark_node;
   /* And then the name of the operator itself.  */
   return cp_parser_operator (parser);
@@ -9061,7 +9341,7 @@ cp_parser_operator (cp_parser* parser)
            /* Consume the `[' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Look for the `]' token.  */
-           cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+           cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
            id = ansi_opname (op == NEW_EXPR
                              ? VEC_NEW_EXPR : VEC_DELETE_EXPR);
          }
@@ -9220,14 +9500,14 @@ cp_parser_operator (cp_parser* parser)
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
       return ansi_opname (CALL_EXPR);
 
     case CPP_OPEN_SQUARE:
       /* Consume the `['.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `]'.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
       return ansi_opname (ARRAY_REF);
 
     default:
@@ -9303,7 +9583,6 @@ cp_parser_template_parameter_list (cp_parser* parser)
   while (true)
     {
       tree parameter;
-      cp_token *token;
       bool is_non_type;
       bool is_parameter_pack;
 
@@ -9324,10 +9603,8 @@ cp_parser_template_parameter_list (cp_parser* parser)
          parameter_list = chainon (parameter_list, err_parm);
        }
 
-      /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If it's not a `,', we're done.  */
-      if (token->type != CPP_COMMA)
+      /* If the next token is not a `,', we're done.  */
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
        break;
       /* Otherwise, consume the `,' token.  */
       cp_lexer_consume_token (parser->lexer);
@@ -9455,6 +9732,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.  */     
@@ -9463,10 +9741,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);
@@ -9513,7 +9792,7 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 
   /* Look for a keyword to tell us what kind of parameter this is.  */
   token = cp_parser_require (parser, CPP_KEYWORD,
-                            "`class', `typename', or `template'");
+                            "%<class%>, %<typename%>, or %<template%>");
   if (!token)
     return error_mark_node;
 
@@ -9560,10 +9839,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 ();
@@ -9584,13 +9864,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
        tree default_argument;
 
        /* Look for the `<'.  */
-       cp_parser_require (parser, CPP_LESS, "`<'");
+       cp_parser_require (parser, CPP_LESS, "%<<%>");
        /* Parse the template-parameter-list.  */
        parameter_list = cp_parser_template_parameter_list (parser);
        /* Look for the `>'.  */
-       cp_parser_require (parser, CPP_GREATER, "`>'");
+       cp_parser_require (parser, CPP_GREATER, "%<>%>");
        /* Look for the `class' keyword.  */
-       cp_parser_require_keyword (parser, RID_CLASS, "`class'");
+       cp_parser_require_keyword (parser, RID_CLASS, "%<class%>");
         /* If the next token is an ellipsis, we have a template
            argument pack. */
         if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
@@ -9631,6 +9911,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,
@@ -9651,7 +9934,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);
@@ -9661,10 +9945,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 ();
@@ -9707,13 +9994,13 @@ cp_parser_template_id (cp_parser *parser,
                       bool is_declaration)
 {
   int i;
-  tree template;
+  tree templ;
   tree arguments;
   tree template_id;
   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
@@ -9761,14 +10048,15 @@ cp_parser_template_id (cp_parser *parser,
 
   /* Parse the template-name.  */
   is_identifier = false;
-  template = cp_parser_template_name (parser, template_keyword_p,
-                                     check_dependency_p,
-                                     is_declaration,
-                                     &is_identifier);
-  if (template == error_mark_node || is_identifier)
+  token = cp_lexer_peek_token (parser->lexer);
+  templ = cp_parser_template_name (parser, template_keyword_p,
+                                  check_dependency_p,
+                                  is_declaration,
+                                  &is_identifier);
+  if (templ == error_mark_node || is_identifier)
     {
       pop_deferring_access_checks ();
-      return template;
+      return templ;
     }
 
   /* If we find the sequence `[:' after a template-name, it's probably
@@ -9787,6 +10075,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))
@@ -9801,15 +10090,17 @@ 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 %<::%>");
-      if (!flag_permissive)
+      if (permerror (next_token->location,
+                    "%<<::%> cannot begin a template-argument list"))
        {
-         static bool hint;
-         if (!hint)
+         static bool hint = false;
+         inform (next_token->location,
+                 "%<<:%> is an alternate spelling for %<[%>."
+                 " Insert whitespace between %<<%> and %<::%>");
+         if (!hint && !flag_permissive)
            {
-             inform ("(if you use -fpermissive G++ will accept your code)");
+             inform (next_token->location, "(if you use %<-fpermissive%>"
+                     " G++ will accept your code)");
              hint = true;
            }
        }
@@ -9817,7 +10108,7 @@ cp_parser_template_id (cp_parser *parser,
   else
     {
       /* Look for the `<' that starts the template-argument-list.  */
-      if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+      if (!cp_parser_require (parser, CPP_LESS, "%<<%>"))
        {
          pop_deferring_access_checks ();
          return error_mark_node;
@@ -9827,10 +10118,10 @@ cp_parser_template_id (cp_parser *parser,
     }
 
   /* Build a representation of the specialization.  */
-  if (TREE_CODE (template) == IDENTIFIER_NODE)
-    template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
-  else if (DECL_CLASS_TEMPLATE_P (template)
-          || DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+  if (TREE_CODE (templ) == IDENTIFIER_NODE)
+    template_id = build_min_nt (TEMPLATE_ID_EXPR, templ, arguments);
+  else if (DECL_CLASS_TEMPLATE_P (templ)
+          || DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
     {
       bool entering_scope;
       /* In "template <typename T> ... A<T>::", A<T> is the abstract A
@@ -9842,17 +10133,17 @@ cp_parser_template_id (cp_parser *parser,
                        && cp_lexer_next_token_is (parser->lexer,
                                                   CPP_SCOPE));
       template_id
-       = finish_template_type (template, arguments, entering_scope);
+       = finish_template_type (templ, arguments, entering_scope);
     }
   else
     {
       /* If it's not a class-template or a template-template, it should be
         a function-template.  */
-      gcc_assert ((DECL_FUNCTION_TEMPLATE_P (template)
-                  || TREE_CODE (template) == OVERLOAD
-                  || BASELINK_P (template)));
+      gcc_assert ((DECL_FUNCTION_TEMPLATE_P (templ)
+                  || TREE_CODE (templ) == OVERLOAD
+                  || BASELINK_P (templ)));
 
-      template_id = lookup_template_function (template, arguments);
+      template_id = lookup_template_function (templ, arguments);
     }
 
   /* If parsing tentatively, replace the sequence of tokens that makes
@@ -9882,7 +10173,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 ();
@@ -9936,6 +10228,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.  */
@@ -9995,8 +10288,9 @@ cp_parser_template_name (cp_parser* parser,
          cp_token_position start = 0;
 
          /* Explain what went wrong.  */
-         error ("non-template %qD used as template", identifier);
-         inform ("use %<%T::template %D%> to indicate that it is a template",
+         error ("%Hnon-template %qD used as template",
+                &token->location, identifier);
+         inform (input_location, "use %<%T::template %D%> to indicate that it is a template",
                  parser->scope, identifier);
          /* If parsing tentatively, find the location of the "<" token.  */
          if (cp_parser_simulate_error (parser))
@@ -10039,7 +10333,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.  */
@@ -10185,7 +10480,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
@@ -10200,9 +10495,10 @@ cp_parser_template_argument (cp_parser* parser)
      Therefore, we try a type-id first.  */
   cp_parser_parse_tentatively (parser);
   argument = cp_parser_type_id (parser);
-  /* If there was no error parsing the type-id but the next token is a '>>',
-     we probably found a typo for '> >'. But there are type-id which are
-     also valid expressions. For instance:
+  /* If there was no error parsing the type-id but the next token is a
+     '>>', our behavior depends on which dialect of C++ we're
+     parsing. In C++98, we probably found a typo for '> >'. But there
+     are type-id which are also valid expressions. For instance:
 
      struct X { int operator >> (int); };
      template <int V> struct Foo {};
@@ -10211,8 +10507,12 @@ cp_parser_template_argument (cp_parser* parser)
      Here 'X()' is a valid type-id of a function type, but the user just
      wanted to write the expression "X() >> 5". Thus, we remember that we
      found a valid type-id, but we still try to parse the argument as an
-     expression to see what happens.  */
+     expression to see what happens. 
+
+     In C++0x, the '>>' will be considered two separate '>'
+     tokens.  */
   if (!cp_parser_error_occurred (parser)
+      && cxx_dialect == cxx98
       && cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
     {
       maybe_type_id = true;
@@ -10232,6 +10532,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,
@@ -10254,7 +10555,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");
@@ -10279,7 +10581,7 @@ cp_parser_template_argument (cp_parser* parser)
     {
       cp_parser_parse_tentatively (parser);
       argument = cp_parser_primary_expression (parser,
-                                              /*adress_p=*/false,
+                                              /*address_p=*/false,
                                               /*cast_p=*/false,
                                               /*template_arg_p=*/true,
                                               &idk);
@@ -10411,6 +10713,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.  */
@@ -10425,7 +10728,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     }
 
   /* Look for the `template' keyword.  */
-  cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
+  cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Let the front end know that we are processing an explicit
      instantiation.  */
   begin_explicit_instantiation ();
@@ -10433,6 +10736,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,
@@ -10465,7 +10769,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,
@@ -10506,12 +10811,14 @@ 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'");
+  cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Look for the `<'.  */
-  cp_parser_require (parser, CPP_LESS, "`<'");
+  cp_parser_require (parser, CPP_LESS, "%<<%>");
   /* Look for the `>'.  */
-  cp_parser_require (parser, CPP_GREATER, "`>'");
+  cp_parser_require (parser, CPP_GREATER, "%<>%>");
   /* We have processed another parameter list.  */
   ++parser->num_template_parameter_lists;
   /* [temp]
@@ -10520,7 +10827,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);
@@ -10635,6 +10942,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;
        }
@@ -10659,6 +10967,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;
        }
@@ -10680,6 +10989,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;
 
@@ -10760,6 +11070,8 @@ cp_parser_type_specifier (cp_parser* parser,
    simple-type-specifier:
      auto
      decltype ( expression )   
+     char16_t
+     char32_t
 
    GNU Extension:
 
@@ -10789,6 +11101,12 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        decl_specs->explicit_char_p = true;
       type = char_type_node;
       break;
+    case RID_CHAR16:
+      type = char16_type_node;
+      break;
+    case RID_CHAR32:
+      type = char32_type_node;
+      break;
     case RID_WCHAR:
       type = wchar_type_node;
       break;
@@ -10831,14 +11149,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       break;
       
     case RID_AUTO:
-      if (cxx_dialect != cxx98)
-        {
-          /* Consume the token.  */
-          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");
-        }
+      maybe_warn_cpp0x ("C++0x auto");
+      type = make_auto ();
       break;
 
     case RID_DECLTYPE:
@@ -10847,6 +11159,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;
@@ -10862,6 +11175,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;
@@ -10883,6 +11197,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;
@@ -10893,7 +11208,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);
     }
@@ -10922,6 +11237,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
@@ -10956,6 +11272,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);
     }
 
@@ -10988,7 +11305,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;
@@ -11050,12 +11368,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)))
@@ -11072,7 +11391,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
@@ -11092,7 +11411,7 @@ cp_parser_nonclass_name (cp_parser* parser)
    elaborated-type-specifier:
      class-key :: [opt] nested-name-specifier [opt] identifier
      class-key :: [opt] nested-name-specifier [opt] template [opt] template-id
-     enum :: [opt] nested-name-specifier [opt] identifier
+     enum-key :: [opt] nested-name-specifier [opt] identifier
      typename :: [opt] nested-name-specifier identifier
      typename :: [opt] nested-name-specifier template [opt]
        template-id
@@ -11121,6 +11440,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))
@@ -11129,6 +11449,17 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       cp_lexer_consume_token (parser->lexer);
       /* Remember that it's an enumeration type.  */
       tag_type = enum_type;
+      /* Parse the optional `struct' or `class' key (for C++0x scoped
+         enums).  */
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS)
+          || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
+        {
+          if (cxx_dialect == cxx98)
+            maybe_warn_cpp0x ("scoped enums");
+
+          /* Consume the `struct' or `class'.  */
+          cp_lexer_consume_token (parser->lexer);
+        }
       /* Parse the attributes.  */
       attributes = cp_parser_attributes_opt (parser);
     }
@@ -11142,7 +11473,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       tag_type = typename_type;
       /* The `typename' keyword is only allowed in templates.  */
       if (!processing_template_decl)
-       pedwarn ("using %<typename%> outside of template");
+       permerror (input_location, "using %<typename%> outside of template");
     }
   /* Otherwise it must be a class-key.  */
   else
@@ -11190,6 +11521,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);
@@ -11211,6 +11543,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)
@@ -11223,7 +11556,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)
        {
@@ -11235,7 +11569,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.  */
@@ -11271,7 +11606,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;
            }
 
@@ -11299,7 +11635,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
              caught elsewhere in parsing.  Those that are pointless arrive
              here.  */
 
-          if (cp_parser_declares_only_class_p (parser)
+          if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
               && !is_friend && !processing_explicit_instantiation)
             warning (0, "declaration %qD does not declare anything", decl);
 
@@ -11371,7 +11707,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);
        }
@@ -11402,7 +11739,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;
 }
@@ -11410,11 +11747,19 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 /* Parse an enum-specifier.
 
    enum-specifier:
-     enum identifier [opt] { enumerator-list [opt] }
+     enum-key identifier [opt] enum-base [opt] { enumerator-list [opt] }
+
+   enum-key:
+     enum
+     enum class   [C++0x]
+     enum struct  [C++0x]
+
+   enum-base:   [C++0x]
+     : type-specifier-seq
 
    GNU Extensions:
-     enum attributes[opt] identifier [opt] { enumerator-list [opt] }
-       attributes[opt]
+     enum-key attributes[opt] identifier [opt] enum-base [opt] 
+       { enumerator-list [opt] }attributes[opt]
 
    Returns an ENUM_TYPE representing the enumeration, or NULL_TREE
    if the token stream isn't an enum-specifier after all.  */
@@ -11425,6 +11770,9 @@ cp_parser_enum_specifier (cp_parser* parser)
   tree identifier;
   tree type;
   tree attributes;
+  bool scoped_enum_p = false;
+  bool has_underlying_type = false;
+  tree underlying_type = NULL_TREE;
 
   /* Parse tentatively so that we can back up if we don't find a
      enum-specifier.  */
@@ -11436,6 +11784,20 @@ cp_parser_enum_specifier (cp_parser* parser)
      the enumeration being defined.  */
   cp_lexer_consume_token (parser->lexer);
 
+  /* Parse the "class" or "struct", which indicates a scoped
+     enumeration type in C++0x.  */
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS)
+      || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
+    {
+      if (cxx_dialect == cxx98)
+        maybe_warn_cpp0x ("scoped enums");
+
+      /* Consume the `struct' or `class' token.  */
+      cp_lexer_consume_token (parser->lexer);
+
+      scoped_enum_p = true;
+    }
+
   attributes = cp_parser_attributes_opt (parser);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
@@ -11443,22 +11805,57 @@ cp_parser_enum_specifier (cp_parser* parser)
   else
     identifier = make_anon_name ();
 
-  /* Look for the `{' but don't consume it yet.  */
-  if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
-    cp_parser_simulate_error (parser);
+  /* Check for the `:' that denotes a specified underlying type in C++0x.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+    {
+      cp_decl_specifier_seq type_specifiers;
 
-  if (!cp_parser_parse_definitely (parser))
-    return NULL_TREE;
+      /* At this point this is surely not elaborated type specifier.  */
+      if (!cp_parser_parse_definitely (parser))
+       return NULL_TREE;
 
-  /* Issue an error message if type-definitions are forbidden here.  */
-  if (!cp_parser_check_type_definition (parser))
-    type = error_mark_node;
-  else
-    /* Create the new type.  We do this before consuming the opening
-       brace so the enum will be recorded as being on the line of its
-       tag (or the 'enum' keyword, if there is no tag).  */
-    type = start_enum (identifier);
-  
+      if (cxx_dialect == cxx98)
+        maybe_warn_cpp0x ("scoped enums");
+
+      /* Consume the `:'.  */
+      cp_lexer_consume_token (parser->lexer);
+
+      has_underlying_type = true;
+
+      /* Parse the type-specifier-seq.  */
+      cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+                                    &type_specifiers);
+
+      /* If that didn't work, stop.  */
+      if (type_specifiers.type != error_mark_node)
+        {
+          underlying_type = grokdeclarator (NULL, &type_specifiers, TYPENAME,
+                                            /*initialized=*/0, NULL);
+          if (underlying_type == error_mark_node)
+            underlying_type = NULL_TREE;
+        }
+    }
+
+  /* Look for the `{' but don't consume it yet.  */
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      cp_parser_error (parser, "expected %<{%>");
+      if (has_underlying_type)
+       return NULL_TREE;
+    }
+
+  if (!has_underlying_type && !cp_parser_parse_definitely (parser))
+    return NULL_TREE;
+
+  /* Issue an error message if type-definitions are forbidden here.  */
+  if (!cp_parser_check_type_definition (parser))
+    type = error_mark_node;
+  else
+    /* Create the new type.  We do this before consuming the opening
+       brace so the enum will be recorded as being on the line of its
+       tag (or the 'enum' keyword, if there is no tag).  */
+    type = start_enum (identifier, underlying_type, scoped_enum_p);
+  
   /* Consume the opening brace.  */
   cp_lexer_consume_token (parser->lexer);
 
@@ -11473,7 +11870,7 @@ cp_parser_enum_specifier (cp_parser* parser)
     cp_parser_enumerator_list (parser, type);
 
   /* Consume the final '}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 
   /* Look for trailing attributes to apply to this enumeration, and
      apply them if appropriate.  */
@@ -11515,8 +11912,8 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
       /* If the next token is a `}', there is a trailing comma.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
        {
-         if (pedantic && !in_system_header)
-           pedwarn ("comma at end of enumerator list");
+         if (!in_system_header)
+           pedwarn (input_location, OPT_pedantic, "comma at end of enumerator list");
          break;
        }
     }
@@ -11574,6 +11971,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)
@@ -11594,7 +11993,7 @@ cp_parser_namespace_name (cp_parser* parser)
        During the lookup of a name preceding the :: scope resolution
        operator, object, function, and enumerator names are ignored.
 
-     (Note that cp_parser_class_or_namespace_name only calls this
+     (Note that cp_parser_qualifying_entity only calls this
      function if the token after the name is the scope resolution
      operator.)  */
   namespace_decl = cp_parser_lookup_name (parser, identifier,
@@ -11602,13 +12001,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;
     }
@@ -11651,7 +12051,7 @@ cp_parser_namespace_definition (cp_parser* parser)
     is_inline = false;
 
   /* Look for the `namespace' keyword.  */
-  cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
 
   /* Get the name of the namespace.  We do not attempt to distinguish
      between an original-namespace-definition and an
@@ -11666,7 +12066,7 @@ cp_parser_namespace_definition (cp_parser* parser)
   attribs = cp_parser_attributes_opt (parser);
 
   /* Look for the `{' to start the namespace.  */
-  cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+  cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
   /* Start the namespace.  */
   push_namespace (identifier);
 
@@ -11674,14 +12074,14 @@ cp_parser_namespace_definition (cp_parser* parser)
      followed by a strong using directive.  */
   if (is_inline)
     {
-      tree namespace = current_namespace;
+      tree name_space = current_namespace;
       /* Set up namespace association.  */
-      DECL_NAMESPACE_ASSOCIATIONS (namespace)
-       = tree_cons (CP_DECL_CONTEXT (namespace), NULL_TREE,
-                    DECL_NAMESPACE_ASSOCIATIONS (namespace));
+      DECL_NAMESPACE_ASSOCIATIONS (name_space)
+       = tree_cons (CP_DECL_CONTEXT (name_space), NULL_TREE,
+                    DECL_NAMESPACE_ASSOCIATIONS (name_space));
       /* Import the contents of the inline namespace.  */
       pop_namespace ();
-      do_using_directive (namespace);
+      do_using_directive (name_space);
       push_namespace (identifier);
     }
 
@@ -11698,7 +12098,7 @@ cp_parser_namespace_definition (cp_parser* parser)
   /* Finish the namespace.  */
   pop_namespace ();
   /* Look for the final `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 }
 
 /* Parse a namespace-body.
@@ -11723,8 +12123,10 @@ 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'");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the identifier.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
@@ -11733,19 +12135,19 @@ 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))
        cp_lexer_consume_token (parser->lexer);
       return;
     }
-  cp_parser_require (parser, CPP_EQ, "`='");
+  cp_parser_require (parser, CPP_EQ, "%<=%>");
   /* Look for the qualified-namespace-specifier.  */
   namespace_specifier
     = cp_parser_qualified_namespace_specifier (parser);
   /* Look for the `;' token.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
   /* Register the alias in the symbol table.  */
   do_namespace_alias (identifier, namespace_specifier);
@@ -11804,7 +12206,7 @@ cp_parser_using_declaration (cp_parser* parser,
   else
     {
       /* Look for the `using' keyword.  */
-      cp_parser_require_keyword (parser, RID_USING, "`using'");
+      cp_parser_require_keyword (parser, RID_USING, "%<using%>");
       
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -11848,6 +12250,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,
@@ -11872,7 +12275,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 ())
@@ -11888,9 +12292,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 ())
@@ -11901,7 +12309,7 @@ cp_parser_using_declaration (cp_parser* parser,
     }
 
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
   
   return true;
 }
@@ -11919,9 +12327,9 @@ cp_parser_using_directive (cp_parser* parser)
   tree attribs;
 
   /* Look for the `using' keyword.  */
-  cp_parser_require_keyword (parser, RID_USING, "`using'");
+  cp_parser_require_keyword (parser, RID_USING, "%<using%>");
   /* And the `namespace' keyword.  */
-  cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
   /* And the optional nested-name-specifier.  */
@@ -11937,7 +12345,7 @@ cp_parser_using_directive (cp_parser* parser)
   /* Update the symbol table.  */
   parse_using_directive (namespace_decl, attribs);
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 }
 
 /* Parse an asm-definition.
@@ -11970,7 +12378,7 @@ cp_parser_asm_definition (cp_parser* parser)
   bool invalid_outputs_p = false;
 
   /* Look for the `asm' keyword.  */
-  cp_parser_require_keyword (parser, RID_ASM, "`asm'");
+  cp_parser_require_keyword (parser, RID_ASM, "%<asm%>");
   /* See if the next token is `volatile'.  */
   if (cp_parser_allow_gnu_extensions_p (parser)
       && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
@@ -11981,7 +12389,7 @@ cp_parser_asm_definition (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the opening `('.  */
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return;
   /* Look for the string.  */
   string = cp_parser_string_literal (parser, false, false);
@@ -12064,10 +12472,10 @@ cp_parser_asm_definition (cp_parser* parser)
        }
     }
   /* Look for the closing `)'.  */
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                           /*consume_paren=*/true);
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
   if (!invalid_inputs_p && !invalid_outputs_p)
     {
@@ -12140,7 +12548,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;
@@ -12148,12 +12557,12 @@ cp_parser_init_declarator (cp_parser* parser,
   tree initializer;
   tree decl = NULL_TREE;
   tree scope;
-  bool is_initialized;
+  int is_initialized;
   /* Only valid if IS_INITIALIZED is true.  In that case, CPP_EQ if
      initialized with "= ..", CPP_OPEN_PAREN if initialized with
      "(...)".  */
   enum cpp_ttype initialization_kind;
-  bool is_parenthesized_init = false;
+  bool is_direct_init = false;
   bool is_non_constant_init;
   int ctor_dtor_or_conv_p;
   bool friend_p;
@@ -12174,6 +12583,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,
@@ -12188,12 +12598,14 @@ 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)
     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
@@ -12205,8 +12617,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
@@ -12219,7 +12633,8 @@ cp_parser_init_declarator (cp_parser* parser,
   token = cp_lexer_peek_token (parser->lexer);
   /* Check to see if the token indicates the start of a
      function-definition.  */
-  if (cp_parser_token_starts_function_definition_p (token))
+  if (function_declarator_p (declarator)
+      && cp_parser_token_starts_function_definition_p (token))
     {
       if (!function_definition_allowed_p)
        {
@@ -12231,12 +12646,18 @@ cp_parser_init_declarator (cp_parser* parser,
        }
       else
        {
+         location_t func_brace_location
+           = cp_lexer_peek_token (parser->lexer)->location;
+
          /* 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;
 
@@ -12251,6 +12672,13 @@ cp_parser_init_declarator (cp_parser* parser,
              = (cp_parser_function_definition_from_specifiers_and_declarator
                 (parser, decl_specifiers, prefix_attributes, declarator));
 
+         if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl))
+           {
+             /* This is where the prologue starts...  */
+             DECL_STRUCT_FUNCTION (decl)->function_start_locus
+               = func_brace_location;
+           }
+
          return decl;
        }
     }
@@ -12270,12 +12698,23 @@ cp_parser_init_declarator (cp_parser* parser,
       return error_mark_node;
     }
 
-  /* An `=' or an `(' indicates an initializer.  */
+  /* An `=' or an `(', or an '{' in C++0x, indicates an initializer.  */
   if (token->type == CPP_EQ
-      || token->type == CPP_OPEN_PAREN)
+      || token->type == CPP_OPEN_PAREN
+      || token->type == CPP_OPEN_BRACE)
     {
-      is_initialized = true;
+      is_initialized = SD_INITIALIZED;
       initialization_kind = token->type;
+
+      if (token->type == CPP_EQ
+         && function_declarator_p (declarator))
+       {
+         cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
+         if (t2->keyword == RID_DEFAULT)
+           is_initialized = SD_DEFAULTED;
+         else if (t2->keyword == RID_DELETE)
+           is_initialized = SD_DELETED;
+       }
     }
   else
     {
@@ -12287,7 +12726,7 @@ cp_parser_init_declarator (cp_parser* parser,
          cp_parser_error (parser, "expected initializer");
          return error_mark_node;
        }
-      is_initialized = false;
+      is_initialized = SD_UNINITIALIZED;
       initialization_kind = CPP_EOF;
     }
 
@@ -12345,7 +12784,7 @@ cp_parser_init_declarator (cp_parser* parser,
       cp_parser_perform_template_parameter_access_checks (checks);
 
       /* Perform the access control checks for the declarator and the
-        the decl-specifiers.  */
+        decl-specifiers.  */
       perform_deferred_access_checks ();
 
       /* Restore the saved value.  */
@@ -12355,12 +12794,13 @@ cp_parser_init_declarator (cp_parser* parser,
 
   /* Parse the initializer.  */
   initializer = NULL_TREE;
-  is_parenthesized_init = false;
+  is_direct_init = false;
   is_non_constant_init = true;
   if (is_initialized)
     {
       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
@@ -12369,7 +12809,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,
@@ -12378,7 +12819,7 @@ cp_parser_init_declarator (cp_parser* parser,
        }
       else
        initializer = cp_parser_initializer (parser,
-                                            &is_parenthesized_init,
+                                            &is_direct_init,
                                             &is_non_constant_init);
     }
 
@@ -12386,7 +12827,8 @@ cp_parser_init_declarator (cp_parser* parser,
      initializer.  Mark Mitchell proposed removing this functionality
      on the GCC mailing lists on 2002-08-13.  This parser accepts the
      attributes -- but ignores them.  */
-  if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init)
+  if (cp_parser_allow_gnu_extensions_p (parser)
+      && initialization_kind == CPP_OPEN_PAREN)
     if (cp_parser_attributes_opt (parser))
       warning (OPT_Wattributes,
               "attributes after parenthesized initializer ignored");
@@ -12419,8 +12861,8 @@ cp_parser_init_declarator (cp_parser* parser,
                         a direct-initialization, which means that an
                         `explicit' constructor is OK.  Otherwise, an
                         `explicit' constructor cannot be used.  */
-                     ((is_parenthesized_init || !is_initialized)
-                    ? 0 : LOOKUP_ONLYCONVERTING));
+                     ((is_direct_init || !is_initialized)
+                      ? 0 : LOOKUP_ONLYCONVERTING));
     }
   else if ((cxx_dialect != cxx98) && friend_p
           && decl && TREE_CODE (decl) == FUNCTION_DECL)
@@ -12619,7 +13061,7 @@ cp_parser_direct_declarator (cp_parser* parser,
               int i (3);
 
             The first is the declaration of a function while the
-            second is the definition of a variable, including its
+            second is the definition of a variable, including its
             initializer.
 
             Having seen only the parenthesis, we cannot know which of
@@ -12637,8 +13079,10 @@ cp_parser_direct_declarator (cp_parser* parser,
 
          if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
            {
-             cp_parameter_declarator *params;
+             tree params;
              unsigned saved_num_template_parameter_lists;
+             bool is_declarator = false;
+             tree t;
 
              /* In a member-declarator, the only valid interpretation
                 of a parenthesis is the start of a
@@ -12665,6 +13109,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                = parser->num_template_parameter_lists;
              parser->num_template_parameter_lists = 0;
 
+             begin_scope (sk_function_parms, NULL_TREE);
+
              /* Parse the parameter-declaration-clause.  */
              params = cp_parser_parameter_declaration_clause (parser);
 
@@ -12677,12 +13123,15 @@ cp_parser_direct_declarator (cp_parser* parser,
                {
                  cp_cv_quals cv_quals;
                  tree exception_specification;
+                 tree late_return;
+
+                 is_declarator = true;
 
                  if (ctor_dtor_or_conv_p)
                    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
                  first = false;
                  /* Consume the `)'.  */
-                 cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+                 cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
                  /* Parse the cv-qualifier-seq.  */
                  cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
@@ -12690,19 +13139,29 @@ cp_parser_direct_declarator (cp_parser* parser,
                  exception_specification
                    = cp_parser_exception_specification_opt (parser);
 
+                 late_return
+                   = cp_parser_late_return_type_opt (parser);
+
                  /* Create the function-declarator.  */
                  declarator = make_call_declarator (declarator,
                                                     params,
                                                     cv_quals,
-                                                    exception_specification);
+                                                    exception_specification,
+                                                    late_return);
                  /* Any subsequent parameter lists are to do with
                     return type, so are not those of the declared
                     function.  */
                  parser->default_arg_ok_p = false;
-
-                 /* Repeat the main loop.  */
-                 continue;
                }
+
+             /* Remove the function parms from scope.  */
+             for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+               pop_binding (DECL_NAME (t), t);
+             leave_scope();
+
+             if (is_declarator)
+               /* Repeat the main loop.  */
+               continue;
            }
 
          /* If this is the first, we can try a parenthesized
@@ -12726,7 +13185,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
              first = false;
              /* Expect a `)'.  */
-             if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+             if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
                declarator = cp_error_declarator;
              if (declarator == cp_error_declarator)
                break;
@@ -12770,14 +13229,15 @@ 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;
                }
            }
          else
            bounds = NULL_TREE;
          /* Look for the closing `]'.  */
-         if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
+         if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"))
            {
              declarator = cp_error_declarator;
              break;
@@ -12792,6 +13252,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);
@@ -12810,6 +13271,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;
@@ -12879,7 +13341,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;
@@ -12905,8 +13368,9 @@ cp_parser_direct_declarator (cp_parser* parser,
                      if (qualifying_scope
                          && CLASSTYPE_USE_TEMPLATE (name_type))
                        {
-                         error ("invalid use of constructor as a template");
-                         inform ("use %<%T::%D%> instead of %<%T::%D%> to "
+                         error ("%Hinvalid use of constructor as a template",
+                                &declarator_id_start_token->location);
+                         inform (input_location, "use %<%T::%D%> instead of %<%T::%D%> to "
                                  "name the constructor in a qualified name",
                                  class_type,
                                  DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
@@ -13064,6 +13528,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,
@@ -13072,13 +13537,13 @@ cp_parser_ptr_operator (cp_parser* parser,
       /* If we found it, and the next token is a `*', then we are
         indeed looking at a pointer-to-member operator.  */
       if (!cp_parser_error_occurred (parser)
-         && cp_parser_require (parser, CPP_MULT, "`*'"))
+         && cp_parser_require (parser, CPP_MULT, "%<*%>"))
        {
          /* Indicate that the `*' operator was used.  */
          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
@@ -13153,7 +13618,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
@@ -13166,6 +13631,30 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
   return cv_quals;
 }
 
+/* Parse a late-specified return type, if any.  This is not a separate
+   non-terminal, but part of a function declarator, which looks like
+
+   -> type-id
+
+   Returns the type indicated by the type-id.  */
+
+static tree
+cp_parser_late_return_type_opt (cp_parser* parser)
+{
+  cp_token *token;
+
+  /* Peek at the next token.  */
+  token = cp_lexer_peek_token (parser->lexer);
+  /* A late-specified return type is indicated by an initial '->'. */
+  if (token->type != CPP_DEREF)
+    return NULL_TREE;
+
+  /* Consume the ->.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  return cp_parser_type_id (parser);
+}
+
 /* Parse a declarator-id.
 
    declarator-id:
@@ -13238,6 +13727,13 @@ cp_parser_type_id (cp_parser* parser)
   if (!cp_parser_parse_definitely (parser))
     abstract_declarator = NULL;
 
+  if (type_specifier_seq.type
+      && type_uses_auto (type_specifier_seq.type))
+    {
+      error ("invalid use of %<auto%>");
+      return error_mark_node;
+    }
+  
   return groktypename (&type_specifier_seq, abstract_declarator);
 }
 
@@ -13263,6 +13759,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);
@@ -13282,6 +13779,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,
@@ -13325,7 +13827,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.
@@ -13338,10 +13840,10 @@ cp_parser_type_specifier_seq (cp_parser* parser,
    value of NULL indicates a parameter-declaration-clause consisting
    only of an ellipsis.  */
 
-static cp_parameter_declarator *
+static tree
 cp_parser_parameter_declaration_clause (cp_parser* parser)
 {
-  cp_parameter_declarator *parameters;
+  tree parameters;
   cp_token *token;
   bool ellipsis_p;
   bool is_error;
@@ -13353,7 +13855,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     {
       /* Consume the `...' token.  */
       cp_lexer_consume_token (parser->lexer);
-      return NULL;
+      return NULL_TREE;
     }
   else if (token->type == CPP_CLOSE_PAREN)
     /* There are no parameters.  */
@@ -13361,10 +13863,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
 #ifndef NO_IMPLICIT_EXTERN_C
       if (in_system_header && current_class_type == NULL
          && current_lang_name == lang_name_c)
-       return NULL;
+       return NULL_TREE;
       else
 #endif
-       return no_parameters;
+       return void_list_node;
     }
   /* Check for `(void)', too, which is a special case.  */
   else if (token->keyword == RID_VOID
@@ -13374,7 +13876,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       /* Consume the `void' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* There are no parameters.  */
-      return no_parameters;
+      return void_list_node;
     }
 
   /* Parse the parameter-declaration-list.  */
@@ -13394,7 +13896,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
       /* Expect an ellipsis.  */
       ellipsis_p
-       = (cp_parser_require (parser, CPP_ELLIPSIS, "`...'") != NULL);
+       = (cp_parser_require (parser, CPP_ELLIPSIS, "%<...%>") != NULL);
     }
   /* It might also be `...' if the optional trailing `,' was
      omitted.  */
@@ -13409,8 +13911,8 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     ellipsis_p = false;
 
   /* Finish the parameter list.  */
-  if (parameters && ellipsis_p)
-    parameters->ellipsis_p = true;
+  if (!ellipsis_p)
+    parameters = chainon (parameters, void_list_node);
 
   return parameters;
 }
@@ -13426,11 +13928,11 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
    `void_list_node' is never appended to the list.  Upon return,
    *IS_ERROR will be true iff an error occurred.  */
 
-static cp_parameter_declarator *
+static tree
 cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
-  cp_parameter_declarator *parameters = NULL;
-  cp_parameter_declarator **tail = &parameters;
+  tree parameters = NULL_TREE;
+  tree *tail = &parameters; 
   bool saved_in_unbraced_linkage_specification_p;
 
   /* Assume all will go well.  */
@@ -13446,6 +13948,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   while (true)
     {
       cp_parameter_declarator *parameter;
+      tree decl = error_mark_node;
       bool parenthesized_p;
       /* Parse the parameter.  */
       parameter
@@ -13453,17 +13956,38 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
                                           /*template_parm_p=*/false,
                                           &parenthesized_p);
 
+      /* We don't know yet if the enclosing context is deprecated, so wait
+        and warn in grokparms if appropriate.  */
+      deprecated_state = DEPRECATED_SUPPRESS;
+
+      if (parameter)
+       decl = grokdeclarator (parameter->declarator,
+                              &parameter->decl_specifiers,
+                              PARM,
+                              parameter->default_argument != NULL_TREE,
+                              &parameter->decl_specifiers.attributes);
+
+      deprecated_state = DEPRECATED_NORMAL;
+
       /* If a parse error occurred parsing the parameter declaration,
         then the entire parameter-declaration-list is erroneous.  */
-      if (!parameter)
+      if (decl == error_mark_node)
        {
          *is_error = true;
-         parameters = NULL;
+         parameters = error_mark_node;
          break;
        }
+
+      if (parameter->decl_specifiers.attributes)
+       cplus_decl_attributes (&decl,
+                              parameter->decl_specifiers.attributes,
+                              0);
+      if (DECL_NAME (decl))
+       decl = pushdecl (decl);
+
       /* Add the new parameter to the list.  */
-      *tail = parameter;
-      tail = &parameter->next;
+      *tail = build_tree_list (parameter->default_argument, decl);
+      tail = &TREE_CHAIN (*tail);
 
       /* Peek at the next token.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
@@ -13552,7 +14076,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.
@@ -13621,6 +14145,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,
@@ -13680,6 +14205,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
          && TYPE_BEING_DEFINED (current_class_type))
        {
          unsigned depth = 0;
+         int maybe_template_id = 0;
          cp_token *first_token;
          cp_token *token;
 
@@ -13698,6 +14224,33 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  /* In valid code, a default argument must be
                     immediately followed by a `,' `)', or `...'.  */
                case CPP_COMMA:
+                 if (depth == 0 && maybe_template_id)
+                   {
+                     /* If we've seen a '<', we might be in a
+                        template-argument-list.  Until Core issue 325 is
+                        resolved, we don't know how this situation ought
+                        to be handled, so try to DTRT.  We check whether
+                        what comes after the comma is a valid parameter
+                        declaration list.  If it is, then the comma ends
+                        the default argument; otherwise the default
+                        argument continues.  */
+                     bool error = false;
+
+                     /* Set ITALP so cp_parser_parameter_declaration_list
+                        doesn't decide to commit to this parse.  */
+                     bool saved_italp = parser->in_template_argument_list_p;
+                     parser->in_template_argument_list_p = true;
+
+                     cp_parser_parse_tentatively (parser);
+                     cp_lexer_consume_token (parser->lexer);
+                     cp_parser_parameter_declaration_list (parser, &error);
+                     if (!cp_parser_error_occurred (parser) && !error)
+                       done = true;
+                     cp_parser_abort_tentative_parse (parser);
+
+                     parser->in_template_argument_list_p = saved_italp;
+                     break;
+                   }
                case CPP_CLOSE_PAREN:
                case CPP_ELLIPSIS:
                  /* If we run into a non-nested `;', `}', or `]',
@@ -13721,6 +14274,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  ++depth;
                  break;
 
+               case CPP_LESS:
+                 if (depth == 0)
+                   /* This might be the comparison operator, or it might
+                      start a template argument list.  */
+                   ++maybe_template_id;
+                 break;
+
                 case CPP_RSHIFT:
                   if (cxx_dialect == cxx98)
                     break;
@@ -13729,17 +14289,22 @@ cp_parser_parameter_declaration (cp_parser *parser,
                      cases.  */
 
                case CPP_GREATER:
-                 /* If we see a non-nested `>', and `>' is not an
-                    operator, then it marks the end of the default
-                    argument.  */
-                 if (!depth && !greater_than_is_operator_p)
-                   done = true;
+                 if (depth == 0)
+                   {
+                     /* This might be an operator, or it might close a
+                        template argument list.  But if a previous '<'
+                        started a template argument list, this will have
+                        closed it, so we can't be in one anymore.  */
+                     maybe_template_id -= 1 + (token->type == CPP_RSHIFT);
+                     if (maybe_template_id < 0)
+                       maybe_template_id = 0;
+                   }
                  break;
 
                  /* 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;
 
@@ -13776,16 +14341,21 @@ 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)
        {
-         if (!flag_pedantic_errors)
+         if (flag_permissive)
            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;
            }
        }
@@ -13801,11 +14371,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;
        }
@@ -13899,14 +14470,14 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser)
    Returns an expression representing the initializer.  If no
    initializer is present, NULL_TREE is returned.
 
-   *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )'
-   production is used, and zero otherwise.  *IS_PARENTHESIZED_INIT is
-   set to FALSE if there is no initializer present.  If there is an
+   *IS_DIRECT_INIT is set to FALSE if the `= initializer-clause'
+   production is used, and TRUE otherwise.  *IS_DIRECT_INIT is
+   set to TRUE if there is no initializer present.  If there is an
    initializer, and it is not a constant-expression, *NON_CONSTANT_P
    is set to true; otherwise it is set to false.  */
 
 static tree
-cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
+cp_parser_initializer (cp_parser* parser, bool* is_direct_init,
                       bool* non_constant_p)
 {
   cp_token *token;
@@ -13917,7 +14488,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
 
   /* Let our caller know whether or not this initializer was
      parenthesized.  */
-  *is_parenthesized_init = (token->type == CPP_OPEN_PAREN);
+  *is_direct_init = (token->type != CPP_EQ);
   /* Assume that the initializer is constant.  */
   *non_constant_p = false;
 
@@ -13933,6 +14504,12 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
                                                    /*cast_p=*/false,
                                                     /*allow_expansion_p=*/true,
                                                    non_constant_p);
+  else if (token->type == CPP_OPEN_BRACE)
+    {
+      maybe_warn_cpp0x ("extended initializer lists");
+      init = cp_parser_braced_list (parser, non_constant_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (init) = 1;
+    }
   else
     {
       /* Anything else is an error.  */
@@ -13947,20 +14524,14 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
 
    initializer-clause:
      assignment-expression
-     { initializer-list , [opt] }
-     { }
+     braced-init-list
 
    Returns an expression representing the initializer.
 
    If the `assignment-expression' production is used the value
    returned is simply a representation for the expression.
 
-   Otherwise, a CONSTRUCTOR is returned.  The CONSTRUCTOR_ELTS will be
-   the elements of the initializer-list (or NULL, if the last
-   production is used).  The TREE_TYPE for the CONSTRUCTOR will be
-   NULL_TREE.  There is no way to detect whether or not the optional
-   trailing `,' was provided.  NON_CONSTANT_P is as for
-   cp_parser_initializer.  */
+   Otherwise, calls cp_parser_braced_list.  */
 
 static tree
 cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
@@ -13982,25 +14553,46 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
        initializer = fold_non_dependent_expr (initializer);
     }
   else
+    initializer = cp_parser_braced_list (parser, non_constant_p);
+
+  return initializer;
+}
+
+/* Parse a brace-enclosed initializer list.
+
+   braced-init-list:
+     { initializer-list , [opt] }
+     { }
+
+   Returns a CONSTRUCTOR.  The CONSTRUCTOR_ELTS will be
+   the elements of the initializer-list (or NULL, if the last
+   production is used).  The TREE_TYPE for the CONSTRUCTOR will be
+   NULL_TREE.  There is no way to detect whether or not the optional
+   trailing `,' was provided.  NON_CONSTANT_P is as for
+   cp_parser_initializer.  */     
+
+static tree
+cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
+{
+  tree initializer;
+
+  /* Consume the `{' token.  */
+  cp_lexer_consume_token (parser->lexer);
+  /* Create a CONSTRUCTOR to represent the braced-initializer.  */
+  initializer = make_node (CONSTRUCTOR);
+  /* If it's not a `}', then there is a non-trivial initializer.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
     {
-      /* Consume the `{' token.  */
-      cp_lexer_consume_token (parser->lexer);
-      /* Create a CONSTRUCTOR to represent the braced-initializer.  */
-      initializer = make_node (CONSTRUCTOR);
-      /* If it's not a `}', then there is a non-trivial initializer.  */
-      if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
-       {
-         /* Parse the initializer list.  */
-         CONSTRUCTOR_ELTS (initializer)
-           = cp_parser_initializer_list (parser, non_constant_p);
-         /* A trailing `,' token is allowed.  */
-         if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-           cp_lexer_consume_token (parser->lexer);
-       }
-      /* Now, there should be a trailing `}'.  */
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+      /* Parse the initializer list.  */
+      CONSTRUCTOR_ELTS (initializer)
+       = cp_parser_initializer_list (parser, non_constant_p);
+      /* A trailing `,' token is allowed.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
     }
-
+  /* Now, there should be a trailing `}'.  */
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+  TREE_TYPE (initializer) = init_list_type_node;
   return initializer;
 }
 
@@ -14045,8 +14637,8 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
        {
          /* Warn the user that they are using an extension.  */
-         if (pedantic)
-           pedwarn ("ISO C++ does not allow designated initializers");
+         pedwarn (input_location, OPT_pedantic, 
+                  "ISO C++ does not allow designated initializers");
          /* Consume the identifier.  */
          identifier = cp_lexer_consume_token (parser->lexer)->u.value;
          /* Consume the `:'.  */
@@ -14128,6 +14720,7 @@ cp_parser_class_name (cp_parser *parser,
   tree scope;
   bool typename_p;
   cp_token *token;
+  tree identifier = NULL_TREE;
 
   /* All class-names start with an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -14153,7 +14746,6 @@ cp_parser_class_name (cp_parser *parser,
       && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
     {
       cp_token *identifier_token;
-      tree identifier;
       bool ambiguous_p;
 
       /* Look for the identifier.  */
@@ -14195,10 +14787,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))
                {
@@ -14256,6 +14850,8 @@ cp_parser_class_name (cp_parser *parser,
 
   if (decl == error_mark_node)
     cp_parser_error (parser, "expected class-name");
+  else if (identifier && !parser->scope)
+    maybe_note_name_used_in_class (identifier, decl);
 
   return decl;
 }
@@ -14277,6 +14873,7 @@ cp_parser_class_specifier (cp_parser* parser)
   bool nested_name_specifier_p;
   unsigned saved_num_template_parameter_lists;
   bool saved_in_function_body;
+  bool saved_in_unbraced_linkage_specification_p;
   tree old_scope = NULL_TREE;
   tree scope = NULL_TREE;
   tree bases;
@@ -14298,7 +14895,7 @@ cp_parser_class_specifier (cp_parser* parser)
     }
 
   /* Look for the `{'.  */
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
     {
       pop_deferring_access_checks ();
       return error_mark_node;
@@ -14328,6 +14925,10 @@ cp_parser_class_specifier (cp_parser* parser)
   /* We are not in a function body.  */
   saved_in_function_body = parser->in_function_body;
   parser->in_function_body = false;
+  /* We are not immediately inside an extern "lang" block.  */
+  saved_in_unbraced_linkage_specification_p
+    = parser->in_unbraced_linkage_specification_p;
+  parser->in_unbraced_linkage_specification_p = false;
 
   /* Start the class.  */
   if (nested_name_specifier_p)
@@ -14345,7 +14946,7 @@ cp_parser_class_specifier (cp_parser* parser)
     cp_parser_member_specification_opt (parser);
 
   /* Look for the trailing `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
   /* We get better error messages by noticing a common problem: a
      missing trailing `;'.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -14440,6 +15041,8 @@ cp_parser_class_specifier (cp_parser* parser)
   parser->in_function_body = saved_in_function_body;
   parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
+  parser->in_unbraced_linkage_specification_p
+    = saved_in_unbraced_linkage_specification_p;
 
   return type;
 }
@@ -14489,7 +15092,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
@@ -14522,6 +15125,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,
@@ -14532,6 +15136,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
@@ -14561,6 +15166,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;
@@ -14595,6 +15201,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,
@@ -14603,7 +15210,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;
        }
@@ -14617,7 +15227,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
@@ -14634,11 +15245,17 @@ cp_parser_class_head (cp_parser* parser,
   cp_parser_commit_to_tentative_parse (parser);
   /* Issue the error about the overly-qualified name now.  */
   if (qualified_p)
-    cp_parser_error (parser,
-                    "global qualification of class name is invalid");
+    {
+      cp_parser_error (parser,
+                      "global qualification of class name is invalid");
+      return error_mark_node;
+    }
   else if (invalid_nested_name_p)
-    cp_parser_error (parser,
-                    "qualified name does not name a class");
+    {
+      cp_parser_error (parser,
+                      "qualified name does not name a class");
+      return error_mark_node;
+    }
   else if (nested_name_specifier)
     {
       tree scope;
@@ -14646,7 +15263,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;
        }
@@ -14658,23 +15276,27 @@ 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;
        }
       /* [dcl.meaning]
 
-        A declarator-id shall not be qualified exception of the
+        A declarator-id shall not be qualified except for the
         definition of a ... nested class outside of its class
-        ... [or] the definition or explicit instantiation of a
+        ... [or] the definition or explicit instantiation of a
         class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
        {
-         pedwarn ("extra qualification ignored");
+         permerror (input_location, "%Hextra qualification not allowed",
+                    &nested_name_specifier_token_start->location);
          nested_name_specifier = NULL_TREE;
          num_templates = 0;
        }
@@ -14685,7 +15307,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.  */
@@ -14697,7 +15320,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.  */
@@ -14712,7 +15336,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
@@ -14748,7 +15373,13 @@ cp_parser_class_head (cp_parser* parser,
            }
        }
 
-      maybe_process_partial_specialization (TREE_TYPE (type));
+      if (maybe_process_partial_specialization (TREE_TYPE (type))
+         == error_mark_node)
+       {
+         type = NULL_TREE;
+         goto done;
+       }
+
       class_type = current_class_type;
       /* Enter the scope indicated by the nested-name-specifier.  */
       pushed_scope = push_scope (nested_name_specifier);
@@ -14787,8 +15418,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;
     }
@@ -14884,7 +15517,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
          /* Remember which access-specifier is active.  */
          current_access_specifier = token->u.value;
          /* Look for the `:'.  */
-         cp_parser_require (parser, CPP_COLON, "`:'");
+         cp_parser_require (parser, CPP_COLON, "%<:%>");
          break;
 
        default:
@@ -14943,7 +15576,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.  */
@@ -15007,6 +15642,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,
@@ -15033,8 +15669,8 @@ cp_parser_member_declaration (cp_parser* parser)
       if (!decl_specifiers.any_specifiers_p)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
-         if (pedantic && !token->in_system_header)
-           pedwarn ("%Hextra %<;%>", &token->location);
+         if (!in_system_header_at (token->location))
+           pedwarn (token->location, OPT_pedantic, "extra %<;%>");
        }
       else
        {
@@ -15052,7 +15688,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 {
@@ -15066,8 +15703,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);
@@ -15090,7 +15727,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
@@ -15148,9 +15787,8 @@ cp_parser_member_declaration (cp_parser* parser)
                                                         sfk_none)
                                   : NULL,
                                   &decl_specifiers,
-                                  width);
-             /* Apply the attributes.  */
-             cplus_decl_attributes (&decl, attributes, /*flags=*/0);
+                                  width,
+                                  attributes);
            }
          else
            {
@@ -15185,7 +15823,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);
@@ -15219,6 +15858,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
@@ -15243,7 +15883,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,
@@ -15259,6 +15900,8 @@ cp_parser_member_declaration (cp_parser* parser)
                  return;
                }
              else
+               if (declarator->kind == cdk_function)
+                 declarator->id_loc = token->location;
                /* Create the declaration.  */
                decl = grokfield (declarator, &decl_specifiers,
                                  initializer, /*init_const_expr_p=*/true,
@@ -15303,7 +15946,7 @@ cp_parser_member_declaration (cp_parser* parser)
        }
     }
 
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 }
 
 /* Parse a pure-specifier.
@@ -15320,21 +15963,30 @@ cp_parser_pure_specifier (cp_parser* parser)
   cp_token *token;
 
   /* Look for the `=' token.  */
-  if (!cp_parser_require (parser, CPP_EQ, "`='"))
+  if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
     return error_mark_node;
   /* Look for the `0' token.  */
   token = cp_lexer_consume_token (parser->lexer);
+
+  /* Accept = default or = delete in c++0x mode.  */
+  if (token->keyword == RID_DEFAULT
+      || token->keyword == RID_DELETE)
+    {
+      maybe_warn_cpp0x ("defaulted and deleted functions");
+      return token->u.value;
+    }
+
   /* c_lex_with_flags marks a single digit '0' with PURE_ZERO.  */
   if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO))
     {
       cp_parser_error (parser,
-                      "invalid pure specifier (only `= 0' is allowed)");
+                      "invalid pure specifier (only %<= 0%> is allowed)");
       cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
-      error ("templates may not be %<virtual%>");
+      error ("%Htemplates may not be %<virtual%>", &token->location);
       return error_mark_node;
     }
 
@@ -15352,7 +16004,7 @@ static tree
 cp_parser_constant_initializer (cp_parser* parser)
 {
   /* Look for the `=' token.  */
-  if (!cp_parser_require (parser, CPP_EQ, "`='"))
+  if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
     return error_mark_node;
 
   /* It is invalid to write:
@@ -15369,7 +16021,7 @@ cp_parser_constant_initializer (cp_parser* parser)
       /* Skip the initializer.  */
       cp_parser_skip_to_closing_brace (parser);
       /* Look for the trailing `}'.  */
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 
       return error_mark_node;
     }
@@ -15403,7 +16055,7 @@ cp_parser_base_clause (cp_parser* parser)
   tree bases = NULL_TREE;
 
   /* Look for the `:' that begins the list.  */
-  cp_parser_require (parser, CPP_COLON, "`:'");
+  cp_parser_require (parser, CPP_COLON, "%<:%>");
 
   /* Scan the base-specifier-list.  */
   while (true)
@@ -15536,11 +16188,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);
     }
 
@@ -15609,7 +16264,7 @@ cp_parser_exception_specification_opt (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);
 
   /* Look for the `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -15631,7 +16286,7 @@ cp_parser_exception_specification_opt (cp_parser* parser)
     type_id_list = empty_except_spec;
 
   /* Look for the `)'.  */
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return type_id_list;
 }
@@ -15690,7 +16345,7 @@ cp_parser_try_block (cp_parser* parser)
 {
   tree try_block;
 
-  cp_parser_require_keyword (parser, RID_TRY, "`try'");
+  cp_parser_require_keyword (parser, RID_TRY, "%<try%>");
   try_block = begin_try_block ();
   cp_parser_compound_statement (parser, NULL, true);
   finish_try_block (try_block);
@@ -15713,7 +16368,7 @@ cp_parser_function_try_block (cp_parser* parser)
   bool ctor_initializer_p;
 
   /* Look for the `try' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_TRY, "`try'"))
+  if (!cp_parser_require_keyword (parser, RID_TRY, "%<try%>"))
     return false;
   /* Let the rest of the front end know where we are.  */
   try_block = begin_function_try_block (&compound_stmt);
@@ -15763,12 +16418,12 @@ cp_parser_handler (cp_parser* parser)
   tree handler;
   tree declaration;
 
-  cp_parser_require_keyword (parser, RID_CATCH, "`catch'");
+  cp_parser_require_keyword (parser, RID_CATCH, "%<catch%>");
   handler = begin_handler ();
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   declaration = cp_parser_exception_declaration (parser);
   finish_handler_parms (declaration, handler);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
   cp_parser_compound_statement (parser, NULL, false);
   finish_handler (handler);
 }
@@ -15838,7 +16493,7 @@ cp_parser_throw_expression (cp_parser* parser)
   tree expression;
   cp_token* token;
 
-  cp_parser_require_keyword (parser, RID_THROW, "`throw'");
+  cp_parser_require_keyword (parser, RID_THROW, "%<throw%>");
   token = cp_lexer_peek_token (parser->lexer);
   /* Figure out whether or not there is an assignment-expression
      following the "throw" keyword.  */
@@ -15883,13 +16538,13 @@ cp_parser_asm_specification_opt (cp_parser* parser)
   /* Consume the `asm' token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Look for the `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
   /* Look for the string-literal.  */
   asm_specification = cp_parser_string_literal (parser, false, false);
 
   /* Look for the `)'.  */
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`('");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return asm_specification;
 }
@@ -15933,7 +16588,7 @@ cp_parser_asm_operand_list (cp_parser* parser)
            name = build_string (IDENTIFIER_LENGTH (name),
                                 IDENTIFIER_POINTER (name));
          /* Look for the closing `]'.  */
-         cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+         cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
        }
       else
        name = NULL_TREE;
@@ -15941,11 +16596,11 @@ cp_parser_asm_operand_list (cp_parser* parser)
       string_literal = cp_parser_string_literal (parser, false, false);
 
       /* Look for the `('.  */
-      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
       /* Parse the expression.  */
       expression = cp_parser_expression (parser, /*cast_p=*/false);
       /* Look for the `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
       if (name == error_mark_node 
          || string_literal == error_mark_node 
@@ -16029,8 +16684,8 @@ cp_parser_attributes_opt (cp_parser* parser)
       /* Consume the `__attribute__' keyword.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the two `(' tokens.  */
-      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
-      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -16043,8 +16698,8 @@ cp_parser_attributes_opt (cp_parser* parser)
        attribute_list = NULL;
 
       /* Look for the two `)' tokens.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
       /* Add these new attributes to the list.  */
       attributes = chainon (attributes, attribute_list);
@@ -16174,7 +16829,7 @@ static void
 cp_parser_label_declaration (cp_parser* parser)
 {
   /* Look for the `__label__' keyword.  */
-  cp_parser_require_keyword (parser, RID_LABEL, "`__label__'");
+  cp_parser_require_keyword (parser, RID_LABEL, "%<__label__%>");
 
   while (true)
     {
@@ -16191,11 +16846,11 @@ cp_parser_label_declaration (cp_parser* parser)
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
        break;
       /* Look for the `,' separating the label declarations.  */
-      cp_parser_require (parser, CPP_COMMA, "`,'");
+      cp_parser_require (parser, CPP_COMMA, "%<,%>");
     }
 
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 }
 
 /* Support Functions */
@@ -16241,7 +16896,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;
@@ -16364,6 +17020,13 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
          decl = lookup_qualified_name (parser->scope, name,
                                        tag_type != none_type,
                                        /*complain=*/true);
+
+         /* If we have a single function from a using decl, pull it out.  */
+         if (decl
+             && TREE_CODE (decl) == OVERLOAD
+             && !really_overloaded_fn (decl))
+           decl = OVL_FUNCTION (decl);
+
          if (pushed_scope)
            pop_scope (pushed_scope);
        }
@@ -16415,7 +17078,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;
@@ -16445,14 +17109,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
@@ -16505,7 +17170,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;
 
@@ -16555,7 +17221,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:
@@ -16563,7 +17230,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;
@@ -16580,7 +17247,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:
@@ -16588,7 +17256,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
@@ -16603,7 +17271,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;
 }
 
@@ -16729,7 +17397,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
      takes one parameter (of type `int') and returns a value of type
      `S::S'.  */
   if (constructor_p
-      && cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+      && cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     {
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
@@ -16861,12 +17529,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.  */
@@ -16875,7 +17545,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)
        {
@@ -16934,20 +17605,23 @@ 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.  */
-  if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"))
+  token = cp_lexer_peek_token (parser->lexer);
+  if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
     return;
 
   /* And the `<'.  */
-  if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+  if (!cp_parser_require (parser, CPP_LESS, "%<<%>"))
     return;
   if (at_class_scope_p () && current_function_decl)
     {
       /* 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;
     }
@@ -16956,7 +17630,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);
@@ -17003,6 +17677,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,
@@ -17015,7 +17690,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);
        }
@@ -17079,6 +17754,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.  */
@@ -17090,6 +17766,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,
@@ -17100,7 +17777,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;
     }
 
@@ -17163,7 +17841,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;
       }
     }
@@ -17178,7 +17857,7 @@ cp_parser_single_declaration (cp_parser* parser,
   /* Look for a trailing `;' after the declaration.  */
   if (!function_definition_p
       && (decl == error_mark_node
-         || !cp_parser_require (parser, CPP_SEMICOLON, "`;'")))
+         || !cp_parser_require (parser, CPP_SEMICOLON, "%<;%>")))
     cp_parser_skip_to_end_of_block_or_statement (parser);
 
   return decl;
@@ -17201,11 +17880,22 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
 {
   tree expression_list;
   tree cast;
+  bool nonconst_p;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      maybe_warn_cpp0x ("extended initializer lists");
+      expression_list = cp_parser_braced_list (parser, &nonconst_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
+      if (TREE_CODE (type) == TYPE_DECL)
+       type = TREE_TYPE (type);
+      return finish_compound_literal (type, expression_list);
+    }
 
   expression_list
     = cp_parser_parenthesized_expression_list (parser, false,
                                               /*cast_p=*/true,
-                                               /*allow_expansion_p=*/true,
+                                              /*allow_expansion_p=*/true,
                                               /*non_constant_p=*/NULL);
 
   cast = build_functional_cast (type, expression_list,
@@ -17256,6 +17946,22 @@ cp_parser_save_member_function_body (cp_parser* parser,
   /* Save away the tokens that make up the body of the
      function.  */
   first = parser->lexer->next_token;
+  /* We can have braced-init-list mem-initializers before the fn body.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      while (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
+            && cp_lexer_next_token_is_not_keyword (parser->lexer, RID_TRY))
+       {
+         /* cache_group will stop after an un-nested { } pair, too.  */
+         if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0))
+           break;
+
+         /* variadic mem-inits have ... after the ')'.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+           cp_lexer_consume_token (parser->lexer);
+       }
+    }
   cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0);
   /* Handle function try blocks.  */
   while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH))
@@ -17365,9 +18071,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
@@ -17570,7 +18276,6 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 static tree
 cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 {
-  static const char *format;
   tree expr = NULL_TREE;
   const char *saved_message;
   char *tmp;
@@ -17578,19 +18283,14 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   bool saved_non_integral_constant_expression_p;
   bool pack_expansion_p = false;
 
-  /* Initialize FORMAT the first time we get here.  */
-  if (!format)
-    format = "types may not be defined in '%s' expressions";
-
   /* Types cannot be defined in a `sizeof' expression.  Save away the
      old message.  */
   saved_message = parser->type_definition_forbidden_message;
   /* And create the new one.  */
-  parser->type_definition_forbidden_message = tmp
-    = XNEWVEC (char, strlen (format)
-              + strlen (IDENTIFIER_POINTER (ridpointers[keyword]))
-              + 1 /* `\0' */);
-  sprintf (tmp, format, IDENTIFIER_POINTER (ridpointers[keyword]));
+  tmp = concat ("types may not be defined in %<",
+               IDENTIFIER_POINTER (ridpointers[keyword]),
+               "%> expressions", NULL);
+  parser->type_definition_forbidden_message = tmp;
 
   /* The restrictions on constant-expressions do not apply inside
      sizeof expressions.  */
@@ -17694,14 +18394,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)
@@ -17713,7 +18414,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;
     }
 
@@ -17754,17 +18455,21 @@ 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;
 
-  /* If the user tries to redeclare bool or wchar_t (with, for
-     example, in "typedef int wchar_t;") we remember that this is what
-     happened.  In system headers, we ignore these declarations so
-     that G++ can work with system headers that are not C++-safe.  */
+  /* If the user tries to redeclare bool, char16_t, char32_t, or wchar_t
+     (with, for example, in "typedef int wchar_t;") we remember that
+     this is what happened.  In system headers, we ignore these
+     declarations so that G++ can work with system headers that are not
+     C++-safe.  */
   if (decl_specs->specs[(int) ds_typedef]
       && !user_defined_p
       && (type_spec == boolean_type_node
+         || type_spec == char16_type_node
+         || type_spec == char32_type_node
          || type_spec == wchar_type_node)
       && (decl_specs->type
          || decl_specs->specs[(int) ds_long]
@@ -17777,6 +18482,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)
@@ -17786,6 +18492,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;
     }
 }
 
@@ -18028,7 +18735,7 @@ static void
 cp_parser_check_class_key (enum tag_types class_key, tree type)
 {
   if ((TREE_CODE (type) == UNION_TYPE) != (class_key == union_type))
-    pedwarn ("%qs tag used in naming %q#T",
+    permerror (input_location, "%qs tag used in naming %q#T",
            class_key == union_type ? "union"
             : class_key == record_type ? "struct" : "class",
             type);
@@ -18040,7 +18747,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;
@@ -18049,7 +18756,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.
@@ -18066,8 +18773,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.  */
@@ -18117,41 +18825,54 @@ cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
   parser->object_scope = NULL_TREE;
 }
 
-/* Consume tokens up through a non-nested END token.  */
+/* Consume tokens up through a non-nested END token.  Returns TRUE if we
+   encounter the end of a block before what we were looking for.  */
 
-static void
+static bool
 cp_parser_cache_group (cp_parser *parser,
                       enum cpp_ttype end,
                       unsigned depth)
 {
   while (true)
     {
-      cp_token *token;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
 
-      /* Abort a parenthesized expression if we encounter a brace.  */
+      /* Abort a parenthesized expression if we encounter a semicolon.  */
       if ((end == CPP_CLOSE_PAREN || depth == 0)
-         && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-       return;
+         && token->type == CPP_SEMICOLON)
+       return true;
       /* If we've reached the end of the file, stop.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)
+      if (token->type == CPP_EOF
          || (end != CPP_PRAGMA_EOL
-             && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL)))
-       return;
-      /* Consume the next token.  */
-      token = cp_lexer_consume_token (parser->lexer);
+             && token->type == CPP_PRAGMA_EOL))
+       return true;
+      if (token->type == CPP_CLOSE_BRACE && depth == 0)
+       /* We've hit the end of an enclosing block, so there's been some
+          kind of syntax error.  */
+       return true;
+
+      /* Consume the token.  */
+      cp_lexer_consume_token (parser->lexer);
       /* See if it starts a new group.  */
       if (token->type == CPP_OPEN_BRACE)
        {
          cp_parser_cache_group (parser, CPP_CLOSE_BRACE, depth + 1);
+         /* In theory this should probably check end == '}', but
+            cp_parser_save_member_function_body needs it to exit
+            after either '}' or ')' when called with ')'.  */
          if (depth == 0)
-           return;
+           return false;
        }
       else if (token->type == CPP_OPEN_PAREN)
-       cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1);
+       {
+         cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1);
+         if (depth == 0 && end == CPP_CLOSE_PAREN)
+           return false;
+       }
       else if (token->type == CPP_PRAGMA)
        cp_parser_cache_group (parser, CPP_PRAGMA_EOL, depth + 1);
       else if (token->type == end)
-       return;
+       return false;
     }
 }
 
@@ -18319,7 +19040,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);
     }
 
@@ -18341,7 +19063,7 @@ cp_parser_objc_message_expression (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '['.  */
   receiver = cp_parser_objc_message_receiver (parser);
   messageargs = cp_parser_objc_message_args (parser);
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
 
   return objc_build_message_expr (build_tree_list (receiver, messageargs));
 }
@@ -18413,7 +19135,7 @@ cp_parser_objc_message_args (cp_parser* parser)
        return build_tree_list (selector, NULL_TREE);
 
       maybe_unary_selector_p = false;
-      cp_parser_require (parser, CPP_COLON, "`:'");
+      cp_parser_require (parser, CPP_COLON, "%<:%>");
       arg = cp_parser_assignment_expression (parser, false);
 
       sel_args
@@ -18452,15 +19174,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, "`('");
+  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, "`)'");
+  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;
     }
 
@@ -18475,9 +19200,9 @@ cp_parser_objc_defs_expression (cp_parser *parser)
   tree name;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@defs'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   name = cp_parser_identifier (parser);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return objc_get_class_ivars (name);
 }
@@ -18495,9 +19220,9 @@ cp_parser_objc_protocol_expression (cp_parser* parser)
   tree proto;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   proto = cp_parser_identifier (parser);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return objc_build_protocol_expr (proto);
 }
@@ -18525,7 +19250,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
   cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@selector'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   token = cp_lexer_peek_token (parser->lexer);
 
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
@@ -18572,7 +19297,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
     }
 
  finish_selector:
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return objc_build_selector_expr (sel_seq);
 }
@@ -18658,7 +19383,7 @@ cp_parser_objc_protocol_refs_opt (cp_parser* parser)
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '<'.  */
       protorefs = cp_parser_objc_identifier_list (parser);
-      cp_parser_require (parser, CPP_GREATER, "`>'");
+      cp_parser_require (parser, CPP_GREATER, "%<>%>");
     }
 
   return protorefs;
@@ -18733,7 +19458,7 @@ cp_parser_objc_protocol_qualifiers (cp_parser* parser)
 static tree
 cp_parser_objc_typename (cp_parser* parser)
 {
-  tree typename = NULL_TREE;
+  tree type_name = NULL_TREE;
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
@@ -18747,11 +19472,11 @@ cp_parser_objc_typename (cp_parser* parser)
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
        cp_type = cp_parser_type_id (parser);
 
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-      typename = build_tree_list (proto_quals, cp_type);
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      type_name = build_tree_list (proto_quals, cp_type);
     }
 
-  return typename;
+  return type_name;
 }
 
 /* Check to see if TYPE refers to an Objective-C selector name.  */
@@ -18775,7 +19500,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;
     }
 
@@ -18808,7 +19533,7 @@ cp_parser_objc_method_keyword_params (cp_parser* parser)
 
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
     {
-      tree selector = NULL_TREE, typename, identifier;
+      tree selector = NULL_TREE, type_name, identifier;
 
       if (token->type != CPP_COLON)
        selector = cp_parser_objc_selector (parser);
@@ -18819,14 +19544,14 @@ cp_parser_objc_method_keyword_params (cp_parser* parser)
        return selector;
 
       maybe_unary_selector_p = false;
-      cp_parser_require (parser, CPP_COLON, "`:'");
-      typename = cp_parser_objc_typename (parser);
+      cp_parser_require (parser, CPP_COLON, "%<:%>");
+      type_name = cp_parser_objc_typename (parser);
       identifier = cp_parser_identifier (parser);
 
       params
        = chainon (params,
                   objc_build_keyword_decl (selector,
-                                           typename,
+                                           type_name,
                                            identifier));
 
       token = cp_lexer_peek_token (parser->lexer);
@@ -19056,11 +19781,10 @@ cp_parser_objc_class_ivars (cp_parser* parser)
          attributes = chainon (prefix_attributes, attributes);
 
          if (width)
-           {
              /* Create the bitfield declaration.  */
-             decl = grokbitfield (declarator, &declspecs, width);
-             cplus_decl_attributes (&decl, attributes, /*flags=*/0);
-           }
+             decl = grokbitfield (declarator, &declspecs,
+                                  width,
+                                  attributes);
          else
            decl = grokfield (declarator, &declspecs,
                              NULL_TREE, /*init_const_expr_p=*/false,
@@ -19106,7 +19830,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;
     }
 
@@ -19149,7 +19874,7 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
       *categ = cp_parser_identifier (parser);
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
     }
 }
 
@@ -19242,7 +19967,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);
     }
 }
@@ -19269,7 +19995,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
   location_t location;
   tree stmt;
 
-  cp_parser_require_keyword (parser, RID_AT_TRY, "`@try'");
+  cp_parser_require_keyword (parser, RID_AT_TRY, "%<@try%>");
   location = cp_lexer_peek_token (parser->lexer)->location;
   /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
      node, lest it get absorbed into the surrounding block.  */
@@ -19283,13 +20009,13 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
       tree parm;
 
       cp_lexer_consume_token (parser->lexer);
-      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
       parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
       parm = grokdeclarator (parmdecl->declarator,
                             &parmdecl->decl_specifiers,
                             PARM, /*initialized=*/0,
                             /*attrlist=*/NULL);
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
       objc_begin_catch_clause (parm);
       cp_parser_compound_statement (parser, NULL, false);
       objc_finish_catch_clause ();
@@ -19321,12 +20047,12 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
   location_t location;
   tree lock, stmt;
 
-  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "`@synchronized'");
+  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "%<@synchronized%>");
 
   location = cp_lexer_peek_token (parser->lexer)->location;
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   lock = cp_parser_expression (parser, false);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
      node, lest it get absorbed into the surrounding block.  */
@@ -19347,7 +20073,7 @@ static tree
 cp_parser_objc_throw_statement (cp_parser *parser) {
   tree expr = NULL_TREE;
 
-  cp_parser_require_keyword (parser, RID_AT_THROW, "`@throw'");
+  cp_parser_require_keyword (parser, RID_AT_THROW, "%<@throw%>");
 
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     expr = cp_parser_assignment_expression (parser, false);
@@ -19373,7 +20099,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);
     }
 
@@ -19406,7 +20133,9 @@ cp_parser_omp_clause_name (cp_parser *parser)
       switch (p[0])
        {
        case 'c':
-         if (!strcmp ("copyin", p))
+         if (!strcmp ("collapse", p))
+           result = PRAGMA_OMP_CLAUSE_COLLAPSE;
+         else if (!strcmp ("copyin", p))
            result = PRAGMA_OMP_CLAUSE_COPYIN;
          else if (!strcmp ("copyprivate", p))
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
@@ -19439,6 +20168,10 @@ cp_parser_omp_clause_name (cp_parser *parser)
          else if (!strcmp ("shared", p))
            result = PRAGMA_OMP_CLAUSE_SHARED;
          break;
+       case 'u':
+         if (!strcmp ("untied", p))
+           result = PRAGMA_OMP_CLAUSE_UNTIED;
+         break;
        }
     }
 
@@ -19451,14 +20184,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 omp_clause_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;
       }
 }
@@ -19481,10 +20215,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,
@@ -19493,9 +20229,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);
@@ -19512,7 +20248,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       cp_lexer_consume_token (parser->lexer);
     }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     {
       int ending;
 
@@ -19536,21 +20272,63 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 static tree
 cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
 {
-  if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return cp_parser_omp_var_list_no_open (parser, kind, list);
   return list;
 }
 
+/* OpenMP 3.0:
+   collapse ( constant-expression ) */
+
+static tree
+cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location)
+{
+  tree c, num;
+  location_t loc;
+  HOST_WIDE_INT n;
+
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+    return list;
+
+  num = cp_parser_constant_expression (parser, false, NULL);
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  if (num == error_mark_node)
+    return list;
+  num = fold_non_dependent_expr (num);
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
+      || !host_integerp (num, 0)
+      || (n = tree_low_cst (num, 0)) <= 0
+      || (int) n != n)
+    {
+      error ("%Hcollapse argument needs positive constant integer expression",
+            &loc);
+      return list;
+    }
+
+  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;
+
+  return c;
+}
+
 /* OpenMP 2.5:
    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;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
@@ -19583,7 +20361,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
       cp_parser_error (parser, "expected %<none%> or %<shared%>");
     }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
@@ -19591,7 +20369,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;
@@ -19603,22 +20381,22 @@ 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;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
   t = cp_parser_condition (parser);
 
   if (t == error_mark_node
-      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*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;
@@ -19631,11 +20409,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;
@@ -19646,22 +20425,24 @@ 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;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
   t = cp_parser_expression (parser, false);
 
   if (t == error_mark_node
-      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*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;
@@ -19674,11 +20455,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;
@@ -19697,7 +20480,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
   enum tree_code code;
   tree nlist, c;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
   switch (cp_lexer_peek_token (parser->lexer)->type)
@@ -19727,7 +20510,8 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
       code = TRUTH_ORIF_EXPR;
       break;
     default:
-      cp_parser_error (parser, "`+', `*', `-', `&', `^', `|', `&&', or `||'");
+      cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, "
+                              "%<|%>, %<&&%>, or %<||%>");
     resync_fail:
       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                             /*or_comma=*/false,
@@ -19736,7 +20520,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
     }
   cp_lexer_consume_token (parser->lexer);
 
-  if (!cp_parser_require (parser, CPP_COLON, "`:'"))
+  if (!cp_parser_require (parser, CPP_COLON, "%<:%>"))
     goto resync_fail;
 
   nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list);
@@ -19751,14 +20535,14 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
    schedule ( schedule-kind , expression )
 
    schedule-kind:
-     static | dynamic | guided | runtime  */
+     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;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
   c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
@@ -19794,31 +20578,38 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
     }
   else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
     OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
+  else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
+    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
   else
     goto invalid_kind;
   cp_lexer_consume_token (parser->lexer);
 
   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 ("%Hschedule %<auto%> does not take "
+              "a %<chunk_size%> parameter", &token->location);
       else
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
-      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
        goto resync_fail;
     }
-  else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`,' or `)'"))
+  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;
 
@@ -19831,6 +20622,22 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
   return list;
 }
 
+/* OpenMP 3.0:
+   untied */
+
+static tree
+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", location);
+
+  c = build_omp_clause (OMP_CLAUSE_UNTIED);
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
 /* Parse all OpenMP clauses.  The set clauses allowed by the directive
    is a bitmask in MASK.  Return the list of clauses found; the result
    of clause default goes in *pdefault.  */
@@ -19841,6 +20648,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))
     {
@@ -19851,11 +20659,17 @@ 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,
+                                                  token->location);
+         c_name = "collapse";
+         break;
        case PRAGMA_OMP_CLAUSE_COPYIN:
          clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYIN, clauses);
          c_name = "copyin";
@@ -19866,7 +20680,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:
@@ -19875,7 +20690,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:
@@ -19884,15 +20699,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:
@@ -19905,7 +20722,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:
@@ -19913,6 +20731,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
                                            clauses);
          c_name = "shared";
          break;
+       case PRAGMA_OMP_CLAUSE_UNTIED:
+         clauses = cp_parser_omp_clause_untied (parser, clauses,
+                                                token->location);
+         c_name = "nowait";
+         break;
        default:
          cp_parser_error (parser, "expected %<#pragma omp%> clause");
          goto saw_error;
@@ -19923,7 +20746,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:
@@ -20093,7 +20916,7 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
       name = cp_parser_identifier (parser);
 
       if (name == error_mark_node
-         || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+         || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
        cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                               /*or_comma=*/false,
                                               /*consume_paren=*/true);
@@ -20122,94 +20945,490 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
   finish_omp_flush ();
 }
 
-/* Parse the restricted form of the for statment allowed by OpenMP.  */
+/* Helper function, to parse omp for increment expression.  */
 
 static tree
-cp_parser_omp_for_loop (cp_parser *parser)
+cp_parser_omp_for_cond (cp_parser *parser, tree decl)
 {
-  tree init, cond, incr, body, decl, pre_body;
-  location_t loc;
+  tree lhs = cp_parser_cast_expression (parser, false, false), rhs;
+  enum tree_code op;
+  cp_token *token;
 
-  if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+  if (lhs != decl)
     {
-      cp_parser_error (parser, "for statement expected");
-      return NULL;
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
     }
-  loc = cp_lexer_consume_token (parser->lexer)->location;
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
-    return NULL;
 
-  init = decl = NULL;
-  pre_body = push_stmt_list ();
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+  token = cp_lexer_peek_token (parser->lexer);
+  op = binops_by_token [token->type].tree_type;
+  switch (op)
     {
-      cp_decl_specifier_seq type_specifiers;
+    case LT_EXPR:
+    case LE_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+      break;
+    default:
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  cp_lexer_consume_token (parser->lexer);
+  rhs = cp_parser_binary_expression (parser, false,
+                                    PREC_RELATIONAL_EXPRESSION);
+  if (rhs == error_mark_node
+      || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  return build2 (op, boolean_type_node, lhs, rhs);
+}
 
-      /* First, try to parse as an initialized declaration.  See
-        cp_parser_condition, from whence the bulk of this is copied.  */
+/* Helper function, to parse omp for increment expression.  */
 
-      cp_parser_parse_tentatively (parser);
-      cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
-                                   &type_specifiers);
-      if (!cp_parser_error_occurred (parser))
+static tree
+cp_parser_omp_for_incr (cp_parser *parser, tree decl)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  enum tree_code op;
+  tree lhs, rhs;
+  cp_id_kind idk;
+  bool decl_first;
+
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    {
+      op = (token->type == CPP_PLUS_PLUS
+           ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
+      cp_lexer_consume_token (parser->lexer);
+      lhs = cp_parser_cast_expression (parser, false, false);
+      if (lhs != decl)
+       return error_mark_node;
+      return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+    }
+
+  lhs = cp_parser_primary_expression (parser, false, false, false, &idk);
+  if (lhs != decl)
+    return error_mark_node;
+
+  token = cp_lexer_peek_token (parser->lexer);
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    {
+      op = (token->type == CPP_PLUS_PLUS
+           ? POSTINCREMENT_EXPR : POSTDECREMENT_EXPR);
+      cp_lexer_consume_token (parser->lexer);
+      return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+    }
+
+  op = cp_parser_assignment_operator_opt (parser);
+  if (op == ERROR_MARK)
+    return error_mark_node;
+
+  if (op != NOP_EXPR)
+    {
+      rhs = cp_parser_assignment_expression (parser, false);
+      rhs = build2 (op, TREE_TYPE (decl), decl, rhs);
+      return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+    }
+
+  lhs = cp_parser_binary_expression (parser, false,
+                                    PREC_ADDITIVE_EXPRESSION);
+  token = cp_lexer_peek_token (parser->lexer);
+  decl_first = lhs == decl;
+  if (decl_first)
+    lhs = NULL_TREE;
+  if (token->type != CPP_PLUS
+      && token->type != CPP_MINUS)
+    return error_mark_node;
+
+  do
+    {
+      op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
+      cp_lexer_consume_token (parser->lexer);
+      rhs = cp_parser_binary_expression (parser, false,
+                                        PREC_ADDITIVE_EXPRESSION);
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
        {
-         tree asm_specification, attributes;
-         cp_declarator *declarator;
-
-         declarator = cp_parser_declarator (parser,
-                                            CP_PARSER_DECLARATOR_NAMED,
-                                            /*ctor_dtor_or_conv_p=*/NULL,
-                                            /*parenthesized_p=*/NULL,
-                                            /*member_p=*/false);
-         attributes = cp_parser_attributes_opt (parser);
-         asm_specification = cp_parser_asm_specification_opt (parser);
+         if (lhs == NULL_TREE)
+           {
+             if (op == PLUS_EXPR)
+               lhs = rhs;
+             else
+               lhs = build_x_unary_op (NEGATE_EXPR, rhs, tf_warning_or_error);
+           }
+         else
+           lhs = build_x_binary_op (op, lhs, ERROR_MARK, rhs, ERROR_MARK,
+                                    NULL, tf_warning_or_error);
+       }
+    }
+  while (token->type == CPP_PLUS || token->type == CPP_MINUS);
+
+  if (!decl_first)
+    {
+      if (rhs != decl || op == MINUS_EXPR)
+       return error_mark_node;
+      rhs = build2 (op, TREE_TYPE (decl), lhs, decl);
+    }
+  else
+    rhs = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, lhs);
+
+  return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+}
+
+/* Parse the restricted form of the for statement allowed by OpenMP.  */
+
+static tree
+cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
+{
+  tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
+  tree for_block = NULL_TREE, real_decl, initv, condv, incrv, declv;
+  tree this_pre_body, cl;
+  location_t loc_first;
+  bool collapse_err = false;
+  int i, collapse = 1, nbraces = 0;
+
+  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
+    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
+      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
+
+  gcc_assert (collapse >= 1);
+
+  declv = make_tree_vec (collapse);
+  initv = make_tree_vec (collapse);
+  condv = make_tree_vec (collapse);
+  incrv = make_tree_vec (collapse);
+
+  loc_first = cp_lexer_peek_token (parser->lexer)->location;
+
+  for (i = 0; i < collapse; i++)
+    {
+      int bracecount = 0;
+      bool add_private_clause = false;
+      location_t loc;
+
+      if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+       {
+         cp_parser_error (parser, "for statement expected");
+         return NULL;
+       }
+      loc = cp_lexer_consume_token (parser->lexer)->location;
+
+      if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+       return NULL;
+
+      init = decl = real_decl = NULL;
+      this_pre_body = push_stmt_list ();
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       {
+         /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
+
+            init-expr:
+                      var = lb
+                      integer-type var = lb
+                      random-access-iterator-type var = lb
+                      pointer-type var = lb
+         */
+         cp_decl_specifier_seq type_specifiers;
+
+         /* First, try to parse as an initialized declaration.  See
+            cp_parser_condition, from whence the bulk of this is copied.  */
 
-         cp_parser_require (parser, CPP_EQ, "`='");
+         cp_parser_parse_tentatively (parser);
+         cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+                                       &type_specifiers);
          if (cp_parser_parse_definitely (parser))
            {
-             tree pushed_scope;
+             /* If parsing a type specifier seq succeeded, then this
+                MUST be a initialized declaration.  */
+             tree asm_specification, attributes;
+             cp_declarator *declarator;
+
+             declarator = cp_parser_declarator (parser,
+                                                CP_PARSER_DECLARATOR_NAMED,
+                                                /*ctor_dtor_or_conv_p=*/NULL,
+                                                /*parenthesized_p=*/NULL,
+                                                /*member_p=*/false);
+             attributes = cp_parser_attributes_opt (parser);
+             asm_specification = cp_parser_asm_specification_opt (parser);
+
+             if (declarator == cp_error_declarator) 
+               cp_parser_skip_to_end_of_statement (parser);
+
+             else 
+               {
+                 tree pushed_scope, auto_node;
+
+                 decl = start_decl (declarator, &type_specifiers,
+                                    SD_INITIALIZED, attributes,
+                                    /*prefix_attributes=*/NULL_TREE,
+                                    &pushed_scope);
+
+                 auto_node = type_uses_auto (TREE_TYPE (decl));
+                 if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+                   {
+                     if (cp_lexer_next_token_is (parser->lexer, 
+                                                 CPP_OPEN_PAREN))
+                       error ("parenthesized initialization is not allowed in "
+                              "OpenMP %<for%> loop");
+                     else
+                       /* Trigger an error.  */
+                       cp_parser_require (parser, CPP_EQ, "%<=%>");
+
+                     init = error_mark_node;
+                     cp_parser_skip_to_end_of_statement (parser);
+                   }
+                 else if (CLASS_TYPE_P (TREE_TYPE (decl))
+                          || type_dependent_expression_p (decl)
+                          || auto_node)
+                   {
+                     bool is_direct_init, is_non_constant_init;
+
+                     init = cp_parser_initializer (parser,
+                                                   &is_direct_init,
+                                                   &is_non_constant_init);
 
-             decl = start_decl (declarator, &type_specifiers,
-                                /*initialized_p=*/false, attributes,
-                                /*prefix_attributes=*/NULL_TREE,
-                                &pushed_scope);
+                     if (auto_node && describable_type (init))
+                       {
+                         TREE_TYPE (decl)
+                           = do_auto_deduction (TREE_TYPE (decl), init,
+                                                auto_node);
+
+                         if (!CLASS_TYPE_P (TREE_TYPE (decl))
+                             && !type_dependent_expression_p (decl))
+                           goto non_class;
+                       }
+                     
+                     cp_finish_decl (decl, init, !is_non_constant_init,
+                                     asm_specification,
+                                     LOOKUP_ONLYCONVERTING);
+                     if (CLASS_TYPE_P (TREE_TYPE (decl)))
+                       {
+                         for_block
+                           = tree_cons (NULL, this_pre_body, for_block);
+                         init = NULL_TREE;
+                       }
+                     else
+                       init = pop_stmt_list (this_pre_body);
+                     this_pre_body = NULL_TREE;
+                   }
+                 else
+                   {
+                     /* Consume '='.  */
+                     cp_lexer_consume_token (parser->lexer);
+                     init = cp_parser_assignment_expression (parser, false);
 
-             init = cp_parser_assignment_expression (parser, false);
+                   non_class:
+                     if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+                       init = error_mark_node;
+                     else
+                       cp_finish_decl (decl, NULL_TREE,
+                                       /*init_const_expr_p=*/false,
+                                       asm_specification,
+                                       LOOKUP_ONLYCONVERTING);
+                   }
 
-             if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
-               init = error_mark_node;
+                 if (pushed_scope)
+                   pop_scope (pushed_scope);
+               }
+           }
+         else 
+           {
+             cp_id_kind idk;
+             /* If parsing a type specifier sequence failed, then
+                this MUST be a simple expression.  */
+             cp_parser_parse_tentatively (parser);
+             decl = cp_parser_primary_expression (parser, false, false,
+                                                  false, &idk);
+             if (!cp_parser_error_occurred (parser)
+                 && decl
+                 && DECL_P (decl)
+                 && CLASS_TYPE_P (TREE_TYPE (decl)))
+               {
+                 tree rhs;
+
+                 cp_parser_parse_definitely (parser);
+                 cp_parser_require (parser, CPP_EQ, "%<=%>");
+                 rhs = cp_parser_assignment_expression (parser, false);
+                 finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR,
+                                                        rhs,
+                                                        tf_warning_or_error));
+                 add_private_clause = true;
+               }
              else
-               cp_finish_decl (decl, NULL_TREE, /*init_const_expr_p=*/false,
-                               asm_specification, LOOKUP_ONLYCONVERTING);
+               {
+                 decl = NULL;
+                 cp_parser_abort_tentative_parse (parser);
+                 init = cp_parser_expression (parser, false);
+                 if (init)
+                   {
+                     if (TREE_CODE (init) == MODIFY_EXPR
+                         || TREE_CODE (init) == MODOP_EXPR)
+                       real_decl = TREE_OPERAND (init, 0);
+                   }
+               }
+           }
+       }
+      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+      if (this_pre_body)
+       {
+         this_pre_body = pop_stmt_list (this_pre_body);
+         if (pre_body)
+           {
+             tree t = pre_body;
+             pre_body = push_stmt_list ();
+             add_stmt (t);
+             add_stmt (this_pre_body);
+             pre_body = pop_stmt_list (pre_body);
+           }
+         else
+           pre_body = this_pre_body;
+       }
 
-             if (pushed_scope)
-               pop_scope (pushed_scope);
+      if (decl)
+       real_decl = decl;
+      if (par_clauses != NULL && real_decl != NULL_TREE)
+       {
+         tree *c;
+         for (c = par_clauses; *c ; )
+           if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE
+               && OMP_CLAUSE_DECL (*c) == real_decl)
+             {
+               error ("%Hiteration variable %qD should not be firstprivate",
+                      &loc, real_decl);
+               *c = OMP_CLAUSE_CHAIN (*c);
+             }
+           else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE
+                    && OMP_CLAUSE_DECL (*c) == real_decl)
+             {
+               /* Add lastprivate (decl) clause to OMP_FOR_CLAUSES,
+                  change it to shared (decl) in OMP_PARALLEL_CLAUSES.  */
+               tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+               OMP_CLAUSE_DECL (l) = real_decl;
+               OMP_CLAUSE_CHAIN (l) = clauses;
+               CP_OMP_CLAUSE_INFO (l) = CP_OMP_CLAUSE_INFO (*c);
+               clauses = l;
+               OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
+               CP_OMP_CLAUSE_INFO (*c) = NULL;
+               add_private_clause = false;
+             }
+           else
+             {
+               if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE
+                   && OMP_CLAUSE_DECL (*c) == real_decl)
+                 add_private_clause = false;
+               c = &OMP_CLAUSE_CHAIN (*c);
+             }
+       }
+
+      if (add_private_clause)
+       {
+         tree c;
+         for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+           {
+             if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+                 && OMP_CLAUSE_DECL (c) == decl)
+               break;
+             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                      && OMP_CLAUSE_DECL (c) == decl)
+               error ("%Hiteration variable %qD should not be firstprivate",
+                      &loc, decl);
+             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                      && OMP_CLAUSE_DECL (c) == decl)
+               error ("%Hiteration variable %qD should not be reduction",
+                      &loc, decl);
+           }
+         if (c == NULL)
+           {
+             c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+             OMP_CLAUSE_DECL (c) = decl;
+             c = finish_omp_clauses (c);
+             if (c)
+               {
+                 OMP_CLAUSE_CHAIN (c) = clauses;
+                 clauses = c;
+               }
            }
        }
-      else
-       cp_parser_abort_tentative_parse (parser);
 
-      /* If parsing as an initialized declaration failed, try again as
-        a simple expression.  */
-      if (decl == NULL)
-       init = cp_parser_expression (parser, false);
-    }
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
-  pre_body = pop_stmt_list (pre_body);
+      cond = NULL;
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       {
+         /* If decl is an iterator, preserve LHS and RHS of the relational
+            expr until finish_omp_for.  */
+         if (decl
+             && (type_dependent_expression_p (decl)
+                 || CLASS_TYPE_P (TREE_TYPE (decl))))
+           cond = cp_parser_omp_for_cond (parser, decl);
+         else
+           cond = cp_parser_condition (parser);
+       }
+      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
-  cond = NULL;
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    cond = cp_parser_condition (parser);
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+      incr = NULL;
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+       {
+         /* If decl is an iterator, preserve the operator on decl
+            until finish_omp_for.  */
+         if (decl
+             && (type_dependent_expression_p (decl)
+                 || CLASS_TYPE_P (TREE_TYPE (decl))))
+           incr = cp_parser_omp_for_incr (parser, decl);
+         else
+           incr = cp_parser_expression (parser, false);
+       }
 
-  incr = NULL;
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
-    incr = cp_parser_expression (parser, false);
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                              /*or_comma=*/false,
+                                              /*consume_paren=*/true);
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
-    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
-                                          /*or_comma=*/false,
-                                          /*consume_paren=*/true);
+      TREE_VEC_ELT (declv, i) = decl;
+      TREE_VEC_ELT (initv, i) = init;
+      TREE_VEC_ELT (condv, i) = cond;
+      TREE_VEC_ELT (incrv, i) = incr;
+
+      if (i == collapse - 1)
+       break;
+
+      /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
+        in between the collapsed for loops to be still considered perfectly
+        nested.  Hopefully the final version clarifies this.
+        For now handle (multiple) {'s and empty statements.  */
+      cp_parser_parse_tentatively (parser);
+      do
+       {
+         if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+           break;
+         else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+           {
+             cp_lexer_consume_token (parser->lexer);
+             bracecount++;
+           }
+         else if (bracecount
+                  && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+           cp_lexer_consume_token (parser->lexer);
+         else
+           {
+             loc = cp_lexer_peek_token (parser->lexer)->location;
+             error ("%Hnot enough collapsed for loops", &loc);
+             collapse_err = true;
+             cp_parser_abort_tentative_parse (parser);
+             declv = NULL_TREE;
+             break;
+           }
+       }
+      while (1);
+
+      if (declv)
+       {
+         cp_parser_parse_definitely (parser);
+         nbraces += bracecount;
+       }
+    }
 
   /* Note that we saved the original contents of this flag when we entered
      the structured block, and so we don't need to re-save it here.  */
@@ -20221,7 +21440,41 @@ cp_parser_omp_for_loop (cp_parser *parser)
   cp_parser_statement (parser, NULL_TREE, false, NULL);
   body = pop_stmt_list (body);
 
-  return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
+  if (declv == NULL_TREE)
+    ret = NULL_TREE;
+  else
+    ret = finish_omp_for (loc_first, declv, initv, condv, incrv, body,
+                         pre_body, clauses);
+
+  while (nbraces)
+    {
+      if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         nbraces--;
+       }
+      else if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+       cp_lexer_consume_token (parser->lexer);
+      else
+       {
+         if (!collapse_err)
+           {
+             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, "%<}%>");
+       }
+    }
+
+  while (for_block)
+    {
+      add_stmt (pop_stmt_list (TREE_VALUE (for_block)));
+      for_block = TREE_CHAIN (for_block);
+    }
+
+  return ret;
 }
 
 /* OpenMP 2.5:
@@ -20235,7 +21488,8 @@ cp_parser_omp_for_loop (cp_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
        | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
-       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)              \
+       | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE))
 
 static tree
 cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
@@ -20249,9 +21503,7 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
   sb = begin_omp_structured_block ();
   save = cp_parser_begin_omp_structured_block (parser);
 
-  ret = cp_parser_omp_for_loop (parser);
-  if (ret)
-    OMP_FOR_CLAUSES (ret) = clauses;
+  ret = cp_parser_omp_for_loop (parser, clauses, NULL);
 
   cp_parser_end_omp_structured_block (parser, save);
   add_stmt (finish_omp_structured_block (sb));
@@ -20297,7 +21549,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
   bool error_suppress = false;
   cp_token *tok;
 
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
     return NULL_TREE;
 
   stmt = push_stmt_list ();
@@ -20352,7 +21604,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 
   substmt = pop_stmt_list (stmt);
 
@@ -20449,9 +21701,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
 
     case PRAGMA_OMP_PARALLEL_FOR:
       c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
-      stmt = cp_parser_omp_for_loop (parser);
-      if (stmt)
-       OMP_FOR_CLAUSES (stmt) = ws_clause;
+      cp_parser_omp_for_loop (parser, ws_clause, &par_clause);
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
@@ -20496,6 +21746,43 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
   return add_stmt (stmt);
 }
 
+/* OpenMP 3.0:
+   # pragma omp task task-clause[optseq] new-line
+     structured-block  */
+
+#define OMP_TASK_CLAUSE_MASK                           \
+       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
+       | (1u << PRAGMA_OMP_CLAUSE_UNTIED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
+       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+
+static tree
+cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree clauses, block;
+  unsigned int save;
+
+  clauses = cp_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
+                                      "#pragma omp task", pragma_tok);
+  block = begin_omp_task ();
+  save = cp_parser_begin_omp_structured_block (parser);
+  cp_parser_statement (parser, NULL_TREE, false, NULL);
+  cp_parser_end_omp_structured_block (parser, save);
+  return finish_omp_task (clauses, block);
+}
+
+/* OpenMP 3.0:
+   # pragma omp taskwait new-line  */
+
+static void
+cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
+{
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+  finish_omp_taskwait ();
+}
+
 /* OpenMP 2.5:
    # pragma omp threadprivate (variable-list) */
 
@@ -20543,6 +21830,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
     case PRAGMA_OMP_SINGLE:
       stmt = cp_parser_omp_single (parser, pragma_tok);
       break;
+    case PRAGMA_OMP_TASK:
+      stmt = cp_parser_omp_task (parser, pragma_tok);
+      break;
     default:
       gcc_unreachable ();
     }
@@ -20581,10 +21871,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)
@@ -20617,7 +21908,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:
@@ -20627,8 +21919,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;
@@ -20642,8 +21934,24 @@ 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;
+       }
+      break;
+
+    case PRAGMA_OMP_TASKWAIT:
+      switch (context)
+       {
+       case pragma_compound:
+         cp_parser_omp_taskwait (parser, pragma_tok);
+         return false;
+       case pragma_stmt:
+         error ("%H%<#pragma omp taskwait%> may only be "
+                "used in compound statements",
+                &pragma_tok->location);
          break;
        default:
          goto bad_stmt;
@@ -20662,14 +21970,15 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
     case PRAGMA_OMP_PARALLEL:
     case PRAGMA_OMP_SECTIONS:
     case PRAGMA_OMP_SINGLE:
+    case PRAGMA_OMP_TASK:
       if (context == pragma_external)
        goto bad_stmt;
       cp_parser_omp_construct (parser, pragma_tok);
       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: