OSDN Git Service

PR libstdc++/37907
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 357d1cb..e64d0bf 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.
@@ -77,6 +76,8 @@ typedef struct cp_token GTY (())
      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.  */
@@ -84,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.  */
@@ -95,8 +94,7 @@ DEF_VEC_ALLOC_P (cp_token_position,heap);
 
 static cp_token eof_token =
 {
-  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 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
@@ -104,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;
@@ -144,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;
 
@@ -251,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.  */
 
@@ -310,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;
@@ -423,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
        {
@@ -438,8 +432,8 @@ 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.  */
@@ -470,7 +464,8 @@ 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;
     }
 }
@@ -853,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
@@ -1013,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;
 
@@ -1024,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;
@@ -1190,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,
@@ -1199,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.  */
 
@@ -1271,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
@@ -1281,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;
@@ -1388,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;
 
@@ -1581,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 *, location_t);
-static tree cp_parser_parenthesized_expression_list
+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 *);
@@ -1607,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, enum cp_parser_prec);
+  (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
@@ -1726,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 *);
@@ -1907,7 +1912,7 @@ static tree cp_parser_maybe_treat_template_as_class
 static bool cp_parser_check_declarator_template_parameters
   (cp_parser *, cp_declarator *, location_t);
 static bool cp_parser_check_template_parameters
-  (cp_parser *, unsigned, location_t);
+  (cp_parser *, unsigned, location_t, cp_declarator *);
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
@@ -2074,7 +2079,8 @@ cp_parser_error (cp_parser* parser, const char* message)
 
       if (token->type == CPP_PRAGMA)
        {
-         error ("%H%<#pragma%> is not allowed here", &token->location);
+         error_at (token->location,
+                   "%<#pragma%> is not allowed here");
          cp_parser_skip_to_pragma_eol (parser, token);
          return;
        }
@@ -2084,7 +2090,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);
     }
 }
 
@@ -2105,26 +2111,26 @@ cp_parser_name_lookup_error (cp_parser* parser,
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-       error ("%H%<%E::%E%> has not been declared",
-              &location, parser->scope, name);
+       error_at (location, "%<%E::%E%> has not been declared",
+                 parser->scope, name);
       else if (parser->scope == global_namespace)
-       error ("%H%<::%E%> has not been declared", &location, name);
+       error_at (location, "%<::%E%> has not been declared", name);
       else if (parser->object_scope
               && !CLASS_TYPE_P (parser->object_scope))
-       error ("%Hrequest for member %qE in non-class type %qT",
-              &location, name, parser->object_scope);
+       error_at (location, "request for member %qE in non-class type %qT",
+                 name, parser->object_scope);
       else if (parser->object_scope)
-       error ("%H%<%T::%E%> has not been declared",
-              &location, parser->object_scope, name);
+       error_at (location, "%<%T::%E%> has not been declared",
+                 parser->object_scope, name);
       else
-       error ("%H%qE has not been declared", &location, name);
+       error_at (location, "%qE has not been declared", name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
+    error_at (location, "%<%E::%E%> %s", parser->scope, name, desired);
   else if (parser->scope == global_namespace)
-    error ("%H%<::%E%> %s", &location, name, desired);
+    error_at (location, "%<::%E%> %s", name, desired);
   else
-    error ("%H%qE %s", &location, name, desired);
+    error_at (location, "%qE %s", name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -2148,22 +2154,21 @@ static void
 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 ("%H%<long long long%> is too long for GCC", &location);
-         else if (pedantic && !in_system_header && warn_long_long
-                   && cxx_dialect == cxx98)
-           pedwarn (location, OPT_Wlong_long, 
-                    "ISO C++ 1998 does not support %<long long%>");
+           error_at (location, "%<long long long%> is too long for GCC");
+         else 
+           pedwarn_cxx98 (location, OPT_Wlong_long, 
+                          "ISO C++ 1998 does not support %<long long%>");
        }
       else if (count > 1)
        {
@@ -2183,7 +2188,7 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
            "__complex",
            "__thread"
          };
-         error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
+         error_at (location, "duplicate %qs", decl_spec_names[ds]);
        }
     }
 }
@@ -2227,7 +2232,8 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
   if (declarator
       && declarator->kind == cdk_function)
     {
-      error ("%Hnew types may not be defined in a return type", &type_location);
+      error_at (type_location,
+               "new types may not be defined in a return type");
       inform (type_location, 
              "(perhaps a semicolon is missing after the definition of %qT)",
              type);
@@ -2249,11 +2255,11 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
   if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
     {
       if (TYPE_P (type))
-       error ("%H%qT is not a template", &location, type);
+       error_at (location, "%qT is not a template", type);
       else if (TREE_CODE (type) == IDENTIFIER_NODE)
-       error ("%H%qE is not a template", &location, type);
+       error_at (location, "%qE is not a template", type);
       else
-       error ("%Hinvalid template-id", &location);
+       error_at (location, "invalid template-id");
       /* Remember the location of the invalid "<".  */
       if (cp_parser_uncommitted_to_tentative_parse_p (parser))
        start = cp_lexer_token_position (parser->lexer, true);
@@ -2315,18 +2321,18 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
   /* 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 ("%Hinvalid use of template-name %qE without an argument list",
-           &location, decl);
+    error_at (location,
+             "invalid use of template-name %qE without an argument list",
+             decl);
   else if (TREE_CODE (id) == BIT_NOT_EXPR)
-    error ("%Hinvalid use of destructor %qD as a type", &location, id);
+    error_at (location, "invalid use of destructor %qD as a type", id);
   else if (TREE_CODE (decl) == TYPE_DECL)
     /* Something like 'unsigned A a;'  */
-    error ("%Hinvalid combination of multiple type-specifiers",
-           &location);
+    error_at (location, "invalid combination of multiple type-specifiers");
   else if (!parser->scope)
     {
       /* Issue an error message.  */
-      error ("%H%qE does not name a type", &location, id);
+      error_at (location, "%qE does not name a type", 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:
 
@@ -2374,11 +2380,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
   else if (parser->scope != error_mark_node)
     {
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-       error ("%H%qE in namespace %qE does not name a type",
-              &location, id, parser->scope);
+       error_at (location, "%qE in namespace %qE does not name a type",
+                 id, parser->scope);
       else if (TYPE_P (parser->scope))
-       error ("%H%qE in class %qT does not name a type",
-               &location, id, parser->scope);
+       error_at (location, "%qE in class %qT does not name a type",
+                 id, parser->scope);
       else
        gcc_unreachable ();
     }
@@ -2617,6 +2623,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;
@@ -2939,8 +2947,9 @@ 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 ("%Hunsupported non-standard concatenation "
-                       "of string literals", &tok->location);
+               error_at (tok->location,
+                         "unsupported non-standard concatenation "
+                         "of string literals");
            }
 
          obstack_grow (&str_ob, &str, sizeof (cpp_string));
@@ -3140,6 +3149,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_at (token->location,
+                   "fixed-point types not supported in C++");
+         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.  */
@@ -3228,9 +3243,9 @@ cp_parser_primary_expression (cp_parser *parser,
            if (!parser->in_function_body
                || parser->in_template_argument_list_p)
              {
-               error ("%Hstatement-expressions are not allowed outside "
-                      "functions nor in template-argument lists",
-                      &token->location);
+               error_at (token->location,
+                         "statement-expressions are not allowed outside "
+                         "functions nor in template-argument lists");
                cp_parser_skip_to_end_of_block_or_statement (parser);
                expr = error_mark_node;
              }
@@ -3247,7 +3262,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
@@ -3287,8 +3302,8 @@ cp_parser_primary_expression (cp_parser *parser,
          cp_lexer_consume_token (parser->lexer);
          if (parser->local_variables_forbidden_p)
            {
-             error ("%H%<this%> may not be used in this context",
-                     &token->location);
+             error_at (token->location,
+                       "%<this%> may not be used in this context");
              return error_mark_node;
            }
          /* Pointers cannot appear in constant-expressions.  */
@@ -3304,16 +3319,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:
          {
@@ -3327,7 +3365,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.  */
@@ -3361,6 +3399,8 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_IS_ENUM:
        case RID_IS_POD:
        case RID_IS_POLYMORPHIC:
+       case RID_IS_STD_LAYOUT:
+       case RID_IS_TRIVIAL:
        case RID_IS_UNION:
          return cp_parser_trait_expr (parser, token->keyword);
 
@@ -3473,8 +3513,9 @@ cp_parser_primary_expression (cp_parser *parser,
                decl = check_for_out_of_scope_variable (decl);
                if (local_variable_p (decl))
                  {
-                   error ("%Hlocal variable %qD may not appear in this context",
-                          &id_expr_token->location, decl);
+                   error_at (id_expr_token->location,
+                             "local variable %qD may not appear in this context",
+                             decl);
                    return error_mark_node;
                  }
              }
@@ -3773,8 +3814,9 @@ cp_parser_unqualified_id (cp_parser* parser,
        if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
          {
            if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-             error ("%Hscope %qT before %<~%> is not a class-name",
-                    &token->location, scope);
+             error_at (token->location,
+                       "scope %qT before %<~%> is not a class-name",
+                       scope);
            cp_parser_simulate_error (parser);
            if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
              cp_lexer_consume_token (parser->lexer);
@@ -3853,6 +3895,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,
@@ -3861,6 +3905,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
@@ -3875,8 +3929,9 @@ 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 ("%Hdeclaration of %<~%T%> as member of %qT",
-                    &token->location, type_decl, scope);
+             error_at (token->location,
+                       "declaration of %<~%T%> as member of %qT",
+                       type_decl, scope);
            cp_parser_simulate_error (parser);
            return error_mark_node;
          }
@@ -3889,8 +3944,9 @@ 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 ("%Htypedef-name %qD used as destructor declarator",
-                &token->location, type_decl);
+         error_at (token->location,
+                   "typedef-name %qD used as destructor declarator",
+                   type_decl);
 
        return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
@@ -3932,10 +3988,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
@@ -4010,7 +4072,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
@@ -4050,12 +4112,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, "%<::%>");
 
@@ -4097,20 +4159,26 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                                                    &ambiguous_decls,
                                                    token->location);
                      if (TREE_CODE (decl) == TEMPLATE_DECL)
-                       error ("%H%qD used without template parameters",
-                              &token->location, decl);
+                       error_at (token->location,
+                                 "%qD used without template parameters",
+                                 decl);
                      else if (ambiguous_decls)
                        {
-                         error ("%Hreference to %qD is ambiguous",
-                                &token->location, token->u.value);
+                         error_at (token->location,
+                                   "reference to %qD is ambiguous",
+                                   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",
-                          token->location);
+                        {
+                          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;
@@ -4229,11 +4297,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.
@@ -4247,18 +4315,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
@@ -4268,7 +4337,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,
@@ -4278,8 +4348,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;
@@ -4342,7 +4430,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;
@@ -4386,7 +4475,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
@@ -4458,7 +4547,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.  */
@@ -4611,7 +4700,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;
 
@@ -4639,7 +4728,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;
@@ -4652,19 +4741,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
@@ -4673,7 +4765,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);
 
@@ -4686,8 +4779,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);
                      }
                  }
              }
@@ -4705,21 +4799,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);
@@ -4728,28 +4825,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);
 
-            if (warn_disallowed_functions)
-              warn_if_disallowed_function_p (postfix_expression);
-
            /* The POSTFIX_EXPRESSION is certainly no longer an id.  */
            idk = CP_ID_KIND_NONE;
+
+           release_tree_vector (args);
          }
          break;
 
@@ -4805,6 +4901,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
@@ -4846,7 +4944,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, "%<]%>");
@@ -4899,6 +4997,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)
@@ -4914,7 +5013,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
        {
-         error ("%H%qE does not have class type", &location, postfix_expression);
+         error_at (location, "%qE does not have class type",
+                   postfix_expression);
          scope = NULL_TREE;
        }
       else
@@ -4998,7 +5098,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
         TYPE_DECL here.  That is invalid code.  */
       if (TREE_CODE (name) == TYPE_DECL)
        {
-         error ("%Hinvalid use of %qD", &token->location, name);
+         error_at (token->location, "invalid use of %qD", name);
          postfix_expression = error_mark_node;
        }
       else
@@ -5053,24 +5153,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;
@@ -5080,7 +5178,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.  */
@@ -5128,7 +5228,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);
@@ -5149,7 +5249,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;
@@ -5185,17 +5285,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;
 }
@@ -5230,7 +5328,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.  */
@@ -5312,7 +5410,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;
@@ -5423,13 +5522,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;
@@ -5448,7 +5548,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)
        {
@@ -5490,7 +5590,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
@@ -5536,10 +5637,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
@@ -5555,7 +5657,11 @@ 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.  */
@@ -5574,8 +5680,8 @@ cp_parser_new_expression (cp_parser* parser)
         message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
        {
-         error ("%Harray bound forbidden after parenthesized type-id",
-                &token->location);
+         error_at (token->location,
+                   "array bound forbidden after parenthesized type-id");
          inform (token->location, 
                  "try removing the parentheses around the type-id");
          cp_parser_direct_new_declarator (parser);
@@ -5591,16 +5697,25 @@ cp_parser_new_expression (cp_parser* parser)
       || 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.
@@ -5610,10 +5725,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
@@ -5690,7 +5805,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;
 }
 
@@ -5755,7 +5870,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       if (!declarator)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
-         expression = cp_parser_expression (parser, /*cast_p=*/false);
+         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
@@ -5770,8 +5885,9 @@ cp_parser_direct_new_declarator (cp_parser* parser)
                                              /*complain=*/true);
              if (!expression)
                {
-                 error ("%Hexpression in new-declarator must have integral "
-                        "or enumeration type", &token->location);
+                 error_at (token->location,
+                           "expression in new-declarator must have integral "
+                           "or enumeration type");
                  expression = error_mark_node;
                }
            }
@@ -5803,28 +5919,26 @@ cp_parser_direct_new_declarator (cp_parser* parser)
      ( 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;
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
+      tree t;
       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);
+      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));
-  if (!expression_list)
-    expression_list = void_zero_node;
 
   return expression_list;
 }
@@ -5875,6 +5989,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:
@@ -5888,7 +6057,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))
@@ -5953,17 +6123,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
@@ -5981,14 +6152,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:
@@ -6072,7 +6245,9 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
 
 static tree
 cp_parser_binary_expression (cp_parser* parser, bool cast_p,
-                            enum cp_parser_prec prec)
+                            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];
@@ -6083,7 +6258,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
   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 (;;)
@@ -6095,11 +6270,11 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
           && token->type == CPP_RSHIFT
           && !parser->greater_than_is_operator_p)
         {
-          warning (OPT_Wc__0x_compat, 
-                   "%H%<>>%> operator will be treated as two right angle brackets in C++0x", 
-                   &token->location);
-          warning (OPT_Wc__0x_compat, 
-                   "suggest parentheses around %<>>%> expression");
+          if (warning_at (token->location, OPT_Wc__0x_compat, 
+                         "%<>>%> operator will be treated as"
+                         " two right angle brackets in C++0x"))
+           inform (token->location,
+                   "suggest parentheses around %<>>%> expression");
         }
 
       new_prec = TOKEN_PRECEDENCE (token);
@@ -6125,6 +6300,13 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
       /* We used the operator token.  */
       cp_lexer_consume_token (parser->lexer);
 
+      /* For "false && x" or "true || x", x will never be executed;
+        disable warnings while evaluating it.  */
+      if (tree_type == TRUTH_ANDIF_EXPR)
+       c_inhibit_evaluation_warnings += lhs == truthvalue_false_node;
+      else if (tree_type == TRUTH_ORIF_EXPR)
+       c_inhibit_evaluation_warnings += lhs == truthvalue_true_node;
+
       /* Extract another operand.  It may be the RHS of this expression
         or the LHS of a new, higher priority expression.  */
       rhs = cp_parser_simple_cast_expression (parser);
@@ -6153,6 +6335,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')
@@ -6169,9 +6352,28 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
          lhs_type = sp->lhs_type;
        }
 
+      /* Undo the disabling of warnings done above.  */
+      if (tree_type == TRUTH_ANDIF_EXPR)
+       c_inhibit_evaluation_warnings -= lhs == truthvalue_false_node;
+      else if (tree_type == TRUTH_ORIF_EXPR)
+       c_inhibit_evaluation_warnings -= lhs == truthvalue_true_node;
+
       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,
@@ -6213,16 +6415,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,
@@ -6243,7 +6455,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;
 
@@ -6256,7 +6469,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, PREC_NOT_OPERATOR);
+      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))
@@ -6391,7 +6605,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;
 
@@ -6401,7 +6615,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)
@@ -6480,7 +6694,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;
@@ -6504,7 +6718,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)
@@ -6547,11 +6762,16 @@ 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;
 
@@ -6647,6 +6867,12 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_POLYMORPHIC:
       kind = CPTK_IS_POLYMORPHIC;
       break;
+    case RID_IS_STD_LAYOUT:
+      kind = CPTK_IS_STD_LAYOUT;
+      break;
+    case RID_IS_TRIVIAL:
+      kind = CPTK_IS_TRIVIAL;
+      break;
     case RID_IS_UNION:
       kind = CPTK_IS_UNION;
       break;
@@ -6872,6 +7098,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);
@@ -6912,10 +7139,11 @@ 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 ("%Hcase label %qE not within a switch statement",
-                &token->location, expr);
+         error_at (token->location,
+                   "case label %qE not within a switch statement",
+                   expr);
       }
       break;
 
@@ -6924,19 +7152,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 ("%Hcase label not within a switch statement", &token->location);
+       error_at (token->location, "case label not within a switch statement");
       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.
@@ -6957,7 +7207,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);
@@ -7044,7 +7294,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
          else
            {
              token = cp_lexer_consume_token (parser->lexer);
-             error ("%H%<else%> without a previous %<if%>", &token->location);
+             error_at (token->location, "%<else%> without a previous %<if%>");
            }
        }
 
@@ -7120,7 +7370,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);
@@ -7133,7 +7394,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
@@ -7151,10 +7424,9 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
                   statement which does have an else clause.  We warn
                   about the potential ambiguity.  */
                if (nested_if)
-                 warning (OPT_Wparentheses,
-                          ("%Hsuggest explicit braces "
-                           "to avoid ambiguous %<else%>"),
-                          EXPR_LOCUS (statement));
+                 warning_at (EXPR_LOCATION (statement), OPT_Wparentheses,
+                             "suggest explicit braces to avoid ambiguous"
+                             " %<else%>");
              }
 
            /* Now we're all done with the if-statement.  */
@@ -7277,7 +7549,7 @@ cp_parser_condition (cp_parser* parser)
          else
            {
              /* Consume the `='.  */
-             cp_lexer_consume_token (parser->lexer);
+             cp_parser_require (parser, CPP_EQ, "%<=%>");
              initializer = cp_parser_initializer_clause (parser, &non_constant_p);
            }
          if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
@@ -7304,49 +7576,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.
@@ -7391,7 +7621,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.  */
@@ -7419,7 +7648,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 `)'.  */
@@ -7451,9 +7680,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, "%<)%>");
 
@@ -7546,7 +7774,7 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (in_statement)
        {
        case 0:
-         error ("%Hbreak statement not within loop or switch", &token->location);
+         error_at (token->location, "break statement not within loop or switch");
          break;
        default:
          gcc_assert ((in_statement & IN_SWITCH_STMT)
@@ -7554,10 +7782,10 @@ cp_parser_jump_statement (cp_parser* parser)
          statement = finish_break_stmt ();
          break;
        case IN_OMP_BLOCK:
-         error ("%Hinvalid exit from OpenMP structured block", &token->location);
+         error_at (token->location, "invalid exit from OpenMP structured block");
          break;
        case IN_OMP_FOR:
-         error ("%Hbreak statement used with OpenMP for loop", &token->location);
+         error_at (token->location, "break statement used with OpenMP for loop");
          break;
        }
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
@@ -7567,14 +7795,14 @@ cp_parser_jump_statement (cp_parser* parser)
       switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
        {
        case 0:
-         error ("%Hcontinue statement not within a loop", &token->location);
+         error_at (token->location, "continue statement not within a loop");
          break;
        case IN_ITERATION_STMT:
        case IN_OMP_FOR:
          statement = finish_continue_stmt ();
          break;
        case IN_OMP_BLOCK:
-         error ("%Hinvalid exit from OpenMP structured block", &token->location);
+         error_at (token->location, "invalid exit from OpenMP structured block");
          break;
        default:
          gcc_unreachable ();
@@ -7593,7 +7821,7 @@ cp_parser_jump_statement (cp_parser* parser)
            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);
+         expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
        else
          /* If the next token is a `;', then there is no
             expression.  */
@@ -7614,7 +7842,7 @@ cp_parser_jump_statement (cp_parser* parser)
          /* 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));
@@ -7680,8 +7908,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))
@@ -7717,6 +7946,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, "%<}%>");
     }
@@ -7971,7 +8204,7 @@ cp_parser_block_declaration (cp_parser *parser,
   else if (token1->keyword == RID_LABEL)
     {
       cp_lexer_consume_token (parser->lexer);
-      error ("%H%<__label__%> not at the beginning of a block", &token1->location);
+      error_at (token1->location, "%<__label__%> not at the beginning of a block");
       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))
@@ -8059,7 +8292,8 @@ cp_parser_simple_declaration (cp_parser* parser,
      (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_BRACE))
+      && 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
@@ -8107,8 +8341,9 @@ cp_parser_simple_declaration (cp_parser* parser,
          if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
            {
              cp_token *token = cp_lexer_peek_token (parser->lexer);
-             error ("%Hmixing declarations and function-definitions is forbidden",
-                    &token->location);
+             error_at (token->location,
+                       "mixing"
+                       " declarations and function-definitions is forbidden");
            }
          /* Otherwise, we're done with the list of declarators.  */
          else
@@ -8247,7 +8482,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
        case RID_FRIEND:
          if (!at_class_scope_p ())
            {
-             error ("%H%<friend%> used outside of class", &token->location);
+             error_at (token->location, "%<friend%> used outside of class");
              cp_lexer_purge_token (parser->lexer);
            }
          else
@@ -8294,26 +8529,23 @@ 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, 
-                 "%H%<auto%> will change meaning in C++0x; please remove it",
-                &token->location);
+              warning_at (token->location, OPT_Wc__0x_compat, "%<auto%>"
+                         " will change meaning in C++0x; please remove it");
 
               /* Set the storage class anyway.  */
               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 ("%HC++0x %<auto%> specifier not supported", &token->location);
+          else
+           /* C++0x auto type-specifier.  */
+           found_decl_spec = false;
           break;
 
        case RID_REGISTER:
@@ -8423,8 +8655,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
-    error ("%Hclass definition may not be declared a friend",
-           &start_token->location);
+    error_at (start_token->location,
+             "class definition may not be declared a friend");
 }
 
 /* Parse an (optional) storage-class-specifier.
@@ -8493,7 +8725,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
 
         A member function template shall not be virtual.  */
       if (PROCESSING_REAL_TEMPLATE_DECL_P ())
-       error ("%Htemplates may not be %<virtual%>", &token->location);
+       error_at (token->location, "templates may not be %<virtual%>");
       else if (decl_specs)
        ++decl_specs->specs[(int) ds_virtual];
       break;
@@ -8670,7 +8902,10 @@ 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, "%<(%>"))
@@ -8751,7 +8986,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
@@ -8770,11 +9005,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.  */
@@ -8890,6 +9126,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;
 }
 
@@ -8970,8 +9216,8 @@ cp_parser_mem_initializer_list (cp_parser* parser)
   /* Let the semantic analysis code know that we are starting the
      mem-initializer-list.  */
   if (!DECL_CONSTRUCTOR_P (current_function_decl))
-    error ("%Honly constructors take base initializers",
-          &token->location);
+    error_at (token->location,
+             "only constructors take base initializers");
 
   /* Loop through the list.  */
   while (true)
@@ -8992,8 +9238,9 @@ cp_parser_mem_initializer_list (cp_parser* parser)
           if (mem_initializer != error_mark_node
               && !TYPE_P (TREE_PURPOSE (mem_initializer)))
             {
-              error ("%Hcannot expand initializer for member %<%D%>",
-                     &token->location, TREE_PURPOSE (mem_initializer));
+              error_at (token->location,
+                       "cannot expand initializer for member %<%D%>",
+                       TREE_PURPOSE (mem_initializer));
               mem_initializer = error_mark_node;
             }
 
@@ -9051,7 +9298,11 @@ cp_parser_mem_initializer (cp_parser* parser)
       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;
@@ -9065,11 +9316,18 @@ cp_parser_mem_initializer (cp_parser* parser)
       expression_list = build_tree_list (NULL_TREE, expression_list);
     }
   else
-    expression_list
-      = cp_parser_parenthesized_expression_list (parser, false,
-                                                /*cast_p=*/false,
-                                                /*allow_expansion_p=*/true,
-                                                /*non_constant_p=*/NULL);
+    {
+      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)
@@ -9103,9 +9361,9 @@ cp_parser_mem_initializer_id (cp_parser* parser)
   /* `typename' is not allowed in this context ([temp.res]).  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
-      error ("%Hkeyword %<typename%> not allowed in this context (a qualified "
-            "member initializer is implicitly a type)",
-            &token->location);
+      error_at (token->location, 
+               "keyword %<typename%> not allowed in this context (a qualified "
+               "member initializer is implicitly a type)");
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the optional `::' operator.  */
@@ -9475,14 +9733,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);
@@ -9631,11 +9892,12 @@ 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 ("%Htemplate parameter pack %qD cannot have a default argument",
-              &start_token->location, id_declarator->u.id.unqualified_name);
+       error_at (start_token->location,
+                 "template parameter pack %qD cannot have a default argument",
+                 id_declarator->u.id.unqualified_name);
       else
-       error ("%Htemplate parameter pack cannot have a default argument",
-              &start_token->location);
+       error_at (start_token->location,
+                 "template parameter pack cannot have a default argument");
       
       /* Parse the default argument, but throw away the result.  */
       cp_parser_default_argument (parser, /*template_parm_p=*/true);
@@ -9729,11 +9991,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("%Htemplate parameter pack %qD cannot have a "
-                        "default argument", &token->location, identifier);
+                  error_at (token->location,
+                           "template parameter pack %qD cannot have a "
+                           "default argument", identifier);
                 else
-                  error ("%Htemplate parameter packs cannot have "
-                        "default arguments", &token->location);
+                  error_at (token->location,
+                           "template parameter packs cannot have "
+                           "default arguments");
                 default_argument = NULL_TREE;
               }
            pop_deferring_access_checks ();
@@ -9835,13 +10099,13 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
             if (*is_parameter_pack)
               {
                 if (identifier)
-                  error ("%Htemplate parameter pack %qD cannot "
-                        "have a default argument",
-                        &token->location, identifier);
+                  error_at (token->location,
+                           "template parameter pack %qD cannot "
+                           "have a default argument",
+                           identifier);
                 else
-                  error ("%Htemplate parameter packs cannot "
-                        "have default arguments",
-                        &token->location);
+                  error_at (token->location, "template parameter packs cannot "
+                           "have default arguments");
                 default_argument = NULL_TREE;
               }
            pop_deferring_access_checks ();
@@ -10063,8 +10327,7 @@ 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 ("%Hparse error in template argument list",
-              &token->location);
+       error_at (token->location, "parse error in template argument list");
     }
 
   pop_deferring_access_checks ();
@@ -10170,7 +10433,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))
@@ -10178,9 +10441,9 @@ cp_parser_template_name (cp_parser* parser,
          cp_token_position start = 0;
 
          /* Explain what went wrong.  */
-         error ("%Hnon-template %qD used as template",
-                &token->location, identifier);
-         inform (input_location, "use %<%T::template %D%> to indicate that it is a template",
+         error_at (token->location, "non-template %qD used as template",
+                   identifier);
+         inform (token->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))
@@ -10310,6 +10573,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_at (token->location,
+                       "expected parameter pack before %<...%>");
+           }
           /* Consume the `...' token. */
           cp_lexer_consume_token (parser->lexer);
 
@@ -10384,7 +10653,7 @@ 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);
+  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
@@ -10572,7 +10841,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.
@@ -10717,7 +10986,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
      linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("%Htemplate specialization with C linkage", &token->location);
+      error_at (token->location, "template specialization with C linkage");
       /* Give it C++ linkage to avoid confusing other parts of the
         front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -10729,7 +10998,6 @@ cp_parser_explicit_specialization (cp_parser* parser)
   if (!begin_specialization ())
     {
       end_specialization ();
-      cp_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
 
@@ -10849,6 +11117,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))
        {
@@ -11039,14 +11308,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 ("%HC++0x %<auto%> specifier not supported", &token->location);
-        }
+      maybe_warn_cpp0x ("C++0x auto");
+      type = make_auto ();
       break;
 
     case RID_DECLTYPE:
@@ -11307,7 +11570,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
@@ -11336,6 +11599,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
   tree identifier;
   tree type = NULL_TREE;
   tree attributes = NULL_TREE;
+  tree globalscope;
   cp_token *token = NULL;
 
   /* See if we're looking at the `enum' keyword.  */
@@ -11345,6 +11609,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);
     }
@@ -11356,9 +11631,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       cp_lexer_consume_token (parser->lexer);
       /* Remember that it's a `typename' type.  */
       tag_type = typename_type;
-      /* The `typename' keyword is only allowed in templates.  */
-      if (!processing_template_decl)
-       permerror (input_location, "using %<typename%> outside of template");
     }
   /* Otherwise it must be a class-key.  */
   else
@@ -11371,10 +11643,10 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
     }
 
   /* Look for the `::' operator.  */
-  cp_parser_global_scope_opt (parser,
-                             /*current_scope_valid_p=*/false);
+  globalscope =  cp_parser_global_scope_opt (parser,
+                                            /*current_scope_valid_p=*/false);
   /* Look for the nested-name-specifier.  */
-  if (tag_type == typename_type)
+  if (tag_type == typename_type && !globalscope)
     {
       if (!cp_parser_nested_name_specifier (parser,
                                           /*typename_keyword_p=*/true,
@@ -11422,7 +11694,11 @@ 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);
     }
 
@@ -11593,7 +11869,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
             there were no qualifying templates.  */
          if (!cp_parser_check_template_parameters (parser,
                                                    /*num_templates=*/0,
-                                                   token->location))
+                                                   token->location,
+                                                   /*declarator=*/NULL))
            return error_mark_node;
          type = xref_tag (tag_type, identifier, ts, template_p);
        }
@@ -11632,11 +11909,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.  */
@@ -11647,6 +11932,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.  */
@@ -11658,6 +11946,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))
@@ -11665,11 +11967,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.  */
@@ -11679,7 +12016,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);
@@ -11702,6 +12039,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);
@@ -11778,6 +12116,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);
 }
@@ -11818,7 +12161,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,
@@ -11833,7 +12176,7 @@ cp_parser_namespace_name (cp_parser* parser)
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
     {
       if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-       error ("%H%qD is not a namespace-name", &token->location, identifier);
+       error_at (token->location, "%qD is not a namespace-name", identifier);
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
@@ -11960,7 +12303,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 ("%H%<namespace%> definition is not allowed here", &token->location);
+      error_at (token->location, "%<namespace%> definition is not allowed here");
       /* Skip the definition.  */
       cp_lexer_consume_token (parser->lexer);
       if (cp_parser_skip_to_closing_brace (parser))
@@ -12100,8 +12443,8 @@ cp_parser_using_declaration (cp_parser* parser,
     /* [namespace.udecl]
 
        A using declaration shall not name a template-id.  */
-    error ("%Ha template-id may not appear in a using-declaration",
-            &token->location);
+    error_at (token->location,
+             "a template-id may not appear in a using-declaration");
   else
     {
       if (at_class_scope_p ())
@@ -12471,15 +12814,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 ("%Han asm-specification is not allowed "
-                  "on a function-definition",
-                  &asm_spec_start_token->location);
+           error_at (asm_spec_start_token->location,
+                     "an asm-specification is not allowed "
+                     "on a function-definition");
          if (attributes)
-           error ("%Hattributes are not allowed on a function-definition",
-                  &attributes_start_token->location);
+           error_at (attributes_start_token->location,
+                     "attributes are not allowed on a function-definition");
          /* This is a function-definition.  */
          *function_definition_p = true;
 
@@ -12494,6 +12840,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;
        }
     }
@@ -12518,7 +12871,7 @@ cp_parser_init_declarator (cp_parser* parser,
       || token->type == CPP_OPEN_PAREN
       || token->type == CPP_OPEN_BRACE)
     {
-      is_initialized = 1;
+      is_initialized = SD_INITIALIZED;
       initialization_kind = token->type;
 
       if (token->type == CPP_EQ
@@ -12526,9 +12879,9 @@ cp_parser_init_declarator (cp_parser* parser,
        {
          cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
          if (t2->keyword == RID_DEFAULT)
-           is_initialized = 2;
+           is_initialized = SD_DEFAULTED;
          else if (t2->keyword == RID_DELETE)
-           is_initialized = 3;
+           is_initialized = SD_DELETED;
        }
     }
   else
@@ -12541,7 +12894,7 @@ cp_parser_init_declarator (cp_parser* parser,
          cp_parser_error (parser, "expected initializer");
          return error_mark_node;
        }
-      is_initialized = 0;
+      is_initialized = SD_UNINITIALIZED;
       initialization_kind = CPP_EOF;
     }
 
@@ -12624,8 +12977,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 ("%Hinitializer provided for function",
-                       &initializer_start_token->location);
+                error_at (initializer_start_token->location,
+                          "initializer provided for function");
               cp_parser_skip_to_closing_parenthesis (parser,
                                                      /*recovering=*/true,
                                                      /*or_comma=*/false,
@@ -12894,8 +13247,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
@@ -12922,6 +13277,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);
 
@@ -12934,6 +13291,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;
@@ -12947,19 +13307,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
@@ -13027,10 +13397,16 @@ cp_parser_direct_declarator (cp_parser* parser,
                 in function scopes.  */
              else if (!parser->in_function_body)
                {
-                 error ("%Harray bound is not an integer constant",
-                        &token->location);
+                 error_at (token->location,
+                           "array bound is not an integer constant");
                  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;
@@ -13045,181 +13421,184 @@ 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;
-         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);
+         {
+           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;
+                 }
+             }
 
-         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 && 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 ("%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)
+             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_at (declarator_id_start_token->location,
+                           "%<%T::%E%> is not a type",
+                           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 ("%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 (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_at (declarator_id_start_token->location,
+                                     "invalid use of constructor as a template");
+                           inform (declarator_id_start_token->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);
@@ -13341,7 +13720,7 @@ cp_parser_ptr_operator (cp_parser* parser,
          code = INDIRECT_REF;
 
          if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-           error ("%H%qD is a namespace", &token->location, parser->scope);
+           error_at (token->location, "%qD is a namespace", parser->scope);
          else
            {
              /* The type of which the member is a member is given by the
@@ -13416,7 +13795,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 
       if (cv_quals & cv_qualifier)
        {
-         error ("%Hduplicate cv-qualifier", &token->location);
+         error_at (token->location, "duplicate cv-qualifier");
          cp_lexer_purge_token (parser->lexer);
        }
       else
@@ -13429,6 +13808,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:
@@ -13479,7 +13882,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;
@@ -13501,7 +13904,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.
@@ -13607,10 +14037,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;
@@ -13622,7 +14052,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.  */
@@ -13630,10 +14060,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
@@ -13643,7 +14073,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.  */
@@ -13678,8 +14108,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;
 }
@@ -13695,12 +14125,13 @@ 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;
+  int index = 0;
 
   /* Assume all will go well.  */
   *is_error = false;
@@ -13715,6 +14146,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
@@ -13722,17 +14154,44 @@ 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);
+
+      if (decl != error_mark_node)
+       {
+         retrofit_lang_decl (decl);
+         DECL_PARM_INDEX (decl) = ++index;
+       }
+
       /* 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)
@@ -14049,7 +14508,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 ("%Hfile ends in default argument", &token->location);
+                 error_at (token->location, "file ends in default argument");
                  done = true;
                  break;
 
@@ -14098,9 +14557,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
            warning (0, "deprecated use of default argument for parameter of non-function");
          else
            {
-             error ("%Hdefault arguments are only "
-                    "permitted for function parameters",
-                    &token->location);
+             error_at (token->location,
+                       "default arguments are only "
+                       "permitted for function parameters");
              default_argument = NULL_TREE;
            }
        }
@@ -14108,20 +14567,23 @@ cp_parser_parameter_declaration (cp_parser *parser,
               || (decl_specifiers.type
                   && PACK_EXPANSION_P (decl_specifiers.type)))
        {
-         const char* kind = template_parm_p? "template " : "";
-         
          /* Find the name of the parameter pack.  */     
          cp_declarator *id_declarator = declarator;
          while (id_declarator && id_declarator->kind != cdk_id)
            id_declarator = id_declarator->declarator;
          
          if (id_declarator && id_declarator->kind == cdk_id)
-           error ("%H%sparameter pack %qD cannot have a default argument",
-                  &declarator_token_start->location,
-                  kind, id_declarator->u.id.unqualified_name);
+           error_at (declarator_token_start->location,
+                     template_parm_p 
+                     ? "template parameter pack %qD"
+                     " cannot have a default argument"
+                     : "parameter pack %qD cannot have a default argument",
+                     id_declarator->u.id.unqualified_name);
          else
-           error ("%H%sparameter pack cannot have a default argument",
-                  &declarator_token_start->location, kind);
+           error_at (declarator_token_start->location,
+                     template_parm_p 
+                     ? "template parameter pack cannot have a default argument"
+                     : "parameter pack cannot have a default argument");
          
          default_argument = NULL_TREE;
        }
@@ -14163,7 +14625,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.  */
@@ -14245,10 +14707,17 @@ cp_parser_initializer (cp_parser* parser, bool* is_direct_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");
@@ -14465,6 +14934,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);
@@ -14490,7 +14960,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.  */
@@ -14536,8 +15005,8 @@ cp_parser_class_name (cp_parser *parser,
                                        identifier_token->location);
          if (ambiguous_decls)
            {
-             error ("%Hreference to %qD is ambiguous",
-                    &identifier_token->location, identifier);
+             error_at (identifier_token->location,
+                       "reference to %qD is ambiguous", identifier);
              print_candidates (ambiguous_decls);
              if (cp_parser_parsing_tentatively (parser))
                {
@@ -14595,6 +15064,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;
 }
@@ -14609,13 +15080,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;
@@ -14667,6 +15137,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)
@@ -14685,10 +15159,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);
@@ -14779,6 +15249,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;
 }
@@ -14999,8 +15471,9 @@ cp_parser_class_head (cp_parser* parser,
       /* Reject typedef-names in class heads.  */
       if (!DECL_IMPLICIT_TYPEDEF_P (type))
        {
-         error ("%Hinvalid class name in declaration of %qD",
-                &type_start_token->location, type);
+         error_at (type_start_token->location,
+                   "invalid class name in declaration of %qD",
+                   type);
          type = NULL_TREE;
          goto done;
        }
@@ -15012,14 +15485,14 @@ cp_parser_class_head (cp_parser* parser,
       if (scope && !is_ancestor (scope, nested_name_specifier))
        {
          if (at_namespace_scope_p ())
-           error ("%Hdeclaration of %qD in namespace %qD which does not "
-                  "enclose %qD",
-                  &type_start_token->location,
-                  type, scope, nested_name_specifier);
+           error_at (type_start_token->location,
+                     "declaration of %qD in namespace %qD which does not "
+                     "enclose %qD",
+                     type, scope, nested_name_specifier);
          else
-           error ("%Hdeclaration of %qD in %qD which does not enclose %qD",
-                  &type_start_token->location,
-                  type, scope, nested_name_specifier);
+           error_at (type_start_token->location,
+                     "declaration of %qD in %qD which does not enclose %qD",
+                     type, scope, nested_name_specifier);
          type = NULL_TREE;
          goto done;
        }
@@ -15031,8 +15504,8 @@ cp_parser_class_head (cp_parser* parser,
         class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
        {
-         permerror (input_location, "%Hextra qualification not allowed",
-                    &nested_name_specifier_token_start->location);
+         permerror (nested_name_specifier_token_start->location,
+                    "extra qualification not allowed");
          nested_name_specifier = NULL_TREE;
          num_templates = 0;
        }
@@ -15043,8 +15516,8 @@ cp_parser_class_head (cp_parser* parser,
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
-      error ("%Han explicit specialization must be preceded by %<template <>%>",
-            &type_start_token->location);
+      error_at (type_start_token->location,
+               "an explicit specialization must be preceded by %<template <>%>");
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
         cp_parser_explicit_specialization.  */
@@ -15057,7 +15530,8 @@ cp_parser_class_head (cp_parser* parser,
   /* Make sure that the right number of template parameters were
      present.  */
   if (!cp_parser_check_template_parameters (parser, num_templates,
-                                           type_start_token->location))
+                                           type_start_token->location,
+                                           /*declarator=*/NULL))
     {
       /* If something went wrong, there is no point in even trying to
         process the class-definition.  */
@@ -15072,8 +15546,8 @@ cp_parser_class_head (cp_parser* parser,
          && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0))
              || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD))
        {
-         error ("%Hfunction template %qD redeclared as a class template",
-                &type_start_token->location, id);
+         error_at (type_start_token->location,
+                   "function template %qD redeclared as a class template", id);
          type = error_mark_node;
        }
       else
@@ -15154,10 +15628,10 @@ cp_parser_class_head (cp_parser* parser,
      that's an error.  */
   if (type != error_mark_node && COMPLETE_TYPE_P (type))
     {
-      error ("%Hredefinition of %q#T",
-            &type_start_token->location, type);
-      error ("%Hprevious definition of %q+#T",
-            &type_start_token->location, type);
+      error_at (type_start_token->location, "redefinition of %q#T",
+               type);
+      error_at (type_start_token->location, "previous definition of %q+#T",
+               type);
       type = NULL_TREE;
       goto done;
     }
@@ -15424,8 +15898,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 ("%Ha class-key must be used when declaring a friend",
-                        &decl_spec_token_start->location);
+                error_at (decl_spec_token_start->location,
+                          "a class-key must be used when declaring a friend");
               /* In this case:
 
                    template <typename T> struct A {
@@ -15439,8 +15913,9 @@ cp_parser_member_declaration (cp_parser* parser)
                   && TYPE_P (decl_specifiers.type))
                 type = decl_specifiers.type;
               if (!type || !TYPE_P (type))
-                error ("%Hfriend declaration does not name a class or "
-                       "function", &decl_spec_token_start->location);
+                error_at (decl_spec_token_start->location,
+                          "friend declaration does not name a class or "
+                          "function");
               else
                 make_friend_class (current_class_type, type,
                                    /*complain=*/true);
@@ -15458,7 +15933,8 @@ 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);
            }
@@ -15619,8 +16095,8 @@ cp_parser_member_declaration (cp_parser* parser)
                     standard, since a pure function may be defined
                     outside of the class-specifier.  */
                  if (initializer)
-                   error ("%Hpure-specifier on function-definition",
-                          &initializer_token_start->location);
+                   error_at (initializer_token_start->location,
+                             "pure-specifier on function-definition");
                  decl = cp_parser_save_member_function_body (parser,
                                                              &decl_specifiers,
                                                              declarator,
@@ -15636,6 +16112,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,
@@ -15700,7 +16178,13 @@ 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
@@ -15720,7 +16204,7 @@ cp_parser_pure_specifier (cp_parser* parser)
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
-      error ("%Htemplates may not be %<virtual%>", &token->location);
+      error_at (token->location, "templates may not be %<virtual%>");
       return error_mark_node;
     }
 
@@ -15924,12 +16408,12 @@ cp_parser_base_specifier (cp_parser* parser)
     {
       token = cp_lexer_peek_token (parser->lexer);
       if (!processing_template_decl)
-       error ("%Hkeyword %<typename%> not allowed outside of templates",
-              &token->location);
+       error_at (token->location,
+                 "keyword %<typename%> not allowed outside of templates");
       else
-       error ("%Hkeyword %<typename%> not allowed in this context "
-              "(the base class is implicitly a type)",
-              &token->location);
+       error_at (token->location,
+                 "keyword %<typename%> not allowed in this context "
+                 "(the base class is implicitly a type)");
       cp_lexer_consume_token (parser->lexer);
     }
 
@@ -16240,7 +16724,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);
 }
@@ -16332,7 +16816,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, "%<)%>");
 
@@ -16485,7 +16969,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.  */
@@ -16493,10 +16982,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;
            }
@@ -16707,35 +17204,11 @@ 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)
-       {
-         if (tag_type)
-           {
-             tree type;
-
-             /* The resolution to Core Issue 180 says that `struct
-                A::B' should be considered a type-name, even if `A'
-                is dependent.  */
-             type = make_typename_type (parser->scope, name, tag_type,
-                                        /*complain=*/tf_error);
-             decl = TYPE_NAME (type);
-           }
-         else if (is_template
-                  && (cp_parser_next_token_ends_template_argument_p (parser)
-                      || cp_lexer_next_token_is (parser->lexer,
-                                                 CPP_CLOSE_PAREN)))
-           decl = make_unbound_class_template (parser->scope,
-                                               name, NULL_TREE,
-                                               /*complain=*/tf_error);
-         else
-           decl = build_qualified_name (/*type=*/NULL_TREE,
-                                        parser->scope, name,
-                                        is_template);
-       }
+         && dependent_p)
+       /* Defer lookup.  */
+       decl = error_mark_node;
       else
        {
          tree pushed_scope = NULL_TREE;
@@ -16756,14 +17229,42 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                                        /*complain=*/true);
 
          /* If we have a single function from a using decl, pull it out.  */
-         if (decl
-             && TREE_CODE (decl) == OVERLOAD
+         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)
+           {
+             tree type;
+
+             /* The resolution to Core Issue 180 says that `struct
+                A::B' should be considered a type-name, even if `A'
+                is dependent.  */
+             type = make_typename_type (parser->scope, name, tag_type,
+                                        /*complain=*/tf_error);
+             decl = TYPE_NAME (type);
+           }
+         else if (is_template
+                  && (cp_parser_next_token_ends_template_argument_p (parser)
+                      || cp_lexer_next_token_is (parser->lexer,
+                                                 CPP_CLOSE_PAREN)))
+           decl = make_unbound_class_template (parser->scope,
+                                               name, NULL_TREE,
+                                               /*complain=*/tf_error);
+         else
+           decl = build_qualified_name (/*type=*/NULL_TREE,
+                                        parser->scope, name,
+                                        is_template);
+       }
       parser->qualifying_scope = parser->scope;
       parser->object_scope = NULL_TREE;
     }
@@ -16812,8 +17313,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 ("%Hreference to %qD is ambiguous",
-                &name_location, name);
+         error_at (name_location, "reference to %qD is ambiguous",
+                   name);
          print_candidates (decl);
        }
       return error_mark_node;
@@ -16954,9 +17455,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,
-                                                 declarator_location);
+      return cp_parser_check_template_parameters 
+       (parser, num_templates, declarator_location, declarator);
+
 
     case cdk_function:
     case cdk_array:
@@ -16977,35 +17478,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,
-                                    location_t location)
+                                    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 ("%Htoo few template-parameter-lists", &location);
+      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 ("%Htoo many template-parameter-lists", &location);
+  error_at (location, "too many template-parameter-lists");
   return false;
 }
 
@@ -17279,8 +17788,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
         returned.  */
       cp_parser_identifier (parser);
       /* Issue an error message.  */
-      error ("%Hnamed return values are no longer supported",
-            &token->location);
+      error_at (token->location,
+               "named return values are no longer supported");
       /* Skip tokens until we reach the start of the function body.  */
       while (true)
        {
@@ -17354,8 +17863,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 ("%Hinvalid declaration of member template in local class",
-            &token->location);
+      error_at (token->location,
+               "invalid declaration of member template in local class");
       cp_parser_skip_to_end_of_block_or_statement (parser);
       return;
     }
@@ -17364,7 +17873,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 ("%Htemplate with C linkage", &token->location);
+      error_at (token->location, "template with C linkage");
       /* Give it C++ linkage to avoid confusing other parts of the
         front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -17511,8 +18020,8 @@ cp_parser_single_declaration (cp_parser* parser,
   /* There are no template typedefs.  */
   if (decl_specifiers.specs[(int) ds_typedef])
     {
-      error ("%Htemplate declaration of %qs",
-            &decl_spec_token_start->location, "typedef");
+      error_at (decl_spec_token_start->location,
+               "template declaration of %<typedef%>");
       decl = error_mark_node;
     }
 
@@ -17575,8 +18084,8 @@ cp_parser_single_declaration (cp_parser* parser,
         && explicit_specialization_p
         && decl_specifiers.storage_class != sc_none)
       {
-        error ("%Hexplicit template specialization cannot have a storage class",
-              &decl_spec_token_start->location);
+        error_at (decl_spec_token_start->location,
+                 "explicit template specialization cannot have a storage class");
         decl = error_mark_node;
       }
     }
@@ -17603,7 +18112,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
@@ -17612,6 +18121,7 @@ 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;
@@ -17626,11 +18136,18 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
       return finish_compound_literal (type, expression_list);
     }
 
-  expression_list
-    = cp_parser_parenthesized_expression_list (parser, false,
-                                              /*cast_p=*/true,
-                                              /*allow_expansion_p=*/true,
-                                              /*non_constant_p=*/NULL);
+
+  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);
@@ -17734,7 +18251,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]
 
@@ -17751,8 +18269,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))
@@ -17793,9 +18313,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
            global source location is still on the token before the
            '>>', so we need to say explicitly where we want it.  */
          cp_token *token = cp_lexer_peek_token (parser->lexer);
-         error ("%H%<>>%> should be %<> >%> "
-                "within a nested template argument list",
-                &token->location);
+         error_at (token->location, "%<>>%> should be %<> >%> "
+                   "within a nested template argument list");
 
          token->type = CPP_GREATER;
        }
@@ -17806,8 +18325,9 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
            Same deal about the token location, but here we can get it
            right by consuming the '>>' before issuing the diagnostic.  */
          cp_token *token = cp_lexer_consume_token (parser->lexer);
-         error ("%Hspurious %<>>%>, use %<>%> to terminate "
-                "a template argument list", &token->location);
+         error_at (token->location,
+                   "spurious %<>>%>, use %<>%> to terminate "
+                   "a template argument list");
        }
     }
   else
@@ -17819,7 +18339,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;
 }
@@ -17969,7 +18490,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);
@@ -18048,7 +18574,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))
@@ -18090,14 +18617,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);
@@ -18135,8 +18663,8 @@ cp_parser_set_storage_class (cp_parser *parser,
 
   if (parser->in_unbraced_linkage_specification_p)
     {
-      error ("%Hinvalid use of %qD in linkage specification",
-            &location, ridpointers[keyword]);
+      error_at (location, "invalid use of %qD in linkage specification",
+               ridpointers[keyword]);
       return;
     }
   else if (decl_specs->storage_class != sc_none)
@@ -18148,7 +18676,7 @@ cp_parser_set_storage_class (cp_parser *parser,
   if ((keyword == RID_EXTERN || keyword == RID_STATIC)
       && decl_specs->specs[(int) ds_thread])
     {
-      error ("%H%<__thread%> before %qD", &location, ridpointers[keyword]);
+      error_at (location, "%<__thread%> before %qD", ridpointers[keyword]);
       decl_specs->specs[(int) ds_thread] = 0;
     }
 
@@ -18490,7 +19018,7 @@ cp_parser_check_access_in_redeclaration (tree decl, location_t location)
        != (current_access_specifier == access_private_node))
       || (TREE_PROTECTED (decl)
          != (current_access_specifier == access_protected_node)))
-    error ("%H%qD redeclared with different access", &location, decl);
+    error_at (location, "%qD redeclared with different access", decl);
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
@@ -18508,8 +19036,9 @@ cp_parser_optional_template_keyword (cp_parser *parser)
       if (!processing_template_decl)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
-         error ("%H%<template%> (as a disambiguator) is only allowed "
-                "within templates", &token->location);
+         error_at (token->location,
+                   "%<template%> (as a disambiguator) is only allowed "
+                   "within templates");
          /* If this part of the token stream is rescanned, the same
             error message would be generated.  So, we purge the token
             from the stream.  */
@@ -18774,8 +19303,9 @@ cp_parser_objc_expression (cp_parser* parser)
          break;
        }
     default:
-      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
-            &kwd->location, kwd->u.value);
+      error_at (kwd->location,
+               "misplaced %<@%D%> Objective-C++ construct",
+               kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -18818,7 +19348,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;
@@ -18870,7 +19400,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,
@@ -18885,7 +19415,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,
@@ -18918,8 +19448,8 @@ cp_parser_objc_encode_expression (cp_parser* parser)
 
   if (!type)
     {
-      error ("%H%<@encode%> must specify a type as an argument",
-            &token->location);
+      error_at (token->location, 
+               "%<@encode%> must specify a type as an argument");
       return error_mark_node;
     }
 
@@ -18982,6 +19512,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, "%<(%>");
@@ -19033,7 +19564,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.
@@ -19234,7 +19765,7 @@ cp_parser_objc_selector (cp_parser* parser)
 
   if (!cp_parser_objc_selector_p (token->type))
     {
-      error ("%Hinvalid Objective-C++ selector name", &token->location);
+      error_at (token->location, "invalid Objective-C++ selector name");
       return error_mark_node;
     }
 
@@ -19565,7 +20096,7 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
     {
       tok = cp_lexer_peek_token (parser->lexer);
-      error ("%Hidentifier expected after %<@protocol%>", &tok->location);
+      error_at (tok->location, "identifier expected after %<@protocol%>");
       goto finish;
     }
 
@@ -19701,8 +20232,8 @@ cp_parser_objc_declaration (cp_parser* parser)
       cp_parser_objc_end_implementation (parser);
       break;
     default:
-      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
-            &kwd->location, kwd->u.value);
+      error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
+               kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 }
@@ -19785,7 +20316,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
@@ -19806,15 +20337,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.  */
@@ -19833,8 +20365,8 @@ cp_parser_objc_statement (cp_parser * parser) {
     case RID_AT_THROW:
       return cp_parser_objc_throw_statement (parser);
     default:
-      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
-            &kwd->location, kwd->u.value);
+      error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
+              kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -19918,7 +20450,7 @@ 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,
+check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
                           const char *name, location_t location)
 {
   tree c;
@@ -19926,7 +20458,7 @@ check_no_duplicate_clause (tree clauses, enum tree_code code,
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
-       error ("%Htoo many %qs clauses", &location, name);
+       error_at (location, "too many %qs clauses", name);
        break;
       }
 }
@@ -19968,7 +20500,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
        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;
@@ -20040,13 +20572,12 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location
       || (n = tree_low_cst (num, 0)) <= 0
       || (int) n != n)
     {
-      error ("%Hcollapse argument needs positive constant integer expression",
-            &loc);
+      error_at (loc, "collapse argument needs positive constant integer expression");
       return list;
     }
 
   check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
-  c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
+  c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
 
@@ -20104,7 +20635,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
     return list;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
-  c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+  c = build_omp_clause (location, OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
 
@@ -20132,7 +20663,7 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
 
   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;
 
@@ -20150,7 +20681,7 @@ cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED,
 
   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;
 }
@@ -20167,7 +20698,7 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
   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, "%<)%>"))
@@ -20178,7 +20709,7 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
   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;
 
@@ -20197,7 +20728,7 @@ cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
   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;
 }
@@ -20279,7 +20810,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location
   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))
     {
@@ -20324,16 +20855,16 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location
       cp_lexer_consume_token (parser->lexer);
 
       token = cp_lexer_peek_token (parser->lexer);
-      t = cp_parser_assignment_expression (parser, false);
+      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 ("%Hschedule %<runtime%> does not take "
-              "a %<chunk_size%> parameter", &token->location);
+       error_at (token->location, "schedule %<runtime%> does not take "
+                 "a %<chunk_size%> parameter");
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
-       error ("%Hschedule %<auto%> does not take "
-              "a %<chunk_size%> parameter", &token->location);
+       error_at (token->location, "schedule %<auto%> does not take "
+                 "a %<chunk_size%> parameter");
       else
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
@@ -20367,7 +20898,7 @@ cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED,
 
   check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
 
-  c = build_omp_clause (OMP_CLAUSE_UNTIED);
+  c = build_omp_clause (location, OMP_CLAUSE_UNTIED);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 }
@@ -20480,7 +21011,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 ("%H%qs is not valid for %qs", &token->location, c_name, where);
+         error_at (token->location, "%qs is not valid for %qs", c_name, where);
        }
     }
  saw_error:
@@ -20553,7 +21084,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:
@@ -20610,7 +21141,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;
@@ -20660,7 +21191,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:
@@ -20673,7 +21204,7 @@ 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 ();
@@ -20684,41 +21215,39 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
 static tree
 cp_parser_omp_for_cond (cp_parser *parser, tree decl)
 {
-  tree lhs = cp_parser_cast_expression (parser, false, false), rhs;
-  enum tree_code op;
-  cp_token *token;
+  tree cond = cp_parser_binary_expression (parser, false, true,
+                                          PREC_NOT_OPERATOR, NULL);
+  bool overloaded_p;
 
-  if (lhs != decl)
+  if (cond == error_mark_node
+      || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     {
       cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
 
-  token = cp_lexer_peek_token (parser->lexer);
-  op = binops_by_token [token->type].tree_type;
-  switch (op)
+  switch (TREE_CODE (cond))
     {
-    case LT_EXPR:
-    case LE_EXPR:
     case GT_EXPR:
     case GE_EXPR:
+    case LT_EXPR:
+    case LE_EXPR:
       break;
     default:
-      cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
 
-  cp_lexer_consume_token (parser->lexer);
-  rhs = cp_parser_binary_expression (parser, false,
-                                    PREC_RELATIONAL_EXPRESSION);
-  if (rhs == error_mark_node
-      || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    {
-      cp_parser_skip_to_end_of_statement (parser);
-      return error_mark_node;
-    }
+  /* 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;
 
-  return build2 (op, boolean_type_node, lhs, rhs);
+  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.  */
@@ -20737,7 +21266,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
       op = (token->type == CPP_PLUS_PLUS
            ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
       cp_lexer_consume_token (parser->lexer);
-      lhs = cp_parser_cast_expression (parser, false, false);
+      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);
@@ -20762,13 +21291,13 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 
   if (op != NOP_EXPR)
     {
-      rhs = cp_parser_assignment_expression (parser, false);
+      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,
-                                    PREC_ADDITIVE_EXPRESSION);
+  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)
@@ -20781,8 +21310,8 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
     {
       op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
       cp_lexer_consume_token (parser->lexer);
-      rhs = cp_parser_binary_expression (parser, false,
-                                        PREC_ADDITIVE_EXPRESSION);
+      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)
        {
@@ -20893,13 +21422,14 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
 
              else 
                {
-                 tree pushed_scope;
+                 tree pushed_scope, auto_node;
 
                  decl = start_decl (declarator, &type_specifiers,
-                                    /*initialized_p=*/false, attributes,
+                                    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, 
@@ -20914,7 +21444,8 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                      cp_parser_skip_to_end_of_statement (parser);
                    }
                  else if (CLASS_TYPE_P (TREE_TYPE (decl))
-                          || type_dependent_expression_p (decl))
+                          || type_dependent_expression_p (decl)
+                          || auto_node)
                    {
                      bool is_direct_init, is_non_constant_init;
 
@@ -20922,6 +21453,17 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                                                    &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);
@@ -20939,8 +21481,9 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                    {
                      /* Consume '='.  */
                      cp_lexer_consume_token (parser->lexer);
-                     init = cp_parser_assignment_expression (parser, false);
+                     init = cp_parser_assignment_expression (parser, false, NULL);
 
+                   non_class:
                      if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
                        init = error_mark_node;
                      else
@@ -20971,7 +21514,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
 
                  cp_parser_parse_definitely (parser);
                  cp_parser_require (parser, CPP_EQ, "%<=%>");
-                 rhs = cp_parser_assignment_expression (parser, false);
+                 rhs = cp_parser_assignment_expression (parser, false, NULL);
                  finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR,
                                                         rhs,
                                                         tf_warning_or_error));
@@ -20981,7 +21524,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                {
                  decl = NULL;
                  cp_parser_abort_tentative_parse (parser);
-                 init = cp_parser_expression (parser, false);
+                 init = cp_parser_expression (parser, false, NULL);
                  if (init)
                    {
                      if (TREE_CODE (init) == MODIFY_EXPR
@@ -21016,8 +21559,8 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
            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);
+               error_at (loc, "iteration variable %qD"
+                         " should not be firstprivate", real_decl);
                *c = OMP_CLAUSE_CHAIN (*c);
              }
            else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE
@@ -21025,7 +21568,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
              {
                /* Add lastprivate (decl) clause to OMP_FOR_CLAUSES,
                   change it to shared (decl) in OMP_PARALLEL_CLAUSES.  */
-               tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+               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);
@@ -21054,16 +21597,17 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                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);
+               error_at (loc, "iteration variable %qD "
+                         "should not be firstprivate",
+                         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);
+               error_at (loc, "iteration variable %qD should not be reduction",
+                         decl);
            }
          if (c == NULL)
            {
-             c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+             c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE);
              OMP_CLAUSE_DECL (c) = decl;
              c = finish_omp_clauses (c);
              if (c)
@@ -21076,16 +21620,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
 
       cond = NULL;
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-       {
-         /* If decl is an iterator, preserve LHS and RHS of the relational
-            expr until finish_omp_for.  */
-         if (decl
-             && (type_dependent_expression_p (decl)
-                 || CLASS_TYPE_P (TREE_TYPE (decl))))
-           cond = cp_parser_omp_for_cond (parser, decl);
-         else
-           cond = cp_parser_condition (parser);
-       }
+       cond = cp_parser_omp_for_cond (parser, decl);
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
       incr = NULL;
@@ -21098,7 +21633,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                  || CLASS_TYPE_P (TREE_TYPE (decl))))
            incr = cp_parser_omp_for_incr (parser, decl);
          else
-           incr = cp_parser_expression (parser, false);
+           incr = cp_parser_expression (parser, false, NULL);
        }
 
       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
@@ -21134,7 +21669,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
          else
            {
              loc = cp_lexer_peek_token (parser->lexer)->location;
-             error ("%Hnot enough collapsed for loops", &loc);
+             error_at (loc, "not enough collapsed for loops");
              collapse_err = true;
              cp_parser_abort_tentative_parse (parser);
              declv = NULL_TREE;
@@ -21179,8 +21714,8 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
        {
          if (!collapse_err)
            {
-             location_t loc = cp_lexer_peek_token (parser->lexer)->location;
-             error ("%Hcollapsed loops not perfectly nested", &loc);
+             error_at (cp_lexer_peek_token (parser->lexer)->location,
+                       "collapsed loops not perfectly nested");
            }
          collapse_err = true;
          cp_parser_statement_seq_opt (parser, NULL);
@@ -21239,7 +21774,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:
@@ -21249,8 +21785,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:
@@ -21385,6 +21922,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))
     {
@@ -21420,12 +21958,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);
+      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;
@@ -21511,7 +22049,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);
@@ -21591,11 +22129,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 ("%Hjunk at end of %<#pragma GCC pch_preprocess%>",
-               &first_token->location);
+       error_at (first_token->location,
+                 "junk at end of %<#pragma GCC pch_preprocess%>");
     }
   else
-    error ("%Hexpected string literal", &first_token->location);
+    error_at (first_token->location, "expected string literal");
 
   /* Skip to the end of the pragma.  */
   while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
@@ -21628,8 +22166,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
   switch (id)
     {
     case PRAGMA_GCC_PCH_PREPROCESS:
-      error ("%H%<#pragma GCC pch_preprocess%> must be first",
-             &pragma_tok->location);
+      error_at (pragma_tok->location,
+               "%<#pragma GCC pch_preprocess%> must be first");
       break;
 
     case PRAGMA_OMP_BARRIER:
@@ -21639,8 +22177,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
          cp_parser_omp_barrier (parser, pragma_tok);
          return false;
        case pragma_stmt:
-         error ("%H%<#pragma omp barrier%> may only be "
-                "used in compound statements", &pragma_tok->location);
+         error_at (pragma_tok->location, "%<#pragma omp barrier%> may only be "
+                   "used in compound statements");
          break;
        default:
          goto bad_stmt;
@@ -21654,8 +22192,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
          cp_parser_omp_flush (parser, pragma_tok);
          return false;
        case pragma_stmt:
-         error ("%H%<#pragma omp flush%> may only be "
-                "used in compound statements", &pragma_tok->location);
+         error_at (pragma_tok->location, "%<#pragma omp flush%> may only be "
+                   "used in compound statements");
          break;
        default:
          goto bad_stmt;
@@ -21669,9 +22207,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
          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);
+         error_at (pragma_tok->location,
+                   "%<#pragma omp taskwait%> may only be "
+                   "used in compound statements");
          break;
        default:
          goto bad_stmt;
@@ -21697,8 +22235,9 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
       return true;
 
     case PRAGMA_OMP_SECTION:
-      error ("%H%<#pragma omp section%> may only be used in "
-            "%<#pragma omp sections%> construct", &pragma_tok->location);
+      error_at (pragma_tok->location, 
+               "%<#pragma omp section%> may only be used in "
+               "%<#pragma omp sections%> construct");
       break;
 
     default: