OSDN Git Service

./:
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 21a762d..bdf3058 100644 (file)
@@ -1,6 +1,6 @@
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005, 2007, 2008  Free Software Foundation, Inc.
+   2005, 2007, 2008, 2009  Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "target.h"
 #include "cgraph.h"
 #include "c-common.h"
+#include "plugin.h"
 
 \f
 /* The lexer.  */
@@ -47,8 +48,7 @@ along with GCC; see the file COPYING3.  If not see
 /* A token's value and its associated deferred access checks and
    qualifying scope.  */
 
-struct tree_check GTY(())
-{
+struct GTY(()) tree_check {
   /* The value associated with the token.  */
   tree value;
   /* The checks that have been associated with value.  */
@@ -60,8 +60,7 @@ struct tree_check GTY(())
 
 /* A C++ token.  */
 
-typedef struct cp_token GTY (())
-{
+typedef struct GTY (()) cp_token {
   /* The kind of token.  */
   ENUM_BITFIELD (cpp_ttype) type : 8;
   /* If this token is a keyword, this value indicates which keyword.
@@ -71,14 +70,14 @@ 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
      KEYWORD is RID_MAX) iff this name was looked up and found to be
      ambiguous.  An error has already been reported.  */
   BOOL_BITFIELD ambiguous_p : 1;
+  /* The location at which this token was found.  */
+  location_t location;
   /* The value associated with this token, if any.  */
   union cp_token_value {
     /* Used for CPP_NESTED_NAME_SPECIFIER and CPP_TEMPLATE_ID.  */
@@ -86,8 +85,6 @@ typedef struct cp_token GTY (())
     /* Use for all other tokens.  */
     tree GTY((tag ("0"))) value;
   } GTY((desc ("(%1.type == CPP_TEMPLATE_ID) || (%1.type == CPP_NESTED_NAME_SPECIFIER)"))) u;
-  /* The location at which this token was found.  */
-  location_t location;
 } cp_token;
 
 /* We use a stack of token pointer for saving token sets.  */
@@ -97,8 +94,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 },
-  0
+  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, 0, { NULL }
 };
 
 /* The cp_lexer structure represents the C++ lexer.  It is responsible
@@ -106,8 +102,7 @@ static cp_token eof_token =
    it to the parser.  Tokens are never added to the cp_lexer after
    it is created.  */
 
-typedef struct cp_lexer GTY (())
-{
+typedef struct GTY (()) cp_lexer {
   /* The memory allocated for the buffer.  NULL if this lexer does not
      own the token buffer.  */
   cp_token * GTY ((length ("%h.buffer_length"))) buffer;
@@ -146,8 +141,7 @@ typedef struct cp_lexer GTY (())
    a cp_token_cache, since everything in here is referenced through
    a lexer.  */
 
-typedef struct cp_token_cache GTY(())
-{
+typedef struct GTY(()) cp_token_cache {
   /* The beginning of the token range.  */
   cp_token * GTY((skip)) first;
 
@@ -253,6 +247,10 @@ static void cp_parser_initial_pragma
 static FILE *cp_lexer_debug_stream;
 #endif /* ENABLE_CHECKING */
 
+/* Nonzero if we are parsing an unevaluated operand: an operand to
+   sizeof, typeof, or alignof.  */
+int cp_unevaluated_operand;
+
 /* Create a new main C++ lexer, the lexer that gets tokens from the
    preprocessor.  */
 
@@ -312,8 +310,7 @@ cp_lexer_new_main (void)
 
   /* Subsequent preprocessor diagnostics should use compiler
      diagnostic functions to get the compiler source location.  */
-  cpp_get_options (parse_in)->client_diagnostic = true;
-  cpp_get_callbacks (parse_in)->error = cp_cpp_error;
+  done_lexing = true;
 
   gcc_assert (lexer->next_token->type != CPP_PURGED);
   return lexer;
@@ -408,7 +405,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
@@ -426,11 +422,6 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
          token->type = CPP_KEYWORD;
          /* Record which keyword.  */
          token->keyword = C_RID_CODE (token->u.value);
-         /* Update the value.  Some keywords are mapped to particular
-            entities, rather than simply having the value of the
-            corresponding IDENTIFIER_NODE.  For example, `__const' is
-            mapped to `const'.  */
-         token->u.value = ridpointers[token->keyword];
        }
       else
        {
@@ -441,12 +432,12 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
               /* Warn about the C++0x keyword (but still treat it as
                  an identifier).  */
               warning (OPT_Wc__0x_compat, 
-                       "identifier %<%s%> will become a keyword in C++0x",
-                       IDENTIFIER_POINTER (token->u.value));
+                       "identifier %qE will become a keyword in C++0x",
+                       token->u.value);
 
               /* 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;
@@ -473,20 +464,19 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
   else if (token->type == CPP_PRAGMA)
     {
       /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
-      token->pragma_kind = TREE_INT_CST_LOW (token->u.value);
+      token->pragma_kind = ((enum pragma_kind)
+                           TREE_INT_CST_LOW (token->u.value));
       token->u.value = NULL_TREE;
     }
 }
 
-/* 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 +519,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
@@ -850,7 +848,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
@@ -1010,9 +1008,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;
 
@@ -1021,6 +1020,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;
@@ -1187,7 +1187,7 @@ function_declarator_p (const cp_declarator *declarator)
 /* Flags that are passed to some parsing functions.  These values can
    be bitwise-ored together.  */
 
-typedef enum cp_parser_flags
+enum
 {
   /* No flags.  */
   CP_PARSER_FLAGS_NONE = 0x0,
@@ -1196,7 +1196,11 @@ typedef enum cp_parser_flags
   CP_PARSER_FLAGS_OPTIONAL = 0x1,
   /* When parsing a type-specifier, do not allow user-defined types.  */
   CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2
-} cp_parser_flags;
+};
+
+/* This type is used for parameters and variables which hold
+   combinations of the above flags.  */
+typedef int cp_parser_flags;
 
 /* The different kinds of declarators we want to parse.  */
 
@@ -1268,7 +1272,7 @@ typedef struct cp_parser_expression_stack_entry
   /* Tree code for the binary operation we are parsing.  */
   enum tree_code tree_type;
   /* Precedence of the binary operation we are parsing.  */
-  int prec;
+  enum cp_parser_prec prec;
 } cp_parser_expression_stack_entry;
 
 /* The stack for storing partial expressions.  We only need NUM_PREC_VALUES
@@ -1278,8 +1282,7 @@ typedef struct cp_parser_expression_stack_entry
   cp_parser_expression_stack[NUM_PREC_VALUES];
 
 /* Context that is saved and restored when parsing tentatively.  */
-typedef struct cp_parser_context GTY (())
-{
+typedef struct GTY (()) cp_parser_context {
   /* If this is a tentative parsing context, the status of the
      tentative parse.  */
   enum cp_parser_status_kind status;
@@ -1369,7 +1372,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)
     {
@@ -1385,8 +1388,7 @@ cp_parser_context_new (cp_parser_context* next)
 
 /* The cp_parser structure represents the C++ parser.  */
 
-typedef struct cp_parser GTY(())
-{
+typedef struct GTY(()) cp_parser {
   /* The lexer from which we are obtaining tokens.  */
   cp_lexer *lexer;
 
@@ -1578,25 +1580,25 @@ 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);
+  (cp_parser *, bool, bool, bool, cp_id_kind *);
 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 *);
-static tree cp_parser_parenthesized_expression_list
+  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
+static VEC(tree,gc) *cp_parser_parenthesized_expression_list
   (cp_parser *, bool, bool, bool, bool *);
 static void cp_parser_pseudo_destructor_name
   (cp_parser *, tree *, tree *);
 static tree cp_parser_unary_expression
-  (cp_parser *, bool, bool);
+  (cp_parser *, bool, bool, cp_id_kind *);
 static enum tree_code cp_parser_unary_operator
   (cp_token *);
 static tree cp_parser_new_expression
   (cp_parser *);
-static tree cp_parser_new_placement
+static VEC(tree,gc) *cp_parser_new_placement
   (cp_parser *);
 static tree cp_parser_new_type_id
   (cp_parser *, tree *);
@@ -1604,22 +1606,22 @@ static cp_declarator *cp_parser_new_declarator_opt
   (cp_parser *);
 static cp_declarator *cp_parser_direct_new_declarator
   (cp_parser *);
-static tree cp_parser_new_initializer
+static VEC(tree,gc) *cp_parser_new_initializer
   (cp_parser *);
 static tree cp_parser_delete_expression
   (cp_parser *);
 static tree cp_parser_cast_expression
-  (cp_parser *, bool, bool);
+  (cp_parser *, bool, bool, cp_id_kind *);
 static tree cp_parser_binary_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
 static tree cp_parser_assignment_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, cp_id_kind *);
 static enum tree_code cp_parser_assignment_operator_opt
   (cp_parser *);
 static tree cp_parser_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, cp_id_kind *);
 static tree cp_parser_constant_expression
   (cp_parser *, bool, bool *);
 static tree cp_parser_builtin_offsetof
@@ -1723,15 +1725,21 @@ 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 tree cp_parser_template_type_arg
+  (cp_parser *);
+static tree cp_parser_type_id_1
+  (cp_parser *, bool);
 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 *);
@@ -1743,6 +1751,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 *);
 
@@ -1894,15 +1904,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, cp_declarator *);
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
@@ -1938,9 +1948,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
@@ -1960,12 +1970,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 *);
@@ -1982,19 +1992,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
@@ -2020,7 +2030,7 @@ static bool cp_parser_is_string_literal
 static bool cp_parser_is_keyword
   (cp_token *, enum rid);
 static tree cp_parser_make_typename_type
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t location);
 static cp_declarator * cp_parser_make_indirect_declarator
   (enum tree_code, tree, cp_cv_quals, cp_declarator *);
 
@@ -2069,7 +2079,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;
        }
@@ -2079,7 +2089,7 @@ cp_parser_error (cp_parser* parser, const char* message)
                        CPP_KEYWORD, keywords are treated like
                        identifiers.  */
                     (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-                    token->u.value);
+                    token->u.value, token->flags);
     }
 }
 
@@ -2092,33 +2102,34 @@ static void
 cp_parser_name_lookup_error (cp_parser* parser,
                             tree name,
                             tree decl,
-                            const char* desired)
+                            const char* desired,
+                            location_t location)
 {
   /* If name lookup completely failed, tell the user that NAME was not
      declared.  */
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-       error ("%<%E::%E%> has not been declared",
-              parser->scope, name);
+       error ("%H%<%E::%E%> has not been declared",
+              &location, parser->scope, name);
       else if (parser->scope == global_namespace)
-       error ("%<::%E%> has not been declared", name);
+       error ("%H%<::%E%> has not been declared", &location, name);
       else if (parser->object_scope
               && !CLASS_TYPE_P (parser->object_scope))
-       error ("request for member %qE in non-class type %qT",
-              name, parser->object_scope);
+       error ("%Hrequest for member %qE in non-class type %qT",
+              &location, name, parser->object_scope);
       else if (parser->object_scope)
-       error ("%<%T::%E%> has not been declared",
-              parser->object_scope, name);
+       error ("%H%<%T::%E%> has not been declared",
+              &location, parser->object_scope, name);
       else
-       error ("%qE has not been declared", name);
+       error ("%H%qE has not been declared", &location, name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("%<%E::%E%> %s", parser->scope, name, desired);
+    error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
   else if (parser->scope == global_namespace)
-    error ("%<::%E%> %s", name, desired);
+    error ("%H%<::%E%> %s", &location, name, desired);
   else
-    error ("%qE %s", name, desired);
+    error ("%H%qE %s", &location, name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -2139,23 +2150,24 @@ 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;
+  int ds;
 
   for (ds = ds_first; ds != ds_last; ++ds)
     {
-      unsigned count = decl_specs->specs[(int)ds];
+      unsigned count = decl_specs->specs[ds];
       if (count < 2)
        continue;
       /* The "long" specifier is a special case because of "long long".  */
       if (ds == ds_long)
        {
          if (count > 2)
-           error ("%<long long long%> is too long for GCC");
-         else if (pedantic && !in_system_header && warn_long_long
-                   && cxx_dialect == cxx98)
-           pedwarn ("ISO C++ 1998 does not support %<long long%>");
+           error ("%H%<long long long%> is too long for GCC", &location);
+         else 
+           pedwarn_cxx98 (location, OPT_Wlong_long, 
+                          "ISO C++ 1998 does not support %<long long%>");
        }
       else if (count > 1)
        {
@@ -2175,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[ds]);
        }
     }
 }
@@ -2201,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
@@ -2218,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);
     }
 }
@@ -2227,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);
@@ -2288,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:
 
@@ -2343,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;
                      }
@@ -2358,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 ();
     }
@@ -2382,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,
@@ -2405,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);
@@ -2598,6 +2621,8 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
          /* Stop if this is an unnested '}', or closes the outermost
             nesting level.  */
          nesting_depth--;
+         if (nesting_depth < 0)
+           return;
          if (!nesting_depth)
            nesting_depth = -1;
          break;
@@ -2693,7 +2718,8 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok)
    using cp_parser_diagnose_invalid_type_name.  */
 
 static tree
-cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
+cp_parser_make_typename_type (cp_parser *parser, tree scope,
+                             tree id, location_t id_location)
 {
   tree result;
   if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -2701,7 +2727,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
       result = make_typename_type (scope, id, typename_type,
                                   /*complain=*/tf_none);
       if (result == error_mark_node)
-       cp_parser_diagnose_invalid_type_name (parser, scope, id);
+       cp_parser_diagnose_invalid_type_name (parser, scope, id, id_location);
       return result;
     }
   return make_typename_type (scope, id, typename_type, tf_error);
@@ -2919,7 +2945,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
              if (type == CPP_STRING)
                type = tok->type;
              else if (tok->type != CPP_STRING)
-               error ("unsupported non-standard concatenation of string literals");
+               error ("%Hunsupported non-standard concatenation "
+                       "of string literals", &tok->location);
            }
 
          obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -3098,7 +3125,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;
@@ -3119,6 +3146,12 @@ cp_parser_primary_expression (cp_parser *parser,
     case CPP_WCHAR:
     case CPP_NUMBER:
       token = cp_lexer_consume_token (parser->lexer);
+      if (TREE_CODE (token->u.value) == FIXED_CST)
+       {
+         error ("%Hfixed-point types not supported in C++",
+                &token->location);
+         return error_mark_node;
+       }
       /* Floating-point literals are only allowed in an integral
         constant expression if they are cast to an integral or
         enumeration type.  */
@@ -3195,8 +3228,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:
@@ -3207,8 +3240,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;
              }
@@ -3225,7 +3259,7 @@ cp_parser_primary_expression (cp_parser *parser,
        else
          {
            /* Parse the parenthesized expression.  */
-           expr = cp_parser_expression (parser, cast_p);
+           expr = cp_parser_expression (parser, cast_p, idk);
            /* Let the front end know that this expression was
               enclosed in parentheses. This matters in case, for
               example, the expression is of the form `A::B', since
@@ -3265,7 +3299,8 @@ cp_parser_primary_expression (cp_parser *parser,
          cp_lexer_consume_token (parser->lexer);
          if (parser->local_variables_forbidden_p)
            {
-             error ("%<this%> may not be used in this context");
+             error ("%H%<this%> may not be used in this context",
+                     &token->location);
              return error_mark_node;
            }
          /* Pointers cannot appear in constant-expressions.  */
@@ -3281,16 +3316,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:
          {
@@ -3304,7 +3362,7 @@ cp_parser_primary_expression (cp_parser *parser,
            cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
            /* Now, parse the assignment-expression.  */
            expression = cp_parser_assignment_expression (parser,
-                                                         /*cast_p=*/false);
+                                                         /*cast_p=*/false, NULL);
            /* Look for the `,'.  */
            cp_parser_require (parser, CPP_COMMA, "%<,%>");
            /* Parse the type-id.  */
@@ -3365,6 +3423,7 @@ cp_parser_primary_expression (cp_parser *parser,
        const char *error_msg;
        bool template_p;
        bool done;
+       cp_token *id_expr_token;
 
       id_expression:
        /* Parse the id-expression.  */
@@ -3377,6 +3436,7 @@ cp_parser_primary_expression (cp_parser *parser,
                                     /*optional_p=*/false);
        if (id_expression == error_mark_node)
          return error_mark_node;
+       id_expr_token = token;
        token = cp_lexer_peek_token (parser->lexer);
        done = (token->type != CPP_OPEN_SQUARE
                && token->type != CPP_OPEN_PAREN
@@ -3400,7 +3460,8 @@ cp_parser_primary_expression (cp_parser *parser,
                                          template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
-                                         &ambiguous_decls);
+                                         &ambiguous_decls,
+                                         id_expr_token->location);
            /* If the lookup was ambiguous, an error will already have
               been issued.  */
            if (ambiguous_decls)
@@ -3447,8 +3508,8 @@ cp_parser_primary_expression (cp_parser *parser,
                decl = check_for_out_of_scope_variable (decl);
                if (local_variable_p (decl))
                  {
-                   error ("local variable %qD may not appear in this context",
-                          decl);
+                   error ("%Hlocal variable %qD may not appear in this context",
+                          &id_expr_token->location, decl);
                    return error_mark_node;
                  }
              }
@@ -3462,7 +3523,8 @@ cp_parser_primary_expression (cp_parser *parser,
                 &parser->non_integral_constant_expression_p,
                 template_p, done, address_p,
                 template_arg_p,
-                &error_msg));
+                &error_msg,
+                 id_expr_token->location));
        if (error_msg)
          cp_parser_error (parser, error_msg);
        return decl;
@@ -3746,7 +3808,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);
@@ -3825,6 +3888,8 @@ cp_parser_unqualified_id (cp_parser* parser,
            parser->scope = NULL_TREE;
            parser->object_scope = NULL_TREE;
            parser->qualifying_scope = NULL_TREE;
+           if (processing_template_decl)
+             cp_parser_parse_tentatively (parser);
            type_decl
              = cp_parser_class_name (parser,
                                      /*typename_keyword_p=*/false,
@@ -3833,6 +3898,16 @@ cp_parser_unqualified_id (cp_parser* parser,
                                      /*check_dependency=*/false,
                                      /*class_head_p=*/false,
                                      declarator_p);
+           if (processing_template_decl
+               && ! cp_parser_parse_definitely (parser))
+             {
+               /* We couldn't find a type with this name, so just accept
+                  it and check for a match at instantiation time.  */
+               type_decl = cp_parser_identifier (parser);
+               if (type_decl != error_mark_node)
+                 type_decl = build_nt (BIT_NOT_EXPR, type_decl);
+               return type_decl;
+             }
          }
        /* If an error occurred, assume that the name of the
           destructor is the same as the name of the qualifying
@@ -3847,8 +3922,8 @@ cp_parser_unqualified_id (cp_parser* parser,
        if (declarator_p && scope && !check_dtor_name (scope, type_decl))
          {
            if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-             error ("declaration of %<~%T%> as member of %qT",
-                    type_decl, scope);
+             error ("%Hdeclaration of %<~%T%> as member of %qT",
+                    &token->location, type_decl, scope);
            cp_parser_simulate_error (parser);
            return error_mark_node;
          }
@@ -3861,8 +3936,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));
       }
@@ -3904,10 +3979,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
@@ -3982,7 +4063,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
@@ -4022,12 +4103,12 @@ 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, "%<::%>");
 
@@ -4066,20 +4147,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;
@@ -4111,10 +4199,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)
@@ -4198,11 +4286,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.
@@ -4216,18 +4304,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
@@ -4237,7 +4326,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,
@@ -4247,8 +4337,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;
@@ -4311,7 +4419,8 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
 
 static tree
 cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
-                              bool member_access_only_p)
+                              bool member_access_only_p,
+                             cp_id_kind * pidk_return)
 {
   cp_token *token;
   enum rid keyword;
@@ -4355,7 +4464,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
        /* And the expression which is being cast.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
-       expression = cp_parser_expression (parser, /*cast_p=*/true);
+       expression = cp_parser_expression (parser, /*cast_p=*/true, & idk);
        cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
        /* Only type conversions to integral or enumeration types
@@ -4427,7 +4536,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            tree expression;
 
            /* Look for an expression.  */
-           expression = cp_parser_expression (parser, /*cast_p=*/false);
+           expression = cp_parser_expression (parser, /*cast_p=*/false, & idk);
            /* Compute its typeid.  */
            postfix_expression = build_typeid (expression);
            /* Look for the `)' token.  */
@@ -4515,8 +4624,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
@@ -4534,7 +4642,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;
              }
          }
@@ -4579,7 +4689,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            bool is_builtin_constant_p;
            bool saved_integral_constant_expression_p = false;
            bool saved_non_integral_constant_expression_p = false;
-           tree args;
+           VEC(tree,gc) *args;
 
             is_member_access = false;
 
@@ -4607,7 +4717,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                  = saved_non_integral_constant_expression_p;
              }
 
-           if (args == error_mark_node)
+           if (args == NULL)
              {
                postfix_expression = error_mark_node;
                break;
@@ -4620,19 +4730,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                                                               "a function call"))
              {
                postfix_expression = error_mark_node;
+               release_tree_vector (args);
                break;
              }
 
            koenig_p = false;
-           if (idk == CP_ID_KIND_UNQUALIFIED)
+           if (idk == CP_ID_KIND_UNQUALIFIED
+               || idk == CP_ID_KIND_TEMPLATE_ID)
              {
                if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
                  {
-                   if (args)
+                   if (!VEC_empty (tree, args))
                      {
                        koenig_p = true;
-                       postfix_expression
-                         = perform_koenig_lookup (postfix_expression, args);
+                       if (!any_type_dependent_arguments_p (args))
+                         postfix_expression
+                           = perform_koenig_lookup (postfix_expression, args);
                      }
                    else
                      postfix_expression
@@ -4641,7 +4754,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                /* We do not perform argument-dependent lookup if
                   normal lookup finds a non-function, in accordance
                   with the expected resolution of DR 218.  */
-               else if (args && is_overloaded_fn (postfix_expression))
+               else if (!VEC_empty (tree, args)
+                        && is_overloaded_fn (postfix_expression))
                  {
                    tree fn = get_first_fn (postfix_expression);
 
@@ -4654,8 +4768,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                    if (!DECL_FUNCTION_MEMBER_P (fn))
                      {
                        koenig_p = true;
-                       postfix_expression
-                         = perform_koenig_lookup (postfix_expression, args);
+                       if (!any_type_dependent_arguments_p (args))
+                         postfix_expression
+                           = perform_koenig_lookup (postfix_expression, args);
                      }
                  }
              }
@@ -4673,21 +4788,24 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                        || any_type_dependent_arguments_p (args)))
                  {
                    postfix_expression
-                     = build_nt_call_list (postfix_expression, args);
+                     = build_nt_call_vec (postfix_expression, args);
+                   release_tree_vector (args);
                    break;
                  }
 
                if (BASELINK_P (fn))
+                 {
                  postfix_expression
                    = (build_new_method_call
-                      (instance, fn, args, NULL_TREE,
+                      (instance, fn, &args, NULL_TREE,
                        (idk == CP_ID_KIND_QUALIFIED
                         ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
                        /*fn_p=*/NULL,
                        tf_warning_or_error));
+                 }
                else
                  postfix_expression
-                   = finish_call_expr (postfix_expression, args,
+                   = finish_call_expr (postfix_expression, &args,
                                        /*disallow_virtual=*/false,
                                        /*koenig_p=*/false,
                                        tf_warning_or_error);
@@ -4696,25 +4814,27 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                     || TREE_CODE (postfix_expression) == MEMBER_REF
                     || TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
              postfix_expression = (build_offset_ref_call_from_tree
-                                   (postfix_expression, args));
+                                   (postfix_expression, &args));
            else if (idk == CP_ID_KIND_QUALIFIED)
              /* A call to a static class member, or a namespace-scope
                 function.  */
              postfix_expression
-               = finish_call_expr (postfix_expression, args,
+               = finish_call_expr (postfix_expression, &args,
                                    /*disallow_virtual=*/true,
                                    koenig_p,
                                    tf_warning_or_error);
            else
              /* All other function calls.  */
              postfix_expression
-               = finish_call_expr (postfix_expression, args,
+               = finish_call_expr (postfix_expression, &args,
                                    /*disallow_virtual=*/false,
                                    koenig_p,
                                    tf_warning_or_error);
 
            /* The POSTFIX_EXPRESSION is certainly no longer an id.  */
            idk = CP_ID_KIND_NONE;
+
+           release_tree_vector (args);
          }
          break;
 
@@ -4731,7 +4851,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;
@@ -4769,6 +4890,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
          break;
 
        default:
+         if (pidk_return != NULL)
+           * pidk_return = idk;
           if (member_access_only_p)
             return is_member_access? postfix_expression : error_mark_node;
           else
@@ -4810,7 +4933,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
   if (for_offsetof)
     index = cp_parser_constant_expression (parser, false, NULL);
   else
-    index = cp_parser_expression (parser, /*cast_p=*/false);
+    index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
   /* Look for the closing `]'.  */
   cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
@@ -4845,7 +4968,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;
@@ -4862,6 +4986,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
   parser->qualifying_scope = NULL_TREE;
   parser->object_scope = NULL_TREE;
   *idk = CP_ID_KIND_NONE;
+
   /* Enter the scope corresponding to the type of the object
      given by the POSTFIX_EXPRESSION.  */
   if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
@@ -4877,7 +5002,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
        {
-         error ("%qE does not have class type", postfix_expression);
+         error ("%H%qE does not have class type", &location, postfix_expression);
          scope = NULL_TREE;
        }
       else
@@ -4933,6 +5058,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
         ordinary class member access expression, rather than a
         pseudo-destructor-name.  */
       bool template_p;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
       /* Parse the id-expression.  */
       name = (cp_parser_id_expression
              (parser,
@@ -4960,7 +5086,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
@@ -5015,24 +5141,22 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
    ALLOW_EXPANSION_P is true if this expression allows expansion of an
    argument pack.
 
-   Returns a TREE_LIST.  The TREE_VALUE of each node is a
-   representation of an assignment-expression.  Note that a TREE_LIST
-   is returned even if there is only a single expression in the list.
-   error_mark_node is returned if the ( and or ) are
-   missing. NULL_TREE is returned on no expressions. The parentheses
-   are eaten. IS_ATTRIBUTE_LIST is true if this is really an attribute
-   list being parsed.  If NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P
-   indicates whether or not all of the expressions in the list were
-   constant.  */
+   Returns a vector of trees.  Each element is a representation of an
+   assignment-expression.  NULL is returned if the ( and or ) are
+   missing.  An empty, but allocated, vector is returned on no
+   expressions.  The parentheses are eaten.  IS_ATTRIBUTE_LIST is true
+   if this is really an attribute list being parsed.  If
+   NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or
+   not all of the expressions in the list were constant.  */
 
-static tree
+static VEC(tree,gc) *
 cp_parser_parenthesized_expression_list (cp_parser* parser,
                                         bool is_attribute_list,
                                         bool cast_p,
                                          bool allow_expansion_p,
                                         bool *non_constant_p)
 {
-  tree expression_list = NULL_TREE;
+  VEC(tree,gc) *expression_list;
   bool fold_expr_p = is_attribute_list;
   tree identifier = NULL_TREE;
   bool saved_greater_than_is_operator_p;
@@ -5042,7 +5166,9 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
     *non_constant_p = false;
 
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
-    return error_mark_node;
+    return NULL;
+
+  expression_list = make_tree_vector ();
 
   /* Within a parenthesized expression, a `>' token is always
      the greater-than operator.  */
@@ -5070,10 +5196,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));
@@ -5081,7 +5216,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                  *non_constant_p = true;
              }
            else
-             expr = cp_parser_assignment_expression (parser, cast_p);
+             expr = cp_parser_assignment_expression (parser, cast_p, NULL);
 
            if (fold_expr_p)
              expr = fold_non_dependent_expr (expr);
@@ -5102,7 +5237,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                expressions to the list, so that we can still tell if
                the correct form for a parenthesized expression-list
                is found. That gives better errors.  */
-           expression_list = tree_cons (NULL_TREE, expr, expression_list);
+           VEC_safe_push (tree, gc, expression_list, expr);
 
            if (expr == error_mark_node)
              goto skip_comma;
@@ -5138,17 +5273,15 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
        {
          parser->greater_than_is_operator_p
            = saved_greater_than_is_operator_p;
-         return error_mark_node;
+         return NULL;
        }
     }
 
   parser->greater_than_is_operator_p
     = saved_greater_than_is_operator_p;
 
-  /* We built up the list in reverse order so we must reverse it now.  */
-  expression_list = nreverse (expression_list);
   if (identifier)
-    expression_list = tree_cons (NULL_TREE, identifier, expression_list);
+    VEC_safe_insert (tree, gc, expression_list, 0, identifier);
 
   return expression_list;
 }
@@ -5183,7 +5316,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.  */
@@ -5265,7 +5398,8 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
+                           cp_id_kind * pidk)
 {
   cp_token *token;
   enum tree_code unary_operator;
@@ -5376,13 +5510,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;
@@ -5401,7 +5536,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
       cast_expression
        = cp_parser_cast_expression (parser,
                                     unary_operator == ADDR_EXPR,
-                                    /*cast_p=*/false);
+                                    /*cast_p=*/false, pidk);
       /* Now, build an appropriate representation.  */
       switch (unary_operator)
        {
@@ -5443,7 +5578,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
     }
 
   return cp_parser_postfix_expression (parser, address_p, cast_p,
-                                       /*member_access_only_p=*/false);
+                                       /*member_access_only_p=*/false,
+                                      pidk);
 }
 
 /* Returns ERROR_MARK if TOKEN is not a unary-operator.  If TOKEN is a
@@ -5489,10 +5625,11 @@ static tree
 cp_parser_new_expression (cp_parser* parser)
 {
   bool global_scope_p;
-  tree placement;
+  VEC(tree,gc) *placement;
   tree type;
-  tree initializer;
+  VEC(tree,gc) *initializer;
   tree nelts;
+  tree ret;
 
   /* Look for the optional `::' operator.  */
   global_scope_p
@@ -5508,25 +5645,33 @@ cp_parser_new_expression (cp_parser* parser)
   placement = cp_parser_new_placement (parser);
   /* If that didn't work out, there's no new-placement.  */
   if (!cp_parser_parse_definitely (parser))
-    placement = NULL_TREE;
+    {
+      if (placement != NULL)
+       release_tree_vector (placement);
+      placement = NULL;
+    }
 
   /* If the next token is a `(', then we have a parenthesized
      type-id.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
+      cp_token *token;
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the type-id.  */
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      token = cp_lexer_peek_token (parser->lexer);
       /* There should not be a direct-new-declarator in this production,
         but GCC used to allowed this, so we check and emit a sensible error
         message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
        {
-         error ("array bound forbidden after parenthesized type-id");
-         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;
@@ -5535,20 +5680,30 @@ 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;
+    initializer = NULL;
 
   /* A new-expression may not appear in an integral constant
      expression.  */
   if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
-    return error_mark_node;
+    ret = error_mark_node;
+  else
+    {
+      /* Create a representation of the new-expression.  */
+      ret = build_new (&placement, type, nelts, &initializer, global_scope_p,
+                      tf_warning_or_error);
+    }
+
+  if (placement != NULL)
+    release_tree_vector (placement);
+  if (initializer != NULL)
+    release_tree_vector (initializer);
 
-  /* Create a representation of the new-expression.  */
-  return build_new (placement, type, nelts, initializer, global_scope_p,
-                    tf_warning_or_error);
+  return ret;
 }
 
 /* Parse a new-placement.
@@ -5558,10 +5713,10 @@ cp_parser_new_expression (cp_parser* parser)
 
    Returns the same representation as for an expression-list.  */
 
-static tree
+static VEC(tree,gc) *
 cp_parser_new_placement (cp_parser* parser)
 {
-  tree expression_list;
+  VEC(tree,gc) *expression_list;
 
   /* Parse the expression-list.  */
   expression_list = (cp_parser_parenthesized_expression_list
@@ -5638,7 +5793,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
        new_declarator = NULL;
     }
 
-  type = groktypename (&type_specifier_seq, new_declarator);
+  type = groktypename (&type_specifier_seq, new_declarator, false);
   return type;
 }
 
@@ -5702,7 +5857,8 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       /* The first expression is not required to be constant.  */
       if (!declarator)
        {
-         expression = cp_parser_expression (parser, /*cast_p=*/false);
+         cp_token *token = cp_lexer_peek_token (parser->lexer);
+         expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
          /* The standard requires that the expression have integral
             type.  DR 74 adds enumeration types.  We believe that the
             real intent is that these expressions be handled like the
@@ -5717,8 +5873,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;
                }
            }
@@ -5748,20 +5904,28 @@ 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.  */
+   Returns a representation of the expression-list.  */
 
-static tree
+static VEC(tree,gc) *
 cp_parser_new_initializer (cp_parser* parser)
 {
-  tree expression_list;
+  VEC(tree,gc) *expression_list;
 
-  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;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      tree t;
+      bool expr_non_constant_p;
+      maybe_warn_cpp0x ("extended initializer lists");
+      t = cp_parser_braced_list (parser, &expr_non_constant_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
+      expression_list = make_tree_vector_single (t);
+    }
+  else
+    expression_list = (cp_parser_parenthesized_expression_list
+                      (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+                       /*non_constant_p=*/NULL));
 
   return expression_list;
 }
@@ -5812,6 +5976,61 @@ cp_parser_delete_expression (cp_parser* parser)
   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:
@@ -5825,7 +6044,8 @@ cp_parser_delete_expression (cp_parser* parser)
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
+                          cp_id_kind * pidk)
 {
   /* If it's a `(', then we might be looking at a cast.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
@@ -5890,17 +6110,18 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_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, pidk);
+
          /* Warn about old-style casts, if so requested.  */
          if (warn_old_style_cast
              && !in_system_header
@@ -5918,14 +6139,16 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
            return error_mark_node;
 
          /* Perform the cast.  */
-         expr = build_c_cast (type, expr);
+         expr = build_c_cast (input_location, 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
      unary-expression.  */
-  return cp_parser_unary_expression (parser, address_p, cast_p);
+  return cp_parser_unary_expression (parser, address_p, cast_p, pidk);
 }
 
 /* Parse a binary expression of the general form:
@@ -6008,18 +6231,21 @@ 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,
+                            bool no_toplevel_fold_p,
+                            enum cp_parser_prec prec,
+                            cp_id_kind * pidk)
 {
   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.  */
-  lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p);
+  lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p, pidk);
   lhs_type = ERROR_MARK;
 
   for (;;)
@@ -6089,6 +6315,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
          goto get_rhs;
 
         pop:
+         lookahead_prec = new_prec;
          /* If the stack is not empty, we have parsed into LHS the right side
             (`4' in the example above) of an expression we had suspended.
             We can use the information on the stack to recover the LHS (`3')
@@ -6106,8 +6333,21 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
        }
 
       overloaded_p = false;
-      lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
-                              &overloaded_p, tf_warning_or_error);
+      /* ??? 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.
+      */
+      if (no_toplevel_fold_p
+         && lookahead_prec <= prec
+         && sp == stack
+         && TREE_CODE_CLASS (tree_type) == tcc_comparison)
+       lhs = build2 (tree_type, boolean_type_node, lhs, rhs);
+      else
+       lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
+                                &overloaded_p, tf_warning_or_error);
       lhs_type = tree_type;
 
       /* If the binary operator required the use of an overloaded operator,
@@ -6149,16 +6389,26 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
   cp_lexer_consume_token (parser->lexer);
   if (cp_parser_allow_gnu_extensions_p (parser)
       && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
-    /* Implicit true clause.  */
-    expr = NULL_TREE;
+    {
+      /* Implicit true clause.  */
+      expr = NULL_TREE;
+      c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
+    }
   else
-    /* Parse the expression.  */
-    expr = cp_parser_expression (parser, /*cast_p=*/false);
+    {
+      /* Parse the expression.  */
+      c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
+      expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+      c_inhibit_evaluation_warnings +=
+       ((logical_or_expr == truthvalue_true_node)
+        - (logical_or_expr == truthvalue_false_node));
+    }
 
   /* The next token should be a `:'.  */
   cp_parser_require (parser, CPP_COLON, "%<:%>");
   /* Parse the assignment-expression.  */
-  assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+  assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
+  c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
 
   /* Build the conditional-expression.  */
   return build_x_conditional_expr (logical_or_expr,
@@ -6179,7 +6429,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
    Returns a representation for the expression.  */
 
 static tree
-cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
+cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
+                                cp_id_kind * pidk)
 {
   tree expr;
 
@@ -6192,7 +6443,8 @@ 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, false,
+                                         PREC_NOT_OPERATOR, pidk);
       /* 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))
@@ -6207,10 +6459,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,
@@ -6251,7 +6507,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)
@@ -6323,7 +6579,7 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_expression (cp_parser* parser, bool cast_p)
+cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
 {
   tree expression = NULL_TREE;
 
@@ -6333,7 +6589,7 @@ cp_parser_expression (cp_parser* parser, bool cast_p)
 
       /* Parse the next assignment-expression.  */
       assignment_expression
-       = cp_parser_assignment_expression (parser, cast_p);
+       = cp_parser_assignment_expression (parser, cast_p, pidk);
       /* If this is the first assignment-expression, we can just
         save it away.  */
       if (!expression)
@@ -6412,7 +6668,7 @@ cp_parser_constant_expression (cp_parser* parser,
      For example, cp_parser_initializer_clauses uses this function to
      determine whether a particular assignment-expression is in fact
      constant.  */
-  expression = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+  expression = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
   /* Restore the old settings.  */
   parser->integral_constant_expression_p
     = saved_integral_constant_expression_p;
@@ -6436,7 +6692,8 @@ cp_parser_constant_expression (cp_parser* parser,
    offsetof-member-designator:
      id-expression
      | offsetof-member-designator "." id-expression
-     | offsetof-member-designator "[" expression "]"  */
+     | offsetof-member-designator "[" expression "]"
+     | offsetof-member-designator "->" id-expression  */
 
 static tree
 cp_parser_builtin_offsetof (cp_parser *parser)
@@ -6444,6 +6701,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
@@ -6459,6 +6717,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
   cp_parser_require (parser, CPP_COMMA, "%<,%>");
+  token = cp_lexer_peek_token (parser->lexer);
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
   expr = build_static_cast (build_pointer_type (type), null_pointer_node,
@@ -6466,10 +6725,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:
@@ -6477,11 +6736,17 @@ cp_parser_builtin_offsetof (cp_parser *parser)
          expr = cp_parser_postfix_open_square_expression (parser, expr, true);
          break;
 
+       case CPP_DEREF:
+         /* offsetof-member-designator "->" identifier */
+         expr = grok_array_decl (expr, integer_zero_node);
+         /* FALLTHRU */
+
        case CPP_DOT:
          /* offsetof-member-designator "." identifier */
          cp_lexer_consume_token (parser->lexer);
-         expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
-                                                        true, &dummy);
+         expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT,
+                                                        expr, true, &dummy,
+                                                        token->location);
          break;
 
        case CPP_CLOSE_PAREN:
@@ -6801,6 +7066,7 @@ static void
 cp_parser_label_for_labeled_statement (cp_parser* parser)
 {
   cp_token *token;
+  tree label = NULL_TREE;
 
   /* The next token should be an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -6841,9 +7107,10 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
          expr_hi = NULL_TREE;
 
        if (parser->in_switch_statement_p)
-         finish_case_label (expr, expr_hi);
+         finish_case_label (token->location, 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;
 
@@ -6852,19 +7119,41 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
 
       if (parser->in_switch_statement_p)
-       finish_case_label (NULL_TREE, NULL_TREE);
+       finish_case_label (token->location, 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:
       /* Anything else must be an ordinary label.  */
-      finish_label_stmt (cp_parser_identifier (parser));
+      label = finish_label_stmt (cp_parser_identifier (parser));
       break;
     }
 
   /* Require the `:' token.  */
   cp_parser_require (parser, CPP_COLON, "%<:%>");
+
+  /* An ordinary label may optionally be followed by attributes.
+     However, this is only permitted if the attributes are then
+     followed by a semicolon.  This is because, for backward
+     compatibility, when parsing
+       lab: __attribute__ ((unused)) int i;
+     we want the attribute to attach to "i", not "lab".  */
+  if (label != NULL_TREE
+      && cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+    {
+      tree attrs;
+
+      cp_parser_parse_tentatively (parser);
+      attrs = cp_parser_attributes_opt (parser);
+      if (attrs == NULL_TREE
+         || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       cp_parser_abort_tentative_parse (parser);
+      else if (!cp_parser_parse_definitely (parser))
+       ;
+      else
+       cplus_decl_attributes (&label, attrs, 0);
+    }
 }
 
 /* Parse an expression-statement.
@@ -6885,7 +7174,7 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
   /* If the next token is a ';', then there is no expression
      statement.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    statement = cp_parser_expression (parser, /*cast_p=*/false);
+    statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
   /* Consume the final `;'.  */
   cp_parser_consume_semicolon_at_end_of_statement (parser);
@@ -6972,7 +7261,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);
            }
        }
 
@@ -7048,7 +7337,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 (loc));
+               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);
@@ -7061,7 +7361,19 @@ 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))
+                 {
+                   location_t loc;
+                   loc = cp_lexer_peek_token (parser->lexer)->location;
+                   warning_at (loc,
+                               OPT_Wempty_body, "suggest braces around "
+                               "empty body in an %<else%> statement");
+                   add_stmt (build_empty_stmt (loc));
+                   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
@@ -7123,7 +7435,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:
 
@@ -7169,31 +7482,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);
 
@@ -7201,7 +7530,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);
@@ -7215,49 +7544,7 @@ cp_parser_condition (cp_parser* parser)
     cp_parser_abort_tentative_parse (parser);
 
   /* Otherwise, we are looking at an expression.  */
-  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);
+  return cp_parser_expression (parser, /*cast_p=*/false, NULL);
 }
 
 /* Parse an iteration-statement.
@@ -7302,7 +7589,6 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* 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, "%<)%>");
        /* Parse the dependent statement.  */
@@ -7330,7 +7616,7 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Look for the `('.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Parse the expression.  */
-       expression = cp_parser_expression (parser, /*cast_p=*/false);
+       expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
        /* We're done with the do-statement.  */
        finish_do_stmt (expression, statement);
        /* Look for the `)'.  */
@@ -7362,9 +7648,8 @@ cp_parser_iteration_statement (cp_parser* parser)
 
        /* 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);
+         expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
        finish_for_expr (expression, statement);
-       check_empty_body (parser, "for");
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
@@ -7425,6 +7710,7 @@ cp_parser_for_init_statement (cp_parser* parser)
      break ;
      continue ;
      return expression [opt] ;
+     return braced-init-list ;
      goto identifier ;
 
    GNU extension:
@@ -7456,7 +7742,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)
@@ -7464,10 +7750,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, "%<;%>");
@@ -7477,14 +7763,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 ();
@@ -7495,12 +7781,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))
-         expr = cp_parser_expression (parser, /*cast_p=*/false);
+       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, NULL);
        else
+         /* If the next token is a `;', then there is no
+            expression.  */
          expr = NULL_TREE;
        /* Build the return-statement.  */
        statement = finish_return_stmt (expr);
@@ -7514,12 +7806,11 @@ 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.  */
-         finish_goto_stmt (cp_parser_expression (parser, /*cast_p=*/false));
+         finish_goto_stmt (cp_parser_expression (parser, /*cast_p=*/false, NULL));
        }
       else
        finish_goto_stmt (cp_parser_identifier (parser));
@@ -7585,8 +7876,9 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p)
   /* Mark if () ; with a special NOP_EXPR.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
     {
+      location_t loc = cp_lexer_peek_token (parser->lexer)->location;
       cp_lexer_consume_token (parser->lexer);
-      statement = add_stmt (build_empty_stmt ());
+      statement = add_stmt (build_empty_stmt (loc));
     }
   /* if a compound is opened, we simply parse the statement directly.  */
   else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
@@ -7622,6 +7914,10 @@ 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, "%<{%>");
+      /* If the next keyword is `__label__' we have a label declaration.  */
+      while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
+       cp_parser_label_declaration (parser);
+      /* Parse an (optional) statement-seq.  */
       cp_parser_statement_seq_opt (parser, NULL_TREE);
       cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
     }
@@ -7654,8 +7950,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;
        }
 
@@ -7876,7 +8172,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))
@@ -7963,7 +8259,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
@@ -8009,7 +8307,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
            {
@@ -8105,6 +8407,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);
@@ -8121,6 +8424,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)
        {
@@ -8188,24 +8496,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:
@@ -8214,7 +8523,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.  */
@@ -8250,7 +8560,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
@@ -8310,12 +8619,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.
@@ -8371,7 +8681,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)
@@ -8383,7 +8694,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;
@@ -8537,6 +8848,7 @@ cp_parser_decltype (cp_parser *parser)
   const char *saved_message;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
+  cp_token *id_expr_start_token;
 
   /* Look for the `decltype' token.  */
   if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
@@ -8559,13 +8871,17 @@ cp_parser_decltype (cp_parser *parser)
   parser->integral_constant_expression_p = false;
 
   /* Do not actually evaluate the expression.  */
-  ++skip_evaluation;
+  ++cp_unevaluated_operand;
+
+  /* Do not warn about problems with the expression.  */
+  ++c_inhibit_evaluation_warnings;
 
   /* Parse the opening `('.  */
   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,
@@ -8588,7 +8904,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
@@ -8608,7 +8925,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
@@ -8637,7 +8955,7 @@ cp_parser_decltype (cp_parser *parser)
       /* Parse a class member access.  */
       expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
                                            /*cast_p=*/false,
-                                           /*member_access_only_p=*/true);
+                                           /*member_access_only_p=*/true, NULL);
 
       if (expr 
           && expr != error_mark_node
@@ -8656,11 +8974,12 @@ cp_parser_decltype (cp_parser *parser)
       cp_parser_abort_tentative_parse (parser);
 
       /* Parse a full expression.  */
-      expr = cp_parser_expression (parser, /*cast_p=*/false);
+      expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
     }
 
   /* Go back to evaluating expressions.  */
-  --skip_evaluation;
+  --cp_unevaluated_operand;
+  --c_inhibit_evaluation_warnings;
 
   /* Restore the old message and the integral constant expression
      flags.  */
@@ -8776,6 +9095,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;
 }
 
@@ -8851,17 +9180,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. */
@@ -8875,8 +9207,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;
             }
 
@@ -8906,6 +9238,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:
 
@@ -8923,24 +9256,46 @@ 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
-    mem_initializer_id = cp_parser_mem_initializer_id (parser);
+    {
+      mem_initializer_id = cp_parser_mem_initializer_id (parser);
+      if (mem_initializer_id == error_mark_node)
+       return mem_initializer_id;
+    }
   member = expand_member_init (mem_initializer_id);
   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
+    {
+      VEC(tree,gc)* vec;
+      vec = cp_parser_parenthesized_expression_list (parser, false,
+                                                    /*cast_p=*/false,
+                                                    /*allow_expansion_p=*/true,
+                                                    /*non_constant_p=*/NULL);
+      if (vec == NULL)
+       return error_mark_node;
+      expression_list = build_tree_list_vec (vec);
+      release_tree_vector (vec);
+    }
+
   if (expression_list == error_mark_node)
     return error_mark_node;
   if (!expression_list)
@@ -8969,11 +9324,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.  */
@@ -9343,14 +9701,17 @@ cp_parser_template_parameter_list (cp_parser* parser)
       tree parameter;
       bool is_non_type;
       bool is_parameter_pack;
+      location_t parm_loc;
 
       /* Parse the template-parameter.  */
+      parm_loc = cp_lexer_peek_token (parser->lexer)->location;
       parameter = cp_parser_template_parameter (parser, 
                                                 &is_non_type,
                                                 &is_parameter_pack);
       /* Add it to the list.  */
       if (parameter != error_mark_node)
        parameter_list = process_template_parm (parameter_list,
+                                               parm_loc,
                                                parameter,
                                                is_non_type,
                                                 is_parameter_pack);
@@ -9490,6 +9851,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.  */     
@@ -9498,10 +9860,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);
@@ -9595,10 +9958,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 ();
@@ -9666,6 +10030,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,
@@ -9686,7 +10053,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);
@@ -9696,10 +10064,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 ();
@@ -9742,13 +10113,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
@@ -9796,14 +10167,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
@@ -9822,6 +10194,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))
@@ -9836,15 +10209,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;
            }
        }
@@ -9862,10 +10237,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
@@ -9877,17 +10252,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
@@ -9917,7 +10292,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 ();
@@ -9971,6 +10347,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.  */
@@ -10022,7 +10399,7 @@ cp_parser_template_name (cp_parser* parser,
          && !template_keyword_p
          && parser->scope && TYPE_P (parser->scope)
          && check_dependency_p
-         && dependent_type_p (parser->scope)
+         && dependent_scope_p (parser->scope)
          /* Do not do this for dtors (or ctors), since they never
             need the template keyword before their name.  */
          && !constructor_name_p (identifier, parser->scope))
@@ -10030,8 +10407,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))
@@ -10074,7 +10452,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.  */
@@ -10160,6 +10539,12 @@ cp_parser_template_argument_list (cp_parser* parser)
          argument pack. */
       if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
         {
+         if (argument == error_mark_node)
+           {
+             cp_token *token = cp_lexer_peek_token (parser->lexer);
+             error ("%Hexpected parameter pack before %<...%>",
+                    &token->location);
+           }
           /* Consume the `...' token. */
           cp_lexer_consume_token (parser->lexer);
 
@@ -10220,7 +10605,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
@@ -10234,10 +10619,11 @@ 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:
+  argument = cp_parser_template_type_arg (parser);
+  /* 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 {};
@@ -10246,8 +10632,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;
@@ -10267,6 +10657,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,
@@ -10289,7 +10680,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");
@@ -10314,7 +10706,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);
@@ -10415,7 +10807,7 @@ cp_parser_template_argument (cp_parser* parser)
      was the only alternative that matched (albeit with a '>' after
      it). We can assume it's just a typo from the user, and a
      diagnostic will then be issued.  */
-  return cp_parser_type_id (parser);
+  return cp_parser_template_type_arg (parser);
 }
 
 /* Parse an explicit-instantiation.
@@ -10446,6 +10838,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.  */
@@ -10468,6 +10861,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,
@@ -10500,7 +10894,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,
@@ -10541,6 +10936,8 @@ static void
 cp_parser_explicit_specialization (cp_parser* parser)
 {
   bool need_lang_pop;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `template' keyword.  */
   cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Look for the `<'.  */
@@ -10555,7 +10952,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);
@@ -10567,7 +10964,6 @@ cp_parser_explicit_specialization (cp_parser* parser)
   if (!begin_specialization ())
     {
       end_specialization ();
-      cp_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
 
@@ -10670,6 +11066,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;
        }
@@ -10686,6 +11083,7 @@ cp_parser_type_specifier (cp_parser* parser,
       cp_parser_parse_tentatively (parser);
       /* Look for the class-specifier.  */
       type_spec = cp_parser_class_specifier (parser);
+      invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec);
       /* If that worked, we're done.  */
       if (cp_parser_parse_definitely (parser))
        {
@@ -10694,6 +11092,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;
        }
@@ -10715,6 +11114,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;
 
@@ -10874,14 +11274,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:
@@ -10890,6 +11284,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;
@@ -10905,6 +11300,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;
@@ -10926,6 +11322,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;
@@ -10936,7 +11333,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);
     }
@@ -10965,6 +11362,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
@@ -10999,6 +11397,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);
     }
 
@@ -11031,7 +11430,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;
@@ -11093,12 +11493,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)))
@@ -11115,7 +11516,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
@@ -11135,7 +11536,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
@@ -11164,6 +11565,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))
@@ -11172,6 +11574,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);
     }
@@ -11185,7 +11598,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
@@ -11233,6 +11646,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);
@@ -11248,12 +11662,17 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
        type = make_typename_type (parser->scope, decl,
                                   typename_type,
                                   /*complain=*/tf_error);
-      else
+      /* If the `typename' keyword is in effect and DECL is not a type
+        decl. Then type is non existant.   */
+      else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
+        type = NULL_TREE; 
+      else 
        type = TREE_TYPE (decl);
     }
 
   if (!type)
     {
+      token = cp_lexer_peek_token (parser->lexer);
       identifier = cp_parser_identifier (parser);
 
       if (identifier == error_mark_node)
@@ -11266,7 +11685,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)
        {
@@ -11278,7 +11698,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.  */
@@ -11314,7 +11735,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;
            }
 
@@ -11342,7 +11764,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);
 
@@ -11414,7 +11836,9 @@ 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,
+                                                   /*declarator=*/NULL))
            return error_mark_node;
          type = xref_tag (tag_type, identifier, ts, template_p);
        }
@@ -11445,7 +11869,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;
 }
@@ -11453,11 +11877,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.  */
@@ -11468,6 +11900,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.  */
@@ -11479,6 +11914,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))
@@ -11486,11 +11935,46 @@ cp_parser_enum_specifier (cp_parser* parser)
   else
     identifier = make_anon_name ();
 
+  /* 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;
+
+      /* At this point this is surely not elaborated type specifier.  */
+      if (!cp_parser_parse_definitely (parser))
+       return NULL_TREE;
+
+      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_simulate_error (parser);
+    {
+      cp_parser_error (parser, "expected %<{%>");
+      if (has_underlying_type)
+       return NULL_TREE;
+    }
 
-  if (!cp_parser_parse_definitely (parser))
+  if (!has_underlying_type && !cp_parser_parse_definitely (parser))
     return NULL_TREE;
 
   /* Issue an error message if type-definitions are forbidden here.  */
@@ -11500,7 +11984,7 @@ cp_parser_enum_specifier (cp_parser* parser)
     /* 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);
+    type = start_enum (identifier, underlying_type, scoped_enum_p);
   
   /* Consume the opening brace.  */
   cp_lexer_consume_token (parser->lexer);
@@ -11523,6 +12007,7 @@ cp_parser_enum_specifier (cp_parser* parser)
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       tree trailing_attr = cp_parser_attributes_opt (parser);
+      trailing_attr = chainon (trailing_attr, attributes);
       cplus_decl_attributes (&type,
                             trailing_attr,
                             (int) ATTR_FLAG_TYPE_IN_PLACE);
@@ -11558,8 +12043,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;
        }
     }
@@ -11599,6 +12084,11 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
   else
     value = NULL_TREE;
 
+  /* If we are processing a template, make sure the initializer of the
+     enumerator doesn't contain any bare template parameter pack.  */
+  if (check_for_bare_parameter_packs (value))
+    value = error_mark_node;
+
   /* Create the enumerator.  */
   build_enumerator (identifier, value, type);
 }
@@ -11617,6 +12107,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)
@@ -11637,7 +12129,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,
@@ -11645,13 +12137,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;
     }
@@ -11717,14 +12210,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);
     }
 
@@ -11766,6 +12259,8 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   tree identifier;
   tree namespace_specifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the identifier.  */
@@ -11776,7 +12271,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
       && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) 
     {
-      error ("%<namespace%> definition is not allowed here");
+      error ("%H%<namespace%> definition is not allowed here", &token->location);
       /* Skip the definition.  */
       cp_lexer_consume_token (parser->lexer);
       if (cp_parser_skip_to_closing_brace (parser))
@@ -11891,6 +12386,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,
@@ -11915,7 +12411,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 ())
@@ -11931,9 +12428,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 ())
@@ -12183,7 +12684,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;
@@ -12191,12 +12693,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;
@@ -12217,6 +12719,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,
@@ -12231,12 +12734,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
@@ -12248,8 +12753,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
@@ -12262,7 +12769,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)
        {
@@ -12274,12 +12782,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;
 
@@ -12294,6 +12808,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;
        }
     }
@@ -12313,12 +12834,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
     {
@@ -12330,7 +12862,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;
     }
 
@@ -12388,7 +12920,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.  */
@@ -12398,12 +12930,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
@@ -12412,7 +12945,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,
@@ -12421,7 +12955,7 @@ cp_parser_init_declarator (cp_parser* parser,
        }
       else
        initializer = cp_parser_initializer (parser,
-                                            &is_parenthesized_init,
+                                            &is_direct_init,
                                             &is_non_constant_init);
     }
 
@@ -12429,7 +12963,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");
@@ -12462,8 +12997,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)
@@ -12662,7 +13197,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
@@ -12680,8 +13215,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
@@ -12708,6 +13245,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);
 
@@ -12720,6 +13259,9 @@ 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;
@@ -12733,19 +13275,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
@@ -12813,9 +13365,16 @@ 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 if (processing_template_decl && !error_operand_p (bounds))
+               {
+                 /* Remember this wasn't a constant-expression.  */
+                 bounds = build_nop (TREE_TYPE (bounds), bounds);
+                 TREE_SIDE_EFFECTS (bounds) = 1;
+               }
            }
          else
            bounds = NULL_TREE;
@@ -12830,177 +13389,183 @@ cp_parser_direct_declarator (cp_parser* parser,
        }
       else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
        {
-         tree qualifying_scope;
-         tree unqualified_name;
-         special_function_kind sfk;
-         bool abstract_ok;
-          bool pack_expansion_p = false;
-
-         /* Parse a declarator-id */
-         abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
-         if (abstract_ok)
-            {
-              cp_parser_parse_tentatively (parser);
+         {
+           tree qualifying_scope;
+           tree unqualified_name;
+           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);
+           if (abstract_ok)
+             {
+               cp_parser_parse_tentatively (parser);
 
-              /* If we see an ellipsis, we should be looking at a
-                 parameter pack. */
-              if (token->type == CPP_ELLIPSIS)
-                {
-                  /* Consume the `...' */
-                  cp_lexer_consume_token (parser->lexer);
+               /* If we see an ellipsis, we should be looking at a
+                  parameter pack. */
+               if (token->type == CPP_ELLIPSIS)
+                 {
+                   /* Consume the `...' */
+                   cp_lexer_consume_token (parser->lexer);
 
-                  pack_expansion_p = true;
-                }
-            }
+                   pack_expansion_p = true;
+                 }
+             }
 
-         unqualified_name
-           = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
-         qualifying_scope = parser->scope;
-         if (abstract_ok)
-           {
-              bool okay = false;
-
-              if (!unqualified_name && pack_expansion_p)
-                {
-                  /* Check whether an error occurred. */
-                  okay = !cp_parser_error_occurred (parser);
-
-                  /* We already consumed the ellipsis to mark a
-                     parameter pack, but we have no way to report it,
-                     so abort the tentative parse. We will be exiting
-                     immediately anyway. */
-                  cp_parser_abort_tentative_parse (parser);
-                }
-              else
-                okay = cp_parser_parse_definitely (parser);
-
-             if (!okay)
-               unqualified_name = error_mark_node;
-             else if (unqualified_name
-                      && (qualifying_scope
-                          || (TREE_CODE (unqualified_name)
-                              != IDENTIFIER_NODE)))
-               {
-                 cp_parser_error (parser, "expected unqualified-id");
-                 unqualified_name = error_mark_node;
-               }
-           }
+           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;
+           if (abstract_ok)
+             {
+               bool okay = false;
 
-         if (!unqualified_name)
-           return NULL;
-         if (unqualified_name == error_mark_node)
-           {
-             declarator = cp_error_declarator;
-              pack_expansion_p = false;
-              declarator->parameter_pack_p = false;
-             break;
-           }
+               if (!unqualified_name && pack_expansion_p)
+                 {
+                   /* Check whether an error occurred. */
+                   okay = !cp_parser_error_occurred (parser);
+
+                   /* We already consumed the ellipsis to mark a
+                      parameter pack, but we have no way to report it,
+                      so abort the tentative parse. We will be exiting
+                      immediately anyway. */
+                   cp_parser_abort_tentative_parse (parser);
+                 }
+               else
+                 okay = cp_parser_parse_definitely (parser);
 
-         if (qualifying_scope && at_namespace_scope_p ()
-             && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
-           {
-             /* In the declaration of a member of a template class
-                outside of the class itself, the SCOPE will sometimes
-                be a TYPENAME_TYPE.  For example, given:
-
-                template <typename T>
-                int S<T>::R::i = 3;
-
-                the SCOPE will be a TYPENAME_TYPE for `S<T>::R'.  In
-                this context, we must resolve S<T>::R to an ordinary
-                type, rather than a typename type.
-
-                The reason we normally avoid resolving TYPENAME_TYPEs
-                is that a specialization of `S' might render
-                `S<T>::R' not a type.  However, if `S' is
-                specialized, then this `i' will not be used, so there
-                is no harm in resolving the types here.  */
-             tree type;
+               if (!okay)
+                 unqualified_name = error_mark_node;
+               else if (unqualified_name
+                        && (qualifying_scope
+                            || (TREE_CODE (unqualified_name)
+                                != IDENTIFIER_NODE)))
+                 {
+                   cp_parser_error (parser, "expected unqualified-id");
+                   unqualified_name = error_mark_node;
+                 }
+             }
 
-             /* Resolve the TYPENAME_TYPE.  */
-             type = resolve_typename_type (qualifying_scope,
-                                           /*only_current_p=*/false);
-             /* If that failed, the declarator is invalid.  */
-             if (TREE_CODE (type) == TYPENAME_TYPE)
-               error ("%<%T::%E%> is not a type",
-                      TYPE_CONTEXT (qualifying_scope),
-                      TYPE_IDENTIFIER (qualifying_scope));
-             qualifying_scope = type;
-           }
+           if (!unqualified_name)
+             return NULL;
+           if (unqualified_name == error_mark_node)
+             {
+               declarator = cp_error_declarator;
+               pack_expansion_p = false;
+               declarator->parameter_pack_p = false;
+               break;
+             }
 
-         sfk = sfk_none;
+           if (qualifying_scope && at_namespace_scope_p ()
+               && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
+             {
+               /* In the declaration of a member of a template class
+                  outside of the class itself, the SCOPE will sometimes
+                  be a TYPENAME_TYPE.  For example, given:
+
+                  template <typename T>
+                  int S<T>::R::i = 3;
+
+                  the SCOPE will be a TYPENAME_TYPE for `S<T>::R'.  In
+                  this context, we must resolve S<T>::R to an ordinary
+                  type, rather than a typename type.
+
+                  The reason we normally avoid resolving TYPENAME_TYPEs
+                  is that a specialization of `S' might render
+                  `S<T>::R' not a type.  However, if `S' is
+                  specialized, then this `i' will not be used, so there
+                  is no harm in resolving the types here.  */
+               tree type;
+
+               /* Resolve the TYPENAME_TYPE.  */
+               type = resolve_typename_type (qualifying_scope,
+                                             /*only_current_p=*/false);
+               /* If that failed, the declarator is invalid.  */
+               if (TREE_CODE (type) == TYPENAME_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;
+             }
 
-         if (unqualified_name)
-           {
-             tree class_type;
+           sfk = sfk_none;
 
-             if (qualifying_scope
-                 && CLASS_TYPE_P (qualifying_scope))
-               class_type = qualifying_scope;
-             else
-               class_type = current_class_type;
+           if (unqualified_name)
+             {
+               tree class_type;
 
-             if (TREE_CODE (unqualified_name) == TYPE_DECL)
-               {
-                 tree name_type = TREE_TYPE (unqualified_name);
-                 if (class_type && same_type_p (name_type, class_type))
-                   {
-                     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 "
-                                 "name the constructor in a qualified name",
-                                 class_type,
-                                 DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
-                                 class_type, name_type);
-                         declarator = cp_error_declarator;
-                         break;
-                       }
-                     else
-                       unqualified_name = constructor_name (class_type);
-                   }
-                 else
-                   {
-                     /* We do not attempt to print the declarator
-                        here because we do not have enough
-                        information about its original syntactic
-                        form.  */
-                     cp_parser_error (parser, "invalid declarator");
-                     declarator = cp_error_declarator;
-                     break;
-                   }
-               }
+               if (qualifying_scope
+                   && CLASS_TYPE_P (qualifying_scope))
+                 class_type = qualifying_scope;
+               else
+                 class_type = current_class_type;
 
-             if (class_type)
-               {
-                 if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
-                   sfk = sfk_destructor;
-                 else if (IDENTIFIER_TYPENAME_P (unqualified_name))
-                   sfk = sfk_conversion;
-                 else if (/* There's no way to declare a constructor
-                             for an anonymous type, even if the type
-                             got a name for linkage purposes.  */
-                          !TYPE_WAS_ANONYMOUS (class_type)
-                          && constructor_name_p (unqualified_name,
-                                                 class_type))
-                   {
-                     unqualified_name = constructor_name (class_type);
-                     sfk = sfk_constructor;
-                   }
+               if (TREE_CODE (unqualified_name) == TYPE_DECL)
+                 {
+                   tree name_type = TREE_TYPE (unqualified_name);
+                   if (class_type && same_type_p (name_type, class_type))
+                     {
+                       if (qualifying_scope
+                           && CLASSTYPE_USE_TEMPLATE (name_type))
+                         {
+                           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)),
+                                   class_type, name_type);
+                           declarator = cp_error_declarator;
+                           break;
+                         }
+                       else
+                         unqualified_name = constructor_name (class_type);
+                     }
+                   else
+                     {
+                       /* We do not attempt to print the declarator
+                          here because we do not have enough
+                          information about its original syntactic
+                          form.  */
+                       cp_parser_error (parser, "invalid declarator");
+                       declarator = cp_error_declarator;
+                       break;
+                     }
+                 }
 
-                 if (ctor_dtor_or_conv_p && sfk != sfk_none)
-                   *ctor_dtor_or_conv_p = -1;
-               }
-           }
-         declarator = make_id_declarator (qualifying_scope,
-                                          unqualified_name,
-                                          sfk);
-         declarator->id_loc = token->location;
-          declarator->parameter_pack_p = pack_expansion_p;
+               if (class_type)
+                 {
+                   if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
+                     sfk = sfk_destructor;
+                   else if (IDENTIFIER_TYPENAME_P (unqualified_name))
+                     sfk = sfk_conversion;
+                   else if (/* There's no way to declare a constructor
+                               for an anonymous type, even if the type
+                               got a name for linkage purposes.  */
+                            !TYPE_WAS_ANONYMOUS (class_type)
+                            && constructor_name_p (unqualified_name,
+                                                   class_type))
+                     {
+                       unqualified_name = constructor_name (class_type);
+                       sfk = sfk_constructor;
+                     }
 
-          if (pack_expansion_p)
-            maybe_warn_variadic_templates ();
+                   if (ctor_dtor_or_conv_p && sfk != sfk_none)
+                     *ctor_dtor_or_conv_p = -1;
+                 }
+             }
+           declarator = make_id_declarator (qualifying_scope,
+                                            unqualified_name,
+                                            sfk);
+           declarator->id_loc = token->location;
+           declarator->parameter_pack_p = pack_expansion_p;
+
+           if (pack_expansion_p)
+             maybe_warn_variadic_templates ();
+         }
 
        handle_declarator:;
          scope = get_scope_of_declarator (declarator);
@@ -13107,6 +13672,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,
@@ -13121,7 +13687,7 @@ cp_parser_ptr_operator (cp_parser* parser,
          code = INDIRECT_REF;
 
          if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-           error ("%qD is a namespace", parser->scope);
+           error ("%H%qD is a namespace", &token->location, parser->scope);
          else
            {
              /* The type of which the member is a member is given by the
@@ -13196,7 +13762,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
@@ -13209,6 +13775,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:
@@ -13259,7 +13849,7 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
    Returns the TYPE specified.  */
 
 static tree
-cp_parser_type_id (cp_parser* parser)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
 {
   cp_decl_specifier_seq type_specifier_seq;
   cp_declarator *abstract_declarator;
@@ -13281,7 +13871,34 @@ cp_parser_type_id (cp_parser* parser)
   if (!cp_parser_parse_definitely (parser))
     abstract_declarator = NULL;
 
-  return groktypename (&type_specifier_seq, abstract_declarator);
+  if (type_specifier_seq.type
+      && type_uses_auto (type_specifier_seq.type))
+    {
+      /* A type-id with type 'auto' is only ok if the abstract declarator
+        is a function declarator with a late-specified return type.  */
+      if (abstract_declarator
+         && abstract_declarator->kind == cdk_function
+         && abstract_declarator->u.function.late_return_type)
+       /* OK */;
+      else
+       {
+         error ("invalid use of %<auto%>");
+         return error_mark_node;
+       }
+    }
+  
+  return groktypename (&type_specifier_seq, abstract_declarator,
+                      is_template_arg);
+}
+
+static tree cp_parser_type_id (cp_parser *parser)
+{
+  return cp_parser_type_id_1 (parser, false);
+}
+
+static tree cp_parser_template_type_arg (cp_parser *parser)
+{
+  return cp_parser_type_id_1 (parser, true);
 }
 
 /* Parse a type-specifier-seq.
@@ -13306,6 +13923,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);
@@ -13325,6 +13943,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,
@@ -13368,7 +13991,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.
@@ -13381,10 +14004,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;
@@ -13396,7 +14019,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.  */
@@ -13404,10 +14027,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
@@ -13417,7 +14040,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.  */
@@ -13452,8 +14075,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;
 }
@@ -13469,11 +14092,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.  */
@@ -13489,6 +14112,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
@@ -13496,17 +14120,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)
@@ -13595,7 +14240,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.
@@ -13664,6 +14309,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,
@@ -13822,7 +14468,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  /* If we run out of tokens, issue an error message.  */
                case CPP_EOF:
                case CPP_PRAGMA_EOL:
-                 error ("file ends in default argument");
+                 error ("%Hfile ends in default argument", &token->location);
                  done = true;
                  break;
 
@@ -13859,16 +14505,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;
            }
        }
@@ -13884,11 +14535,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;
        }
@@ -13930,7 +14582,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
   if (template_parm_p)
     push_deferring_access_checks (dk_no_deferred);
   default_argument
-    = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+    = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
   if (template_parm_p)
     pop_deferring_access_checks ();
   /* Restore saved state.  */
@@ -13982,14 +14634,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;
@@ -14000,7 +14652,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;
 
@@ -14012,10 +14664,23 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
       init = cp_parser_initializer_clause (parser, non_constant_p);
     }
   else if (token->type == CPP_OPEN_PAREN)
-    init = cp_parser_parenthesized_expression_list (parser, false,
-                                                   /*cast_p=*/false,
-                                                    /*allow_expansion_p=*/true,
-                                                   non_constant_p);
+    {
+      VEC(tree,gc) *vec;
+      vec = cp_parser_parenthesized_expression_list (parser, false,
+                                                    /*cast_p=*/false,
+                                                    /*allow_expansion_p=*/true,
+                                                    non_constant_p);
+      if (vec == NULL)
+       return error_mark_node;
+      init = build_tree_list_vec (vec);
+      release_tree_vector (vec);
+    }
+  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.  */
@@ -14030,20 +14695,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)
@@ -14065,25 +14724,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;
 }
 
@@ -14128,8 +14808,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 `:'.  */
@@ -14211,6 +14891,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);
@@ -14236,7 +14917,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.  */
@@ -14278,10 +14958,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))
                {
@@ -14339,6 +15021,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;
 }
@@ -14353,13 +15037,12 @@ cp_parser_class_name (cp_parser *parser,
 static tree
 cp_parser_class_specifier (cp_parser* parser)
 {
-  cp_token *token;
   tree type;
   tree attributes = NULL_TREE;
-  int has_trailing_semicolon;
   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;
@@ -14411,6 +15094,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)
@@ -14429,10 +15116,6 @@ cp_parser_class_specifier (cp_parser* parser)
 
   /* Look for the trailing `}'.  */
   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);
-  has_trailing_semicolon = (token->type == CPP_SEMICOLON);
   /* Look for trailing attributes to apply to this class.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
     attributes = cp_parser_attributes_opt (parser);
@@ -14523,6 +15206,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;
 }
@@ -14572,7 +15257,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
@@ -14605,6 +15290,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,
@@ -14615,6 +15301,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
@@ -14644,6 +15331,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;
@@ -14678,6 +15366,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,
@@ -14686,7 +15375,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;
        }
@@ -14700,7 +15392,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
@@ -14717,11 +15410,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;
@@ -14729,7 +15428,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;
        }
@@ -14741,23 +15441,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;
        }
@@ -14768,7 +15472,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.  */
@@ -14780,7 +15485,9 @@ 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,
+                                           /*declarator=*/NULL))
     {
       /* If something went wrong, there is no point in even trying to
         process the class-definition.  */
@@ -14795,7 +15502,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
@@ -14831,7 +15539,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);
@@ -14870,8 +15584,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;
     }
@@ -15026,7 +15742,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.  */
@@ -15090,6 +15808,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,
@@ -15116,8 +15835,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
        {
@@ -15135,7 +15854,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 {
@@ -15149,8 +15869,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);
@@ -15168,12 +15888,15 @@ cp_parser_member_declaration (cp_parser* parser)
                 know it is an anonymous aggregate.  */
              fixup_anonymous_aggr (type);
              /* And make the corresponding data member.  */
-             decl = build_decl (FIELD_DECL, NULL_TREE, type);
+             decl = build_decl (decl_spec_token_start->location,
+                                FIELD_DECL, NULL_TREE, type);
              /* Add it to the class.  */
              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
@@ -15231,9 +15954,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
            {
@@ -15268,7 +15990,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);
@@ -15302,6 +16025,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
@@ -15326,7 +16050,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,
@@ -15342,6 +16067,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,
@@ -15406,7 +16133,22 @@ cp_parser_pure_specifier (cp_parser* parser)
   if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
     return error_mark_node;
   /* Look for the `0' token.  */
-  token = cp_lexer_consume_token (parser->lexer);
+  token = cp_lexer_peek_token (parser->lexer);
+
+  if (token->type == CPP_EOF
+      || token->type == CPP_PRAGMA_EOL)
+    return error_mark_node;
+
+  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))
     {
@@ -15417,7 +16159,7 @@ cp_parser_pure_specifier (cp_parser* parser)
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
-      error ("templates may not be %<virtual%>");
+      error ("%Htemplates may not be %<virtual%>", &token->location);
       return error_mark_node;
     }
 
@@ -15619,11 +16361,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);
     }
 
@@ -15934,7 +16679,7 @@ cp_parser_throw_expression (cp_parser* parser)
     expression = NULL_TREE;
   else
     expression = cp_parser_assignment_expression (parser,
-                                                 /*cast_p=*/false);
+                                                 /*cast_p=*/false, NULL);
 
   return build_throw (expression);
 }
@@ -16026,7 +16771,7 @@ cp_parser_asm_operand_list (cp_parser* parser)
       /* Look for the `('.  */
       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
       /* Parse the expression.  */
-      expression = cp_parser_expression (parser, /*cast_p=*/false);
+      expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
       /* Look for the `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
@@ -16179,7 +16924,12 @@ cp_parser_attribute_list (cp_parser* parser)
 
          /* Save away the identifier that indicates which attribute
             this is.  */
-         identifier = token->u.value;
+         identifier = (token->type == CPP_KEYWORD) 
+           /* For keywords, use the canonical spelling, not the
+              parsed identifier.  */
+           ? ridpointers[(int) token->keyword]
+           : token->u.value;
+         
          attribute = build_tree_list (identifier, NULL_TREE);
 
          /* Peek at the next token.  */
@@ -16187,10 +16937,18 @@ cp_parser_attribute_list (cp_parser* parser)
          /* If it's an `(', then parse the attribute arguments.  */
          if (token->type == CPP_OPEN_PAREN)
            {
-             arguments = cp_parser_parenthesized_expression_list
-                         (parser, true, /*cast_p=*/false,
-                           /*allow_expansion_p=*/false,
-                          /*non_constant_p=*/NULL);
+             VEC(tree,gc) *vec;
+             vec = cp_parser_parenthesized_expression_list
+                   (parser, true, /*cast_p=*/false,
+                    /*allow_expansion_p=*/false,
+                    /*non_constant_p=*/NULL);
+             if (vec == NULL)
+               arguments = error_mark_node;
+             else
+               {
+                 arguments = build_tree_list_vec (vec);
+                 release_tree_vector (vec);
+               }
              /* Save the arguments away.  */
              TREE_VALUE (attribute) = arguments;
            }
@@ -16324,7 +17082,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;
@@ -16400,11 +17159,43 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
         cannot look up the name if the scope is not a class type; it
         might, for example, be a template type parameter.  */
       dependent_p = (TYPE_P (parser->scope)
-                    && !(parser->in_declarator_p
-                         && currently_open_class (parser->scope))
-                    && dependent_type_p (parser->scope));
+                    && dependent_scope_p (parser->scope));
       if ((check_dependency || !CLASS_TYPE_P (parser->scope))
-          && dependent_p)
+         && dependent_p)
+       /* Defer lookup.  */
+       decl = error_mark_node;
+      else
+       {
+         tree pushed_scope = NULL_TREE;
+
+         /* If PARSER->SCOPE is a dependent type, then it must be a
+            class type, and we must not be checking dependencies;
+            otherwise, we would have processed this lookup above.  So
+            that PARSER->SCOPE is not considered a dependent base by
+            lookup_member, we must enter the scope here.  */
+         if (dependent_p)
+           pushed_scope = push_scope (parser->scope);
+         /* If the PARSER->SCOPE is a template specialization, it
+            may be instantiated during name lookup.  In that case,
+            errors may be issued.  Even if we rollback the current
+            tentative parse, those errors are valid.  */
+         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 (TREE_CODE (decl) == OVERLOAD
+             && !really_overloaded_fn (decl))
+           decl = OVL_FUNCTION (decl);
+
+         if (pushed_scope)
+           pop_scope (pushed_scope);
+       }
+
+      /* If the scope is a dependent type and either we deferred lookup or
+        we did lookup but didn't find the name, rememeber the name.  */
+      if (decl == error_mark_node && TYPE_P (parser->scope)
+         && dependent_type_p (parser->scope))
        {
          if (tag_type)
            {
@@ -16429,27 +17220,6 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                                         parser->scope, name,
                                         is_template);
        }
-      else
-       {
-         tree pushed_scope = NULL_TREE;
-
-         /* If PARSER->SCOPE is a dependent type, then it must be a
-            class type, and we must not be checking dependencies;
-            otherwise, we would have processed this lookup above.  So
-            that PARSER->SCOPE is not considered a dependent base by
-            lookup_member, we must enter the scope here.  */
-         if (dependent_p)
-           pushed_scope = push_scope (parser->scope);
-         /* If the PARSER->SCOPE is a template specialization, it
-            may be instantiated during name lookup.  In that case,
-            errors may be issued.  Even if we rollback the current
-            tentative parse, those errors are valid.  */
-         decl = lookup_qualified_name (parser->scope, name,
-                                       tag_type != none_type,
-                                       /*complain=*/true);
-         if (pushed_scope)
-           pop_scope (pushed_scope);
-       }
       parser->qualifying_scope = parser->scope;
       parser->object_scope = NULL_TREE;
     }
@@ -16498,7 +17268,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;
@@ -16528,14 +17299,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
@@ -16588,7 +17360,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;
 
@@ -16637,8 +17410,9 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
           additional level of template parameters.  */
        ++num_templates;
 
-      return cp_parser_check_template_parameters (parser,
-                                                 num_templates);
+      return cp_parser_check_template_parameters 
+       (parser, num_templates, declarator_location, declarator);
+
 
     case cdk_function:
     case cdk_array:
@@ -16646,7 +17420,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;
@@ -16659,34 +17433,43 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 /* NUM_TEMPLATES were used in the current declaration.  If that is
    invalid, return FALSE and issue an error messages.  Otherwise,
-   return TRUE.  */
+   return TRUE.  If DECLARATOR is non-NULL, then we are checking a
+   declarator and we can print more accurate diagnostics.  */
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
-                                    unsigned num_templates)
+                                    unsigned num_templates,
+                                    location_t location,
+                                    cp_declarator *declarator)
 {
+  /* If there are the same number of template classes and parameter
+     lists, that's OK.  */
+  if (parser->num_template_parameter_lists == num_templates)
+    return true;
+  /* If there are more, but only one more, then we are referring to a
+     member template.  That's OK too.  */
+  if (parser->num_template_parameter_lists == num_templates + 1)
+    return true;
   /* If there are more template classes than parameter lists, we have
      something like:
 
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      error ("too few template-parameter-lists");
+      if (declarator)
+       error_at (location, "specializing member %<%T::%E%> "
+                 "requires %<template<>%> syntax", 
+                 declarator->u.id.qualifying_scope,
+                 declarator->u.id.unqualified_name);
+      else 
+       error_at (location, "too few template-parameter-lists");
       return false;
     }
-  /* If there are the same number of template classes and parameter
-     lists, that's OK.  */
-  if (parser->num_template_parameter_lists == num_templates)
-    return true;
-  /* If there are more, but only one more, then we are referring to a
-     member template.  That's OK too.  */
-  if (parser->num_template_parameter_lists == num_templates + 1)
-      return true;
   /* Otherwise, there are too many template parameter lists.  We have
      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;
 }
 
@@ -16944,12 +17727,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.  */
@@ -16958,7 +17743,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)
        {
@@ -17017,8 +17803,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
+  cp_token *token;
 
   /* Look for the `template' keyword.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
     return;
 
@@ -17030,7 +17818,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* 14.5.2.2 [temp.mem]
 
          A local class shall not have member templates.  */
-      error ("invalid declaration of member template in local class");
+      error ("%Hinvalid declaration of member template in local class",
+            &token->location);
       cp_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
@@ -17039,7 +17828,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);
@@ -17086,6 +17875,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,
@@ -17098,7 +17888,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);
        }
@@ -17162,6 +17952,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.  */
@@ -17173,6 +17964,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,
@@ -17183,7 +17975,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;
     }
 
@@ -17246,7 +18039,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;
       }
     }
@@ -17273,7 +18067,7 @@ static tree
 cp_parser_simple_cast_expression (cp_parser *parser)
 {
   return cp_parser_cast_expression (parser, /*address_p=*/false,
-                                   /*cast_p=*/false);
+                                   /*cast_p=*/false, NULL);
 }
 
 /* Parse a functional cast to TYPE.  Returns an expression
@@ -17282,14 +18076,33 @@ cp_parser_simple_cast_expression (cp_parser *parser)
 static tree
 cp_parser_functional_cast (cp_parser* parser, tree type)
 {
+  VEC(tree,gc) *vec;
   tree expression_list;
   tree cast;
+  bool nonconst_p;
 
-  expression_list
-    = cp_parser_parenthesized_expression_list (parser, false,
-                                              /*cast_p=*/true,
-                                               /*allow_expansion_p=*/true,
-                                              /*non_constant_p=*/NULL);
+  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);
+    }
+
+
+  vec = cp_parser_parenthesized_expression_list (parser, false,
+                                                /*cast_p=*/true,
+                                                /*allow_expansion_p=*/true,
+                                                /*non_constant_p=*/NULL);
+  if (vec == NULL)
+    expression_list = error_mark_node;
+  else
+    {
+      expression_list = build_tree_list_vec (vec);
+      release_tree_vector (vec);
+    }
 
   cast = build_functional_cast (type, expression_list,
                                 tf_warning_or_error);
@@ -17339,6 +18152,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))
@@ -17377,7 +18206,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   tree saved_qualifying_scope;
   tree saved_object_scope;
   bool saved_greater_than_is_operator_p;
-  bool saved_skip_evaluation;
+  int saved_unevaluated_operand;
+  int saved_inhibit_evaluation_warnings;
 
   /* [temp.names]
 
@@ -17394,8 +18224,10 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   saved_object_scope = parser->object_scope;
   /* We need to evaluate the template arguments, even though this
      template-id may be nested within a "sizeof".  */
-  saved_skip_evaluation = skip_evaluation;
-  skip_evaluation = false;
+  saved_unevaluated_operand = cp_unevaluated_operand;
+  cp_unevaluated_operand = 0;
+  saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+  c_inhibit_evaluation_warnings = 0;
   /* Parse the template-argument-list itself.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER)
       || cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
@@ -17448,9 +18280,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
@@ -17462,7 +18294,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   parser->scope = saved_scope;
   parser->qualifying_scope = saved_qualifying_scope;
   parser->object_scope = saved_object_scope;
-  skip_evaluation = saved_skip_evaluation;
+  cp_unevaluated_operand = saved_unevaluated_operand;
+  c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
 
   return arguments;
 }
@@ -17612,7 +18445,12 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
       /* Parse the assignment-expression.  */
-      parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+      parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
+      if (parsed_arg == error_mark_node)
+       {
+         cp_parser_pop_lexer (parser);
+         continue;
+       }
 
       if (!processing_template_decl)
        parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg);
@@ -17691,7 +18529,8 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
     }
 
   /* Do not actually evaluate the expression.  */
-  ++skip_evaluation;
+  ++cp_unevaluated_operand;
+  ++c_inhibit_evaluation_warnings;
   /* If it's a `(', then we might be looking at the type-id
      construction.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
@@ -17733,14 +18572,15 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
      looking at the unary-expression production.  */
   if (!expr)
     expr = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                      /*cast_p=*/false);
+                                      /*cast_p=*/false, NULL);
 
   if (pack_expansion_p)
     /* Build a pack expansion. */
     expr = make_pack_expansion (expr);
 
   /* Go back to evaluating expressions.  */
-  --skip_evaluation;
+  --cp_unevaluated_operand;
+  --c_inhibit_evaluation_warnings;
 
   /* Free the message we created.  */
   free (tmp);
@@ -17771,14 +18611,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)
@@ -17790,7 +18631,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;
     }
 
@@ -17831,6 +18672,7 @@ cp_parser_set_storage_class (cp_parser *parser,
 static void
 cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
                              tree type_spec,
+                             location_t location,
                              bool user_defined_p)
 {
   decl_specs->any_specifiers_p = true;
@@ -17857,6 +18699,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)
@@ -17866,6 +18709,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;
     }
 }
 
@@ -18108,7 +18952,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);
@@ -18120,7 +18964,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;
@@ -18129,7 +18973,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.
@@ -18146,8 +18990,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.  */
@@ -18197,41 +19042,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;
     }
 }
 
@@ -18399,7 +19257,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);
     }
 
@@ -18442,7 +19301,7 @@ cp_parser_objc_message_receiver (cp_parser* parser)
   /* An Objective-C message receiver may be either (1) a type
      or (2) an expression.  */
   cp_parser_parse_tentatively (parser);
-  rcv = cp_parser_expression (parser, false);
+  rcv = cp_parser_expression (parser, false, NULL);
 
   if (cp_parser_parse_definitely (parser))
     return rcv;
@@ -18494,7 +19353,7 @@ cp_parser_objc_message_args (cp_parser* parser)
 
       maybe_unary_selector_p = false;
       cp_parser_require (parser, CPP_COLON, "%<:%>");
-      arg = cp_parser_assignment_expression (parser, false);
+      arg = cp_parser_assignment_expression (parser, false, NULL);
 
       sel_args
        = chainon (sel_args,
@@ -18509,7 +19368,7 @@ cp_parser_objc_message_args (cp_parser* parser)
       tree arg;
 
       cp_lexer_consume_token (parser->lexer);
-      arg = cp_parser_assignment_expression (parser, false);
+      arg = cp_parser_assignment_expression (parser, false, NULL);
 
       addl_args
        = chainon (addl_args,
@@ -18532,15 +19391,18 @@ static tree
 cp_parser_objc_encode_expression (cp_parser* parser)
 {
   tree type;
+  cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  token = cp_lexer_peek_token (parser->lexer);
   type = complete_type (cp_parser_type_id (parser));
   cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   if (!type)
     {
-      error ("%<@encode%> must specify a type as an argument");
+      error ("%H%<@encode%> must specify a type as an argument",
+            &token->location);
       return error_mark_node;
     }
 
@@ -18603,6 +19465,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
   tree sel_seq = NULL_TREE;
   bool maybe_unary_selector_p = true;
   cp_token *token;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@selector'.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
@@ -18654,7 +19517,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
  finish_selector:
   cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
-  return objc_build_selector_expr (sel_seq);
+  return objc_build_selector_expr (loc, sel_seq);
 }
 
 /* Parse a list of identifiers.
@@ -18813,7 +19676,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))
     {
@@ -18828,10 +19691,10 @@ cp_parser_objc_typename (cp_parser* parser)
        cp_type = cp_parser_type_id (parser);
 
       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
-      typename = build_tree_list (proto_quals, cp_type);
+      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.  */
@@ -18855,7 +19718,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;
     }
 
@@ -18888,7 +19751,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);
@@ -18900,13 +19763,13 @@ cp_parser_objc_method_keyword_params (cp_parser* parser)
 
       maybe_unary_selector_p = false;
       cp_parser_require (parser, CPP_COLON, "%<:%>");
-      typename = cp_parser_objc_typename (parser);
+      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);
@@ -19136,11 +19999,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,
@@ -19186,7 +20048,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;
     }
 
@@ -19322,7 +20185,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);
     }
 }
@@ -19405,7 +20269,7 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
 
   location = cp_lexer_peek_token (parser->lexer)->location;
   cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
-  lock = cp_parser_expression (parser, false);
+  lock = cp_parser_expression (parser, false, NULL);
   cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
@@ -19426,15 +20290,16 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
 static tree
 cp_parser_objc_throw_statement (cp_parser *parser) {
   tree expr = NULL_TREE;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   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);
+    expr = cp_parser_assignment_expression (parser, false, NULL);
 
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
-  return objc_build_throw_stmt (expr);
+  return objc_build_throw_stmt (loc, expr);
 }
 
 /* Parse an Objective-C statement.  */
@@ -19453,7 +20318,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);
     }
 
@@ -19486,7 +20352,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;
@@ -19519,6 +20387,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;
        }
     }
 
@@ -19531,14 +20403,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;
       }
 }
@@ -19561,10 +20434,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,
@@ -19573,12 +20448,12 @@ 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);
+         tree u = build_omp_clause (token->location, kind);
          OMP_CLAUSE_DECL (u) = decl;
          OMP_CLAUSE_CHAIN (u) = list;
          list = u;
@@ -19621,11 +20496,53 @@ cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree 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 (loc, 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;
@@ -19671,8 +20588,8 @@ 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");
-  c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
+  c = build_omp_clause (location, OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
 
@@ -19683,7 +20600,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
    if ( expression ) */
 
 static tree
-cp_parser_omp_clause_if (cp_parser *parser, tree list)
+cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
 {
   tree t, c;
 
@@ -19698,9 +20615,9 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
 
-  c = build_omp_clause (OMP_CLAUSE_IF);
+  c = build_omp_clause (location, OMP_CLAUSE_IF);
   OMP_CLAUSE_IF_EXPR (c) = t;
   OMP_CLAUSE_CHAIN (c) = list;
 
@@ -19711,13 +20628,14 @@ 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);
+  c = build_omp_clause (location, OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
@@ -19726,14 +20644,15 @@ 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, "%<(%>"))
     return list;
 
-  t = cp_parser_expression (parser, false);
+  t = cp_parser_expression (parser, false, NULL);
 
   if (t == error_mark_node
       || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
@@ -19741,9 +20660,10 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
+                            "num_threads", location);
 
-  c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
+  c = build_omp_clause (location, OMP_CLAUSE_NUM_THREADS);
   OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
   OMP_CLAUSE_CHAIN (c) = list;
 
@@ -19754,13 +20674,15 @@ 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);
+  c = build_omp_clause (location, OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
@@ -19807,8 +20729,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,
@@ -19832,17 +20754,17 @@ 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);
+  c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
@@ -19875,21 +20797,28 @@ 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);
 
-      t = cp_parser_assignment_expression (parser, false);
+      token = cp_lexer_peek_token (parser->lexer);
+      t = cp_parser_assignment_expression (parser, false, NULL);
 
       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;
 
@@ -19899,7 +20828,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
   else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<,%> or %<)%>"))
     goto resync_fail;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
@@ -19912,6 +20841,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 (location, 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.  */
@@ -19922,6 +20867,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))
     {
@@ -19932,11 +20878,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";
@@ -19947,7 +20899,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:
@@ -19956,7 +20909,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:
@@ -19965,15 +20918,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:
@@ -19986,7 +20941,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:
@@ -19994,6 +20950,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;
@@ -20004,7 +20965,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:
@@ -20077,7 +21038,7 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
   lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                   /*cast_p=*/false);
+                                   /*cast_p=*/false, NULL);
   switch (TREE_CODE (lhs))
     {
     case ERROR_MARK:
@@ -20134,7 +21095,7 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
        }
       cp_lexer_consume_token (parser->lexer);
 
-      rhs = cp_parser_expression (parser, false);
+      rhs = cp_parser_expression (parser, false, NULL);
       if (rhs == error_mark_node)
        goto saw_error;
       break;
@@ -20184,7 +21145,7 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
   stmt = cp_parser_omp_structured_block (parser);
-  return c_finish_omp_critical (stmt, name);
+  return c_finish_omp_critical (input_location, stmt, name);
 }
 
 /* OpenMP 2.5:
@@ -20197,100 +21158,485 @@ static void
 cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
 {
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
-    (void) cp_parser_omp_var_list (parser, 0, NULL);
+    (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
   cp_parser_require_pragma_eol (parser, 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 cond = cp_parser_binary_expression (parser, false, true,
+                                          PREC_NOT_OPERATOR, NULL);
+  bool overloaded_p;
 
-  if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+  if (cond == error_mark_node
+      || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     {
-      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))
+  switch (TREE_CODE (cond))
     {
-      cp_decl_specifier_seq type_specifiers;
+    case GT_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case LE_EXPR:
+      break;
+    default:
+      return error_mark_node;
+    }
 
-      /* First, try to parse as an initialized declaration.  See
-        cp_parser_condition, from whence the bulk of this is copied.  */
+  /* 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))))
+    return cond;
 
-      cp_parser_parse_tentatively (parser);
-      cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
-                                   &type_specifiers);
-      if (!cp_parser_error_occurred (parser))
+  return build_x_binary_op (TREE_CODE (cond),
+                           TREE_OPERAND (cond, 0), ERROR_MARK,
+                           TREE_OPERAND (cond, 1), ERROR_MARK,
+                           &overloaded_p, tf_warning_or_error);
+}
+
+/* Helper function, to parse omp for increment expression.  */
+
+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, NULL);
+      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, NULL);
+      rhs = build2 (op, TREE_TYPE (decl), decl, rhs);
+      return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+    }
+
+  lhs = cp_parser_binary_expression (parser, false, false,
+                                    PREC_ADDITIVE_EXPRESSION, NULL);
+  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, false,
+                                        PREC_ADDITIVE_EXPRESSION, NULL);
+      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;
 
-         cp_parser_require (parser, CPP_EQ, "%<=%>");
+         /* First, try to parse as an initialized declaration.  See
+            cp_parser_condition, from whence the bulk of this is copied.  */
+
+         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);
 
-             decl = start_decl (declarator, &type_specifiers,
-                                /*initialized_p=*/false, attributes,
-                                /*prefix_attributes=*/NULL_TREE,
-                                &pushed_scope);
+             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);
+
+                     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, NULL);
 
-             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, NULL);
+                 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, NULL);
+                 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 (loc, 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 (loc, 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))
+       cond = cp_parser_omp_for_cond (parser, decl);
+      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, NULL);
+       }
 
-  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.  */
@@ -20302,7 +21648,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:
@@ -20316,7 +21696,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)
@@ -20330,9 +21711,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));
@@ -20348,7 +21727,8 @@ static tree
 cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
 {
   cp_parser_require_pragma_eol (parser, pragma_tok);
-  return c_finish_omp_master (cp_parser_omp_structured_block (parser));
+  return c_finish_omp_master (input_location,
+                             cp_parser_omp_structured_block (parser));
 }
 
 /* OpenMP 2.5:
@@ -20358,8 +21738,9 @@ cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
 static tree
 cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok)
 {
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
   cp_parser_require_pragma_eol (parser, pragma_tok);
-  return c_finish_omp_ordered (cp_parser_omp_structured_block (parser));
+  return c_finish_omp_ordered (loc, cp_parser_omp_structured_block (parser));
 }
 
 /* OpenMP 2.5:
@@ -20494,6 +21875,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
   tree stmt, clauses, par_clause, ws_clause, block;
   unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
   unsigned int save;
+  location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
     {
@@ -20529,14 +21911,12 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
       break;
 
     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;
+      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
+      cp_parser_omp_for_loop (parser, ws_clause, &par_clause);
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
-      c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+      c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
       stmt = cp_parser_omp_sections_scope (parser);
       if (stmt)
        OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
@@ -20577,6 +21957,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) */
 
@@ -20585,7 +22002,7 @@ cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok)
 {
   tree vars;
 
-  vars = cp_parser_omp_var_list (parser, 0, NULL);
+  vars = cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
   finish_omp_threadprivate (vars);
@@ -20624,6 +22041,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 ();
     }
@@ -20662,10 +22082,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)
@@ -20698,7 +22119,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:
@@ -20708,8 +22130,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;
@@ -20723,8 +22145,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;
@@ -20743,14 +22181,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: