OSDN Git Service

PR c++/37877
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 63a6b88..f497d66 100644 (file)
@@ -1,13 +1,13 @@
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005  Free Software Foundation, Inc.
+   2005, 2007, 2008  Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GCC is distributed in the hope that it will be useful, but
    any later version.
 
    GCC is distributed in the hope that it will be useful, but
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.
 
-   You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, USA.  */
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
 #include "system.h"
 
 #include "config.h"
 #include "system.h"
 /* The cp_lexer_* routines mediate between the lexer proper (in libcpp
    and c-lex.c) and the C++ parser.  */
 
 /* The cp_lexer_* routines mediate between the lexer proper (in libcpp
    and c-lex.c) and the C++ parser.  */
 
+/* A token's value and its associated deferred access checks and
+   qualifying scope.  */
+
+struct tree_check GTY(())
+{
+  /* The value associated with the token.  */
+  tree value;
+  /* The checks that have been associated with value.  */
+  VEC (deferred_access_check, gc)* checks;
+  /* The token's qualifying scope (used when it is a
+     CPP_NESTED_NAME_SPECIFIER).  */
+  tree qualifying_scope;
+};
+
 /* A C++ token.  */
 
 typedef struct cp_token GTY (())
 /* A C++ token.  */
 
 typedef struct cp_token GTY (())
@@ -58,8 +71,6 @@ typedef struct cp_token GTY (())
   unsigned char flags;
   /* Identifier for the pragma.  */
   ENUM_BITFIELD (pragma_kind) pragma_kind : 6;
   unsigned char flags;
   /* Identifier for the pragma.  */
   ENUM_BITFIELD (pragma_kind) pragma_kind : 6;
-  /* True if this token is from a system header.  */
-  BOOL_BITFIELD in_system_header : 1;
   /* True if this token is from a context where it is implicitly extern "C" */
   BOOL_BITFIELD implicit_extern_c : 1;
   /* True for a CPP_NAME token that is not a keyword (i.e., for which
   /* True if this token is from a context where it is implicitly extern "C" */
   BOOL_BITFIELD implicit_extern_c : 1;
   /* True for a CPP_NAME token that is not a keyword (i.e., for which
@@ -67,7 +78,12 @@ typedef struct cp_token GTY (())
      ambiguous.  An error has already been reported.  */
   BOOL_BITFIELD ambiguous_p : 1;
   /* The value associated with this token, if any.  */
      ambiguous.  An error has already been reported.  */
   BOOL_BITFIELD ambiguous_p : 1;
   /* The value associated with this token, if any.  */
-  tree value;
+  union cp_token_value {
+    /* Used for CPP_NESTED_NAME_SPECIFIER and CPP_TEMPLATE_ID.  */
+    struct tree_check* GTY((tag ("1"))) tree_check_value;
+    /* 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;
   /* The location at which this token was found.  */
   location_t location;
 } cp_token;
@@ -77,14 +93,10 @@ typedef struct cp_token *cp_token_position;
 DEF_VEC_P (cp_token_position);
 DEF_VEC_ALLOC_P (cp_token_position,heap);
 
 DEF_VEC_P (cp_token_position);
 DEF_VEC_ALLOC_P (cp_token_position,heap);
 
-static const cp_token eof_token =
+static cp_token eof_token =
 {
 {
-  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, NULL_TREE,
-#if USE_MAPPED_LOCATION
+  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, { NULL },
   0
   0
-#else
-  {0, 0}
-#endif
 };
 
 /* The cp_lexer structure represents the C++ lexer.  It is responsible
 };
 
 /* The cp_lexer structure represents the C++ lexer.  It is responsible
@@ -257,9 +269,6 @@ cp_lexer_new_main (void)
      allocating any memory.  */
   cp_parser_initial_pragma (&first_token);
 
      allocating any memory.  */
   cp_parser_initial_pragma (&first_token);
 
-  /* Tell c_lex_with_flags not to merge string constants.  */
-  c_lex_return_raw_strings = true;
-
   c_common_no_more_pch ();
 
   /* Allocate the memory.  */
   c_common_no_more_pch ();
 
   /* Allocate the memory.  */
@@ -297,7 +306,7 @@ cp_lexer_new_main (void)
   lexer->buffer = buffer;
   lexer->buffer_length = alloc - space;
   lexer->last_token = pos;
   lexer->buffer = buffer;
   lexer->buffer_length = alloc - space;
   lexer->last_token = pos;
-  lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token;
+  lexer->next_token = lexer->buffer_length ? buffer : &eof_token;
 
   /* Subsequent preprocessor diagnostics should use compiler
      diagnostic functions to get the compiler source location.  */
 
   /* Subsequent preprocessor diagnostics should use compiler
      diagnostic functions to get the compiler source location.  */
@@ -321,7 +330,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
   /* We do not own the buffer.  */
   lexer->buffer = NULL;
   lexer->buffer_length = 0;
   /* We do not own the buffer.  */
   lexer->buffer = NULL;
   lexer->buffer_length = 0;
-  lexer->next_token = first == last ? (cp_token *)&eof_token : first;
+  lexer->next_token = first == last ? &eof_token : first;
   lexer->last_token = last;
 
   lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
   lexer->last_token = last;
 
   lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
@@ -382,20 +391,21 @@ cp_lexer_saving_tokens (const cp_lexer* lexer)
 }
 
 /* Store the next token from the preprocessor in *TOKEN.  Return true
 }
 
 /* Store the next token from the preprocessor in *TOKEN.  Return true
-   if we reach EOF.  */
+   if we reach EOF.  If LEXER is NULL, assume we are handling an
+   initial #pragma pch_preprocess, and thus want the lexer to return
+   processed strings.  */
 
 static void
 
 static void
-cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
-                                cp_token *token)
+cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
 {
   static int is_extern_c = 0;
 
    /* Get a new token from the preprocessor.  */
   token->type
 {
   static int is_extern_c = 0;
 
    /* Get a new token from the preprocessor.  */
   token->type
-    = c_lex_with_flags (&token->value, &token->location, &token->flags);
+    = c_lex_with_flags (&token->u.value, &token->location, &token->flags,
+                       lexer == NULL ? 0 : C_LEX_RAW_STRINGS);
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
-  token->in_system_header = in_system_header;
 
   /* On some systems, some header files are surrounded by an
      implicit extern "C" block.  Set a flag in the token if it
 
   /* On some systems, some header files are surrounded by an
      implicit extern "C" block.  Set a flag in the token if it
@@ -407,20 +417,35 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
   /* Check to see if this token is a keyword.  */
   if (token->type == CPP_NAME)
     {
   /* Check to see if this token is a keyword.  */
   if (token->type == CPP_NAME)
     {
-      if (C_IS_RESERVED_WORD (token->value))
+      if (C_IS_RESERVED_WORD (token->u.value))
        {
          /* Mark this token as a keyword.  */
          token->type = CPP_KEYWORD;
          /* Record which keyword.  */
        {
          /* Mark this token as a keyword.  */
          token->type = CPP_KEYWORD;
          /* Record which keyword.  */
-         token->keyword = C_RID_CODE (token->value);
+         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'.  */
          /* 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->value = ridpointers[token->keyword];
+         token->u.value = ridpointers[token->keyword];
        }
       else
        {
        }
       else
        {
+          if (warn_cxx0x_compat
+              && C_RID_CODE (token->u.value) >= RID_FIRST_CXX0X
+              && C_RID_CODE (token->u.value) <= RID_LAST_CXX0X)
+            {
+              /* 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));
+
+              /* Clear out the C_RID_CODE so we don't warn about this
+                 particular identifier-turned-keyword again.  */
+              C_SET_RID_CODE (token->u.value, RID_MAX);
+            }
+
          token->ambiguous_p = false;
          token->keyword = RID_MAX;
        }
          token->ambiguous_p = false;
          token->keyword = RID_MAX;
        }
@@ -429,7 +454,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
   else if (token->type == CPP_AT_NAME)
     {
       token->type = CPP_KEYWORD;
   else if (token->type == CPP_AT_NAME)
     {
       token->type = CPP_KEYWORD;
-      switch (C_RID_CODE (token->value))
+      switch (C_RID_CODE (token->u.value))
        {
        /* Map 'class' to '@class', 'private' to '@private', etc.  */
        case RID_CLASS: token->keyword = RID_AT_CLASS; break;
        {
        /* Map 'class' to '@class', 'private' to '@private', etc.  */
        case RID_CLASS: token->keyword = RID_AT_CLASS; break;
@@ -439,25 +464,24 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
        case RID_THROW: token->keyword = RID_AT_THROW; break;
        case RID_TRY: token->keyword = RID_AT_TRY; break;
        case RID_CATCH: token->keyword = RID_AT_CATCH; break;
        case RID_THROW: token->keyword = RID_AT_THROW; break;
        case RID_TRY: token->keyword = RID_AT_TRY; break;
        case RID_CATCH: token->keyword = RID_AT_CATCH; break;
-       default: token->keyword = C_RID_CODE (token->value);
+       default: token->keyword = C_RID_CODE (token->u.value);
        }
     }
   else if (token->type == CPP_PRAGMA)
     {
       /* We smuggled the cpp_token->u.pragma value in an INTEGER_CST.  */
        }
     }
   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->value);
-      token->value = NULL;
+      token->pragma_kind = TREE_INT_CST_LOW (token->u.value);
+      token->u.value = NULL_TREE;
     }
 }
 
     }
 }
 
-/* Update the globals input_location and in_system_header from TOKEN.  */
+/* Update the globals input_location and the input file stack from TOKEN.  */
 static inline void
 cp_lexer_set_source_position_from_token (cp_token *token)
 {
   if (token->type != CPP_EOF)
     {
       input_location = token->location;
 static inline void
 cp_lexer_set_source_position_from_token (cp_token *token)
 {
   if (token->type != CPP_EOF)
     {
       input_location = token->location;
-      in_system_header = token->in_system_header;
     }
 }
 
     }
 }
 
@@ -500,6 +524,65 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
   return cp_lexer_peek_token (lexer)->keyword == keyword;
 }
 
   return cp_lexer_peek_token (lexer)->keyword == keyword;
 }
 
+/* Return true if the next token is not the indicated KEYWORD.  */
+
+static inline bool
+cp_lexer_next_token_is_not_keyword (cp_lexer* lexer, enum rid keyword)
+{
+  return cp_lexer_peek_token (lexer)->keyword != keyword;
+}
+
+/* Return true if the next token is a keyword for a decl-specifier.  */
+
+static bool
+cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
+{
+  cp_token *token;
+
+  token = cp_lexer_peek_token (lexer);
+  switch (token->keyword) 
+    {
+      /* auto specifier: storage-class-specifier in C++,
+         simple-type-specifier in C++0x.  */
+    case RID_AUTO:
+      /* Storage classes.  */
+    case RID_REGISTER:
+    case RID_STATIC:
+    case RID_EXTERN:
+    case RID_MUTABLE:
+    case RID_THREAD:
+      /* Elaborated type specifiers.  */
+    case RID_ENUM:
+    case RID_CLASS:
+    case RID_STRUCT:
+    case RID_UNION:
+    case RID_TYPENAME:
+      /* Simple type specifiers.  */
+    case RID_CHAR:
+    case RID_CHAR16:
+    case RID_CHAR32:
+    case RID_WCHAR:
+    case RID_BOOL:
+    case RID_SHORT:
+    case RID_INT:
+    case RID_LONG:
+    case RID_SIGNED:
+    case RID_UNSIGNED:
+    case RID_FLOAT:
+    case RID_DOUBLE:
+    case RID_VOID:
+      /* GNU extensions.  */ 
+    case RID_ATTRIBUTE:
+    case RID_TYPEOF:
+      /* C++0x extensions.  */
+    case RID_DECLTYPE:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
 /* Return a pointer to the Nth token in the token stream.  If N is 1,
    then this is precisely equivalent to cp_lexer_peek_token (except
    that it is not inline).  One would like to disallow that case, but
 /* Return a pointer to the Nth token in the token stream.  If N is 1,
    then this is precisely equivalent to cp_lexer_peek_token (except
    that it is not inline).  One would like to disallow that case, but
@@ -526,7 +609,7 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
       ++token;
       if (token == lexer->last_token)
        {
       ++token;
       if (token == lexer->last_token)
        {
-         token = (cp_token *)&eof_token;
+         token = &eof_token;
          break;
        }
 
          break;
        }
 
@@ -559,7 +642,7 @@ cp_lexer_consume_token (cp_lexer* lexer)
       lexer->next_token++;
       if (lexer->next_token == lexer->last_token)
        {
       lexer->next_token++;
       if (lexer->next_token == lexer->last_token)
        {
-         lexer->next_token = (cp_token *)&eof_token;
+         lexer->next_token = &eof_token;
          break;
        }
 
          break;
        }
 
@@ -591,7 +674,7 @@ cp_lexer_purge_token (cp_lexer *lexer)
   gcc_assert (tok != &eof_token);
   tok->type = CPP_PURGED;
   tok->location = UNKNOWN_LOCATION;
   gcc_assert (tok != &eof_token);
   tok->type = CPP_PURGED;
   tok->location = UNKNOWN_LOCATION;
-  tok->value = NULL_TREE;
+  tok->u.value = NULL_TREE;
   tok->keyword = RID_MAX;
 
   do
   tok->keyword = RID_MAX;
 
   do
@@ -599,7 +682,7 @@ cp_lexer_purge_token (cp_lexer *lexer)
       tok++;
       if (tok == lexer->last_token)
        {
       tok++;
       if (tok == lexer->last_token)
        {
-         tok = (cp_token *)&eof_token;
+         tok = &eof_token;
          break;
        }
     }
          break;
        }
     }
@@ -625,7 +708,7 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
     {
       tok->type = CPP_PURGED;
       tok->location = UNKNOWN_LOCATION;
     {
       tok->type = CPP_PURGED;
       tok->location = UNKNOWN_LOCATION;
-      tok->value = NULL_TREE;
+      tok->u.value = NULL_TREE;
       tok->keyword = RID_MAX;
     }
 }
       tok->keyword = RID_MAX;
     }
 }
@@ -703,16 +786,18 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
     case CPP_KEYWORD:
       /* Some keywords have a value that is not an IDENTIFIER_NODE.
         For example, `struct' is mapped to an INTEGER_CST.  */
     case CPP_KEYWORD:
       /* Some keywords have a value that is not an IDENTIFIER_NODE.
         For example, `struct' is mapped to an INTEGER_CST.  */
-      if (TREE_CODE (token->value) != IDENTIFIER_NODE)
+      if (TREE_CODE (token->u.value) != IDENTIFIER_NODE)
        break;
       /* else fall through */
     case CPP_NAME:
        break;
       /* else fall through */
     case CPP_NAME:
-      fputs (IDENTIFIER_POINTER (token->value), stream);
+      fputs (IDENTIFIER_POINTER (token->u.value), stream);
       break;
 
     case CPP_STRING:
       break;
 
     case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
     case CPP_WSTRING:
     case CPP_WSTRING:
-      fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->value));
+      fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
       break;
 
     default:
       break;
 
     default:
@@ -768,13 +853,13 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
    VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
 
 static cp_declarator *make_call_declarator
    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
   (cp_cv_quals, cp_declarator *);
 static cp_declarator *make_reference_declarator
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
   (cp_cv_quals, cp_declarator *);
 static cp_declarator *make_reference_declarator
-  (cp_cv_quals, cp_declarator *);
+  (cp_cv_quals, cp_declarator *, bool);
 static cp_parameter_declarator *make_parameter_declarator
   (cp_decl_specifier_seq *, cp_declarator *, tree);
 static cp_declarator *make_ptrmem_declarator
 static cp_parameter_declarator *make_parameter_declarator
   (cp_decl_specifier_seq *, cp_declarator *, tree);
 static cp_declarator *make_ptrmem_declarator
@@ -807,6 +892,7 @@ make_declarator (cp_declarator_kind kind)
   declarator->kind = kind;
   declarator->attributes = NULL_TREE;
   declarator->declarator = NULL;
   declarator->kind = kind;
   declarator->attributes = NULL_TREE;
   declarator->declarator = NULL;
+  declarator->parameter_pack_p = false;
 
   return declarator;
 }
 
   return declarator;
 }
@@ -844,7 +930,7 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name,
   declarator->u.id.qualifying_scope = qualifying_scope;
   declarator->u.id.unqualified_name = unqualified_name;
   declarator->u.id.sfk = sfk;
   declarator->u.id.qualifying_scope = qualifying_scope;
   declarator->u.id.unqualified_name = unqualified_name;
   declarator->u.id.sfk = sfk;
-
+  
   return declarator;
 }
 
   return declarator;
 }
 
@@ -861,6 +947,13 @@ make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
   declarator->declarator = target;
   declarator->u.pointer.qualifiers = cv_qualifiers;
   declarator->u.pointer.class_type = NULL_TREE;
   declarator->declarator = target;
   declarator->u.pointer.qualifiers = cv_qualifiers;
   declarator->u.pointer.class_type = NULL_TREE;
+  if (target)
+    {
+      declarator->parameter_pack_p = target->parameter_pack_p;
+      target->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
 
   return declarator;
 }
 
   return declarator;
 }
@@ -868,14 +961,22 @@ make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
 /* Like make_pointer_declarator -- but for references.  */
 
 cp_declarator *
 /* Like make_pointer_declarator -- but for references.  */
 
 cp_declarator *
-make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
+make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
+                          bool rvalue_ref)
 {
   cp_declarator *declarator;
 
   declarator = make_declarator (cdk_reference);
   declarator->declarator = target;
 {
   cp_declarator *declarator;
 
   declarator = make_declarator (cdk_reference);
   declarator->declarator = target;
-  declarator->u.pointer.qualifiers = cv_qualifiers;
-  declarator->u.pointer.class_type = NULL_TREE;
+  declarator->u.reference.qualifiers = cv_qualifiers;
+  declarator->u.reference.rvalue_ref = rvalue_ref;
+  if (target)
+    {
+      declarator->parameter_pack_p = target->parameter_pack_p;
+      target->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
 
   return declarator;
 }
 
   return declarator;
 }
@@ -894,6 +995,14 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
   declarator->u.pointer.qualifiers = cv_qualifiers;
   declarator->u.pointer.class_type = class_type;
 
   declarator->u.pointer.qualifiers = cv_qualifiers;
   declarator->u.pointer.class_type = class_type;
 
+  if (pointee)
+    {
+      declarator->parameter_pack_p = pointee->parameter_pack_p;
+      pointee->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
+
   return declarator;
 }
 
   return declarator;
 }
 
@@ -904,9 +1013,10 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
 
 cp_declarator *
 make_call_declarator (cp_declarator *target,
 
 cp_declarator *
 make_call_declarator (cp_declarator *target,
-                     cp_parameter_declarator *parms,
+                     tree parms,
                      cp_cv_quals cv_qualifiers,
                      cp_cv_quals cv_qualifiers,
-                     tree exception_specification)
+                     tree exception_specification,
+                     tree late_return_type)
 {
   cp_declarator *declarator;
 
 {
   cp_declarator *declarator;
 
@@ -915,6 +1025,14 @@ 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.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;
+      target->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
 
   return declarator;
 }
 
   return declarator;
 }
@@ -930,10 +1048,48 @@ make_array_declarator (cp_declarator *element, tree bounds)
   declarator = make_declarator (cdk_array);
   declarator->declarator = element;
   declarator->u.array.bounds = bounds;
   declarator = make_declarator (cdk_array);
   declarator->declarator = element;
   declarator->u.array.bounds = bounds;
+  if (element)
+    {
+      declarator->parameter_pack_p = element->parameter_pack_p;
+      element->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
 
   return declarator;
 }
 
 
   return declarator;
 }
 
+/* Determine whether the declarator we've seen so far can be a
+   parameter pack, when followed by an ellipsis.  */
+static bool 
+declarator_can_be_parameter_pack (cp_declarator *declarator)
+{
+  /* Search for a declarator name, or any other declarator that goes
+     after the point where the ellipsis could appear in a parameter
+     pack. If we find any of these, then this declarator can not be
+     made into a parameter pack.  */
+  bool found = false;
+  while (declarator && !found)
+    {
+      switch ((int)declarator->kind)
+       {
+       case cdk_id:
+       case cdk_array:
+         found = true;
+         break;
+
+       case cdk_error:
+         return true;
+
+       default:
+         declarator = declarator->declarator;
+         break;
+       }
+    }
+
+  return !found;
+}
+
 cp_parameter_declarator *no_parameters;
 
 /* Create a parameter declarator with the indicated DECL_SPECIFIERS,
 cp_parameter_declarator *no_parameters;
 
 /* Create a parameter declarator with the indicated DECL_SPECIFIERS,
@@ -960,6 +1116,24 @@ make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
   return parameter;
 }
 
   return parameter;
 }
 
+/* Returns true iff DECLARATOR  is a declaration for a function.  */
+
+static bool
+function_declarator_p (const cp_declarator *declarator)
+{
+  while (declarator)
+    {
+      if (declarator->kind == cdk_function
+         && declarator->declarator->kind == cdk_id)
+       return true;
+      if (declarator->kind == cdk_id
+         || declarator->kind == cdk_error)
+       return false;
+      declarator = declarator->declarator;
+    }
+  return false;
+}
 /* The parser.  */
 
 /* Overview
 /* The parser.  */
 
 /* Overview
@@ -1090,8 +1264,15 @@ typedef enum cp_parser_status_kind
 
 typedef struct cp_parser_expression_stack_entry
 {
 
 typedef struct cp_parser_expression_stack_entry
 {
+  /* Left hand side of the binary operation we are currently
+     parsing.  */
   tree lhs;
   tree lhs;
+  /* Original tree code for left hand side, if it was a binary
+     expression itself (used for -Wparentheses).  */
+  enum tree_code lhs_type;
+  /* Tree code for the binary operation we are parsing.  */
   enum tree_code tree_type;
   enum tree_code tree_type;
+  /* Precedence of the binary operation we are parsing.  */
   int prec;
 } cp_parser_expression_stack_entry;
 
   int prec;
 } cp_parser_expression_stack_entry;
 
@@ -1150,8 +1331,6 @@ static const cp_parser_binary_operations_map_node binops[] = {
   { CPP_GREATER, GT_EXPR, PREC_RELATIONAL_EXPRESSION },
   { CPP_LESS_EQ, LE_EXPR, PREC_RELATIONAL_EXPRESSION },
   { CPP_GREATER_EQ, GE_EXPR, PREC_RELATIONAL_EXPRESSION },
   { CPP_GREATER, GT_EXPR, PREC_RELATIONAL_EXPRESSION },
   { CPP_LESS_EQ, LE_EXPR, PREC_RELATIONAL_EXPRESSION },
   { CPP_GREATER_EQ, GE_EXPR, PREC_RELATIONAL_EXPRESSION },
-  { CPP_MIN, MIN_EXPR, PREC_RELATIONAL_EXPRESSION },
-  { CPP_MAX, MAX_EXPR, PREC_RELATIONAL_EXPRESSION },
 
   { CPP_EQ_EQ, EQ_EXPR, PREC_EQUALITY_EXPRESSION },
   { CPP_NOT_EQ, NE_EXPR, PREC_EQUALITY_EXPRESSION },
 
   { CPP_EQ_EQ, EQ_EXPR, PREC_EQUALITY_EXPRESSION },
   { CPP_NOT_EQ, NE_EXPR, PREC_EQUALITY_EXPRESSION },
@@ -1195,7 +1374,7 @@ cp_parser_context_new (cp_parser_context* next)
 
   /* No errors have occurred yet in this context.  */
   context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
 
   /* No errors have occurred yet in this context.  */
   context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
-  /* If this is not the bottomost context, copy information that we
+  /* If this is not the bottommost context, copy information that we
      need from the previous context.  */
   if (next)
     {
      need from the previous context.  */
   if (next)
     {
@@ -1256,7 +1435,9 @@ typedef struct cp_parser GTY(())
 
   /* TRUE if the `>' token should be interpreted as the greater-than
      operator.  FALSE if it is the end of a template-id or
 
   /* TRUE if the `>' token should be interpreted as the greater-than
      operator.  FALSE if it is the end of a template-id or
-     template-parameter-list.  */
+     template-parameter-list. In C++0x mode, this flag also applies to
+     `>>' tokens, which are viewed as two consecutive `>' tokens when
+     this flag is FALSE.  */
   bool greater_than_is_operator_p;
 
   /* TRUE if default arguments are allowed within a parameter list
   bool greater_than_is_operator_p;
 
   /* TRUE if default arguments are allowed within a parameter list
@@ -1303,6 +1484,7 @@ typedef struct cp_parser GTY(())
 #define IN_ITERATION_STMT      2
 #define IN_OMP_BLOCK           4
 #define IN_OMP_FOR             8
 #define IN_ITERATION_STMT      2
 #define IN_OMP_BLOCK           4
 #define IN_OMP_FOR             8
+#define IN_IF_STMT             16
   unsigned char in_statement;
 
   /* TRUE if we are presently parsing the body of a switch statement.
   unsigned char in_statement;
 
   /* TRUE if we are presently parsing the body of a switch statement.
@@ -1324,6 +1506,10 @@ typedef struct cp_parser GTY(())
      character set.  */
   bool translate_strings_p;
 
      character set.  */
   bool translate_strings_p;
 
+  /* TRUE if we are presently parsing the body of a function, but not
+     a local class.  */
+  bool in_function_body;
+
   /* If non-NULL, then we are parsing a construct where new type
      definitions are not permitted.  The string stored here will be
      issued as an error message if a type is defined.  */
   /* If non-NULL, then we are parsing a construct where new type
      definitions are not permitted.  The string stored here will be
      issued as an error message if a type is defined.  */
@@ -1397,16 +1583,16 @@ 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);
   (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, bool, bool);
 static tree cp_parser_postfix_expression
-  (cp_parser *, bool, bool);
+  (cp_parser *, bool, bool, bool);
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
-  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
+  (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
 static tree cp_parser_parenthesized_expression_list
 static tree cp_parser_parenthesized_expression_list
-  (cp_parser *, bool, bool, bool *);
+  (cp_parser *, bool, bool, bool, bool *);
 static void cp_parser_pseudo_destructor_name
   (cp_parser *, tree *, tree *);
 static tree cp_parser_unary_expression
 static void cp_parser_pseudo_destructor_name
   (cp_parser *, tree *, tree *);
 static tree cp_parser_unary_expression
@@ -1430,7 +1616,7 @@ static tree cp_parser_delete_expression
 static tree cp_parser_cast_expression
   (cp_parser *, bool, bool);
 static tree cp_parser_binary_expression
 static tree cp_parser_cast_expression
   (cp_parser *, bool, bool);
 static tree cp_parser_binary_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, enum cp_parser_prec);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
 static tree cp_parser_assignment_expression
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
 static tree cp_parser_assignment_expression
@@ -1447,9 +1633,9 @@ static tree cp_parser_builtin_offsetof
 /* Statements [gram.stmt.stmt]  */
 
 static void cp_parser_statement
 /* Statements [gram.stmt.stmt]  */
 
 static void cp_parser_statement
-  (cp_parser *, tree, bool);
-static tree cp_parser_labeled_statement
-  (cp_parser *, tree, bool);
+  (cp_parser *, tree, bool, bool *);
+static void cp_parser_label_for_labeled_statement
+  (cp_parser *);
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
@@ -1457,7 +1643,7 @@ static tree cp_parser_compound_statement
 static void cp_parser_statement_seq_opt
   (cp_parser *, tree);
 static tree cp_parser_selection_statement
 static void cp_parser_statement_seq_opt
   (cp_parser *, tree);
 static tree cp_parser_selection_statement
-  (cp_parser *);
+  (cp_parser *, bool *);
 static tree cp_parser_condition
   (cp_parser *);
 static tree cp_parser_iteration_statement
 static tree cp_parser_condition
   (cp_parser *);
 static tree cp_parser_iteration_statement
@@ -1470,7 +1656,7 @@ static void cp_parser_declaration_statement
   (cp_parser *);
 
 static tree cp_parser_implicitly_scoped_statement
   (cp_parser *);
 
 static tree cp_parser_implicitly_scoped_statement
-  (cp_parser *);
+  (cp_parser *, bool *);
 static void cp_parser_already_scoped_statement
   (cp_parser *);
 
 static void cp_parser_already_scoped_statement
   (cp_parser *);
 
@@ -1497,6 +1683,8 @@ static tree cp_parser_simple_type_specifier
   (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
 static tree cp_parser_type_name
   (cp_parser *);
   (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
 static tree cp_parser_type_name
   (cp_parser *);
+static tree cp_parser_nonclass_name 
+  (cp_parser* parser);
 static tree cp_parser_elaborated_type_specifier
   (cp_parser *, bool, bool);
 static tree cp_parser_enum_specifier
 static tree cp_parser_elaborated_type_specifier
   (cp_parser *, bool, bool);
 static tree cp_parser_enum_specifier
@@ -1515,19 +1703,23 @@ static tree cp_parser_qualified_namespace_specifier
   (cp_parser *);
 static void cp_parser_namespace_alias_definition
   (cp_parser *);
   (cp_parser *);
 static void cp_parser_namespace_alias_definition
   (cp_parser *);
-static void cp_parser_using_declaration
-  (cp_parser *);
+static bool cp_parser_using_declaration
+  (cp_parser *, bool);
 static void cp_parser_using_directive
   (cp_parser *);
 static void cp_parser_asm_definition
   (cp_parser *);
 static void cp_parser_linkage_specification
   (cp_parser *);
 static void cp_parser_using_directive
   (cp_parser *);
 static void cp_parser_asm_definition
   (cp_parser *);
 static void cp_parser_linkage_specification
   (cp_parser *);
+static void cp_parser_static_assert
+  (cp_parser *, bool);
+static tree cp_parser_decltype
+  (cp_parser *);
 
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
 
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
-  (cp_parser *, cp_decl_specifier_seq *, tree, bool, bool, int, bool *);
+  (cp_parser *, cp_decl_specifier_seq *, VEC (deferred_access_check,gc)*, bool, bool, int, bool *);
 static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
 static cp_declarator *cp_parser_direct_declarator
 static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
 static cp_declarator *cp_parser_direct_declarator
@@ -1536,24 +1728,30 @@ 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 *);
   (cp_parser *, tree *, cp_cv_quals *);
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
+static tree cp_parser_late_return_type_opt
+  (cp_parser *);
 static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
   (cp_parser *);
 static void cp_parser_type_specifier_seq
   (cp_parser *, bool, cp_decl_specifier_seq *);
 static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
   (cp_parser *);
 static void cp_parser_type_specifier_seq
   (cp_parser *, bool, cp_decl_specifier_seq *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_clause
+static tree cp_parser_parameter_declaration_clause
   (cp_parser *);
   (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 *);
   (cp_parser *, bool *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
   (cp_parser *, bool, bool *);
+static tree cp_parser_default_argument 
+  (cp_parser *, bool);
 static void cp_parser_function_body
   (cp_parser *);
 static tree cp_parser_initializer
   (cp_parser *, bool *, bool *);
 static tree cp_parser_initializer_clause
   (cp_parser *, bool *);
 static void cp_parser_function_body
   (cp_parser *);
 static tree cp_parser_initializer
   (cp_parser *, bool *, bool *);
 static tree cp_parser_initializer_clause
   (cp_parser *, bool *);
+static tree cp_parser_braced_list
+  (cp_parser*, bool*);
 static VEC(constructor_elt,gc) *cp_parser_initializer_list
   (cp_parser *, bool *);
 
 static VEC(constructor_elt,gc) *cp_parser_initializer_list
   (cp_parser *, bool *);
 
@@ -1567,7 +1765,7 @@ static tree cp_parser_class_name
 static tree cp_parser_class_specifier
   (cp_parser *);
 static tree cp_parser_class_head
 static tree cp_parser_class_specifier
   (cp_parser *);
 static tree cp_parser_class_head
-  (cp_parser *, bool *, tree *);
+  (cp_parser *, bool *, tree *, tree *);
 static enum tag_types cp_parser_class_key
   (cp_parser *);
 static void cp_parser_member_specification_opt
 static enum tag_types cp_parser_class_key
   (cp_parser *);
 static void cp_parser_member_specification_opt
@@ -1617,9 +1815,9 @@ static void cp_parser_template_declaration
 static tree cp_parser_template_parameter_list
   (cp_parser *);
 static tree cp_parser_template_parameter
 static tree cp_parser_template_parameter_list
   (cp_parser *);
 static tree cp_parser_template_parameter
-  (cp_parser *, bool *);
+  (cp_parser *, bool *, bool *);
 static tree cp_parser_type_parameter
 static tree cp_parser_type_parameter
-  (cp_parser *);
+  (cp_parser *, bool *);
 static tree cp_parser_template_id
   (cp_parser *, bool, bool, bool);
 static tree cp_parser_template_name
 static tree cp_parser_template_id
   (cp_parser *, bool, bool, bool);
 static tree cp_parser_template_name
@@ -1705,15 +1903,15 @@ static tree cp_parser_objc_statement
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
-  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
+  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t);
 static tree cp_parser_lookup_name_simple
 static tree cp_parser_lookup_name_simple
-  (cp_parser *, tree);
+  (cp_parser *, tree, location_t);
 static tree cp_parser_maybe_treat_template_as_class
   (tree, bool);
 static bool cp_parser_check_declarator_template_parameters
 static tree cp_parser_maybe_treat_template_as_class
   (tree, bool);
 static bool cp_parser_check_declarator_template_parameters
-  (cp_parser *, cp_declarator *);
+  (cp_parser *, cp_declarator *, location_t);
 static bool cp_parser_check_template_parameters
 static bool cp_parser_check_template_parameters
-  (cp_parser *, unsigned);
+  (cp_parser *, unsigned, location_t);
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
 static tree cp_parser_simple_cast_expression
   (cp_parser *);
 static tree cp_parser_global_scope_opt
@@ -1727,9 +1925,9 @@ static tree cp_parser_function_definition_after_declarator
 static void cp_parser_template_declaration_after_export
   (cp_parser *, bool);
 static void cp_parser_perform_template_parameter_access_checks
 static void cp_parser_template_declaration_after_export
   (cp_parser *, bool);
 static void cp_parser_perform_template_parameter_access_checks
-  (tree);
+  (VEC (deferred_access_check,gc)*);
 static tree cp_parser_single_declaration
 static tree cp_parser_single_declaration
-  (cp_parser *, tree, bool, bool *);
+  (cp_parser *, VEC (deferred_access_check,gc)*, bool, bool, bool *);
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
@@ -1744,12 +1942,14 @@ static void cp_parser_late_parsing_default_args
   (cp_parser *, tree);
 static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
   (cp_parser *, tree);
 static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
+static tree cp_parser_trait_expr
+  (cp_parser *, enum rid);
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
-  (cp_parser *, cp_decl_specifier_seq *, enum rid);
+  (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
 static void cp_parser_set_decl_spec_type
 static void cp_parser_set_decl_spec_type
-  (cp_decl_specifier_seq *, tree, bool);
+  (cp_decl_specifier_seq *, tree, location_t, bool);
 static bool cp_parser_friend_p
   (const cp_decl_specifier_seq *);
 static cp_token *cp_parser_require
 static bool cp_parser_friend_p
   (const cp_decl_specifier_seq *);
 static cp_token *cp_parser_require
@@ -1769,12 +1969,12 @@ static enum tag_types cp_parser_token_is_class_key
 static void cp_parser_check_class_key
   (enum tag_types, tree type);
 static void cp_parser_check_access_in_redeclaration
 static void cp_parser_check_class_key
   (enum tag_types, tree type);
 static void cp_parser_check_access_in_redeclaration
-  (tree type);
+  (tree type, location_t location);
 static bool cp_parser_optional_template_keyword
   (cp_parser *);
 static void cp_parser_pre_parsed_nested_name_specifier
   (cp_parser *);
 static bool cp_parser_optional_template_keyword
   (cp_parser *);
 static void cp_parser_pre_parsed_nested_name_specifier
   (cp_parser *);
-static void cp_parser_cache_group
+static bool cp_parser_cache_group
   (cp_parser *, enum cpp_ttype, unsigned);
 static void cp_parser_parse_tentatively
   (cp_parser *);
   (cp_parser *, enum cpp_ttype, unsigned);
 static void cp_parser_parse_tentatively
   (cp_parser *);
@@ -1791,19 +1991,19 @@ static bool cp_parser_uncommitted_to_tentative_parse_p
 static void cp_parser_error
   (cp_parser *, const char *);
 static void cp_parser_name_lookup_error
 static void cp_parser_error
   (cp_parser *, const char *);
 static void cp_parser_name_lookup_error
-  (cp_parser *, tree, tree, const char *);
+  (cp_parser *, tree, tree, const char *, location_t);
 static bool cp_parser_simulate_error
   (cp_parser *);
 static bool cp_parser_simulate_error
   (cp_parser *);
-static void cp_parser_check_type_definition
+static bool cp_parser_check_type_definition
   (cp_parser *);
 static void cp_parser_check_for_definition_in_return_type
   (cp_parser *);
 static void cp_parser_check_for_definition_in_return_type
-  (cp_declarator *, tree);
+  (cp_declarator *, tree, location_t type_location);
 static void cp_parser_check_for_invalid_template_id
 static void cp_parser_check_for_invalid_template_id
-  (cp_parser *, tree);
+  (cp_parser *, tree, location_t location);
 static bool cp_parser_non_integral_constant_expression
   (cp_parser *, const char *);
 static void cp_parser_diagnose_invalid_type_name
 static bool cp_parser_non_integral_constant_expression
   (cp_parser *, const char *);
 static void cp_parser_diagnose_invalid_type_name
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t);
 static bool cp_parser_parse_and_diagnose_invalid_type_name
   (cp_parser *);
 static int cp_parser_skip_to_closing_parenthesis
 static bool cp_parser_parse_and_diagnose_invalid_type_name
   (cp_parser *);
 static int cp_parser_skip_to_closing_parenthesis
@@ -1814,10 +2014,10 @@ static void cp_parser_consume_semicolon_at_end_of_statement
   (cp_parser *);
 static void cp_parser_skip_to_end_of_block_or_statement
   (cp_parser *);
   (cp_parser *);
 static void cp_parser_skip_to_end_of_block_or_statement
   (cp_parser *);
-static void cp_parser_skip_to_closing_brace
+static bool cp_parser_skip_to_closing_brace
+  (cp_parser *);
+static void cp_parser_skip_to_end_of_template_parameter_list
   (cp_parser *);
   (cp_parser *);
-static void cp_parser_skip_until_found
-  (cp_parser *, enum cpp_ttype, const char *);
 static void cp_parser_skip_to_pragma_eol
   (cp_parser*, cp_token *);
 static bool cp_parser_error_occurred
 static void cp_parser_skip_to_pragma_eol
   (cp_parser*, cp_token *);
 static bool cp_parser_error_occurred
@@ -1829,7 +2029,9 @@ static bool cp_parser_is_string_literal
 static bool cp_parser_is_keyword
   (cp_token *, enum rid);
 static tree cp_parser_make_typename_type
 static bool cp_parser_is_keyword
   (cp_token *, enum rid);
 static tree cp_parser_make_typename_type
-  (cp_parser *, tree, tree);
+  (cp_parser *, tree, tree, location_t location);
+static cp_declarator * cp_parser_make_indirect_declarator
+  (enum tree_code, tree, cp_cv_quals, cp_declarator *);
 
 /* Returns nonzero if we are parsing tentatively.  */
 
 
 /* Returns nonzero if we are parsing tentatively.  */
 
@@ -1844,7 +2046,10 @@ cp_parser_parsing_tentatively (cp_parser* parser)
 static bool
 cp_parser_is_string_literal (cp_token* token)
 {
 static bool
 cp_parser_is_string_literal (cp_token* token)
 {
-  return (token->type == CPP_STRING || token->type == CPP_WSTRING);
+  return (token->type == CPP_STRING ||
+         token->type == CPP_STRING16 ||
+         token->type == CPP_STRING32 ||
+         token->type == CPP_WSTRING);
 }
 
 /* Returns nonzero if TOKEN is the indicated KEYWORD.  */
 }
 
 /* Returns nonzero if TOKEN is the indicated KEYWORD.  */
@@ -1855,16 +2060,6 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword)
   return token->keyword == keyword;
 }
 
   return token->keyword == keyword;
 }
 
-/* A minimum or maximum operator has been seen.  As these are
-   deprecated, issue a warning.  */
-
-static inline void
-cp_parser_warn_min_max (void)
-{
-  if (warn_deprecated && !in_system_header)
-    warning (OPT_Wdeprecated, "minimum/maximum operators are deprecated");
-}
-
 /* If not parsing tentatively, issue a diagnostic of the form
       FILE:LINE: MESSAGE before TOKEN
    where TOKEN is the next token in the input stream.  MESSAGE
 /* If not parsing tentatively, issue a diagnostic of the form
       FILE:LINE: MESSAGE before TOKEN
    where TOKEN is the next token in the input stream.  MESSAGE
@@ -1883,7 +2078,7 @@ cp_parser_error (cp_parser* parser, const char* message)
 
       if (token->type == CPP_PRAGMA)
        {
 
       if (token->type == CPP_PRAGMA)
        {
-         error ("%<#pragma%> is not allowed here");
+         error ("%H%<#pragma%> is not allowed here", &token->location);
          cp_parser_skip_to_pragma_eol (parser, token);
          return;
        }
          cp_parser_skip_to_pragma_eol (parser, token);
          return;
        }
@@ -1893,7 +2088,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),
                        CPP_KEYWORD, keywords are treated like
                        identifiers.  */
                     (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-                    token->value);
+                    token->u.value);
     }
 }
 
     }
 }
 
@@ -1906,33 +2101,34 @@ static void
 cp_parser_name_lookup_error (cp_parser* parser,
                             tree name,
                             tree decl,
 cp_parser_name_lookup_error (cp_parser* parser,
                             tree name,
                             tree decl,
-                            const char* desired)
+                            const char* desired,
+                            location_t location)
 {
   /* If name lookup completely failed, tell the user that NAME was not
      declared.  */
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
 {
   /* If name lookup completely failed, tell the user that NAME was not
      declared.  */
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-       error ("%<%D::%D%> has not been declared",
-              parser->scope, name);
+       error ("%H%<%E::%E%> has not been declared",
+              &location, parser->scope, name);
       else if (parser->scope == global_namespace)
       else if (parser->scope == global_namespace)
-       error ("%<::%D%> has not been declared", name);
+       error ("%H%<::%E%> has not been declared", &location, name);
       else if (parser->object_scope
               && !CLASS_TYPE_P (parser->object_scope))
       else if (parser->object_scope
               && !CLASS_TYPE_P (parser->object_scope))
-       error ("request for member %qD in non-class type %qT",
-              name, parser->object_scope);
+       error ("%Hrequest for member %qE in non-class type %qT",
+              &location, name, parser->object_scope);
       else if (parser->object_scope)
       else if (parser->object_scope)
-       error ("%<%T::%D%> has not been declared",
-              parser->object_scope, name);
+       error ("%H%<%T::%E%> has not been declared",
+              &location, parser->object_scope, name);
       else
       else
-       error ("%qD has not been declared", name);
+       error ("%H%qE has not been declared", &location, name);
     }
   else if (parser->scope && parser->scope != global_namespace)
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("%<%D::%D%> %s", parser->scope, name, desired);
+    error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
   else if (parser->scope == global_namespace)
   else if (parser->scope == global_namespace)
-    error ("%<::%D%> %s", name, desired);
+    error ("%H%<::%E%> %s", &location, name, desired);
   else
   else
-    error ("%qD %s", name, desired);
+    error ("%H%qE %s", &location, name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -1950,28 +2146,79 @@ cp_parser_simulate_error (cp_parser* parser)
   return false;
 }
 
   return false;
 }
 
+/* Check for repeated decl-specifiers.  */
+
+static void
+cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
+                          location_t location)
+{
+  cp_decl_spec ds;
+
+  for (ds = ds_first; ds != ds_last; ++ds)
+    {
+      unsigned count = decl_specs->specs[(int)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%>");
+       }
+      else if (count > 1)
+       {
+         static const char *const decl_spec_names[] = {
+           "signed",
+           "unsigned",
+           "short",
+           "long",
+           "const",
+           "volatile",
+           "restrict",
+           "inline",
+           "virtual",
+           "explicit",
+           "friend",
+           "typedef",
+           "__complex",
+           "__thread"
+         };
+         error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
+       }
+    }
+}
+
 /* This function is called when a type is defined.  If type
    definitions are forbidden at this point, an error message is
    issued.  */
 
 /* This function is called when a type is defined.  If type
    definitions are forbidden at this point, an error message is
    issued.  */
 
-static void
+static bool
 cp_parser_check_type_definition (cp_parser* parser)
 {
   /* If types are forbidden here, issue a message.  */
   if (parser->type_definition_forbidden_message)
 cp_parser_check_type_definition (cp_parser* parser)
 {
   /* If types are forbidden here, issue a message.  */
   if (parser->type_definition_forbidden_message)
-    /* Use `%s' to print the string in case there are any escape
-       characters in the message.  */
-    error ("%s", parser->type_definition_forbidden_message);
+    {
+      /* Don't use `%s' to print the string, because quotations (`%<', `%>')
+        in the message need to be interpreted.  */
+      error (parser->type_definition_forbidden_message);
+      return false;
+    }
+  return true;
 }
 
 /* This function is called when the DECLARATOR is processed.  The TYPE
    was a type defined in the decl-specifiers.  If it is invalid to
    define a type in the decl-specifiers for DECLARATOR, an error is
 }
 
 /* This function is called when the DECLARATOR is processed.  The TYPE
    was a type defined in the decl-specifiers.  If it is invalid to
    define a type in the decl-specifiers for DECLARATOR, an error is
-   issued.  */
+   issued. TYPE_LOCATION is the location of TYPE and is used
+   for error reporting.  */
 
 static void
 cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
 
 static void
 cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
-                                              tree type)
+                                              tree type, location_t type_location)
 {
   /* [dcl.fct] forbids type definitions in return types.
      Unfortunately, it's not easy to know whether or not we are
 {
   /* [dcl.fct] forbids type definitions in return types.
      Unfortunately, it's not easy to know whether or not we are
@@ -1984,8 +2231,9 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
   if (declarator
       && declarator->kind == cdk_function)
     {
   if (declarator
       && declarator->kind == cdk_function)
     {
-      error ("new types may not be defined in a return type");
-      inform ("(perhaps a semicolon is missing after the definition of %qT)",
+      error ("%Hnew types may not be defined in a return type", &type_location);
+      inform (type_location, 
+             "(perhaps a semicolon is missing after the definition of %qT)",
              type);
     }
 }
              type);
     }
 }
@@ -1993,22 +2241,23 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
 /* A type-specifier (TYPE) has been parsed which cannot be followed by
    "<" in any valid C++ program.  If the next token is indeed "<",
    issue a message warning the user about what appears to be an
 /* A type-specifier (TYPE) has been parsed which cannot be followed by
    "<" in any valid C++ program.  If the next token is indeed "<",
    issue a message warning the user about what appears to be an
-   invalid attempt to form a template-id.  */
+   invalid attempt to form a template-id. LOCATION is the location
+   of the type-specifier (TYPE) */
 
 static void
 cp_parser_check_for_invalid_template_id (cp_parser* parser,
 
 static void
 cp_parser_check_for_invalid_template_id (cp_parser* parser,
-                                        tree type)
+                                        tree type, location_t location)
 {
   cp_token_position start = 0;
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
     {
       if (TYPE_P (type))
 {
   cp_token_position start = 0;
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
     {
       if (TYPE_P (type))
-       error ("%qT is not a template", type);
+       error ("%H%qT is not a template", &location, type);
       else if (TREE_CODE (type) == IDENTIFIER_NODE)
       else if (TREE_CODE (type) == IDENTIFIER_NODE)
-       error ("%qE is not a template", type);
+       error ("%H%qE is not a template", &location, type);
       else
       else
-       error ("invalid template-id");
+       error ("%Hinvalid template-id", &location);
       /* Remember the location of the invalid "<".  */
       if (cp_parser_uncommitted_to_tentative_parse_p (parser))
        start = cp_lexer_token_position (parser->lexer, true);
       /* Remember the location of the invalid "<".  */
       if (cp_parser_uncommitted_to_tentative_parse_p (parser))
        start = cp_lexer_token_position (parser->lexer, true);
@@ -2037,7 +2286,13 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
     {
       if (!parser->allow_non_integral_constant_expression_p)
        {
     {
       if (!parser->allow_non_integral_constant_expression_p)
        {
-         error ("%s cannot appear in a constant-expression", thing);
+         /* Don't use `%s' to print THING, because quotations (`%<', `%>')
+            in the message need to be interpreted.  */
+         char *message = concat (thing,
+                                 " cannot appear in a constant-expression",
+                                 NULL);
+         error (message);
+         free (message);
          return true;
        }
     }
          return true;
        }
     }
@@ -2048,26 +2303,34 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
    qualifying scope (or NULL, if none) for ID.  This function commits
    to the current active tentative parse, if any.  (Otherwise, the
    problematic construct might be encountered again later, resulting
    qualifying scope (or NULL, if none) for ID.  This function commits
    to the current active tentative parse, if any.  (Otherwise, the
    problematic construct might be encountered again later, resulting
-   in duplicate error messages.)  */
+   in duplicate error messages.) LOCATION is the location of ID.  */
 
 static void
 
 static void
-cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
+cp_parser_diagnose_invalid_type_name (cp_parser *parser,
+                                     tree scope, tree id,
+                                     location_t location)
 {
   tree decl, old_scope;
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
 {
   tree decl, old_scope;
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
-  decl = cp_parser_lookup_name_simple (parser, id);
+  decl = cp_parser_lookup_name_simple (parser, id, location);
   parser->scope = old_scope;
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
   parser->scope = old_scope;
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
-    error ("invalid use of template-name %qE without an argument list",
-      decl);
+    error ("%Hinvalid use of template-name %qE without an argument list",
+           &location, decl);
+  else if (TREE_CODE (id) == BIT_NOT_EXPR)
+    error ("%Hinvalid use of destructor %qD as a type", &location, id);
+  else if (TREE_CODE (decl) == TYPE_DECL)
+    /* Something like 'unsigned A a;'  */
+    error ("%Hinvalid combination of multiple type-specifiers",
+           &location);
   else if (!parser->scope)
     {
       /* Issue an error message.  */
   else if (!parser->scope)
     {
       /* Issue an error message.  */
-      error ("%qE does not name a type", id);
+      error ("%H%qE does not name a type", &location, id);
       /* If we're in a template class, it's possible that the user was
         referring to a type from a base class.  For example:
 
       /* If we're in a template class, it's possible that the user was
         referring to a type from a base class.  For example:
 
@@ -2099,7 +2362,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
                    if (TREE_CODE (field) == TYPE_DECL
                        && DECL_NAME (field) == id)
                      {
                    if (TREE_CODE (field) == TYPE_DECL
                        && DECL_NAME (field) == id)
                      {
-                       inform ("(perhaps %<typename %T::%E%> was intended)",
+                       inform (location, 
+                               "(perhaps %<typename %T::%E%> was intended)",
                                BINFO_TYPE (b), id);
                        break;
                      }
                                BINFO_TYPE (b), id);
                        break;
                      }
@@ -2114,10 +2378,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
   else if (parser->scope != error_mark_node)
     {
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
   else if (parser->scope != error_mark_node)
     {
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-       error ("%qE in namespace %qE does not name a type",
-              id, parser->scope);
+       error ("%H%qE in namespace %qE does not name a type",
+              &location, id, parser->scope);
       else if (TYPE_P (parser->scope))
       else if (TYPE_P (parser->scope))
-       error ("%qE in class %qT does not name a type", id, parser->scope);
+       error ("%H%qE in class %qT does not name a type",
+               &location, id, parser->scope);
       else
        gcc_unreachable ();
     }
       else
        gcc_unreachable ();
     }
@@ -2138,6 +2403,7 @@ static bool
 cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
 {
   tree id;
 cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
 {
   tree id;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   cp_parser_parse_tentatively (parser);
   id = cp_parser_id_expression (parser,
 
   cp_parser_parse_tentatively (parser);
   id = cp_parser_id_expression (parser,
@@ -2151,17 +2417,18 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
      the scope is dependent, we cannot do much.  */
   if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
       || (parser->scope && TYPE_P (parser->scope)
      the scope is dependent, we cannot do much.  */
   if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
       || (parser->scope && TYPE_P (parser->scope)
-         && dependent_type_p (parser->scope)))
+         && dependent_type_p (parser->scope))
+      || TREE_CODE (id) == TYPE_DECL)
     {
       cp_parser_abort_tentative_parse (parser);
       return false;
     }
     {
       cp_parser_abort_tentative_parse (parser);
       return false;
     }
-  if (!cp_parser_parse_definitely (parser)
-      || TREE_CODE (id) != IDENTIFIER_NODE)
+  if (!cp_parser_parse_definitely (parser))
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
-  cp_parser_diagnose_invalid_type_name (parser, parser->scope, id);
+  cp_parser_diagnose_invalid_type_name (parser, parser->scope,
+                                       id, token->location);
   /* Skip to the end of the declaration; there's no point in
      trying to process it.  */
   cp_parser_skip_to_end_of_block_or_statement (parser);
   /* Skip to the end of the declaration; there's no point in
      trying to process it.  */
   cp_parser_skip_to_end_of_block_or_statement (parser);
@@ -2314,7 +2581,7 @@ static void
 cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
 {
   /* Look for the trailing `;'.  */
 cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
 {
   /* Look for the trailing `;'.  */
-  if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
+  if (!cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"))
     {
       /* If there is additional (erroneous) input, skip to the end of
         the statement.  */
     {
       /* If there is additional (erroneous) input, skip to the end of
         the statement.  */
@@ -2373,9 +2640,10 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
 }
 
 /* Skip tokens until a non-nested closing curly brace is the next
 }
 
 /* Skip tokens until a non-nested closing curly brace is the next
-   token.  */
+   token, or there are no more tokens. Return true in the first case,
+   false otherwise.  */
 
 
-static void
+static bool
 cp_parser_skip_to_closing_brace (cp_parser *parser)
 {
   unsigned nesting_depth = 0;
 cp_parser_skip_to_closing_brace (cp_parser *parser)
 {
   unsigned nesting_depth = 0;
@@ -2389,13 +2657,13 @@ cp_parser_skip_to_closing_brace (cp_parser *parser)
        case CPP_EOF:
        case CPP_PRAGMA_EOL:
          /* If we've run out of tokens, stop.  */
        case CPP_EOF:
        case CPP_PRAGMA_EOL:
          /* If we've run out of tokens, stop.  */
-         return;
+         return false;
 
        case CPP_CLOSE_BRACE:
          /* If the next token is a non-nested `}', then we have reached
             the end of the current block.  */
          if (nesting_depth-- == 0)
 
        case CPP_CLOSE_BRACE:
          /* If the next token is a non-nested `}', then we have reached
             the end of the current block.  */
          if (nesting_depth-- == 0)
-           return;
+           return true;
          break;
 
        case CPP_OPEN_BRACE:
          break;
 
        case CPP_OPEN_BRACE:
@@ -2448,7 +2716,8 @@ cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok)
    using cp_parser_diagnose_invalid_type_name.  */
 
 static tree
    using cp_parser_diagnose_invalid_type_name.  */
 
 static tree
-cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
+cp_parser_make_typename_type (cp_parser *parser, tree scope,
+                             tree id, location_t id_location)
 {
   tree result;
   if (TREE_CODE (id) == IDENTIFIER_NODE)
 {
   tree result;
   if (TREE_CODE (id) == IDENTIFIER_NODE)
@@ -2456,12 +2725,36 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
       result = make_typename_type (scope, id, typename_type,
                                   /*complain=*/tf_none);
       if (result == error_mark_node)
       result = make_typename_type (scope, id, typename_type,
                                   /*complain=*/tf_none);
       if (result == error_mark_node)
-       cp_parser_diagnose_invalid_type_name (parser, scope, id);
+       cp_parser_diagnose_invalid_type_name (parser, scope, id, id_location);
       return result;
     }
   return make_typename_type (scope, id, typename_type, tf_error);
 }
 
       return result;
     }
   return make_typename_type (scope, id, typename_type, tf_error);
 }
 
+/* This is a wrapper around the
+   make_{pointer,ptrmem,reference}_declarator functions that decides
+   which one to call based on the CODE and CLASS_TYPE arguments. The
+   CODE argument should be one of the values returned by
+   cp_parser_ptr_operator. */
+static cp_declarator *
+cp_parser_make_indirect_declarator (enum tree_code code, tree class_type,
+                                   cp_cv_quals cv_qualifiers,
+                                   cp_declarator *target)
+{
+  if (code == ERROR_MARK)
+    return cp_error_declarator;
+
+  if (code == INDIRECT_REF)
+    if (class_type == NULL_TREE)
+      return make_pointer_declarator (cv_qualifiers, target);
+    else
+      return make_ptrmem_declarator (cv_qualifiers, class_type, target);
+  else if (code == ADDR_EXPR && class_type == NULL_TREE)
+    return make_reference_declarator (cv_qualifiers, target, false);
+  else if (code == NON_LVALUE_EXPR && class_type == NULL_TREE)
+    return make_reference_declarator (cv_qualifiers, target, true);
+  gcc_unreachable ();
+}
 
 /* Create a new C++ parser.  */
 
 
 /* Create a new C++ parser.  */
 
@@ -2526,6 +2819,9 @@ cp_parser_new (void)
   /* String literals should be translated to the execution character set.  */
   parser->translate_strings_p = true;
 
   /* String literals should be translated to the execution character set.  */
   parser->translate_strings_p = true;
 
+  /* We are not parsing a function body.  */
+  parser->in_function_body = false;
+
   /* The unparsed function queue is empty.  */
   parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
 
   /* The unparsed function queue is empty.  */
   parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
 
@@ -2581,7 +2877,7 @@ cp_parser_identifier (cp_parser* parser)
   /* Look for the identifier.  */
   token = cp_parser_require (parser, CPP_NAME, "identifier");
   /* Return the value.  */
   /* Look for the identifier.  */
   token = cp_parser_require (parser, CPP_NAME, "identifier");
   /* Return the value.  */
-  return token ? token->value : error_mark_node;
+  return token ? token->u.value : error_mark_node;
 }
 
 /* Parse a sequence of adjacent string constants.  Returns a
 }
 
 /* Parse a sequence of adjacent string constants.  Returns a
@@ -2602,11 +2898,11 @@ static tree
 cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
 {
   tree value;
 cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
 {
   tree value;
-  bool wide = false;
   size_t count;
   struct obstack str_ob;
   cpp_string str, istr, *strs;
   cp_token *tok;
   size_t count;
   struct obstack str_ob;
   cpp_string str, istr, *strs;
   cp_token *tok;
+  enum cpp_ttype type;
 
   tok = cp_lexer_peek_token (parser->lexer);
   if (!cp_parser_is_string_literal (tok))
 
   tok = cp_lexer_peek_token (parser->lexer);
   if (!cp_parser_is_string_literal (tok))
@@ -2615,6 +2911,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
+  type = tok->type;
+
   /* Try to avoid the overhead of creating and destroying an obstack
      for the common case of just one string.  */
   if (!cp_parser_is_string_literal
   /* Try to avoid the overhead of creating and destroying an obstack
      for the common case of just one string.  */
   if (!cp_parser_is_string_literal
@@ -2622,11 +2920,9 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
     {
       cp_lexer_consume_token (parser->lexer);
 
     {
       cp_lexer_consume_token (parser->lexer);
 
-      str.text = (const unsigned char *)TREE_STRING_POINTER (tok->value);
-      str.len = TREE_STRING_LENGTH (tok->value);
+      str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
+      str.len = TREE_STRING_LENGTH (tok->u.value);
       count = 1;
       count = 1;
-      if (tok->type == CPP_WSTRING)
-       wide = true;
 
       strs = &str;
     }
 
       strs = &str;
     }
@@ -2639,10 +2935,17 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
        {
          cp_lexer_consume_token (parser->lexer);
          count++;
        {
          cp_lexer_consume_token (parser->lexer);
          count++;
-         str.text = (unsigned char *)TREE_STRING_POINTER (tok->value);
-         str.len = TREE_STRING_LENGTH (tok->value);
-         if (tok->type == CPP_WSTRING)
-           wide = true;
+         str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
+         str.len = TREE_STRING_LENGTH (tok->u.value);
+
+         if (type != tok->type)
+           {
+             if (type == CPP_STRING)
+               type = tok->type;
+             else if (tok->type != CPP_STRING)
+               error ("%Hunsupported non-standard concatenation "
+                       "of string literals", &tok->location);
+           }
 
          obstack_grow (&str_ob, &str, sizeof (cpp_string));
 
 
          obstack_grow (&str_ob, &str, sizeof (cpp_string));
 
@@ -2653,19 +2956,35 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
       strs = (cpp_string *) obstack_finish (&str_ob);
     }
 
       strs = (cpp_string *) obstack_finish (&str_ob);
     }
 
-  if (wide && !wide_ok)
+  if (type != CPP_STRING && !wide_ok)
     {
       cp_parser_error (parser, "a wide string is invalid in this context");
     {
       cp_parser_error (parser, "a wide string is invalid in this context");
-      wide = false;
+      type = CPP_STRING;
     }
 
   if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
     }
 
   if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
-      (parse_in, strs, count, &istr, wide))
+      (parse_in, strs, count, &istr, type))
     {
     {
-      value = build_string (istr.len, (char *)istr.text);
-      free ((void *)istr.text);
+      value = build_string (istr.len, (const char *)istr.text);
+      free (CONST_CAST (unsigned char *, istr.text));
+
+      switch (type)
+       {
+       default:
+       case CPP_STRING:
+         TREE_TYPE (value) = char_array_type_node;
+         break;
+       case CPP_STRING16:
+         TREE_TYPE (value) = char16_array_type_node;
+         break;
+       case CPP_STRING32:
+         TREE_TYPE (value) = char32_array_type_node;
+         break;
+       case CPP_WSTRING:
+         TREE_TYPE (value) = wchar_array_type_node;
+         break;
+       }
 
 
-      TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
       value = fix_string_type (value);
     }
   else
       value = fix_string_type (value);
     }
   else
@@ -2762,6 +3081,25 @@ cp_parser_translation_unit (cp_parser* parser)
      __builtin_va_arg ( assignment-expression , type-id )
      __builtin_offsetof ( type-id , offsetof-expression )
 
      __builtin_va_arg ( assignment-expression , type-id )
      __builtin_offsetof ( type-id , offsetof-expression )
 
+   C++ Extensions:
+     __has_nothrow_assign ( type-id )   
+     __has_nothrow_constructor ( type-id )
+     __has_nothrow_copy ( type-id )
+     __has_trivial_assign ( type-id )   
+     __has_trivial_constructor ( type-id )
+     __has_trivial_copy ( type-id )
+     __has_trivial_destructor ( type-id )
+     __has_virtual_destructor ( type-id )     
+     __is_abstract ( type-id )
+     __is_base_of ( type-id , type-id )
+     __is_class ( type-id )
+     __is_convertible_to ( type-id , type-id )     
+     __is_empty ( type-id )
+     __is_enum ( type-id )
+     __is_pod ( type-id )
+     __is_polymorphic ( type-id )
+     __is_union ( type-id )
+
    Objective-C++ Extension:
 
    primary-expression:
    Objective-C++ Extension:
 
    primary-expression:
@@ -2785,7 +3123,7 @@ cp_parser_primary_expression (cp_parser *parser,
                              bool template_arg_p,
                              cp_id_kind *idk)
 {
                              bool template_arg_p,
                              cp_id_kind *idk)
 {
-  cp_token *token;
+  cp_token *token = NULL;
 
   /* Assume the primary expression is not an id-expression.  */
   *idk = CP_ID_KIND_NONE;
 
   /* Assume the primary expression is not an id-expression.  */
   *idk = CP_ID_KIND_NONE;
@@ -2801,13 +3139,15 @@ cp_parser_primary_expression (cp_parser *parser,
           string-literal
           boolean-literal  */
     case CPP_CHAR:
           string-literal
           boolean-literal  */
     case CPP_CHAR:
+    case CPP_CHAR16:
+    case CPP_CHAR32:
     case CPP_WCHAR:
     case CPP_NUMBER:
       token = cp_lexer_consume_token (parser->lexer);
       /* Floating-point literals are only allowed in an integral
         constant expression if they are cast to an integral or
         enumeration type.  */
     case CPP_WCHAR:
     case CPP_NUMBER:
       token = cp_lexer_consume_token (parser->lexer);
       /* Floating-point literals are only allowed in an integral
         constant expression if they are cast to an integral or
         enumeration type.  */
-      if (TREE_CODE (token->value) == REAL_CST
+      if (TREE_CODE (token->u.value) == REAL_CST
          && parser->integral_constant_expression_p
          && pedantic)
        {
          && parser->integral_constant_expression_p
          && pedantic)
        {
@@ -2832,6 +3172,11 @@ cp_parser_primary_expression (cp_parser *parser,
                  && next_token->type != CPP_CLOSE_SQUARE
                  /* The closing ">" in a template-argument-list.  */
                  && (next_token->type != CPP_GREATER
                  && next_token->type != CPP_CLOSE_SQUARE
                  /* The closing ">" in a template-argument-list.  */
                  && (next_token->type != CPP_GREATER
+                     || parser->greater_than_is_operator_p)
+                 /* C++0x only: A ">>" treated like two ">" tokens,
+                     in a template-argument-list.  */
+                 && (next_token->type != CPP_RSHIFT
+                      || (cxx_dialect == cxx98)
                      || parser->greater_than_is_operator_p))
                cast_p = false;
            }
                      || parser->greater_than_is_operator_p))
                cast_p = false;
            }
@@ -2844,9 +3189,11 @@ cp_parser_primary_expression (cp_parser *parser,
            cp_parser_non_integral_constant_expression
              (parser, "floating-point literal");
        }
            cp_parser_non_integral_constant_expression
              (parser, "floating-point literal");
        }
-      return token->value;
+      return token->u.value;
 
     case CPP_STRING:
 
     case CPP_STRING:
+    case CPP_STRING16:
+    case CPP_STRING32:
     case CPP_WSTRING:
       /* ??? Should wide strings be allowed when parser->translate_strings_p
         is false (i.e. in attributes)?  If not, we can kill the third
     case CPP_WSTRING:
       /* ??? Should wide strings be allowed when parser->translate_strings_p
         is false (i.e. in attributes)?  If not, we can kill the third
@@ -2873,8 +3220,8 @@ cp_parser_primary_expression (cp_parser *parser,
            && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
          {
            /* Statement-expressions are not allowed by the standard.  */
            && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
          {
            /* Statement-expressions are not allowed by the standard.  */
-           if (pedantic)
-             pedwarn ("ISO C++ forbids braced-groups within expressions");
+           pedwarn (token->location, OPT_pedantic, 
+                    "ISO C++ forbids braced-groups within expressions");
 
            /* And they're not allowed outside of a function-body; you
               cannot, for example, write:
 
            /* And they're not allowed outside of a function-body; you
               cannot, for example, write:
@@ -2882,14 +3229,24 @@ cp_parser_primary_expression (cp_parser *parser,
                 int i = ({ int j = 3; j + 1; });
 
               at class or namespace scope.  */
                 int i = ({ int j = 3; j + 1; });
 
               at class or namespace scope.  */
-           if (!at_function_scope_p ())
-             error ("statement-expressions are allowed only inside functions");
-           /* Start the statement-expression.  */
-           expr = begin_stmt_expr ();
-           /* Parse the compound-statement.  */
-           cp_parser_compound_statement (parser, expr, false);
-           /* Finish up.  */
-           expr = finish_stmt_expr (expr, false);
+           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);
+               cp_parser_skip_to_end_of_block_or_statement (parser);
+               expr = error_mark_node;
+             }
+           else
+             {
+               /* Start the statement-expression.  */
+               expr = begin_stmt_expr ();
+               /* Parse the compound-statement.  */
+               cp_parser_compound_statement (parser, expr, false);
+               /* Finish up.  */
+               expr = finish_stmt_expr (expr, false);
+             }
          }
        else
          {
          }
        else
          {
@@ -2907,7 +3264,7 @@ cp_parser_primary_expression (cp_parser *parser,
        parser->greater_than_is_operator_p
          = saved_greater_than_is_operator_p;
        /* Consume the `)'.  */
        parser->greater_than_is_operator_p
          = saved_greater_than_is_operator_p;
        /* Consume the `)'.  */
-       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
          cp_parser_skip_to_end_of_statement (parser);
 
        return expr;
          cp_parser_skip_to_end_of_statement (parser);
 
        return expr;
@@ -2934,12 +3291,12 @@ cp_parser_primary_expression (cp_parser *parser,
          cp_lexer_consume_token (parser->lexer);
          if (parser->local_variables_forbidden_p)
            {
          cp_lexer_consume_token (parser->lexer);
          if (parser->local_variables_forbidden_p)
            {
-             error ("%<this%> may not be used in this context");
+             error ("%H%<this%> may not be used in this context",
+                     &token->location);
              return error_mark_node;
            }
          /* Pointers cannot appear in constant-expressions.  */
              return error_mark_node;
            }
          /* Pointers cannot appear in constant-expressions.  */
-         if (cp_parser_non_integral_constant_expression (parser,
-                                                         "`this'"))
+         if (cp_parser_non_integral_constant_expression (parser, "%<this%>"))
            return error_mark_node;
          return finish_this_expr ();
 
            return error_mark_node;
          return finish_this_expr ();
 
@@ -2951,16 +3308,39 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_FUNCTION_NAME:
        case RID_PRETTY_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
        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->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:
          {
 
        case RID_VA_ARG:
          {
@@ -2971,20 +3351,20 @@ cp_parser_primary_expression (cp_parser *parser,
               `va_arg'.  Consume the `__builtin_va_arg' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Look for the opening `('.  */
               `va_arg'.  Consume the `__builtin_va_arg' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Look for the opening `('.  */
-           cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+           cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
            /* Now, parse the assignment-expression.  */
            expression = cp_parser_assignment_expression (parser,
                                                          /*cast_p=*/false);
            /* Look for the `,'.  */
            /* Now, parse the assignment-expression.  */
            expression = cp_parser_assignment_expression (parser,
                                                          /*cast_p=*/false);
            /* Look for the `,'.  */
-           cp_parser_require (parser, CPP_COMMA, "`,'");
+           cp_parser_require (parser, CPP_COMMA, "%<,%>");
            /* Parse the type-id.  */
            type = cp_parser_type_id (parser);
            /* Look for the closing `)'.  */
            /* Parse the type-id.  */
            type = cp_parser_type_id (parser);
            /* Look for the closing `)'.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
            /* Using `va_arg' in a constant-expression is not
               allowed.  */
            if (cp_parser_non_integral_constant_expression (parser,
            /* Using `va_arg' in a constant-expression is not
               allowed.  */
            if (cp_parser_non_integral_constant_expression (parser,
-                                                           "`va_arg'"))
+                                                           "%<va_arg%>"))
              return error_mark_node;
            return build_x_va_arg (expression, type);
          }
              return error_mark_node;
            return build_x_va_arg (expression, type);
          }
@@ -2992,7 +3372,26 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_OFFSETOF:
          return cp_parser_builtin_offsetof (parser);
 
        case RID_OFFSETOF:
          return cp_parser_builtin_offsetof (parser);
 
-         /* Objective-C++ expressions.  */
+       case RID_HAS_NOTHROW_ASSIGN:
+       case RID_HAS_NOTHROW_CONSTRUCTOR:
+       case RID_HAS_NOTHROW_COPY:        
+       case RID_HAS_TRIVIAL_ASSIGN:
+       case RID_HAS_TRIVIAL_CONSTRUCTOR:
+       case RID_HAS_TRIVIAL_COPY:        
+       case RID_HAS_TRIVIAL_DESTRUCTOR:
+       case RID_HAS_VIRTUAL_DESTRUCTOR:
+       case RID_IS_ABSTRACT:
+       case RID_IS_BASE_OF:
+       case RID_IS_CLASS:
+       case RID_IS_CONVERTIBLE_TO:
+       case RID_IS_EMPTY:
+       case RID_IS_ENUM:
+       case RID_IS_POD:
+       case RID_IS_POLYMORPHIC:
+       case RID_IS_UNION:
+         return cp_parser_trait_expr (parser, token->keyword);
+
+       /* Objective-C++ expressions.  */
        case RID_AT_ENCODE:
        case RID_AT_PROTOCOL:
        case RID_AT_SELECTOR:
        case RID_AT_ENCODE:
        case RID_AT_PROTOCOL:
        case RID_AT_SELECTOR:
@@ -3016,6 +3415,7 @@ cp_parser_primary_expression (cp_parser *parser,
        const char *error_msg;
        bool template_p;
        bool done;
        const char *error_msg;
        bool template_p;
        bool done;
+       cp_token *id_expr_token;
 
       id_expression:
        /* Parse the id-expression.  */
 
       id_expression:
        /* Parse the id-expression.  */
@@ -3028,6 +3428,7 @@ cp_parser_primary_expression (cp_parser *parser,
                                     /*optional_p=*/false);
        if (id_expression == error_mark_node)
          return error_mark_node;
                                     /*optional_p=*/false);
        if (id_expression == error_mark_node)
          return error_mark_node;
+       id_expr_token = token;
        token = cp_lexer_peek_token (parser->lexer);
        done = (token->type != CPP_OPEN_SQUARE
                && token->type != CPP_OPEN_PAREN
        token = cp_lexer_peek_token (parser->lexer);
        done = (token->type != CPP_OPEN_SQUARE
                && token->type != CPP_OPEN_PAREN
@@ -3051,7 +3452,8 @@ cp_parser_primary_expression (cp_parser *parser,
                                          template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
                                          template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
-                                         &ambiguous_decls);
+                                         &ambiguous_decls,
+                                         id_expr_token->location);
            /* If the lookup was ambiguous, an error will already have
               been issued.  */
            if (ambiguous_decls)
            /* If the lookup was ambiguous, an error will already have
               been issued.  */
            if (ambiguous_decls)
@@ -3064,7 +3466,19 @@ cp_parser_primary_expression (cp_parser *parser,
            /* If name lookup gives us a SCOPE_REF, then the
               qualifying scope was dependent.  */
            if (TREE_CODE (decl) == SCOPE_REF)
            /* If name lookup gives us a SCOPE_REF, then the
               qualifying scope was dependent.  */
            if (TREE_CODE (decl) == SCOPE_REF)
-             return decl;
+             {
+               /* At this point, we do not know if DECL is a valid
+                  integral constant expression.  We assume that it is
+                  in fact such an expression, so that code like:
+
+                     template <int N> struct A {
+                       int a[B<N>::i];
+                     };
+                    
+                  is accepted.  At template-instantiation time, we
+                  will check that B<N>::i is actually a constant.  */
+               return decl;
+             }
            /* Check to see if DECL is a local variable in a context
               where that is forbidden.  */
            if (parser->local_variables_forbidden_p
            /* Check to see if DECL is a local variable in a context
               where that is forbidden.  */
            if (parser->local_variables_forbidden_p
@@ -3086,8 +3500,8 @@ cp_parser_primary_expression (cp_parser *parser,
                decl = check_for_out_of_scope_variable (decl);
                if (local_variable_p (decl))
                  {
                decl = check_for_out_of_scope_variable (decl);
                if (local_variable_p (decl))
                  {
-                   error ("local variable %qD may not appear in this context",
-                          decl);
+                   error ("%Hlocal variable %qD may not appear in this context",
+                          &id_expr_token->location, decl);
                    return error_mark_node;
                  }
              }
                    return error_mark_node;
                  }
              }
@@ -3101,7 +3515,8 @@ cp_parser_primary_expression (cp_parser *parser,
                 &parser->non_integral_constant_expression_p,
                 template_p, done, address_p,
                 template_arg_p,
                 &parser->non_integral_constant_expression_p,
                 template_p, done, address_p,
                 template_arg_p,
-                &error_msg));
+                &error_msg,
+                 id_expr_token->location));
        if (error_msg)
          cp_parser_error (parser, error_msg);
        return decl;
        if (error_msg)
          cp_parser_error (parser, error_msg);
        return decl;
@@ -3109,9 +3524,11 @@ cp_parser_primary_expression (cp_parser *parser,
 
       /* Anything else is an error.  */
     default:
 
       /* Anything else is an error.  */
     default:
-      /* ...unless we have an Objective-C++ message or string literal, that is.  */
+      /* ...unless we have an Objective-C++ message or string literal,
+         that is.  */
       if (c_dialect_objc ()
       if (c_dialect_objc ()
-         && (token->type == CPP_OPEN_SQUARE || token->type == CPP_OBJC_STRING))
+         && (token->type == CPP_OPEN_SQUARE
+              || token->type == CPP_OBJC_STRING))
        return cp_parser_objc_expression (parser);
 
       cp_parser_error (parser, "expected primary-expression");
        return cp_parser_objc_expression (parser);
 
       cp_parser_error (parser, "expected primary-expression");
@@ -3373,13 +3790,32 @@ cp_parser_unqualified_id (cp_parser* parser,
        object_scope = parser->object_scope;
        qualifying_scope = parser->qualifying_scope;
 
        object_scope = parser->object_scope;
        qualifying_scope = parser->qualifying_scope;
 
+       /* Check for invalid scopes.  */
+       if (scope == error_mark_node)
+         {
+           if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+             cp_lexer_consume_token (parser->lexer);
+           return error_mark_node;
+         }
+       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);
+           cp_parser_simulate_error (parser);
+           if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+             cp_lexer_consume_token (parser->lexer);
+           return error_mark_node;
+         }
+       gcc_assert (!scope || TYPE_P (scope));
+
        /* If the name is of the form "X::~X" it's OK.  */
        token = cp_lexer_peek_token (parser->lexer);
        /* If the name is of the form "X::~X" it's OK.  */
        token = cp_lexer_peek_token (parser->lexer);
-       if (scope && TYPE_P (scope)
+       if (scope
            && token->type == CPP_NAME
            && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
                == CPP_OPEN_PAREN)
            && token->type == CPP_NAME
            && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
                == CPP_OPEN_PAREN)
-           && constructor_name_p (token->value, scope))
+           && constructor_name_p (token->u.value, scope))
          {
            cp_lexer_consume_token (parser->lexer);
            return build_nt (BIT_NOT_EXPR, scope);
          {
            cp_lexer_consume_token (parser->lexer);
            return build_nt (BIT_NOT_EXPR, scope);
@@ -3457,7 +3893,7 @@ cp_parser_unqualified_id (cp_parser* parser,
           destructor is the same as the name of the qualifying
           class.  That allows us to keep parsing after running
           into ill-formed destructor names.  */
           destructor is the same as the name of the qualifying
           class.  That allows us to keep parsing after running
           into ill-formed destructor names.  */
-       if (type_decl == error_mark_node && scope && TYPE_P (scope))
+       if (type_decl == error_mark_node && scope)
          return build_nt (BIT_NOT_EXPR, scope);
        else if (type_decl == error_mark_node)
          return error_mark_node;
          return build_nt (BIT_NOT_EXPR, scope);
        else if (type_decl == error_mark_node)
          return error_mark_node;
@@ -3466,8 +3902,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))
        if (declarator_p && scope && !check_dtor_name (scope, type_decl))
          {
            if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-             error ("declaration of %<~%T%> as member of %qT",
-                    type_decl, scope);
+             error ("%Hdeclaration of %<~%T%> as member of %qT",
+                    &token->location, type_decl, scope);
+           cp_parser_simulate_error (parser);
            return error_mark_node;
          }
 
            return error_mark_node;
          }
 
@@ -3479,8 +3916,8 @@ cp_parser_unqualified_id (cp_parser* parser,
            && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
            && !DECL_SELF_REFERENCE_P (type_decl)
            && !cp_parser_uncommitted_to_tentative_parse_p (parser))
            && !DECL_IMPLICIT_TYPEDEF_P (type_decl)
            && !DECL_SELF_REFERENCE_P (type_decl)
            && !cp_parser_uncommitted_to_tentative_parse_p (parser))
-         error ("typedef-name %qD used as destructor declarator",
-                type_decl);
+         error ("%Htypedef-name %qD used as destructor declarator",
+                &token->location, type_decl);
 
        return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
 
        return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
       }
@@ -3522,10 +3959,16 @@ cp_parser_unqualified_id (cp_parser* parser,
 
 /* Parse an (optional) nested-name-specifier.
 
 
 /* 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]
 
      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
    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
@@ -3574,6 +4017,17 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
        {
          /* Grab the nested-name-specifier and continue the loop.  */
          cp_parser_pre_parsed_nested_name_specifier (parser);
        {
          /* Grab the nested-name-specifier and continue the loop.  */
          cp_parser_pre_parsed_nested_name_specifier (parser);
+         /* If we originally encountered this nested-name-specifier
+            with IS_DECLARATION set to false, we will not have
+            resolved TYPENAME_TYPEs, so we must do so here.  */
+         if (is_declaration
+             && TREE_CODE (parser->scope) == TYPENAME_TYPE)
+           {
+             new_scope = resolve_typename_type (parser->scope,
+                                                /*only_current_p=*/false);
+             if (TREE_CODE (new_scope) != TYPENAME_TYPE)
+               parser->scope = new_scope;
+           }
          success = true;
          continue;
        }
          success = true;
          continue;
        }
@@ -3589,7 +4043,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
       else
        {
          /* If the next token is not an identifier, then it is
       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
          if (token->type != CPP_NAME)
            break;
          /* If the following token is neither a `<' (to begin a
@@ -3629,14 +4083,14 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                                               /*only_current_p=*/false);
       /* Parse the qualifying entity.  */
       new_scope
                                               /*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.  */
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "`::'");
+      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
 
       /* If we found what we wanted, we keep going; otherwise, we're
         done.  */
 
       /* If we found what we wanted, we keep going; otherwise, we're
         done.  */
@@ -3668,25 +4122,32 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                      tree decl;
                      tree ambiguous_decls;
 
                      tree decl;
                      tree ambiguous_decls;
 
-                     decl = cp_parser_lookup_name (parser, token->value,
+                     decl = cp_parser_lookup_name (parser, token->u.value,
                                                    none_type,
                                                    /*is_template=*/false,
                                                    /*is_namespace=*/false,
                                                    /*check_dependency=*/true,
                                                    none_type,
                                                    /*is_template=*/false,
                                                    /*is_namespace=*/false,
                                                    /*check_dependency=*/true,
-                                                   &ambiguous_decls);
+                                                   &ambiguous_decls,
+                                                   token->location);
                      if (TREE_CODE (decl) == TEMPLATE_DECL)
                      if (TREE_CODE (decl) == TEMPLATE_DECL)
-                       error ("%qD used without template parameters", decl);
+                       error ("%H%qD used without template parameters",
+                              &token->location, decl);
                      else if (ambiguous_decls)
                        {
                      else if (ambiguous_decls)
                        {
-                         error ("reference to %qD is ambiguous",
-                                token->value);
+                         error ("%Hreference to %qD is ambiguous",
+                                &token->location, token->u.value);
                          print_candidates (ambiguous_decls);
                          decl = error_mark_node;
                        }
                      else
                          print_candidates (ambiguous_decls);
                          decl = error_mark_node;
                        }
                      else
-                       cp_parser_name_lookup_error
-                         (parser, token->value, decl,
-                          "is not a class or namespace");
+                        {
+                          const char* msg = "is not a class or namespace";
+                          if (cxx_dialect != cxx98)
+                            msg = "is not a class, namespace, or enumeration";
+                          cp_parser_name_lookup_error
+                            (parser, token->u.value, decl, msg,
+                            token->location);
+                        }
                    }
                  parser->scope = error_mark_node;
                  error_p = true;
                    }
                  parser->scope = error_mark_node;
                  error_p = true;
@@ -3718,10 +4179,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
          && !(TREE_CODE (new_scope) == TYPENAME_TYPE
               && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
                   == TEMPLATE_ID_EXPR)))
          && !(TREE_CODE (new_scope) == TYPENAME_TYPE
               && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
                   == TEMPLATE_ID_EXPR)))
-       pedwarn (TYPE_P (new_scope)
-                ? "%qT is not a template"
-                : "%qD is not a template",
-                new_scope);
+       permerror (input_location, TYPE_P (new_scope)
+                  ? "%qT is not a template"
+                  : "%qD is not a template",
+                  new_scope);
       /* If it is a class scope, try to complete it; we are about to
         be looking up names inside the class.  */
       if (TYPE_P (new_scope)
       /* If it is a class scope, try to complete it; we are about to
         be looking up names inside the class.  */
       if (TYPE_P (new_scope)
@@ -3730,7 +4191,15 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
          && !COMPLETE_TYPE_P (new_scope)
          /* Do not try to complete dependent types.  */
          && !dependent_type_p (new_scope))
          && !COMPLETE_TYPE_P (new_scope)
          /* Do not try to complete dependent types.  */
          && !dependent_type_p (new_scope))
-       new_scope = complete_type (new_scope);
+       {
+         new_scope = complete_type (new_scope);
+         /* If it is a typedef to current class, use the current
+            class instead, as the typedef won't have any names inside
+            it yet.  */
+         if (!COMPLETE_TYPE_P (new_scope)
+             && currently_open_class (new_scope))
+           new_scope = TYPE_MAIN_VARIANT (new_scope);
+       }
       /* Make sure we look in the right scope the next time through
         the loop.  */
       parser->scope = new_scope;
       /* Make sure we look in the right scope the next time through
         the loop.  */
       parser->scope = new_scope;
@@ -3744,17 +4213,17 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
   if (success && start)
     {
       cp_token *token;
   if (success && start)
     {
       cp_token *token;
-      tree access_checks;
 
       token = cp_lexer_token_at (parser->lexer, start);
       /* Reset the contents of the START token.  */
       token->type = CPP_NESTED_NAME_SPECIFIER;
       /* Retrieve any deferred checks.  Do not pop this access checks yet
         so the memory will not be reclaimed during token replacing below.  */
 
       token = cp_lexer_token_at (parser->lexer, start);
       /* Reset the contents of the START token.  */
       token->type = CPP_NESTED_NAME_SPECIFIER;
       /* Retrieve any deferred checks.  Do not pop this access checks yet
         so the memory will not be reclaimed during token replacing below.  */
-      access_checks = get_deferred_access_checks ();
-      token->value = build_tree_list (copy_list (access_checks),
-                                     parser->scope);
-      TREE_TYPE (token->value) = parser->qualifying_scope;
+      token->u.tree_check_value = GGC_CNEW (struct tree_check);
+      token->u.tree_check_value->value = parser->scope;
+      token->u.tree_check_value->checks = get_deferred_access_checks ();
+      token->u.tree_check_value->qualifying_scope =
+       parser->qualifying_scope;
       token->keyword = RID_MAX;
 
       /* Purge all subsequent tokens.  */
       token->keyword = RID_MAX;
 
       /* Purge all subsequent tokens.  */
@@ -3797,11 +4266,11 @@ cp_parser_nested_name_specifier (cp_parser *parser,
   return scope;
 }
 
   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.
 
    TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect.
    TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect.
@@ -3815,18 +4284,19 @@ cp_parser_nested_name_specifier (cp_parser *parser,
    ERROR_MARK_NODE is returned.  */
 
 static tree
    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;
 {
   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
 
   /* Before we try to parse the class-name, we must save away the
      current PARSER->SCOPE since cp_parser_class_name will destroy
@@ -3836,7 +4306,8 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
   saved_object_scope = parser->object_scope;
   /* Try for a class-name first.  If the SAVED_SCOPE is a type, then
      there is no need to look for a namespace-name.  */
   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,
   if (!only_class_p)
     cp_parser_parse_tentatively (parser);
   scope = cp_parser_class_name (parser,
@@ -3846,8 +4317,26 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
                                check_dependency_p,
                                /*class_head_p=*/false,
                                is_declaration);
                                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 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;
     {
       /* Restore the saved scope.  */
       parser->scope = saved_scope;
@@ -3903,15 +4392,20 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
    `&' operator.  CAST_P is true if this expression is the target of a
    cast.
 
    `&' operator.  CAST_P is true if this expression is the target of a
    cast.
 
+   If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are
+   class member access expressions [expr.ref].
+
    Returns a representation of the expression.  */
 
 static tree
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
+                              bool member_access_only_p)
 {
   cp_token *token;
   enum rid keyword;
   cp_id_kind idk = CP_ID_KIND_NONE;
   tree postfix_expression = NULL_TREE;
 {
   cp_token *token;
   enum rid keyword;
   cp_id_kind idk = CP_ID_KIND_NONE;
   tree postfix_expression = NULL_TREE;
+  bool is_member_access = false;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -3939,24 +4433,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
          = "types may not be defined in casts";
 
        /* Look for the opening `<'.  */
          = "types may not be defined in casts";
 
        /* Look for the opening `<'.  */
-       cp_parser_require (parser, CPP_LESS, "`<'");
+       cp_parser_require (parser, CPP_LESS, "%<<%>");
        /* Parse the type to which we are casting.  */
        type = cp_parser_type_id (parser);
        /* Look for the closing `>'.  */
        /* Parse the type to which we are casting.  */
        type = cp_parser_type_id (parser);
        /* Look for the closing `>'.  */
-       cp_parser_require (parser, CPP_GREATER, "`>'");
+       cp_parser_require (parser, CPP_GREATER, "%<>%>");
        /* Restore the old message.  */
        parser->type_definition_forbidden_message = saved_message;
 
        /* And the expression which is being cast.  */
        /* Restore the old message.  */
        parser->type_definition_forbidden_message = saved_message;
 
        /* And the expression which is being cast.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        expression = cp_parser_expression (parser, /*cast_p=*/true);
        expression = cp_parser_expression (parser, /*cast_p=*/true);
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
        /* Only type conversions to integral or enumeration types
           can be used in constant-expressions.  */
 
        /* Only type conversions to integral or enumeration types
           can be used in constant-expressions.  */
-       if (parser->integral_constant_expression_p
-           && !dependent_type_p (type)
-           && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+       if (!cast_valid_in_integral_constant_expression_p (type)
            && (cp_parser_non_integral_constant_expression
                (parser,
                 "a cast to a type other than an integral or "
            && (cp_parser_non_integral_constant_expression
                (parser,
                 "a cast to a type other than an integral or "
@@ -3967,19 +4459,20 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
          {
          case RID_DYNCAST:
            postfix_expression
          {
          case RID_DYNCAST:
            postfix_expression
-             = build_dynamic_cast (type, expression);
+             = build_dynamic_cast (type, expression, tf_warning_or_error);
            break;
          case RID_STATCAST:
            postfix_expression
            break;
          case RID_STATCAST:
            postfix_expression
-             = build_static_cast (type, expression);
+             = build_static_cast (type, expression, tf_warning_or_error);
            break;
          case RID_REINTCAST:
            postfix_expression
            break;
          case RID_REINTCAST:
            postfix_expression
-             = build_reinterpret_cast (type, expression);
+             = build_reinterpret_cast (type, expression, 
+                                        tf_warning_or_error);
            break;
          case RID_CONSTCAST:
            postfix_expression
            break;
          case RID_CONSTCAST:
            postfix_expression
-             = build_const_cast (type, expression);
+             = build_const_cast (type, expression, tf_warning_or_error);
            break;
          default:
            gcc_unreachable ();
            break;
          default:
            gcc_unreachable ();
@@ -3996,11 +4489,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
        /* Consume the `typeid' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Look for the `(' token.  */
        /* Consume the `typeid' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Look for the `(' token.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Types cannot be defined in a `typeid' expression.  */
        saved_message = parser->type_definition_forbidden_message;
        parser->type_definition_forbidden_message
        /* Types cannot be defined in a `typeid' expression.  */
        saved_message = parser->type_definition_forbidden_message;
        parser->type_definition_forbidden_message
-         = "types may not be defined in a `typeid\' expression";
+         = "types may not be defined in a %<typeid%> expression";
        /* We can't be sure yet whether we're looking at a type-id or an
           expression.  */
        cp_parser_parse_tentatively (parser);
        /* We can't be sure yet whether we're looking at a type-id or an
           expression.  */
        cp_parser_parse_tentatively (parser);
@@ -4012,7 +4505,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
        /* Look for the `)' token.  Otherwise, we can't be sure that
           we're not looking at an expression: consider `typeid (int
           (3))', for example.  */
        /* Look for the `)' token.  Otherwise, we can't be sure that
           we're not looking at an expression: consider `typeid (int
           (3))', for example.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
        /* If all went well, simply lookup the type-id.  */
        if (cp_parser_parse_definitely (parser))
          postfix_expression = get_typeid (type);
        /* If all went well, simply lookup the type-id.  */
        if (cp_parser_parse_definitely (parser))
          postfix_expression = get_typeid (type);
@@ -4026,14 +4519,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
            /* Compute its typeid.  */
            postfix_expression = build_typeid (expression);
            /* Look for the `)' token.  */
            /* Compute its typeid.  */
            postfix_expression = build_typeid (expression);
            /* Look for the `)' token.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
          }
          }
+       /* Restore the saved message.  */
+       parser->type_definition_forbidden_message = saved_message;
        /* `typeid' may not appear in an integral constant expression.  */
        if (cp_parser_non_integral_constant_expression(parser,
        /* `typeid' may not appear in an integral constant expression.  */
        if (cp_parser_non_integral_constant_expression(parser,
-                                                      "`typeid' operator"))
+                                                      "%<typeid%> operator"))
          return error_mark_node;
          return error_mark_node;
-       /* Restore the saved message.  */
-       parser->type_definition_forbidden_message = saved_message;
       }
       break;
 
       }
       break;
 
@@ -4087,9 +4580,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
            type = cp_parser_type_id (parser);
            parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
            /* Look for the `)'.  */
            type = cp_parser_type_id (parser);
            parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
            /* Look for the `)'.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
            /* Look for the `{'.  */
            /* Look for the `{'.  */
-           cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+           cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
            /* If things aren't going well, there's no need to
               keep going.  */
            if (!cp_parser_error_occurred (parser))
            /* If things aren't going well, there's no need to
               keep going.  */
            if (!cp_parser_error_occurred (parser))
@@ -4102,7 +4595,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
                  cp_lexer_consume_token (parser->lexer);
                /* Look for the final `}'.  */
                if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
                  cp_lexer_consume_token (parser->lexer);
                /* Look for the final `}'.  */
-               cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+               cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
              }
            /* If that worked, we're definitely looking at a
               compound-literal expression.  */
              }
            /* If that worked, we're definitely looking at a
               compound-literal expression.  */
@@ -4110,11 +4603,27 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
              {
                /* Warn the user that a compound literal is not
                   allowed in standard C++.  */
              {
                /* Warn the user that a compound literal is not
                   allowed in standard C++.  */
-               if (pedantic)
-                 pedwarn ("ISO C++ forbids compound-literals");
+               pedwarn (input_location, OPT_pedantic, "ISO C++ forbids compound-literals");
+               /* For simplicity, we disallow compound literals in
+                  constant-expressions.  We could
+                  allow compound literals of integer type, whose
+                  initializer was a constant, in constant
+                  expressions.  Permitting that usage, as a further
+                  extension, would not change the meaning of any
+                  currently accepted programs.  (Of course, as
+                  compound literals are not part of ISO C++, the
+                  standard has nothing to say.)  */
+               if (cp_parser_non_integral_constant_expression 
+                   (parser, "non-constant compound literals"))
+                 {
+                   postfix_expression = error_mark_node;
+                   break;
+                 }
                /* Form the representation of the compound-literal.  */
                postfix_expression
                /* Form the representation of the compound-literal.  */
                postfix_expression
-                 = finish_compound_literal (type, initializer_list);
+                 = (finish_compound_literal
+                    (type, build_constructor (init_list_type_node,
+                                              initializer_list)));
                break;
              }
          }
                break;
              }
          }
@@ -4149,6 +4658,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                                                        postfix_expression,
                                                        false);
          idk = CP_ID_KIND_NONE;
                                                        postfix_expression,
                                                        false);
          idk = CP_ID_KIND_NONE;
+          is_member_access = false;
          break;
 
        case CPP_OPEN_PAREN:
          break;
 
        case CPP_OPEN_PAREN:
@@ -4160,6 +4670,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
            bool saved_non_integral_constant_expression_p = false;
            tree args;
 
            bool saved_non_integral_constant_expression_p = false;
            tree args;
 
+            is_member_access = false;
+
            is_builtin_constant_p
              = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
            if (is_builtin_constant_p)
            is_builtin_constant_p
              = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
            if (is_builtin_constant_p)
@@ -4174,7 +4686,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
              }
            args = (cp_parser_parenthesized_expression_list
                    (parser, /*is_attribute_list=*/false,
              }
            args = (cp_parser_parenthesized_expression_list
                    (parser, /*is_attribute_list=*/false,
-                    /*cast_p=*/false,
+                    /*cast_p=*/false, /*allow_expansion_p=*/true,
                     /*non_constant_p=*/NULL));
            if (is_builtin_constant_p)
              {
                     /*non_constant_p=*/NULL));
            if (is_builtin_constant_p)
              {
@@ -4250,8 +4762,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                        || any_type_dependent_arguments_p (args)))
                  {
                    postfix_expression
                        || any_type_dependent_arguments_p (args)))
                  {
                    postfix_expression
-                     = build_min_nt (CALL_EXPR, postfix_expression,
-                                     args, NULL_TREE);
+                     = build_nt_call_list (postfix_expression, args);
                    break;
                  }
 
                    break;
                  }
 
@@ -4261,12 +4772,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                       (instance, fn, args, NULL_TREE,
                        (idk == CP_ID_KIND_QUALIFIED
                         ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
                       (instance, fn, args, NULL_TREE,
                        (idk == CP_ID_KIND_QUALIFIED
                         ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
-                       /*fn_p=*/NULL));
+                       /*fn_p=*/NULL,
+                       tf_warning_or_error));
                else
                  postfix_expression
                    = finish_call_expr (postfix_expression, args,
                                        /*disallow_virtual=*/false,
                else
                  postfix_expression
                    = finish_call_expr (postfix_expression, args,
                                        /*disallow_virtual=*/false,
-                                       /*koenig_p=*/false);
+                                       /*koenig_p=*/false,
+                                       tf_warning_or_error);
              }
            else if (TREE_CODE (postfix_expression) == OFFSET_REF
                     || TREE_CODE (postfix_expression) == MEMBER_REF
              }
            else if (TREE_CODE (postfix_expression) == OFFSET_REF
                     || TREE_CODE (postfix_expression) == MEMBER_REF
@@ -4279,13 +4792,18 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
              postfix_expression
                = finish_call_expr (postfix_expression, args,
                                    /*disallow_virtual=*/true,
              postfix_expression
                = finish_call_expr (postfix_expression, args,
                                    /*disallow_virtual=*/true,
-                                   koenig_p);
+                                   koenig_p,
+                                   tf_warning_or_error);
            else
              /* All other function calls.  */
              postfix_expression
                = finish_call_expr (postfix_expression, args,
                                    /*disallow_virtual=*/false,
            else
              /* All other function calls.  */
              postfix_expression
                = finish_call_expr (postfix_expression, args,
                                    /*disallow_virtual=*/false,
-                                   koenig_p);
+                                   koenig_p,
+                                   tf_warning_or_error);
+
+            if (warn_disallowed_functions)
+              warn_if_disallowed_function_p (postfix_expression);
 
            /* The POSTFIX_EXPRESSION is certainly no longer an id.  */
            idk = CP_ID_KIND_NONE;
 
            /* The POSTFIX_EXPRESSION is certainly no longer an id.  */
            idk = CP_ID_KIND_NONE;
@@ -4305,7 +4823,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
          postfix_expression
            = cp_parser_postfix_dot_deref_expression (parser, token->type,
                                                      postfix_expression,
          postfix_expression
            = cp_parser_postfix_dot_deref_expression (parser, token->type,
                                                      postfix_expression,
-                                                     false, &idk);
+                                                     false, &idk,
+                                                     token->location);
+
+          is_member_access = true;
          break;
 
        case CPP_PLUS_PLUS:
          break;
 
        case CPP_PLUS_PLUS:
@@ -4321,6 +4842,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                                                          "an increment"))
            postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
                                                          "an increment"))
            postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
+          is_member_access = false;
          break;
 
        case CPP_MINUS_MINUS:
          break;
 
        case CPP_MINUS_MINUS:
@@ -4336,10 +4858,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                                                          "a decrement"))
            postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
                                                          "a decrement"))
            postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
+          is_member_access = false;
          break;
 
        default:
          break;
 
        default:
-         return postfix_expression;
+          if (member_access_only_p)
+            return is_member_access? postfix_expression : error_mark_node;
+          else
+            return postfix_expression;
        }
     }
 
        }
     }
 
@@ -4380,7 +4906,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
     index = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* Look for the closing `]'.  */
     index = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* Look for the closing `]'.  */
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
 
   /* Build the ARRAY_REF.  */
   postfix_expression = grok_array_decl (postfix_expression, index);
 
   /* Build the ARRAY_REF.  */
   postfix_expression = grok_array_decl (postfix_expression, index);
@@ -4412,7 +4938,8 @@ static tree
 cp_parser_postfix_dot_deref_expression (cp_parser *parser,
                                        enum cpp_ttype token_type,
                                        tree postfix_expression,
 cp_parser_postfix_dot_deref_expression (cp_parser *parser,
                                        enum cpp_ttype token_type,
                                        tree postfix_expression,
-                                       bool for_offsetof, cp_id_kind *idk)
+                                       bool for_offsetof, cp_id_kind *idk,
+                                       location_t location)
 {
   tree name;
   bool dependent_p;
 {
   tree name;
   bool dependent_p;
@@ -4444,7 +4971,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
        {
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
       if (scope == unknown_type_node)
        {
-         error ("%qE does not have class type", postfix_expression);
+         error ("%H%qE does not have class type", &location, postfix_expression);
          scope = NULL_TREE;
        }
       else
          scope = NULL_TREE;
        }
       else
@@ -4468,8 +4995,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
   pseudo_destructor_p = false;
 
   /* If the SCOPE is a scalar type, then, if this is a valid program,
   pseudo_destructor_p = false;
 
   /* If the SCOPE is a scalar type, then, if this is a valid program,
-     we must be looking at a pseudo-destructor-name.  */
-  if (scope && SCALAR_TYPE_P (scope))
+     we must be looking at a pseudo-destructor-name.  If POSTFIX_EXPRESSION
+     is type dependent, it can be pseudo-destructor-name or something else.
+     Try to parse it as pseudo-destructor-name first.  */
+  if ((scope && SCALAR_TYPE_P (scope)) || dependent_p)
     {
       tree s;
       tree type;
     {
       tree s;
       tree type;
@@ -4478,7 +5007,12 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* Parse the pseudo-destructor-name.  */
       s = NULL_TREE;
       cp_parser_pseudo_destructor_name (parser, &s, &type);
       /* Parse the pseudo-destructor-name.  */
       s = NULL_TREE;
       cp_parser_pseudo_destructor_name (parser, &s, &type);
-      if (cp_parser_parse_definitely (parser))
+      if (dependent_p
+         && (cp_parser_error_occurred (parser)
+             || TREE_CODE (type) != TYPE_DECL
+             || !SCALAR_TYPE_P (TREE_TYPE (type))))
+       cp_parser_abort_tentative_parse (parser);
+      else if (cp_parser_parse_definitely (parser))
        {
          pseudo_destructor_p = true;
          postfix_expression
        {
          pseudo_destructor_p = true;
          postfix_expression
@@ -4493,6 +5027,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
         ordinary class member access expression, rather than a
         pseudo-destructor-name.  */
       bool template_p;
         ordinary class member access expression, rather than a
         pseudo-destructor-name.  */
       bool template_p;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
       /* Parse the id-expression.  */
       name = (cp_parser_id_expression
              (parser,
       /* Parse the id-expression.  */
       name = (cp_parser_id_expression
              (parser,
@@ -4520,7 +5055,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
         TYPE_DECL here.  That is invalid code.  */
       if (TREE_CODE (name) == TYPE_DECL)
        {
         TYPE_DECL here.  That is invalid code.  */
       if (TREE_CODE (name) == TYPE_DECL)
        {
-         error ("invalid use of %qD", name);
+         error ("%Hinvalid use of %qD", &token->location, name);
          postfix_expression = error_mark_node;
        }
       else
          postfix_expression = error_mark_node;
        }
       else
@@ -4537,10 +5072,11 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
            }
          if (scope && name && BASELINK_P (name))
            adjust_result_of_qualified_name_lookup
            }
          if (scope && name && BASELINK_P (name))
            adjust_result_of_qualified_name_lookup
-             (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
+             (name, BINFO_TYPE (BASELINK_ACCESS_BINFO (name)), scope);
          postfix_expression
            = finish_class_member_access_expr (postfix_expression, name,
          postfix_expression
            = finish_class_member_access_expr (postfix_expression, name,
-                                              template_p);
+                                              template_p, 
+                                              tf_warning_or_error);
        }
     }
 
        }
     }
 
@@ -4552,7 +5088,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
      constant-expressions.  */
   if (!for_offsetof
       && (cp_parser_non_integral_constant_expression
      constant-expressions.  */
   if (!for_offsetof
       && (cp_parser_non_integral_constant_expression
-         (parser, token_type == CPP_DEREF ? "'->'" : "`.'")))
+         (parser, token_type == CPP_DEREF ? "%<->%>" : "%<.%>")))
     postfix_expression = error_mark_node;
 
   return postfix_expression;
     postfix_expression = error_mark_node;
 
   return postfix_expression;
@@ -4571,6 +5107,9 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 
    CAST_P is true if this expression is the target of a cast.
 
 
    CAST_P is true if this expression is the target of a cast.
 
+   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.
    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.
@@ -4585,19 +5124,27 @@ static tree
 cp_parser_parenthesized_expression_list (cp_parser* parser,
                                         bool is_attribute_list,
                                         bool cast_p,
 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;
   bool fold_expr_p = is_attribute_list;
   tree identifier = NULL_TREE;
                                         bool *non_constant_p)
 {
   tree expression_list = NULL_TREE;
   bool fold_expr_p = is_attribute_list;
   tree identifier = NULL_TREE;
+  bool saved_greater_than_is_operator_p;
 
   /* Assume all the expressions will be constant.  */
   if (non_constant_p)
     *non_constant_p = false;
 
 
   /* Assume all the expressions will be constant.  */
   if (non_constant_p)
     *non_constant_p = false;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return error_mark_node;
 
     return error_mark_node;
 
+  /* Within a parenthesized expression, a `>' token is always
+     the greater-than operator.  */
+  saved_greater_than_is_operator_p
+    = parser->greater_than_is_operator_p;
+  parser->greater_than_is_operator_p = true;
+
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
   /* Consume expressions until there are no more.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
     while (true)
@@ -4614,14 +5161,23 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
            /* Consume the identifier.  */
            token = cp_lexer_consume_token (parser->lexer);
            /* Save the identifier.  */
            /* Consume the identifier.  */
            token = cp_lexer_consume_token (parser->lexer);
            /* Save the identifier.  */
-           identifier = token->value;
+           identifier = token->u.value;
          }
        else
          {
          }
        else
          {
+           bool expr_non_constant_p;
+
            /* Parse the next assignment-expression.  */
            /* Parse the next assignment-expression.  */
-           if (non_constant_p)
+           if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+             {
+               /* A braced-init-list.  */
+               maybe_warn_cpp0x ("extended initializer lists");
+               expr = cp_parser_braced_list (parser, &expr_non_constant_p);
+               if (non_constant_p && expr_non_constant_p)
+                 *non_constant_p = true;
+             }
+           else if (non_constant_p)
              {
              {
-               bool expr_non_constant_p;
                expr = (cp_parser_constant_expression
                        (parser, /*allow_non_constant_p=*/true,
                         &expr_non_constant_p));
                expr = (cp_parser_constant_expression
                        (parser, /*allow_non_constant_p=*/true,
                         &expr_non_constant_p));
@@ -4634,6 +5190,18 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
            if (fold_expr_p)
              expr = fold_non_dependent_expr (expr);
 
            if (fold_expr_p)
              expr = fold_non_dependent_expr (expr);
 
+            /* If we have an ellipsis, then this is an expression
+              expansion.  */
+            if (allow_expansion_p
+                && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+              {
+                /* Consume the `...'.  */
+                cp_lexer_consume_token (parser->lexer);
+
+                /* Build the argument pack.  */
+                expr = make_pack_expansion (expr);
+              }
+
             /* Add it to the list.  We add error_mark_node
                expressions to the list, so that we can still tell if
                the correct form for a parenthesized expression-list
             /* Add it to the list.  We add error_mark_node
                expressions to the list, so that we can still tell if
                the correct form for a parenthesized expression-list
@@ -4657,7 +5225,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
        cp_lexer_consume_token (parser->lexer);
       }
 
        cp_lexer_consume_token (parser->lexer);
       }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     {
       int ending;
 
     {
       int ending;
 
@@ -4671,9 +5239,16 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
       if (ending < 0)
        goto get_comma;
       if (!ending)
       if (ending < 0)
        goto get_comma;
       if (!ending)
-       return error_mark_node;
+       {
+         parser->greater_than_is_operator_p
+           = saved_greater_than_is_operator_p;
+         return error_mark_node;
+       }
     }
 
     }
 
+  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)
   /* We built up the list in reverse order so we must reverse it now.  */
   expression_list = nreverse (expression_list);
   if (identifier)
@@ -4712,7 +5287,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
                                            /*typename_keyword_p=*/false,
                                            /*check_dependency_p=*/true,
                                            /*type_p=*/false,
                                            /*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.  */
        != NULL_TREE);
   /* Now, if we saw a nested-name-specifier, we might be doing the
      second production.  */
@@ -4727,41 +5302,42 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
                             /*check_dependency_p=*/false,
                             /*is_declaration=*/true);
       /* Look for the `::' token.  */
                             /*check_dependency_p=*/false,
                             /*is_declaration=*/true);
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "`::'");
+      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
     }
   /* If the next token is not a `~', then there might be some
      additional qualification.  */
   else if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMPL))
     {
     }
   /* If the next token is not a `~', then there might be some
      additional qualification.  */
   else if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMPL))
     {
-      /* Look for the type-name.  */
-      *scope = TREE_TYPE (cp_parser_type_name (parser));
-
-      if (*scope == error_mark_node)
-       return;
-
-      /* If we don't have ::~, then something has gone wrong.  Since
-        the only caller of this function is looking for something
-        after `.' or `->' after a scalar type, most likely the
-        program is trying to get a member of a non-aggregate
-        type.  */
-      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE)
-         || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_COMPL)
+      /* At this point, we're looking for "type-name :: ~".  The type-name
+        must not be a class-name, since this is a pseudo-destructor.  So,
+        it must be either an enum-name, or a typedef-name -- both of which
+        are just identifiers.  So, we peek ahead to check that the "::"
+        and "~" tokens are present; if they are not, then we can avoid
+        calling type_name.  */
+      if (cp_lexer_peek_token (parser->lexer)->type != CPP_NAME
+         || cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SCOPE
+         || cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_COMPL)
        {
        {
-         cp_parser_error (parser, "request for member of non-aggregate type");
+         cp_parser_error (parser, "non-scalar type");
          return;
        }
 
          return;
        }
 
+      /* Look for the type-name.  */
+      *scope = TREE_TYPE (cp_parser_nonclass_name (parser));
+      if (*scope == error_mark_node)
+       return;
+
       /* Look for the `::' token.  */
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "`::'");
+      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
     }
   else
     *scope = NULL_TREE;
 
   /* Look for the `~'.  */
     }
   else
     *scope = NULL_TREE;
 
   /* Look for the `~'.  */
-  cp_parser_require (parser, CPP_COMPL, "`~'");
+  cp_parser_require (parser, CPP_COMPL, "%<~%>");
   /* Look for the type-name again.  We are not responsible for
      checking that it matches the first type-name.  */
   /* Look for the type-name again.  We are not responsible for
      checking that it matches the first type-name.  */
-  *type = cp_parser_type_name (parser);
+  *type = cp_parser_nonclass_name (parser);
 }
 
 /* Parse a unary-expression.
 }
 
 /* Parse a unary-expression.
@@ -4822,7 +5398,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
            if (TYPE_P (operand))
              return cxx_sizeof_or_alignof_type (operand, op, true);
            else
            if (TYPE_P (operand))
              return cxx_sizeof_or_alignof_type (operand, op, true);
            else
-             return cxx_sizeof_or_alignof_expr (operand, op);
+             return cxx_sizeof_or_alignof_expr (operand, op, true);
          }
 
        case RID_NEW:
          }
 
        case RID_NEW:
@@ -4859,7 +5435,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
            /* Create the complete representation.  */
            return build_x_unary_op ((keyword == RID_REALPART
                                      ? REALPART_EXPR : IMAGPART_EXPR),
            /* Create the complete representation.  */
            return build_x_unary_op ((keyword == RID_REALPART
                                      ? REALPART_EXPR : IMAGPART_EXPR),
-                                    expression);
+                                    expression,
+                                     tf_warning_or_error);
          }
          break;
 
          }
          break;
 
@@ -4902,13 +5479,19 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
               && token->type == CPP_AND_AND)
        {
          tree identifier;
               && token->type == CPP_AND_AND)
        {
          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.  */
 
          /* Consume the '&&' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Look for the identifier.  */
          identifier = cp_parser_identifier (parser);
          /* Create an expression representing the address.  */
-         return 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;
+         return expression;
        }
     }
   if (unary_operator != ERROR_MARK)
        }
     }
   if (unary_operator != ERROR_MARK)
@@ -4928,21 +5511,23 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
       switch (unary_operator)
        {
        case INDIRECT_REF:
       switch (unary_operator)
        {
        case INDIRECT_REF:
-         non_constant_p = "`*'";
-         expression = build_x_indirect_ref (cast_expression, "unary *");
+         non_constant_p = "%<*%>";
+         expression = build_x_indirect_ref (cast_expression, "unary *",
+                                             tf_warning_or_error);
          break;
 
        case ADDR_EXPR:
          break;
 
        case ADDR_EXPR:
-         non_constant_p = "`&'";
+         non_constant_p = "%<&%>";
          /* Fall through.  */
        case BIT_NOT_EXPR:
          /* Fall through.  */
        case BIT_NOT_EXPR:
-         expression = build_x_unary_op (unary_operator, cast_expression);
+         expression = build_x_unary_op (unary_operator, cast_expression,
+                                         tf_warning_or_error);
          break;
 
        case PREINCREMENT_EXPR:
        case PREDECREMENT_EXPR:
          non_constant_p = (unary_operator == PREINCREMENT_EXPR
          break;
 
        case PREINCREMENT_EXPR:
        case PREDECREMENT_EXPR:
          non_constant_p = (unary_operator == PREINCREMENT_EXPR
-                           ? "`++'" : "`--'");
+                           ? "%<++%>" : "%<--%>");
          /* Fall through.  */
        case UNARY_PLUS_EXPR:
        case NEGATE_EXPR:
          /* Fall through.  */
        case UNARY_PLUS_EXPR:
        case NEGATE_EXPR:
@@ -4962,7 +5547,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
       return expression;
     }
 
       return expression;
     }
 
-  return cp_parser_postfix_expression (parser, address_p, cast_p);
+  return cp_parser_postfix_expression (parser, address_p, cast_p,
+                                       /*member_access_only_p=*/false);
 }
 
 /* Returns ERROR_MARK if TOKEN is not a unary-operator.  If TOKEN is a
 }
 
 /* Returns ERROR_MARK if TOKEN is not a unary-operator.  If TOKEN is a
@@ -5019,7 +5605,7 @@ cp_parser_new_expression (cp_parser* parser)
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `new' operator.  */
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `new' operator.  */
-  cp_parser_require_keyword (parser, RID_NEW, "`new'");
+  cp_parser_require_keyword (parser, RID_NEW, "%<new%>");
   /* There's no easy way to tell a new-placement from the
      `( type-id )' construct.  */
   cp_parser_parse_tentatively (parser);
   /* There's no easy way to tell a new-placement from the
      `( type-id )' construct.  */
   cp_parser_parse_tentatively (parser);
@@ -5033,19 +5619,23 @@ cp_parser_new_expression (cp_parser* parser)
      type-id.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
      type-id.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
+      cp_token *token;
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the type-id.  */
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the type-id.  */
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      token = cp_lexer_peek_token (parser->lexer);
       /* There should not be a direct-new-declarator in this production,
         but GCC used to allowed this, so we check and emit a sensible error
         message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
        {
       /* There should not be a direct-new-declarator in this production,
         but GCC used to allowed this, so we check and emit a sensible error
         message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
        {
-         error ("array bound forbidden after parenthesized type-id");
-         inform ("try removing the parentheses around the type-id");
+         error ("%Harray bound forbidden after parenthesized type-id",
+                &token->location);
+         inform (token->location, 
+                 "try removing the parentheses around the type-id");
          cp_parser_direct_new_declarator (parser);
        }
       nelts = NULL_TREE;
          cp_parser_direct_new_declarator (parser);
        }
       nelts = NULL_TREE;
@@ -5054,19 +5644,21 @@ cp_parser_new_expression (cp_parser* parser)
   else
     type = cp_parser_new_type_id (parser, &nelts);
 
   else
     type = cp_parser_new_type_id (parser, &nelts);
 
-  /* If the next token is a `(', then we have a new-initializer.  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+  /* If the next token is a `(' or '{', then we have a new-initializer.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+      || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     initializer = cp_parser_new_initializer (parser);
   else
     initializer = NULL_TREE;
 
   /* A new-expression may not appear in an integral constant
      expression.  */
     initializer = cp_parser_new_initializer (parser);
   else
     initializer = NULL_TREE;
 
   /* A new-expression may not appear in an integral constant
      expression.  */
-  if (cp_parser_non_integral_constant_expression (parser, "`new'"))
+  if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
     return error_mark_node;
 
   /* Create a representation of the new-expression.  */
     return error_mark_node;
 
   /* Create a representation of the new-expression.  */
-  return build_new (placement, type, nelts, initializer, global_scope_p);
+  return build_new (placement, type, nelts, initializer, global_scope_p,
+                    tf_warning_or_error);
 }
 
 /* Parse a new-placement.
 }
 
 /* Parse a new-placement.
@@ -5083,7 +5675,7 @@ cp_parser_new_placement (cp_parser* parser)
 
   /* Parse the expression-list.  */
   expression_list = (cp_parser_parenthesized_expression_list
 
   /* Parse the expression-list.  */
   expression_list = (cp_parser_parenthesized_expression_list
-                    (parser, false, /*cast_p=*/false,
+                    (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
                      /*non_constant_p=*/NULL));
 
   return expression_list;
                      /*non_constant_p=*/NULL));
 
   return expression_list;
@@ -5157,11 +5749,6 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
     }
 
   type = groktypename (&type_specifier_seq, new_declarator);
     }
 
   type = groktypename (&type_specifier_seq, new_declarator);
-  if (TREE_CODE (type) == ARRAY_TYPE && *nelts == NULL_TREE)
-    {
-      *nelts = array_type_nelts_top (type);
-      type = TREE_TYPE (type);
-    }
   return type;
 }
 
   return type;
 }
 
@@ -5192,15 +5779,8 @@ cp_parser_new_declarator_opt (cp_parser* parser)
       /* Parse another optional declarator.  */
       declarator = cp_parser_new_declarator_opt (parser);
 
       /* Parse another optional declarator.  */
       declarator = cp_parser_new_declarator_opt (parser);
 
-      /* Create the representation of the declarator.  */
-      if (type)
-       declarator = make_ptrmem_declarator (cv_quals, type, declarator);
-      else if (code == INDIRECT_REF)
-       declarator = make_pointer_declarator (cv_quals, declarator);
-      else
-       declarator = make_reference_declarator (cv_quals, declarator);
-
-      return declarator;
+      return cp_parser_make_indirect_declarator
+       (code, type, cv_quals, declarator);
     }
 
   /* If the next token is a `[', there is a direct-new-declarator.  */
     }
 
   /* If the next token is a `[', there is a direct-new-declarator.  */
@@ -5228,10 +5808,11 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       tree expression;
 
       /* Look for the opening `['.  */
       tree expression;
 
       /* Look for the opening `['.  */
-      cp_parser_require (parser, CPP_OPEN_SQUARE, "`['");
+      cp_parser_require (parser, CPP_OPEN_SQUARE, "%<[%>");
       /* The first expression is not required to be constant.  */
       if (!declarator)
        {
       /* The first expression is not required to be constant.  */
       if (!declarator)
        {
+         cp_token *token = cp_lexer_peek_token (parser->lexer);
          expression = cp_parser_expression (parser, /*cast_p=*/false);
          /* The standard requires that the expression have integral
             type.  DR 74 adds enumeration types.  We believe that the
          expression = cp_parser_expression (parser, /*cast_p=*/false);
          /* The standard requires that the expression have integral
             type.  DR 74 adds enumeration types.  We believe that the
@@ -5247,8 +5828,8 @@ cp_parser_direct_new_declarator (cp_parser* parser)
                                              /*complain=*/true);
              if (!expression)
                {
                                              /*complain=*/true);
              if (!expression)
                {
-                 error ("expression in new-declarator must have integral "
-                        "or enumeration type");
+                 error ("%Hexpression in new-declarator must have integral "
+                        "or enumeration type", &token->location);
                  expression = error_mark_node;
                }
            }
                  expression = error_mark_node;
                }
            }
@@ -5260,7 +5841,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
                                           /*allow_non_constant=*/false,
                                           NULL);
       /* Look for the closing `]'.  */
                                           /*allow_non_constant=*/false,
                                           NULL);
       /* Look for the closing `]'.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
 
       /* Add this bound to the declarator.  */
       declarator = make_array_declarator (declarator, expression);
 
       /* Add this bound to the declarator.  */
       declarator = make_array_declarator (declarator, expression);
@@ -5278,6 +5859,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
 
    new-initializer:
      ( expression-list [opt] )
 
    new-initializer:
      ( expression-list [opt] )
+     braced-init-list
 
    Returns a representation of the expression-list.  If there is no
    expression-list, VOID_ZERO_NODE is returned.  */
 
    Returns a representation of the expression-list.  If there is no
    expression-list, VOID_ZERO_NODE is returned.  */
@@ -5287,9 +5869,18 @@ cp_parser_new_initializer (cp_parser* parser)
 {
   tree expression_list;
 
 {
   tree expression_list;
 
-  expression_list = (cp_parser_parenthesized_expression_list
-                    (parser, false, /*cast_p=*/false,
-                     /*non_constant_p=*/NULL));
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      bool expr_non_constant_p;
+      maybe_warn_cpp0x ("extended initializer lists");
+      expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
+      expression_list = build_tree_list (NULL_TREE, expression_list);
+    }
+  else
+    expression_list = (cp_parser_parenthesized_expression_list
+                      (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+                       /*non_constant_p=*/NULL));
   if (!expression_list)
     expression_list = void_zero_node;
 
   if (!expression_list)
     expression_list = void_zero_node;
 
@@ -5317,14 +5908,14 @@ cp_parser_delete_expression (cp_parser* parser)
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `delete' keyword.  */
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `delete' keyword.  */
-  cp_parser_require_keyword (parser, RID_DELETE, "`delete'");
+  cp_parser_require_keyword (parser, RID_DELETE, "%<delete%>");
   /* See if the array syntax is in use.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
     {
       /* Consume the `[' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the `]' token.  */
   /* See if the array syntax is in use.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
     {
       /* Consume the `[' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the `]' token.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
       /* Remember that this is the `[]' construct.  */
       array_p = true;
     }
       /* Remember that this is the `[]' construct.  */
       array_p = true;
     }
@@ -5336,12 +5927,67 @@ cp_parser_delete_expression (cp_parser* parser)
 
   /* A delete-expression may not appear in an integral constant
      expression.  */
 
   /* A delete-expression may not appear in an integral constant
      expression.  */
-  if (cp_parser_non_integral_constant_expression (parser, "`delete'"))
+  if (cp_parser_non_integral_constant_expression (parser, "%<delete%>"))
     return error_mark_node;
 
   return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
 }
 
     return error_mark_node;
 
   return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
 }
 
+/* Returns true if TOKEN may start a cast-expression and false
+   otherwise.  */
+
+static bool
+cp_parser_token_starts_cast_expression (cp_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_COMMA:
+    case CPP_SEMICOLON:
+    case CPP_QUERY:
+    case CPP_COLON:
+    case CPP_CLOSE_SQUARE:
+    case CPP_CLOSE_PAREN:
+    case CPP_CLOSE_BRACE:
+    case CPP_DOT:
+    case CPP_DOT_STAR:
+    case CPP_DEREF:
+    case CPP_DEREF_STAR:
+    case CPP_DIV:
+    case CPP_MOD:
+    case CPP_LSHIFT:
+    case CPP_RSHIFT:
+    case CPP_LESS:
+    case CPP_GREATER:
+    case CPP_LESS_EQ:
+    case CPP_GREATER_EQ:
+    case CPP_EQ_EQ:
+    case CPP_NOT_EQ:
+    case CPP_EQ:
+    case CPP_MULT_EQ:
+    case CPP_DIV_EQ:
+    case CPP_MOD_EQ:
+    case CPP_PLUS_EQ:
+    case CPP_MINUS_EQ:
+    case CPP_RSHIFT_EQ:
+    case CPP_LSHIFT_EQ:
+    case CPP_AND_EQ:
+    case CPP_XOR_EQ:
+    case CPP_OR_EQ:
+    case CPP_XOR:
+    case CPP_OR:
+    case CPP_OR_OR:
+    case CPP_EOF:
+      return false;
+
+      /* '[' may start a primary-expression in obj-c++.  */
+    case CPP_OPEN_SQUARE:
+      return c_dialect_objc ();
+
+    default:
+      return true;
+    }
+}
+
 /* Parse a cast-expression.
 
    cast-expression:
 /* Parse a cast-expression.
 
    cast-expression:
@@ -5413,24 +6059,25 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
          /* Look for the type-id.  */
          type = cp_parser_type_id (parser);
          /* Look for the closing `)'.  */
          /* Look for the type-id.  */
          type = cp_parser_type_id (parser);
          /* Look for the closing `)'.  */
-         cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+         cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
          parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
        }
 
       /* Restore the saved message.  */
       parser->type_definition_forbidden_message = saved_message;
 
          parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
        }
 
       /* Restore the saved message.  */
       parser->type_definition_forbidden_message = saved_message;
 
-      /* If ok so far, parse the dependent expression. We cannot be
-        sure it is a cast. Consider `(T ())'.  It is a parenthesized
-        ctor of T, but looks like a cast to function returning T
-        without a dependent expression.  */
-      if (!cp_parser_error_occurred (parser))
-       expr = cp_parser_cast_expression (parser,
-                                         /*address_p=*/false,
-                                         /*cast_p=*/true);
-
-      if (cp_parser_parse_definitely (parser))
+      /* At this point this can only be either a cast or a
+        parenthesized ctor such as `(T ())' that looks like a cast to
+        function returning T.  */
+      if (!cp_parser_error_occurred (parser)
+         && cp_parser_token_starts_cast_expression (cp_lexer_peek_token
+                                                    (parser->lexer)))
        {
        {
+         cp_parser_parse_definitely (parser);
+         expr = cp_parser_cast_expression (parser,
+                                           /*address_p=*/false,
+                                           /*cast_p=*/true);
+
          /* Warn about old-style casts, if so requested.  */
          if (warn_old_style_cast
              && !in_system_header
          /* Warn about old-style casts, if so requested.  */
          if (warn_old_style_cast
              && !in_system_header
@@ -5440,9 +6087,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
 
          /* Only type conversions to integral or enumeration types
             can be used in constant-expressions.  */
 
          /* Only type conversions to integral or enumeration types
             can be used in constant-expressions.  */
-         if (parser->integral_constant_expression_p
-             && !dependent_type_p (type)
-             && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+         if (!cast_valid_in_integral_constant_expression_p (type)
              && (cp_parser_non_integral_constant_expression
                  (parser,
                   "a cast to a type other than an integral or "
              && (cp_parser_non_integral_constant_expression
                  (parser,
                   "a cast to a type other than an integral or "
@@ -5453,6 +6098,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
          expr = build_c_cast (type, expr);
          return expr;
        }
          expr = build_c_cast (type, expr);
          return expr;
        }
+      else 
+        cp_parser_abort_tentative_parse (parser);
     }
 
   /* If we get here, then it's not a cast, so it must be a
     }
 
   /* If we get here, then it's not a cast, so it must be a
@@ -5532,31 +6179,44 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
    The binops_by_token map is used to get the tree codes for each <token> type.
    binary-expressions are associated according to a precedence table.  */
 
    The binops_by_token map is used to get the tree codes for each <token> type.
    binary-expressions are associated according to a precedence table.  */
 
-#define TOKEN_PRECEDENCE(token) \
-  ((token->type == CPP_GREATER && !parser->greater_than_is_operator_p) \
-   ? PREC_NOT_OPERATOR \
-   : binops_by_token[token->type].prec)
+#define TOKEN_PRECEDENCE(token)                                     \
+(((token->type == CPP_GREATER                               \
+   || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT)) \
+  && !parser->greater_than_is_operator_p)                   \
+ ? PREC_NOT_OPERATOR                                        \
+ : binops_by_token[token->type].prec)
 
 static tree
 
 static tree
-cp_parser_binary_expression (cp_parser* parser, bool cast_p)
+cp_parser_binary_expression (cp_parser* parser, bool cast_p,
+                            enum cp_parser_prec prec)
 {
   cp_parser_expression_stack stack;
   cp_parser_expression_stack_entry *sp = &stack[0];
   tree lhs, rhs;
   cp_token *token;
 {
   cp_parser_expression_stack stack;
   cp_parser_expression_stack_entry *sp = &stack[0];
   tree lhs, rhs;
   cp_token *token;
-  enum tree_code tree_type;
-  enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
+  enum tree_code tree_type, lhs_type, rhs_type;
+  enum cp_parser_prec new_prec, lookahead_prec;
   bool overloaded_p;
 
   /* Parse the first expression.  */
   lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p);
   bool overloaded_p;
 
   /* Parse the first expression.  */
   lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p);
+  lhs_type = ERROR_MARK;
 
   for (;;)
     {
       /* Get an operator token.  */
       token = cp_lexer_peek_token (parser->lexer);
 
   for (;;)
     {
       /* Get an operator token.  */
       token = cp_lexer_peek_token (parser->lexer);
-      if (token->type == CPP_MIN || token->type == CPP_MAX)
-       cp_parser_warn_min_max ();
+
+      if (warn_cxx0x_compat
+          && 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");
+        }
 
       new_prec = TOKEN_PRECEDENCE (token);
 
 
       new_prec = TOKEN_PRECEDENCE (token);
 
@@ -5584,6 +6244,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
       /* 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);
       /* 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);
+      rhs_type = ERROR_MARK;
 
       /* Get another operator token.  Look up its precedence to avoid
         building a useless (immediately popped) stack entry for common
 
       /* Get another operator token.  Look up its precedence to avoid
         building a useless (immediately popped) stack entry for common
@@ -5599,8 +6260,10 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
          sp->prec = prec;
          sp->tree_type = tree_type;
          sp->lhs = lhs;
          sp->prec = prec;
          sp->tree_type = tree_type;
          sp->lhs = lhs;
+         sp->lhs_type = lhs_type;
          sp++;
          lhs = rhs;
          sp++;
          lhs = rhs;
+         lhs_type = rhs_type;
          prec = new_prec;
          new_prec = lookahead_prec;
          goto get_rhs;
          prec = new_prec;
          new_prec = lookahead_prec;
          goto get_rhs;
@@ -5617,11 +6280,22 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
          prec = sp->prec;
          tree_type = sp->tree_type;
          rhs = lhs;
          prec = sp->prec;
          tree_type = sp->tree_type;
          rhs = lhs;
+         rhs_type = lhs_type;
          lhs = sp->lhs;
          lhs = sp->lhs;
+         lhs_type = sp->lhs_type;
        }
 
       overloaded_p = false;
        }
 
       overloaded_p = false;
-      lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p);
+      /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
+        ERROR_MARK for everything that is not a binary expression.
+        This makes warn_about_parentheses miss some warnings that
+        involve unary operators.  For unary expressions we should
+        pass the correct tree_code unless the unary expression was
+        surrounded by parentheses.
+      */
+      lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
+                              &overloaded_p, tf_warning_or_error);
+      lhs_type = tree_type;
 
       /* If the binary operator required the use of an overloaded operator,
         then this expression cannot be an integral constant-expression.
 
       /* If the binary operator required the use of an overloaded operator,
         then this expression cannot be an integral constant-expression.
@@ -5669,14 +6343,15 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
     expr = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* The next token should be a `:'.  */
     expr = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* The next token should be a `:'.  */
-  cp_parser_require (parser, CPP_COLON, "`:'");
+  cp_parser_require (parser, CPP_COLON, "%<:%>");
   /* Parse the assignment-expression.  */
   assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false);
 
   /* Build the conditional-expression.  */
   return build_x_conditional_expr (logical_or_expr,
                                   expr,
   /* Parse the assignment-expression.  */
   assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false);
 
   /* Build the conditional-expression.  */
   return build_x_conditional_expr (logical_or_expr,
                                   expr,
-                                  assignment_expr);
+                                  assignment_expr,
+                                   tf_warning_or_error);
 }
 
 /* Parse an assignment-expression.
 }
 
 /* Parse an assignment-expression.
@@ -5704,7 +6379,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
   else
     {
       /* Parse the binary expressions (logical-or-expression).  */
   else
     {
       /* Parse the binary expressions (logical-or-expression).  */
-      expr = cp_parser_binary_expression (parser, cast_p);
+      expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR);
       /* If the next token is a `?' then we're actually looking at a
         conditional-expression.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
       /* 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))
@@ -5719,10 +6394,14 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
            = cp_parser_assignment_operator_opt (parser);
          if (assignment_operator != ERROR_MARK)
            {
            = cp_parser_assignment_operator_opt (parser);
          if (assignment_operator != ERROR_MARK)
            {
-             tree rhs;
+             bool non_constant_p;
 
              /* Parse the right-hand side of the assignment.  */
 
              /* Parse the right-hand side of the assignment.  */
-             rhs = cp_parser_assignment_expression (parser, cast_p);
+             tree rhs = cp_parser_initializer_clause (parser, &non_constant_p);
+
+             if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
+               maybe_warn_cpp0x ("extended initializer lists");
+
              /* An assignment may not appear in a
                 constant-expression.  */
              if (cp_parser_non_integral_constant_expression (parser,
              /* An assignment may not appear in a
                 constant-expression.  */
              if (cp_parser_non_integral_constant_expression (parser,
@@ -5731,7 +6410,8 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
              /* Build the assignment expression.  */
              expr = build_x_modify_expr (expr,
                                          assignment_operator,
              /* Build the assignment expression.  */
              expr = build_x_modify_expr (expr,
                                          assignment_operator,
-                                         rhs);
+                                         rhs,
+                                         tf_warning_or_error);
            }
        }
     }
            }
        }
     }
@@ -5762,7 +6442,7 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
   enum tree_code op;
   cp_token *token;
 
   enum tree_code op;
   cp_token *token;
 
-  /* Peek at the next toen.  */
+  /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   switch (token->type)
   token = cp_lexer_peek_token (parser->lexer);
 
   switch (token->type)
@@ -5811,16 +6491,6 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
       op = BIT_IOR_EXPR;
       break;
 
       op = BIT_IOR_EXPR;
       break;
 
-    case CPP_MIN_EQ:
-      op = MIN_EXPR;
-      cp_parser_warn_min_max ();
-      break;
-
-    case CPP_MAX_EQ:
-      op = MAX_EXPR;
-      cp_parser_warn_min_max ();
-      break;
-
     default:
       /* Nothing else is an assignment operator.  */
       op = ERROR_MARK;
     default:
       /* Nothing else is an assignment operator.  */
       op = ERROR_MARK;
@@ -5861,7 +6531,8 @@ cp_parser_expression (cp_parser* parser, bool cast_p)
        expression = assignment_expression;
       else
        expression = build_x_compound_expr (expression,
        expression = assignment_expression;
       else
        expression = build_x_compound_expr (expression,
-                                           assignment_expression);
+                                           assignment_expression,
+                                            tf_warning_or_error);
       /* If the next token is not a comma, then we are done with the
         expression.  */
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
       /* If the next token is not a comma, then we are done with the
         expression.  */
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
@@ -5964,6 +6635,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   int save_ice_p, save_non_ice_p;
   tree type, expr;
   cp_id_kind dummy;
   int save_ice_p, save_non_ice_p;
   tree type, expr;
   cp_id_kind dummy;
+  cp_token *token;
 
   /* We're about to accept non-integral-constant things, but will
      definitely yield an integral constant expression.  Save and
 
   /* We're about to accept non-integral-constant things, but will
      definitely yield an integral constant expression.  Save and
@@ -5974,21 +6646,23 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   /* Consume the "__builtin_offsetof" token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Consume the opening `('.  */
   /* Consume the "__builtin_offsetof" token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Consume the opening `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   /* Parse the type-id.  */
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
   /* Parse the type-id.  */
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
-  cp_parser_require (parser, CPP_COMMA, "`,'");
+  cp_parser_require (parser, CPP_COMMA, "%<,%>");
+  token = cp_lexer_peek_token (parser->lexer);
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
-  expr = build_static_cast (build_pointer_type (type), null_pointer_node);
+  expr = build_static_cast (build_pointer_type (type), null_pointer_node,
+                            tf_warning_or_error);
 
   /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
   expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
 
   /* Parse the offsetof-member-designator.  We begin as if we saw "expr->".  */
   expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
-                                                true, &dummy);
+                                                true, &dummy, token->location);
   while (true)
     {
   while (true)
     {
-      cp_token *token = cp_lexer_peek_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
       switch (token->type)
        {
        case CPP_OPEN_SQUARE:
       switch (token->type)
        {
        case CPP_OPEN_SQUARE:
@@ -6000,7 +6674,8 @@ cp_parser_builtin_offsetof (cp_parser *parser)
          /* offsetof-member-designator "." identifier */
          cp_lexer_consume_token (parser->lexer);
          expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
          /* offsetof-member-designator "." identifier */
          cp_lexer_consume_token (parser->lexer);
          expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
-                                                        true, &dummy);
+                                                        true, &dummy,
+                                                        token->location);
          break;
 
        case CPP_CLOSE_PAREN:
          break;
 
        case CPP_CLOSE_PAREN:
@@ -6011,7 +6686,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
        default:
          /* Error.  We know the following require will fail, but
             that gives the proper error message.  */
        default:
          /* Error.  We know the following require will fail, but
             that gives the proper error message.  */
-         cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+         cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
          cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
          expr = error_mark_node;
          goto failure;
          cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
          expr = error_mark_node;
          goto failure;
@@ -6033,6 +6708,118 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   return expr;
 }
 
   return expr;
 }
 
+/* Parse a trait expression.  */
+
+static tree
+cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
+{
+  cp_trait_kind kind;
+  tree type1, type2 = NULL_TREE;
+  bool binary = false;
+  cp_decl_specifier_seq decl_specs;
+
+  switch (keyword)
+    {
+    case RID_HAS_NOTHROW_ASSIGN:
+      kind = CPTK_HAS_NOTHROW_ASSIGN;
+      break;
+    case RID_HAS_NOTHROW_CONSTRUCTOR:
+      kind = CPTK_HAS_NOTHROW_CONSTRUCTOR;
+      break;
+    case RID_HAS_NOTHROW_COPY:
+      kind = CPTK_HAS_NOTHROW_COPY;
+      break;
+    case RID_HAS_TRIVIAL_ASSIGN:
+      kind = CPTK_HAS_TRIVIAL_ASSIGN;
+      break;
+    case RID_HAS_TRIVIAL_CONSTRUCTOR:
+      kind = CPTK_HAS_TRIVIAL_CONSTRUCTOR;
+      break;
+    case RID_HAS_TRIVIAL_COPY:
+      kind = CPTK_HAS_TRIVIAL_COPY;
+      break;
+    case RID_HAS_TRIVIAL_DESTRUCTOR:
+      kind = CPTK_HAS_TRIVIAL_DESTRUCTOR;
+      break;
+    case RID_HAS_VIRTUAL_DESTRUCTOR:
+      kind = CPTK_HAS_VIRTUAL_DESTRUCTOR;
+      break;
+    case RID_IS_ABSTRACT:
+      kind = CPTK_IS_ABSTRACT;
+      break;
+    case RID_IS_BASE_OF:
+      kind = CPTK_IS_BASE_OF;
+      binary = true;
+      break;
+    case RID_IS_CLASS:
+      kind = CPTK_IS_CLASS;
+      break;
+    case RID_IS_CONVERTIBLE_TO:
+      kind = CPTK_IS_CONVERTIBLE_TO;
+      binary = true;
+      break;
+    case RID_IS_EMPTY:
+      kind = CPTK_IS_EMPTY;
+      break;
+    case RID_IS_ENUM:
+      kind = CPTK_IS_ENUM;
+      break;
+    case RID_IS_POD:
+      kind = CPTK_IS_POD;
+      break;
+    case RID_IS_POLYMORPHIC:
+      kind = CPTK_IS_POLYMORPHIC;
+      break;
+    case RID_IS_UNION:
+      kind = CPTK_IS_UNION;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  /* Consume the token.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+
+  type1 = cp_parser_type_id (parser);
+
+  if (type1 == error_mark_node)
+    return error_mark_node;
+
+  /* Build a trivial decl-specifier-seq.  */
+  clear_decl_specs (&decl_specs);
+  decl_specs.type = type1;
+
+  /* Call grokdeclarator to figure out what type this is.  */
+  type1 = grokdeclarator (NULL, &decl_specs, TYPENAME,
+                         /*initialized=*/0, /*attrlist=*/NULL);
+
+  if (binary)
+    {
+      cp_parser_require (parser, CPP_COMMA, "%<,%>");
+      type2 = cp_parser_type_id (parser);
+
+      if (type2 == error_mark_node)
+       return error_mark_node;
+
+      /* Build a trivial decl-specifier-seq.  */
+      clear_decl_specs (&decl_specs);
+      decl_specs.type = type2;
+
+      /* Call grokdeclarator to figure out what type this is.  */
+      type2 = grokdeclarator (NULL, &decl_specs, TYPENAME,
+                             /*initialized=*/0, /*attrlist=*/NULL);
+    }
+
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+
+  /* Complete the trait expression, which may mean either processing
+     the trait expr now or saving it for template instantiation.  */
+  return finish_trait_expr (kind, type1, type2);
+}
+
 /* Statements [gram.stmt.stmt]  */
 
 /* Parse a statement.
 /* Statements [gram.stmt.stmt]  */
 
 /* Parse a statement.
@@ -6048,17 +6835,23 @@ cp_parser_builtin_offsetof (cp_parser *parser)
      try-block
 
   IN_COMPOUND is true when the statement is nested inside a
      try-block
 
   IN_COMPOUND is true when the statement is nested inside a
-  cp_parser_compound_statement; this matters for certain pragmas.  */
+  cp_parser_compound_statement; this matters for certain pragmas.
+
+  If IF_P is not NULL, *IF_P is set to indicate whether the statement
+  is a (possibly labeled) if statement which is not enclosed in braces
+  and has an else clause.  This is used to implement -Wparentheses.  */
 
 static void
 cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
 static void
 cp_parser_statement (cp_parser* parser, tree in_statement_expr,
-                    bool in_compound)
+                    bool in_compound, bool *if_p)
 {
   tree statement;
   cp_token *token;
   location_t statement_location;
 
  restart:
 {
   tree statement;
   cp_token *token;
   location_t statement_location;
 
  restart:
+  if (if_p != NULL)
+    *if_p = false;
   /* There is no statement yet.  */
   statement = NULL_TREE;
   /* Peek at the next token.  */
   /* There is no statement yet.  */
   statement = NULL_TREE;
   /* Peek at the next token.  */
@@ -6075,13 +6868,15 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
        {
        case RID_CASE:
        case RID_DEFAULT:
        {
        case RID_CASE:
        case RID_DEFAULT:
-         statement = cp_parser_labeled_statement (parser, in_statement_expr,
-                                                  in_compound);
-         break;
+         /* Looks like a labeled-statement with a case label.
+            Parse the label, and then use tail recursion to parse
+            the statement.  */
+         cp_parser_label_for_labeled_statement (parser);
+         goto restart;
 
        case RID_IF:
        case RID_SWITCH:
 
        case RID_IF:
        case RID_SWITCH:
-         statement = cp_parser_selection_statement (parser);
+         statement = cp_parser_selection_statement (parser, if_p);
          break;
 
        case RID_WHILE:
          break;
 
        case RID_WHILE:
@@ -6110,6 +6905,11 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
          statement = cp_parser_try_block (parser);
          break;
 
          statement = cp_parser_try_block (parser);
          break;
 
+       case RID_NAMESPACE:
+         /* This must be a namespace alias definition.  */
+         cp_parser_declaration_statement (parser);
+         return;
+         
        default:
          /* It might be a keyword like `int' that can start a
             declaration-statement.  */
        default:
          /* It might be a keyword like `int' that can start a
             declaration-statement.  */
@@ -6122,8 +6922,13 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
         labeled-statement.  */
       token = cp_lexer_peek_nth_token (parser->lexer, 2);
       if (token->type == CPP_COLON)
         labeled-statement.  */
       token = cp_lexer_peek_nth_token (parser->lexer, 2);
       if (token->type == CPP_COLON)
-       statement = cp_parser_labeled_statement (parser, in_statement_expr,
-                                                in_compound);
+       {
+         /* Looks like a labeled-statement with an ordinary label.
+            Parse the label, and then use tail recursion to parse
+            the statement.  */
+         cp_parser_label_for_labeled_statement (parser);
+         goto restart;
+       }
     }
   /* Anything that starts with a `{' must be a compound-statement.  */
   else if (token->type == CPP_OPEN_BRACE)
     }
   /* Anything that starts with a `{' must be a compound-statement.  */
   else if (token->type == CPP_OPEN_BRACE)
@@ -6173,30 +6978,23 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
     SET_EXPR_LOCATION (statement, statement_location);
 }
 
     SET_EXPR_LOCATION (statement, statement_location);
 }
 
-/* Parse a labeled-statement.
+/* Parse the label for a labeled-statement, i.e.
 
 
-   labeled-statement:
-     identifier : statement
-     case constant-expression : statement
-     default : statement
+   identifier :
+   case constant-expression :
+   default :
 
    GNU Extension:
 
    GNU Extension:
+   case constant-expression ... constant-expression : statement
 
 
-   labeled-statement:
-     case constant-expression ... constant-expression : statement
+   When a label is parsed without errors, the label is added to the
+   parse tree by the finish_* functions, so this function doesn't
+   have to return the label.  */
 
 
-   Returns the new CASE_LABEL_EXPR, for a `case' or `default' label.
-   For an ordinary label, returns a LABEL_EXPR.
-
-   IN_COMPOUND is as for cp_parser_statement: true when we're nested
-   inside a compound.  */
-
-static tree
-cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
-                            bool in_compound)
+static void
+cp_parser_label_for_labeled_statement (cp_parser* parser)
 {
   cp_token *token;
 {
   cp_token *token;
-  tree statement = error_mark_node;
 
   /* The next token should be an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* The next token should be an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -6204,7 +7002,7 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
       && token->type != CPP_KEYWORD)
     {
       cp_parser_error (parser, "expected labeled-statement");
       && token->type != CPP_KEYWORD)
     {
       cp_parser_error (parser, "expected labeled-statement");
-      return error_mark_node;
+      return;
     }
 
   switch (token->keyword)
     }
 
   switch (token->keyword)
@@ -6237,9 +7035,10 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
          expr_hi = NULL_TREE;
 
        if (parser->in_switch_statement_p)
          expr_hi = NULL_TREE;
 
        if (parser->in_switch_statement_p)
-         statement = finish_case_label (expr, expr_hi);
+         finish_case_label (expr, expr_hi);
        else
        else
-         error ("case label %qE not within a switch statement", expr);
+         error ("%Hcase label %qE not within a switch statement",
+                &token->location, expr);
       }
       break;
 
       }
       break;
 
@@ -6248,24 +7047,19 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
       cp_lexer_consume_token (parser->lexer);
 
       if (parser->in_switch_statement_p)
       cp_lexer_consume_token (parser->lexer);
 
       if (parser->in_switch_statement_p)
-       statement = finish_case_label (NULL_TREE, NULL_TREE);
+       finish_case_label (NULL_TREE, NULL_TREE);
       else
       else
-       error ("case label not within a switch statement");
+       error ("%Hcase label not within a switch statement", &token->location);
       break;
 
     default:
       /* Anything else must be an ordinary label.  */
       break;
 
     default:
       /* Anything else must be an ordinary label.  */
-      statement = finish_label_stmt (cp_parser_identifier (parser));
+      finish_label_stmt (cp_parser_identifier (parser));
       break;
     }
 
   /* Require the `:' token.  */
       break;
     }
 
   /* Require the `:' token.  */
-  cp_parser_require (parser, CPP_COLON, "`:'");
-  /* Parse the labeled statement.  */
-  cp_parser_statement (parser, in_statement_expr, in_compound);
-
-  /* Return the label, in the case of a `case' or `default' label.  */
-  return statement;
+  cp_parser_require (parser, CPP_COLON, "%<:%>");
 }
 
 /* Parse an expression-statement.
 }
 
 /* Parse an expression-statement.
@@ -6309,6 +7103,15 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
    compound-statement:
      { statement-seq [opt] }
 
    compound-statement:
      { statement-seq [opt] }
 
+   GNU extension:
+
+   compound-statement:
+     { label-declaration-seq [opt] statement-seq [opt] }
+
+   label-declaration-seq:
+     label-declaration
+     label-declaration-seq label-declaration
+
    Returns a tree representing the statement.  */
 
 static tree
    Returns a tree representing the statement.  */
 
 static tree
@@ -6318,16 +7121,19 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   tree compound_stmt;
 
   /* Consume the `{'.  */
   tree compound_stmt;
 
   /* Consume the `{'.  */
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
     return error_mark_node;
   /* Begin the compound-statement.  */
   compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
     return error_mark_node;
   /* Begin the compound-statement.  */
   compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
+  /* 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, in_statement_expr);
   /* Finish the compound-statement.  */
   finish_compound_stmt (compound_stmt);
   /* Consume the `}'.  */
   /* Parse an (optional) statement-seq.  */
   cp_parser_statement_seq_opt (parser, in_statement_expr);
   /* Finish the compound-statement.  */
   finish_compound_stmt (compound_stmt);
   /* Consume the `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 
   return compound_stmt;
 }
 
   return compound_stmt;
 }
@@ -6351,9 +7157,22 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
          || token->type == CPP_EOF
          || token->type == CPP_PRAGMA_EOL)
        break;
          || token->type == CPP_EOF
          || token->type == CPP_PRAGMA_EOL)
        break;
+      
+      /* If we are in a compound statement and find 'else' then
+        something went wrong.  */
+      else if (token->type == CPP_KEYWORD && token->keyword == RID_ELSE)
+       {
+         if (parser->in_statement & IN_IF_STMT) 
+           break;
+         else
+           {
+             token = cp_lexer_consume_token (parser->lexer);
+             error ("%H%<else%> without a previous %<if%>", &token->location);
+           }
+       }
 
       /* Parse the statement.  */
 
       /* Parse the statement.  */
-      cp_parser_statement (parser, in_statement_expr, true);
+      cp_parser_statement (parser, in_statement_expr, true, NULL);
     }
 }
 
     }
 }
 
@@ -6364,14 +7183,22 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
      if ( condition ) statement else statement
      switch ( condition ) statement
 
      if ( condition ) statement else statement
      switch ( condition ) statement
 
-   Returns the new IF_STMT or SWITCH_STMT.  */
+   Returns the new IF_STMT or SWITCH_STMT.
+
+   If IF_P is not NULL, *IF_P is set to indicate whether the statement
+   is a (possibly labeled) if statement which is not enclosed in
+   braces and has an else clause.  This is used to implement
+   -Wparentheses.  */
 
 static tree
 
 static tree
-cp_parser_selection_statement (cp_parser* parser)
+cp_parser_selection_statement (cp_parser* parser, bool *if_p)
 {
   cp_token *token;
   enum rid keyword;
 
 {
   cp_token *token;
   enum rid keyword;
 
+  if (if_p != NULL)
+    *if_p = false;
+
   /* Peek at the next token.  */
   token = cp_parser_require (parser, CPP_KEYWORD, "selection-statement");
 
   /* Peek at the next token.  */
   token = cp_parser_require (parser, CPP_KEYWORD, "selection-statement");
 
@@ -6386,7 +7213,7 @@ cp_parser_selection_statement (cp_parser* parser)
        tree condition;
 
        /* Look for the `('.  */
        tree condition;
 
        /* Look for the `('.  */
-       if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+       if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
          {
            cp_parser_skip_to_end_of_statement (parser);
            return error_mark_node;
          {
            cp_parser_skip_to_end_of_statement (parser);
            return error_mark_node;
@@ -6401,17 +7228,35 @@ cp_parser_selection_statement (cp_parser* parser)
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        /* Look for the `)'.  */
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        /* Look for the `)'.  */
-       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
          cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                                 /*consume_paren=*/true);
 
        if (keyword == RID_IF)
          {
          cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                                 /*consume_paren=*/true);
 
        if (keyword == RID_IF)
          {
+           bool nested_if;
+           unsigned char in_statement;
+
            /* Add the condition.  */
            finish_if_stmt_cond (condition, statement);
 
            /* Parse the then-clause.  */
            /* Add the condition.  */
            finish_if_stmt_cond (condition, statement);
 
            /* Parse the then-clause.  */
-           cp_parser_implicitly_scoped_statement (parser);
+           in_statement = parser->in_statement;
+           parser->in_statement |= IN_IF_STMT;
+           if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+             {
+               location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+               add_stmt (build_empty_stmt ());
+               cp_lexer_consume_token (parser->lexer);
+               if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
+                 warning_at (loc, OPT_Wempty_body, "suggest braces around "
+                             "empty body in an %<if%> statement");
+               nested_if = false;
+             }
+           else
+             cp_parser_implicitly_scoped_statement (parser, &nested_if);
+           parser->in_statement = in_statement;
+
            finish_then_clause (statement);
 
            /* If the next token is `else', parse the else-clause.  */
            finish_then_clause (statement);
 
            /* If the next token is `else', parse the else-clause.  */
@@ -6422,8 +7267,38 @@ cp_parser_selection_statement (cp_parser* parser)
                cp_lexer_consume_token (parser->lexer);
                begin_else_clause (statement);
                /* Parse the else-clause.  */
                cp_lexer_consume_token (parser->lexer);
                begin_else_clause (statement);
                /* Parse the else-clause.  */
-               cp_parser_implicitly_scoped_statement (parser);
+               if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+                 {
+                   warning_at (cp_lexer_peek_token (parser->lexer)->location,
+                               OPT_Wempty_body, "suggest braces around "
+                               "empty body in an %<else%> statement");
+                   add_stmt (build_empty_stmt ());
+                   cp_lexer_consume_token (parser->lexer);
+                 }
+               else
+                 cp_parser_implicitly_scoped_statement (parser, NULL);
+
                finish_else_clause (statement);
                finish_else_clause (statement);
+
+               /* If we are currently parsing a then-clause, then
+                  IF_P will not be NULL.  We set it to true to
+                  indicate that this if statement has an else clause.
+                  This may trigger the Wparentheses warning below
+                  when we get back up to the parent if statement.  */
+               if (if_p != NULL)
+                 *if_p = true;
+             }
+           else
+             {
+               /* This if statement does not have an else clause.  If
+                  NESTED_IF is true, then the then-clause is an if
+                  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));
              }
 
            /* Now we're all done with the if-statement.  */
              }
 
            /* Now we're all done with the if-statement.  */
@@ -6442,7 +7317,7 @@ cp_parser_selection_statement (cp_parser* parser)
            in_statement = parser->in_statement;
            parser->in_switch_statement_p = true;
            parser->in_statement |= IN_SWITCH_STMT;
            in_statement = parser->in_statement;
            parser->in_switch_statement_p = true;
            parser->in_statement |= IN_SWITCH_STMT;
-           cp_parser_implicitly_scoped_statement (parser);
+           cp_parser_implicitly_scoped_statement (parser, NULL);
            parser->in_switch_statement_p = in_switch_statement_p;
            parser->in_statement = in_statement;
 
            parser->in_switch_statement_p = in_switch_statement_p;
            parser->in_statement = in_statement;
 
@@ -6464,7 +7339,8 @@ cp_parser_selection_statement (cp_parser* parser)
 
    condition:
      expression
 
    condition:
      expression
-     type-specifier-seq declarator = assignment-expression
+     type-specifier-seq declarator = initializer-clause
+     type-specifier-seq declarator braced-init-list
 
    GNU Extension:
 
 
    GNU Extension:
 
@@ -6510,31 +7386,47 @@ cp_parser_condition (cp_parser* parser)
       attributes = cp_parser_attributes_opt (parser);
       /* Parse the asm-specification.  */
       asm_specification = cp_parser_asm_specification_opt (parser);
       attributes = cp_parser_attributes_opt (parser);
       /* Parse the asm-specification.  */
       asm_specification = cp_parser_asm_specification_opt (parser);
-      /* If the next token is not an `=', then we might still be
+      /* If the next token is not an `=' or '{', then we might still be
         looking at an expression.  For example:
 
           if (A(a).x)
 
         looks like a decl-specifier-seq and a declarator -- but then
         there is no `=', so this is an expression.  */
         looking at an expression.  For example:
 
           if (A(a).x)
 
         looks like a decl-specifier-seq and a declarator -- but then
         there is no `=', so this is an expression.  */
-      cp_parser_require (parser, CPP_EQ, "`='");
-      /* If we did see an `=', then we are looking at a declaration
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
+         && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+       cp_parser_simulate_error (parser);
+       
+      /* If we did see an `=' or '{', then we are looking at a declaration
         for sure.  */
       if (cp_parser_parse_definitely (parser))
        {
          tree pushed_scope;
          bool non_constant_p;
         for sure.  */
       if (cp_parser_parse_definitely (parser))
        {
          tree pushed_scope;
          bool non_constant_p;
+         bool flags = LOOKUP_ONLYCONVERTING;
 
          /* Create the declaration.  */
          decl = start_decl (declarator, &type_specifiers,
                             /*initialized_p=*/true,
                             attributes, /*prefix_attributes=*/NULL_TREE,
                             &pushed_scope);
 
          /* Create the declaration.  */
          decl = start_decl (declarator, &type_specifiers,
                             /*initialized_p=*/true,
                             attributes, /*prefix_attributes=*/NULL_TREE,
                             &pushed_scope);
-         /* Parse the assignment-expression.  */
-         initializer
-           = cp_parser_constant_expression (parser,
-                                            /*allow_non_constant_p=*/true,
-                                            &non_constant_p);
+
+         /* Parse the initializer.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+           {
+             initializer = cp_parser_braced_list (parser, &non_constant_p);
+             CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1;
+             flags = 0;
+           }
+         else
+           {
+             /* Consume the `='.  */
+             cp_parser_require (parser, CPP_EQ, "%<=%>");
+             initializer = cp_parser_initializer_clause (parser, &non_constant_p);
+           }
+         if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
+           maybe_warn_cpp0x ("extended initializer lists");
+
          if (!non_constant_p)
            initializer = fold_non_dependent_expr (initializer);
 
          if (!non_constant_p)
            initializer = fold_non_dependent_expr (initializer);
 
@@ -6542,7 +7434,7 @@ cp_parser_condition (cp_parser* parser)
          cp_finish_decl (decl,
                          initializer, !non_constant_p,
                          asm_specification,
          cp_finish_decl (decl,
                          initializer, !non_constant_p,
                          asm_specification,
-                         LOOKUP_ONLYCONVERTING);
+                         flags);
 
          if (pushed_scope)
            pop_scope (pushed_scope);
 
          if (pushed_scope)
            pop_scope (pushed_scope);
@@ -6597,12 +7489,12 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Begin the while-statement.  */
        statement = begin_while_stmt ();
        /* Look for the `('.  */
        /* Begin the while-statement.  */
        statement = begin_while_stmt ();
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        finish_while_stmt_cond (condition, statement);
        /* Look for the `)'.  */
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        finish_while_stmt_cond (condition, statement);
        /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
        /* Parse the dependent statement.  */
        parser->in_statement = IN_ITERATION_STMT;
        cp_parser_already_scoped_statement (parser);
        /* Parse the dependent statement.  */
        parser->in_statement = IN_ITERATION_STMT;
        cp_parser_already_scoped_statement (parser);
@@ -6620,21 +7512,21 @@ cp_parser_iteration_statement (cp_parser* parser)
        statement = begin_do_stmt ();
        /* Parse the body of the do-statement.  */
        parser->in_statement = IN_ITERATION_STMT;
        statement = begin_do_stmt ();
        /* Parse the body of the do-statement.  */
        parser->in_statement = IN_ITERATION_STMT;
-       cp_parser_implicitly_scoped_statement (parser);
+       cp_parser_implicitly_scoped_statement (parser, NULL);
        parser->in_statement = in_statement;
        finish_do_body (statement);
        /* Look for the `while' keyword.  */
        parser->in_statement = in_statement;
        finish_do_body (statement);
        /* Look for the `while' keyword.  */
-       cp_parser_require_keyword (parser, RID_WHILE, "`while'");
+       cp_parser_require_keyword (parser, RID_WHILE, "%<while%>");
        /* Look for the `('.  */
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Parse the expression.  */
        expression = cp_parser_expression (parser, /*cast_p=*/false);
        /* We're done with the do-statement.  */
        finish_do_stmt (expression, statement);
        /* Look for the `)'.  */
        /* Parse the expression.  */
        expression = cp_parser_expression (parser, /*cast_p=*/false);
        /* We're done with the do-statement.  */
        finish_do_stmt (expression, statement);
        /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
        /* Look for the `;'.  */
        /* Look for the `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       }
       break;
 
       }
       break;
 
@@ -6646,7 +7538,7 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Begin the for-statement.  */
        statement = begin_for_stmt ();
        /* Look for the `('.  */
        /* Begin the for-statement.  */
        statement = begin_for_stmt ();
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Parse the initialization.  */
        cp_parser_for_init_statement (parser);
        finish_for_init_stmt (statement);
        /* Parse the initialization.  */
        cp_parser_for_init_statement (parser);
        finish_for_init_stmt (statement);
@@ -6656,14 +7548,14 @@ cp_parser_iteration_statement (cp_parser* parser)
          condition = cp_parser_condition (parser);
        finish_for_cond (condition, statement);
        /* Look for the `;'.  */
          condition = cp_parser_condition (parser);
        finish_for_cond (condition, statement);
        /* Look for the `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
        /* If there's an expression, process it.  */
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
          expression = cp_parser_expression (parser, /*cast_p=*/false);
        finish_for_expr (expression, statement);
        /* Look for the `)'.  */
 
        /* If there's an expression, process it.  */
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
          expression = cp_parser_expression (parser, /*cast_p=*/false);
        finish_for_expr (expression, statement);
        /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
        /* Parse the body of the for-statement.  */
        parser->in_statement = IN_ITERATION_STMT;
 
        /* Parse the body of the for-statement.  */
        parser->in_statement = IN_ITERATION_STMT;
@@ -6722,6 +7614,7 @@ cp_parser_for_init_statement (cp_parser* parser)
      break ;
      continue ;
      return expression [opt] ;
      break ;
      continue ;
      return expression [opt] ;
+     return braced-init-list ;
      goto identifier ;
 
    GNU extension:
      goto identifier ;
 
    GNU extension:
@@ -6737,6 +7630,7 @@ cp_parser_jump_statement (cp_parser* parser)
   tree statement = error_mark_node;
   cp_token *token;
   enum rid keyword;
   tree statement = error_mark_node;
   cp_token *token;
   enum rid keyword;
+  unsigned char in_statement;
 
   /* Peek at the next token.  */
   token = cp_parser_require (parser, CPP_KEYWORD, "jump-statement");
 
   /* Peek at the next token.  */
   token = cp_parser_require (parser, CPP_KEYWORD, "jump-statement");
@@ -6748,38 +7642,39 @@ cp_parser_jump_statement (cp_parser* parser)
   switch (keyword)
     {
     case RID_BREAK:
   switch (keyword)
     {
     case RID_BREAK:
-      switch (parser->in_statement)
+      in_statement = parser->in_statement & ~IN_IF_STMT;      
+      switch (in_statement)
        {
        case 0:
        {
        case 0:
-         error ("break statement not within loop or switch");
+         error ("%Hbreak statement not within loop or switch", &token->location);
          break;
        default:
          break;
        default:
-         gcc_assert ((parser->in_statement & IN_SWITCH_STMT)
-                     || parser->in_statement == IN_ITERATION_STMT);
+         gcc_assert ((in_statement & IN_SWITCH_STMT)
+                     || in_statement == IN_ITERATION_STMT);
          statement = finish_break_stmt ();
          break;
        case IN_OMP_BLOCK:
          statement = finish_break_stmt ();
          break;
        case IN_OMP_BLOCK:
-         error ("invalid exit from OpenMP structured block");
+         error ("%Hinvalid exit from OpenMP structured block", &token->location);
          break;
        case IN_OMP_FOR:
          break;
        case IN_OMP_FOR:
-         error ("break statement used with OpenMP for loop");
+         error ("%Hbreak statement used with OpenMP for loop", &token->location);
          break;
        }
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       break;
 
     case RID_CONTINUE:
          break;
        }
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       break;
 
     case RID_CONTINUE:
-      switch (parser->in_statement & ~IN_SWITCH_STMT)
+      switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
        {
        case 0:
        {
        case 0:
-         error ("continue statement not within a loop");
+         error ("%Hcontinue statement not within a loop", &token->location);
          break;
        case IN_ITERATION_STMT:
        case IN_OMP_FOR:
          statement = finish_continue_stmt ();
          break;
        case IN_OMP_BLOCK:
          break;
        case IN_ITERATION_STMT:
        case IN_OMP_FOR:
          statement = finish_continue_stmt ();
          break;
        case IN_OMP_BLOCK:
-         error ("invalid exit from OpenMP structured block");
+         error ("%Hinvalid exit from OpenMP structured block", &token->location);
          break;
        default:
          gcc_unreachable ();
          break;
        default:
          gcc_unreachable ();
@@ -6790,12 +7685,18 @@ cp_parser_jump_statement (cp_parser* parser)
     case RID_RETURN:
       {
        tree expr;
     case RID_RETURN:
       {
        tree expr;
+       bool expr_non_constant_p;
 
 
-       /* If the next token is a `;', then there is no
-          expression.  */
-       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+         {
+           maybe_warn_cpp0x ("extended initializer lists");
+           expr = cp_parser_braced_list (parser, &expr_non_constant_p);
+         }
+       else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
          expr = cp_parser_expression (parser, /*cast_p=*/false);
        else
          expr = cp_parser_expression (parser, /*cast_p=*/false);
        else
+         /* If the next token is a `;', then there is no
+            expression.  */
          expr = NULL_TREE;
        /* Build the return-statement.  */
        statement = finish_return_stmt (expr);
          expr = NULL_TREE;
        /* Build the return-statement.  */
        statement = finish_return_stmt (expr);
@@ -6809,8 +7710,7 @@ cp_parser_jump_statement (cp_parser* parser)
       if (cp_lexer_next_token_is (parser->lexer, CPP_MULT))
        {
          /* Issue a warning about this use of a GNU extension.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_MULT))
        {
          /* Issue a warning about this use of a GNU extension.  */
-         if (pedantic)
-           pedwarn ("ISO C++ forbids computed gotos");
+         pedwarn (token->location, OPT_pedantic, "ISO C++ forbids computed gotos");
          /* Consume the '*' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Parse the dependent expression.  */
          /* Consume the '*' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Parse the dependent expression.  */
@@ -6862,13 +7762,21 @@ cp_parser_declaration_statement (cp_parser* parser)
    but ensures that is in its own scope, even if it is not a
    compound-statement.
 
    but ensures that is in its own scope, even if it is not a
    compound-statement.
 
+   If IF_P is not NULL, *IF_P is set to indicate whether the statement
+   is a (possibly labeled) if statement which is not enclosed in
+   braces and has an else clause.  This is used to implement
+   -Wparentheses.
+
    Returns the new statement.  */
 
 static tree
    Returns the new statement.  */
 
 static tree
-cp_parser_implicitly_scoped_statement (cp_parser* parser)
+cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p)
 {
   tree statement;
 
 {
   tree statement;
 
+  if (if_p != NULL)
+    *if_p = false;
+
   /* Mark if () ; with a special NOP_EXPR.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
     {
   /* Mark if () ; with a special NOP_EXPR.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
     {
@@ -6884,7 +7792,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
       /* Create a compound-statement.  */
       statement = begin_compound_stmt (0);
       /* Parse the dependent-statement.  */
       /* Create a compound-statement.  */
       statement = begin_compound_stmt (0);
       /* Parse the dependent-statement.  */
-      cp_parser_statement (parser, NULL_TREE, false);
+      cp_parser_statement (parser, NULL_TREE, false, if_p);
       /* Finish the dummy compound-statement.  */
       finish_compound_stmt (statement);
     }
       /* Finish the dummy compound-statement.  */
       finish_compound_stmt (statement);
     }
@@ -6903,14 +7811,14 @@ cp_parser_already_scoped_statement (cp_parser* parser)
 {
   /* If the token is a `{', then we must take special action.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
 {
   /* If the token is a `{', then we must take special action.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
-    cp_parser_statement (parser, NULL_TREE, false);
+    cp_parser_statement (parser, NULL_TREE, false, NULL);
   else
     {
       /* Avoid calling cp_parser_compound_statement, so that we
         don't create a new scope.  Do everything else by hand.  */
   else
     {
       /* Avoid calling cp_parser_compound_statement, so that we
         don't create a new scope.  Do everything else by hand.  */
-      cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+      cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
       cp_parser_statement_seq_opt (parser, NULL_TREE);
       cp_parser_statement_seq_opt (parser, NULL_TREE);
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
     }
 }
 
     }
 }
 
@@ -6941,8 +7849,8 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
          /* A declaration consisting of a single semicolon is
             invalid.  Allow it unless we're being pedantic.  */
          cp_lexer_consume_token (parser->lexer);
          /* A declaration consisting of a single semicolon is
             invalid.  Allow it unless we're being pedantic.  */
          cp_lexer_consume_token (parser->lexer);
-         if (pedantic && !in_system_header)
-           pedwarn ("extra %<;%>");
+         if (!in_system_header)
+           pedwarn (input_location, OPT_pedantic, "extra %<;%>");
          continue;
        }
 
          continue;
        }
 
@@ -7068,6 +7976,10 @@ cp_parser_declaration (cp_parser* parser)
               || token2.type == CPP_OPEN_BRACE
               || token2.keyword == RID_ATTRIBUTE))
     cp_parser_namespace_definition (parser);
               || token2.type == CPP_OPEN_BRACE
               || token2.keyword == RID_ATTRIBUTE))
     cp_parser_namespace_definition (parser);
+  /* An inline (associated) namespace definition.  */
+  else if (token1.keyword == RID_INLINE
+          && token2.keyword == RID_NAMESPACE)
+    cp_parser_namespace_definition (parser);
   /* Objective-C++ declaration/definition.  */
   else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
     cp_parser_objc_declaration (parser);
   /* Objective-C++ declaration/definition.  */
   else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
     cp_parser_objc_declaration (parser);
@@ -7094,7 +8006,11 @@ cp_parser_declaration (cp_parser* parser)
 
    block-declaration:
      __extension__ block-declaration
 
    block-declaration:
      __extension__ block-declaration
-     label-declaration
+
+   C++0x Extension:
+
+   block-declaration:
+     static_assert-declaration
 
    If STATEMENT_P is TRUE, then this block-declaration is occurring as
    part of a declaration-statement.  */
 
    If STATEMENT_P is TRUE, then this block-declaration is occurring as
    part of a declaration-statement.  */
@@ -7147,15 +8063,23 @@ cp_parser_block_declaration (cp_parser *parser,
        cp_parser_using_directive (parser);
       /* Otherwise, it's a using-declaration.  */
       else
        cp_parser_using_directive (parser);
       /* Otherwise, it's a using-declaration.  */
       else
-       cp_parser_using_declaration (parser);
+       cp_parser_using_declaration (parser,
+                                    /*access_declaration_p=*/false);
     }
     }
-  /* If the next keyword is `__label__' we have a label declaration.  */
+  /* If the next keyword is `__label__' we have a misplaced label
+     declaration.  */
   else if (token1->keyword == RID_LABEL)
     {
   else if (token1->keyword == RID_LABEL)
     {
-      if (statement_p)
-       cp_parser_commit_to_tentative_parse (parser);
-      cp_parser_label_declaration (parser);
+      cp_lexer_consume_token (parser->lexer);
+      error ("%H%<__label__%> not at the beginning of a block", &token1->location);
+      cp_parser_skip_to_end_of_statement (parser);
+      /* If the next token is now a `;', consume it.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+       cp_lexer_consume_token (parser->lexer);
     }
     }
+  /* If the next token is `static_assert' we have a static assertion.  */
+  else if (token1->keyword == RID_STATIC_ASSERT)
+    cp_parser_static_assert (parser, /*member_p=*/false);
   /* Anything else must be a simple-declaration.  */
   else
     cp_parser_simple_declaration (parser, !statement_p);
   /* Anything else must be a simple-declaration.  */
   else
     cp_parser_simple_declaration (parser, !statement_p);
@@ -7234,7 +8158,9 @@ cp_parser_simple_declaration (cp_parser* parser,
      is not a parenthesis, then we must be looking at a declaration.
      (After "int (" we might be looking at a functional cast.)  */
   if (decl_specifiers.any_specifiers_p
      is not a parenthesis, then we must be looking at a declaration.
      (After "int (" we might be looking at a functional cast.)  */
   if (decl_specifiers.any_specifiers_p
-      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
+      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)
+      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
+      && !cp_parser_error_occurred (parser))
     cp_parser_commit_to_tentative_parse (parser);
 
   /* Keep going until we hit the `;' at the end of the simple
     cp_parser_commit_to_tentative_parse (parser);
 
   /* Keep going until we hit the `;' at the end of the simple
@@ -7259,7 +8185,7 @@ cp_parser_simple_declaration (cp_parser* parser,
 
       /* Parse the init-declarator.  */
       decl = cp_parser_init_declarator (parser, &decl_specifiers,
 
       /* Parse the init-declarator.  */
       decl = cp_parser_init_declarator (parser, &decl_specifiers,
-                                       /*checks=*/NULL_TREE,
+                                       /*checks=*/NULL,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
                                        declares_class_or_enum,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
                                        declares_class_or_enum,
@@ -7280,7 +8206,11 @@ cp_parser_simple_declaration (cp_parser* parser,
 
             which is erroneous.  */
          if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
 
             which is erroneous.  */
          if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-           error ("mixing declarations and function-definitions is forbidden");
+           {
+             cp_token *token = cp_lexer_peek_token (parser->lexer);
+             error ("%Hmixing declarations and function-definitions is forbidden",
+                    &token->location);
+           }
          /* Otherwise, we're done with the list of declarators.  */
          else
            {
          /* Otherwise, we're done with the list of declarators.  */
          else
            {
@@ -7332,7 +8262,7 @@ cp_parser_simple_declaration (cp_parser* parser,
     }
 
   /* Consume the `;'.  */
     }
 
   /* Consume the `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
  done:
   pop_deferring_access_checks ();
 
  done:
   pop_deferring_access_checks ();
@@ -7376,7 +8306,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
                              int* declares_class_or_enum)
 {
   bool constructor_possible_p = !parser->in_declarator_p;
                              int* declares_class_or_enum)
 {
   bool constructor_possible_p = !parser->in_declarator_p;
-  cp_decl_spec ds;
+  cp_token *start_token = NULL;
 
   /* Clear DECL_SPECS.  */
   clear_decl_specs (decl_specs);
 
   /* Clear DECL_SPECS.  */
   clear_decl_specs (decl_specs);
@@ -7393,6 +8323,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
+
+      /* Save the first token of the decl spec list for error
+         reporting.  */
+      if (!start_token)
+       start_token = token;
       /* Handle attributes.  */
       if (token->keyword == RID_ATTRIBUTE)
        {
       /* Handle attributes.  */
       if (token->keyword == RID_ATTRIBUTE)
        {
@@ -7413,7 +8348,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
        case RID_FRIEND:
          if (!at_class_scope_p ())
            {
        case RID_FRIEND:
          if (!at_class_scope_p ())
            {
-             error ("%<friend%> used outside of class");
+             error ("%H%<friend%> used outside of class", &token->location);
              cp_lexer_purge_token (parser->lexer);
            }
          else
              cp_lexer_purge_token (parser->lexer);
            }
          else
@@ -7445,6 +8380,9 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
          /* The "typedef" keyword can only occur in a declaration; we
             may as well commit at this point.  */
          cp_parser_commit_to_tentative_parse (parser);
          /* The "typedef" keyword can only occur in a declaration; we
             may as well commit at this point.  */
          cp_parser_commit_to_tentative_parse (parser);
+
+          if (decl_specs->storage_class != sc_none)
+            decl_specs->conflicting_specifiers_p = true;
          break;
 
          /* storage-class-specifier:
          break;
 
          /* storage-class-specifier:
@@ -7457,13 +8395,35 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
             GNU Extension:
               thread  */
        case RID_AUTO:
             GNU Extension:
               thread  */
        case RID_AUTO:
+          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);
+
+              /* Set the storage class anyway.  */
+              cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
+                                          token->location);
+            }
+          else
+           /* C++0x auto type-specifier.  */
+           found_decl_spec = false;
+          break;
+
        case RID_REGISTER:
        case RID_STATIC:
        case RID_EXTERN:
        case RID_MUTABLE:
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
        case RID_REGISTER:
        case RID_STATIC:
        case RID_EXTERN:
        case RID_MUTABLE:
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
-         cp_parser_set_storage_class (parser, decl_specs, token->keyword);
+          cp_parser_set_storage_class (parser, decl_specs, token->keyword,
+                                      token->location);
          break;
        case RID_THREAD:
          /* Consume the token.  */
          break;
        case RID_THREAD:
          /* Consume the token.  */
@@ -7499,7 +8459,6 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
                                        /*is_declaration=*/true,
                                        &decl_spec_declares_class_or_enum,
                                        &is_cv_qualifier);
                                        /*is_declaration=*/true,
                                        &decl_spec_declares_class_or_enum,
                                        &is_cv_qualifier);
-
          *declares_class_or_enum |= decl_spec_declares_class_or_enum;
 
          /* If this type-specifier referenced a user-defined type
          *declares_class_or_enum |= decl_spec_declares_class_or_enum;
 
          /* If this type-specifier referenced a user-defined type
@@ -7559,46 +8518,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
-  /* Check for repeated decl-specifiers.  */
-  for (ds = ds_first; ds != ds_last; ++ds)
-    {
-      unsigned count = decl_specs->specs[(int)ds];
-      if (count < 2)
-       continue;
-      /* The "long" specifier is a special case because of "long long".  */
-      if (ds == ds_long)
-       {
-         if (count > 2)
-           error ("%<long long long%> is too long for GCC");
-         else if (pedantic && !in_system_header && warn_long_long)
-           pedwarn ("ISO C++ does not support %<long long%>");
-       }
-      else if (count > 1)
-       {
-         static const char *const decl_spec_names[] = {
-           "signed",
-           "unsigned",
-           "short",
-           "long",
-           "const",
-           "volatile",
-           "restrict",
-           "inline",
-           "virtual",
-           "explicit",
-           "friend",
-           "typedef",
-           "__complex",
-           "__thread"
-         };
-         error ("duplicate %qs", decl_spec_names[(int)ds]);
-       }
-    }
+  cp_parser_check_decl_spec (decl_specs, start_token->location);
 
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
 
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
-    error ("class definition may not be declared a friend");
+    error ("%Hclass definition may not be declared a friend",
+           &start_token->location);
 }
 
 /* Parse an (optional) storage-class-specifier.
 }
 
 /* Parse an (optional) storage-class-specifier.
@@ -7623,13 +8549,17 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
   switch (cp_lexer_peek_token (parser->lexer)->keyword)
     {
     case RID_AUTO:
   switch (cp_lexer_peek_token (parser->lexer)->keyword)
     {
     case RID_AUTO:
+      if (cxx_dialect != cxx98)
+        return NULL_TREE;
+      /* Fall through for C++98.  */
+
     case RID_REGISTER:
     case RID_STATIC:
     case RID_EXTERN:
     case RID_MUTABLE:
     case RID_THREAD:
       /* Consume the token.  */
     case RID_REGISTER:
     case RID_STATIC:
     case RID_EXTERN:
     case RID_MUTABLE:
     case RID_THREAD:
       /* Consume the token.  */
-      return cp_lexer_consume_token (parser->lexer)->value;
+      return cp_lexer_consume_token (parser->lexer)->u.value;
 
     default:
       return NULL_TREE;
 
     default:
       return NULL_TREE;
@@ -7650,7 +8580,8 @@ static tree
 cp_parser_function_specifier_opt (cp_parser* parser,
                                  cp_decl_specifier_seq *decl_specs)
 {
 cp_parser_function_specifier_opt (cp_parser* parser,
                                  cp_decl_specifier_seq *decl_specs)
 {
-  switch (cp_lexer_peek_token (parser->lexer)->keyword)
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  switch (token->keyword)
     {
     case RID_INLINE:
       if (decl_specs)
     {
     case RID_INLINE:
       if (decl_specs)
@@ -7662,7 +8593,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
 
         A member function template shall not be virtual.  */
       if (PROCESSING_REAL_TEMPLATE_DECL_P ())
 
         A member function template shall not be virtual.  */
       if (PROCESSING_REAL_TEMPLATE_DECL_P ())
-       error ("templates may not be %<virtual%>");
+       error ("%Htemplates may not be %<virtual%>", &token->location);
       else if (decl_specs)
        ++decl_specs->specs[(int) ds_virtual];
       break;
       else if (decl_specs)
        ++decl_specs->specs[(int) ds_virtual];
       break;
@@ -7677,7 +8608,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
     }
 
   /* Consume the token.  */
     }
 
   /* Consume the token.  */
-  return cp_lexer_consume_token (parser->lexer)->value;
+  return cp_lexer_consume_token (parser->lexer)->u.value;
 }
 
 /* Parse a linkage-specification.
 }
 
 /* Parse a linkage-specification.
@@ -7692,7 +8623,7 @@ cp_parser_linkage_specification (cp_parser* parser)
   tree linkage;
 
   /* Look for the `extern' keyword.  */
   tree linkage;
 
   /* Look for the `extern' keyword.  */
-  cp_parser_require_keyword (parser, RID_EXTERN, "`extern'");
+  cp_parser_require_keyword (parser, RID_EXTERN, "%<extern%>");
 
   /* Look for the string-literal.  */
   linkage = cp_parser_string_literal (parser, false, false);
 
   /* Look for the string-literal.  */
   linkage = cp_parser_string_literal (parser, false, false);
@@ -7722,7 +8653,7 @@ cp_parser_linkage_specification (cp_parser* parser)
       /* Parse the declarations.  */
       cp_parser_declaration_seq_opt (parser);
       /* Look for the closing `}'.  */
       /* Parse the declarations.  */
       cp_parser_declaration_seq_opt (parser);
       /* Look for the closing `}'.  */
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
     }
   /* Otherwise, there's just one declaration.  */
   else
     }
   /* Otherwise, there's just one declaration.  */
   else
@@ -7741,6 +8672,237 @@ cp_parser_linkage_specification (cp_parser* parser)
   pop_lang_context ();
 }
 
   pop_lang_context ();
 }
 
+/* Parse a static_assert-declaration.
+
+   static_assert-declaration:
+     static_assert ( constant-expression , string-literal ) ; 
+
+   If MEMBER_P, this static_assert is a class member.  */
+
+static void 
+cp_parser_static_assert(cp_parser *parser, bool member_p)
+{
+  tree condition;
+  tree message;
+  cp_token *token;
+  location_t saved_loc;
+
+  /* Peek at the `static_assert' token so we can keep track of exactly
+     where the static assertion started.  */
+  token = cp_lexer_peek_token (parser->lexer);
+  saved_loc = token->location;
+
+  /* Look for the `static_assert' keyword.  */
+  if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, 
+                                  "%<static_assert%>"))
+    return;
+
+  /*  We know we are in a static assertion; commit to any tentative
+      parse.  */
+  if (cp_parser_parsing_tentatively (parser))
+    cp_parser_commit_to_tentative_parse (parser);
+
+  /* Parse the `(' starting the static assertion condition.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+
+  /* Parse the constant-expression.  */
+  condition = 
+    cp_parser_constant_expression (parser,
+                                   /*allow_non_constant_p=*/false,
+                                   /*non_constant_p=*/NULL);
+
+  /* Parse the separating `,'.  */
+  cp_parser_require (parser, CPP_COMMA, "%<,%>");
+
+  /* Parse the string-literal message.  */
+  message = cp_parser_string_literal (parser, 
+                                      /*translate=*/false,
+                                      /*wide_ok=*/true);
+
+  /* A `)' completes the static assertion.  */
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+    cp_parser_skip_to_closing_parenthesis (parser, 
+                                           /*recovering=*/true, 
+                                           /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  /* A semicolon terminates the declaration.  */
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+
+  /* Complete the static assertion, which may mean either processing 
+     the static assert now or saving it for template instantiation.  */
+  finish_static_assert (condition, message, saved_loc, member_p);
+}
+
+/* Parse a `decltype' type. Returns the type. 
+
+   simple-type-specifier:
+     decltype ( expression )  */
+
+static tree
+cp_parser_decltype (cp_parser *parser)
+{
+  tree expr;
+  bool id_expression_or_member_access_p = false;
+  const char *saved_message;
+  bool saved_integral_constant_expression_p;
+  bool saved_non_integral_constant_expression_p;
+  cp_token *id_expr_start_token;
+
+  /* Look for the `decltype' token.  */
+  if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
+    return error_mark_node;
+
+  /* Types cannot be defined in a `decltype' expression.  Save away the
+     old message.  */
+  saved_message = parser->type_definition_forbidden_message;
+
+  /* And create the new one.  */
+  parser->type_definition_forbidden_message
+    = "types may not be defined in %<decltype%> expressions";
+
+  /* The restrictions on constant-expressions do not apply inside
+     decltype expressions.  */
+  saved_integral_constant_expression_p
+    = parser->integral_constant_expression_p;
+  saved_non_integral_constant_expression_p
+    = parser->non_integral_constant_expression_p;
+  parser->integral_constant_expression_p = false;
+
+  /* Do not actually evaluate the expression.  */
+  ++skip_evaluation;
+
+  /* Parse the opening `('.  */
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+    return error_mark_node;
+  
+  /* First, try parsing an id-expression.  */
+  id_expr_start_token = cp_lexer_peek_token (parser->lexer);
+  cp_parser_parse_tentatively (parser);
+  expr = cp_parser_id_expression (parser,
+                                  /*template_keyword_p=*/false,
+                                  /*check_dependency_p=*/true,
+                                  /*template_p=*/NULL,
+                                  /*declarator_p=*/false,
+                                  /*optional_p=*/false);
+
+  if (!cp_parser_error_occurred (parser) && expr != error_mark_node)
+    {
+      bool non_integral_constant_expression_p = false;
+      tree id_expression = expr;
+      cp_id_kind idk;
+      const char *error_msg;
+
+      if (TREE_CODE (expr) == IDENTIFIER_NODE)
+       /* Lookup the name we got back from the id-expression.  */
+       expr = cp_parser_lookup_name (parser, expr,
+                                     none_type,
+                                     /*is_template=*/false,
+                                     /*is_namespace=*/false,
+                                     /*check_dependency=*/true,
+                                     /*ambiguous_decls=*/NULL,
+                                     id_expr_start_token->location);
+
+      if (expr
+          && expr != error_mark_node
+          && TREE_CODE (expr) != TEMPLATE_ID_EXPR
+          && TREE_CODE (expr) != TYPE_DECL
+         && (TREE_CODE (expr) != BIT_NOT_EXPR
+             || !TYPE_P (TREE_OPERAND (expr, 0)))
+          && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+        {
+          /* Complete lookup of the id-expression.  */
+          expr = (finish_id_expression
+                  (id_expression, expr, parser->scope, &idk,
+                   /*integral_constant_expression_p=*/false,
+                   /*allow_non_integral_constant_expression_p=*/true,
+                   &non_integral_constant_expression_p,
+                   /*template_p=*/false,
+                   /*done=*/true,
+                   /*address_p=*/false,
+                   /*template_arg_p=*/false,
+                   &error_msg,
+                  id_expr_start_token->location));
+
+          if (expr == error_mark_node)
+            /* We found an id-expression, but it was something that we
+               should not have found. This is an error, not something
+               we can recover from, so note that we found an
+               id-expression and we'll recover as gracefully as
+               possible.  */
+            id_expression_or_member_access_p = true;
+        }
+
+      if (expr 
+          && expr != error_mark_node
+          && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+        /* We have an id-expression.  */
+        id_expression_or_member_access_p = true;
+    }
+
+  if (!id_expression_or_member_access_p)
+    {
+      /* Abort the id-expression parse.  */
+      cp_parser_abort_tentative_parse (parser);
+
+      /* Parsing tentatively, again.  */
+      cp_parser_parse_tentatively (parser);
+
+      /* Parse a class member access.  */
+      expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
+                                           /*cast_p=*/false,
+                                           /*member_access_only_p=*/true);
+
+      if (expr 
+          && expr != error_mark_node
+          && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+        /* We have an id-expression.  */
+        id_expression_or_member_access_p = true;
+    }
+
+  if (id_expression_or_member_access_p)
+    /* We have parsed the complete id-expression or member access.  */
+    cp_parser_parse_definitely (parser);
+  else
+    {
+      /* Abort our attempt to parse an id-expression or member access
+         expression.  */
+      cp_parser_abort_tentative_parse (parser);
+
+      /* Parse a full expression.  */
+      expr = cp_parser_expression (parser, /*cast_p=*/false);
+    }
+
+  /* Go back to evaluating expressions.  */
+  --skip_evaluation;
+
+  /* Restore the old message and the integral constant expression
+     flags.  */
+  parser->type_definition_forbidden_message = saved_message;
+  parser->integral_constant_expression_p
+    = saved_integral_constant_expression_p;
+  parser->non_integral_constant_expression_p
+    = saved_non_integral_constant_expression_p;
+
+  if (expr == error_mark_node)
+    {
+      /* Skip everything up to the closing `)'.  */
+      cp_parser_skip_to_closing_parenthesis (parser, true, false,
+                                             /*consume_paren=*/true);
+      return error_mark_node;
+    }
+  
+  /* Parse to the closing `)'.  */
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+    {
+      cp_parser_skip_to_closing_parenthesis (parser, true, false,
+                                            /*consume_paren=*/true);
+      return error_mark_node;
+    }
+
+  return finish_decltype_type (expr, id_expression_or_member_access_p);
+}
+
 /* Special member functions [gram.special] */
 
 /* Parse a conversion-function-id.
 /* Special member functions [gram.special] */
 
 /* Parse a conversion-function-id.
@@ -7760,7 +8922,7 @@ cp_parser_conversion_function_id (cp_parser* parser)
   tree pushed_scope = NULL_TREE;
 
   /* Look for the `operator' token.  */
   tree pushed_scope = NULL_TREE;
 
   /* Look for the `operator' token.  */
-  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'"))
+  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%<operator%>"))
     return error_mark_node;
   /* When we parse the conversion-type-id, the current scope will be
      reset.  However, we need that information in able to look up the
     return error_mark_node;
   /* When we parse the conversion-type-id, the current scope will be
      reset.  However, we need that information in able to look up the
@@ -7828,6 +8990,16 @@ cp_parser_conversion_type_id (cp_parser* parser)
                                    /*initialized=*/0, &attributes);
   if (attributes)
     cplus_decl_attributes (&type_specified, attributes, /*flags=*/0);
                                    /*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;
 }
 
   return type_specified;
 }
 
@@ -7857,16 +9029,8 @@ cp_parser_conversion_declarator_opt (cp_parser* parser)
       /* Parse another optional declarator.  */
       declarator = cp_parser_conversion_declarator_opt (parser);
 
       /* Parse another optional declarator.  */
       declarator = cp_parser_conversion_declarator_opt (parser);
 
-      /* Create the representation of the declarator.  */
-      if (class_type)
-       declarator = make_ptrmem_declarator (cv_quals, class_type,
-                                            declarator);
-      else if (code == INDIRECT_REF)
-       declarator = make_pointer_declarator (cv_quals, declarator);
-      else
-       declarator = make_reference_declarator (cv_quals, declarator);
-
-      return declarator;
+      return cp_parser_make_indirect_declarator
+       (code, class_type, cv_quals, declarator);
    }
 
   return NULL;
    }
 
   return NULL;
@@ -7904,26 +9068,49 @@ cp_parser_ctor_initializer_opt (cp_parser* parser)
 /* Parse a mem-initializer-list.
 
    mem-initializer-list:
 /* Parse a mem-initializer-list.
 
    mem-initializer-list:
-     mem-initializer
-     mem-initializer , mem-initializer-list  */
+     mem-initializer ... [opt]
+     mem-initializer ... [opt] , mem-initializer-list  */
 
 static void
 cp_parser_mem_initializer_list (cp_parser* parser)
 {
   tree mem_initializer_list = NULL_TREE;
 
 static void
 cp_parser_mem_initializer_list (cp_parser* parser)
 {
   tree mem_initializer_list = NULL_TREE;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Let the semantic analysis code know that we are starting the
      mem-initializer-list.  */
   if (!DECL_CONSTRUCTOR_P (current_function_decl))
 
   /* Let the semantic analysis code know that we are starting the
      mem-initializer-list.  */
   if (!DECL_CONSTRUCTOR_P (current_function_decl))
-    error ("only constructors take base initializers");
+    error ("%Honly constructors take base initializers",
+          &token->location);
 
   /* Loop through the list.  */
   while (true)
     {
       tree mem_initializer;
 
 
   /* Loop through the list.  */
   while (true)
     {
       tree mem_initializer;
 
+      token = cp_lexer_peek_token (parser->lexer);
       /* Parse the mem-initializer.  */
       mem_initializer = cp_parser_mem_initializer (parser);
       /* Parse the mem-initializer.  */
       mem_initializer = cp_parser_mem_initializer (parser);
+      /* If the next token is a `...', we're expanding member initializers. */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+        {
+          /* Consume the `...'. */
+          cp_lexer_consume_token (parser->lexer);
+
+          /* The TREE_PURPOSE must be a _TYPE, because base-specifiers
+             can be expanded but members cannot. */
+          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));
+              mem_initializer = error_mark_node;
+            }
+
+          /* Construct the pack expansion type. */
+          if (mem_initializer != error_mark_node)
+            mem_initializer = make_pack_expansion (mem_initializer);
+        }
       /* Add it to the list, unless it was erroneous.  */
       if (mem_initializer != error_mark_node)
        {
       /* Add it to the list, unless it was erroneous.  */
       if (mem_initializer != error_mark_node)
        {
@@ -7946,6 +9133,7 @@ cp_parser_mem_initializer_list (cp_parser* parser)
 
    mem-initializer:
      mem-initializer-id ( expression-list [opt] )
 
    mem-initializer:
      mem-initializer-id ( expression-list [opt] )
+     mem-initializer-id braced-init-list
 
    GNU extension:
 
 
    GNU extension:
 
@@ -7963,11 +9151,13 @@ cp_parser_mem_initializer (cp_parser* parser)
   tree mem_initializer_id;
   tree expression_list;
   tree member;
   tree mem_initializer_id;
   tree expression_list;
   tree member;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
 
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
-      pedwarn ("anachronistic old-style base class initializer");
+      permerror (token->location,
+                "anachronistic old-style base class initializer");
       mem_initializer_id = NULL_TREE;
     }
   else
       mem_initializer_id = NULL_TREE;
     }
   else
@@ -7976,10 +9166,20 @@ cp_parser_mem_initializer (cp_parser* parser)
   if (member && !DECL_P (member))
     in_base_initializer = 1;
 
   if (member && !DECL_P (member))
     in_base_initializer = 1;
 
-  expression_list
-    = cp_parser_parenthesized_expression_list (parser, false,
-                                              /*cast_p=*/false,
-                                              /*non_constant_p=*/NULL);
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      bool expr_non_constant_p;
+      maybe_warn_cpp0x ("extended initializer lists");
+      expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
+      expression_list = build_tree_list (NULL_TREE, expression_list);
+    }
+  else
+    expression_list
+      = cp_parser_parenthesized_expression_list (parser, false,
+                                                /*cast_p=*/false,
+                                                /*allow_expansion_p=*/true,
+                                                /*non_constant_p=*/NULL);
   if (expression_list == error_mark_node)
     return error_mark_node;
   if (!expression_list)
   if (expression_list == error_mark_node)
     return error_mark_node;
   if (!expression_list)
@@ -8008,11 +9208,14 @@ cp_parser_mem_initializer_id (cp_parser* parser)
   bool template_p = false;
   tree id;
 
   bool template_p = false;
   tree id;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* `typename' is not allowed in this context ([temp.res]).  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
   /* `typename' is not allowed in this context ([temp.res]).  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
-      error ("keyword %<typename%> not allowed in this context (a qualified "
-            "member initializer is implicitly a type)");
+      error ("%Hkeyword %<typename%> not allowed in this context (a qualified "
+            "member initializer is implicitly a type)",
+            &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the optional `::' operator.  */
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the optional `::' operator.  */
@@ -8082,7 +9285,7 @@ static tree
 cp_parser_operator_function_id (cp_parser* parser)
 {
   /* Look for the `operator' keyword.  */
 cp_parser_operator_function_id (cp_parser* parser)
 {
   /* Look for the `operator' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'"))
+  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%<operator%>"))
     return error_mark_node;
   /* And then the name of the operator itself.  */
   return cp_parser_operator (parser);
     return error_mark_node;
   /* And then the name of the operator itself.  */
   return cp_parser_operator (parser);
@@ -8138,7 +9341,7 @@ cp_parser_operator (cp_parser* parser)
            /* Consume the `[' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Look for the `]' token.  */
            /* Consume the `[' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Look for the `]' token.  */
-           cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+           cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
            id = ansi_opname (op == NEW_EXPR
                              ? VEC_NEW_EXPR : VEC_DELETE_EXPR);
          }
            id = ansi_opname (op == NEW_EXPR
                              ? VEC_NEW_EXPR : VEC_DELETE_EXPR);
          }
@@ -8297,37 +9500,16 @@ cp_parser_operator (cp_parser* parser)
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `)'.  */
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
       return ansi_opname (CALL_EXPR);
 
     case CPP_OPEN_SQUARE:
       /* Consume the `['.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `]'.  */
       return ansi_opname (CALL_EXPR);
 
     case CPP_OPEN_SQUARE:
       /* Consume the `['.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `]'.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
       return ansi_opname (ARRAY_REF);
 
       return ansi_opname (ARRAY_REF);
 
-      /* Extensions.  */
-    case CPP_MIN:
-      id = ansi_opname (MIN_EXPR);
-      cp_parser_warn_min_max ();
-      break;
-
-    case CPP_MAX:
-      id = ansi_opname (MAX_EXPR);
-      cp_parser_warn_min_max ();
-      break;
-
-    case CPP_MIN_EQ:
-      id = ansi_assopname (MIN_EXPR);
-      cp_parser_warn_min_max ();
-      break;
-
-    case CPP_MAX_EQ:
-      id = ansi_assopname (MAX_EXPR);
-      cp_parser_warn_min_max ();
-      break;
-
     default:
       /* Anything else is an error.  */
       break;
     default:
       /* Anything else is an error.  */
       break;
@@ -8401,20 +9583,28 @@ cp_parser_template_parameter_list (cp_parser* parser)
   while (true)
     {
       tree parameter;
   while (true)
     {
       tree parameter;
-      cp_token *token;
       bool is_non_type;
       bool is_non_type;
+      bool is_parameter_pack;
 
       /* Parse the template-parameter.  */
 
       /* Parse the template-parameter.  */
-      parameter = cp_parser_template_parameter (parser, &is_non_type);
+      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,
                                                parameter,
       /* Add it to the list.  */
       if (parameter != error_mark_node)
        parameter_list = process_template_parm (parameter_list,
                                                parameter,
-                                               is_non_type);
-      /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If it's not a `,', we're done.  */
-      if (token->type != CPP_COMMA)
+                                               is_non_type,
+                                                is_parameter_pack);
+      else
+       {
+         tree err_parm = build_tree_list (parameter, parameter);
+         TREE_VALUE (err_parm) = error_mark_node;
+         parameter_list = chainon (parameter_list, err_parm);
+       }
+
+      /* If the next token is not a `,', we're done.  */
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
        break;
       /* Otherwise, consume the `,' token.  */
       cp_lexer_consume_token (parser->lexer);
        break;
       /* Otherwise, consume the `,' token.  */
       cp_lexer_consume_token (parser->lexer);
@@ -8432,22 +9622,27 @@ cp_parser_template_parameter_list (cp_parser* parser)
    If all goes well, returns a TREE_LIST.  The TREE_VALUE represents
    the parameter.  The TREE_PURPOSE is the default value, if any.
    Returns ERROR_MARK_NODE on failure.  *IS_NON_TYPE is set to true
    If all goes well, returns a TREE_LIST.  The TREE_VALUE represents
    the parameter.  The TREE_PURPOSE is the default value, if any.
    Returns ERROR_MARK_NODE on failure.  *IS_NON_TYPE is set to true
-   iff this parameter is a non-type parameter.  */
+   iff this parameter is a non-type parameter.  *IS_PARAMETER_PACK is
+   set to true iff this parameter is a parameter pack. */
 
 static tree
 
 static tree
-cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
+cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
+                              bool *is_parameter_pack)
 {
   cp_token *token;
   cp_parameter_declarator *parameter_declarator;
 {
   cp_token *token;
   cp_parameter_declarator *parameter_declarator;
+  cp_declarator *id_declarator;
   tree parm;
 
   /* Assume it is a type parameter or a template parameter.  */
   *is_non_type = false;
   tree parm;
 
   /* Assume it is a type parameter or a template parameter.  */
   *is_non_type = false;
+  /* Assume it not a parameter pack. */
+  *is_parameter_pack = false;
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* If it is `class' or `template', we have a type-parameter.  */
   if (token->keyword == RID_TEMPLATE)
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* If it is `class' or `template', we have a type-parameter.  */
   if (token->keyword == RID_TEMPLATE)
-    return cp_parser_type_parameter (parser);
+    return cp_parser_type_parameter (parser, is_parameter_pack);
   /* If it is `class' or `typename' we do not know yet whether it is a
      type parameter or a non-type parameter.  Consider:
 
   /* If it is `class' or `typename' we do not know yet whether it is a
      type parameter or a non-type parameter.  Consider:
 
@@ -8465,6 +9660,10 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
     {
       /* Peek at the token after `class' or `typename'.  */
       token = cp_lexer_peek_nth_token (parser->lexer, 2);
     {
       /* Peek at the token after `class' or `typename'.  */
       token = cp_lexer_peek_nth_token (parser->lexer, 2);
+      /* If it's an ellipsis, we have a template type parameter
+         pack. */
+      if (token->type == CPP_ELLIPSIS)
+        return cp_parser_type_parameter (parser, is_parameter_pack);
       /* If it's an identifier, skip it.  */
       if (token->type == CPP_NAME)
        token = cp_lexer_peek_nth_token (parser->lexer, 3);
       /* If it's an identifier, skip it.  */
       if (token->type == CPP_NAME)
        token = cp_lexer_peek_nth_token (parser->lexer, 3);
@@ -8473,7 +9672,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
       if (token->type == CPP_COMMA
          || token->type == CPP_EQ
          || token->type == CPP_GREATER)
       if (token->type == CPP_COMMA
          || token->type == CPP_EQ
          || token->type == CPP_GREATER)
-       return cp_parser_type_parameter (parser);
+       return cp_parser_type_parameter (parser, is_parameter_pack);
     }
 
   /* Otherwise, it is a non-type parameter.
     }
 
   /* Otherwise, it is a non-type parameter.
@@ -8488,12 +9687,77 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
   parameter_declarator
      = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
                                        /*parenthesized_p=*/NULL);
   parameter_declarator
      = cp_parser_parameter_declaration (parser, /*template_parm_p=*/true,
                                        /*parenthesized_p=*/NULL);
+
+  /* If the parameter declaration is marked as a parameter pack, set
+     *IS_PARAMETER_PACK to notify the caller. Also, unmark the
+     declarator's PACK_EXPANSION_P, otherwise we'll get errors from
+     grokdeclarator. */
+  if (parameter_declarator
+      && parameter_declarator->declarator
+      && parameter_declarator->declarator->parameter_pack_p)
+    {
+      *is_parameter_pack = true;
+      parameter_declarator->declarator->parameter_pack_p = false;
+    }
+
+  /* If the next token is an ellipsis, and we don't already have it
+     marked as a parameter pack, then we have a parameter pack (that
+     has no declarator).  */
+  if (!*is_parameter_pack
+      && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
+      && declarator_can_be_parameter_pack (parameter_declarator->declarator))
+    {
+      /* Consume the `...'.  */
+      cp_lexer_consume_token (parser->lexer);
+      maybe_warn_variadic_templates ();
+      
+      *is_parameter_pack = true;
+    }
+  /* We might end up with a pack expansion as the type of the non-type
+     template parameter, in which case this is a non-type template
+     parameter pack.  */
+  else if (parameter_declarator
+          && parameter_declarator->decl_specifiers.type
+          && PACK_EXPANSION_P (parameter_declarator->decl_specifiers.type))
+    {
+      *is_parameter_pack = true;
+      parameter_declarator->decl_specifiers.type = 
+       PACK_EXPANSION_PATTERN (parameter_declarator->decl_specifiers.type);
+    }
+
+  if (*is_parameter_pack && cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+    {
+      /* Parameter packs cannot have default arguments.  However, a
+        user may try to do so, so we'll parse them and give an
+        appropriate diagnostic here.  */
+
+      /* Consume the `='.  */
+      cp_token *start_token = cp_lexer_peek_token (parser->lexer);
+      cp_lexer_consume_token (parser->lexer);
+      
+      /* Find the name of the parameter pack.  */     
+      id_declarator = parameter_declarator->declarator;
+      while (id_declarator && id_declarator->kind != cdk_id)
+       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);
+      else
+       error ("%Htemplate parameter pack cannot have a default argument",
+              &start_token->location);
+      
+      /* Parse the default argument, but throw away the result.  */
+      cp_parser_default_argument (parser, /*template_parm_p=*/true);
+    }
+
   parm = grokdeclarator (parameter_declarator->declarator,
                         &parameter_declarator->decl_specifiers,
                         PARM, /*initialized=*/0,
                         /*attrlist=*/NULL);
   if (parm == error_mark_node)
     return error_mark_node;
   parm = grokdeclarator (parameter_declarator->declarator,
                         &parameter_declarator->decl_specifiers,
                         PARM, /*initialized=*/0,
                         /*attrlist=*/NULL);
   if (parm == error_mark_node)
     return error_mark_node;
+
   return build_tree_list (parameter_declarator->default_argument, parm);
 }
 
   return build_tree_list (parameter_declarator->default_argument, parm);
 }
 
@@ -8508,19 +9772,27 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
      template < template-parameter-list > class identifier [opt]
        = id-expression
 
      template < template-parameter-list > class identifier [opt]
        = id-expression
 
+   GNU Extension (variadic templates):
+
+   type-parameter:
+     class ... identifier [opt]
+     typename ... identifier [opt]
+
    Returns a TREE_LIST.  The TREE_VALUE is itself a TREE_LIST.  The
    TREE_PURPOSE is the default-argument, if any.  The TREE_VALUE is
    Returns a TREE_LIST.  The TREE_VALUE is itself a TREE_LIST.  The
    TREE_PURPOSE is the default-argument, if any.  The TREE_VALUE is
-   the declaration of the parameter.  */
+   the declaration of the parameter.
+
+   Sets *IS_PARAMETER_PACK if this is a template parameter pack. */
 
 static tree
 
 static tree
-cp_parser_type_parameter (cp_parser* parser)
+cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 {
   cp_token *token;
   tree parameter;
 
   /* Look for a keyword to tell us what kind of parameter this is.  */
   token = cp_parser_require (parser, CPP_KEYWORD,
 {
   cp_token *token;
   tree parameter;
 
   /* Look for a keyword to tell us what kind of parameter this is.  */
   token = cp_parser_require (parser, CPP_KEYWORD,
-                            "`class', `typename', or `template'");
+                            "%<class%>, %<typename%>, or %<template%>");
   if (!token)
     return error_mark_node;
 
   if (!token)
     return error_mark_node;
 
@@ -8532,6 +9804,17 @@ cp_parser_type_parameter (cp_parser* parser)
        tree identifier;
        tree default_argument;
 
        tree identifier;
        tree default_argument;
 
+        /* If the next token is an ellipsis, we have a template
+           argument pack. */
+        if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+          {
+            /* Consume the `...' token. */
+            cp_lexer_consume_token (parser->lexer);
+            maybe_warn_variadic_templates ();
+
+            *is_parameter_pack = true;
+          }
+
        /* If the next token is an identifier, then it names the
           parameter.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
        /* If the next token is an identifier, then it names the
           parameter.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
@@ -8550,6 +9833,19 @@ cp_parser_type_parameter (cp_parser* parser)
            /* Parse the default-argument.  */
            push_deferring_access_checks (dk_no_deferred);
            default_argument = cp_parser_type_id (parser);
            /* Parse the default-argument.  */
            push_deferring_access_checks (dk_no_deferred);
            default_argument = cp_parser_type_id (parser);
+
+            /* Template parameter packs cannot have default
+               arguments. */
+            if (*is_parameter_pack)
+              {
+                if (identifier)
+                  error ("%Htemplate parameter pack %qD cannot have a "
+                        "default argument", &token->location, identifier);
+                else
+                  error ("%Htemplate parameter packs cannot have "
+                        "default arguments", &token->location);
+                default_argument = NULL_TREE;
+              }
            pop_deferring_access_checks ();
          }
        else
            pop_deferring_access_checks ();
          }
        else
@@ -8568,13 +9864,23 @@ cp_parser_type_parameter (cp_parser* parser)
        tree default_argument;
 
        /* Look for the `<'.  */
        tree default_argument;
 
        /* Look for the `<'.  */
-       cp_parser_require (parser, CPP_LESS, "`<'");
+       cp_parser_require (parser, CPP_LESS, "%<<%>");
        /* Parse the template-parameter-list.  */
        parameter_list = cp_parser_template_parameter_list (parser);
        /* Look for the `>'.  */
        /* Parse the template-parameter-list.  */
        parameter_list = cp_parser_template_parameter_list (parser);
        /* Look for the `>'.  */
-       cp_parser_require (parser, CPP_GREATER, "`>'");
+       cp_parser_require (parser, CPP_GREATER, "%<>%>");
        /* Look for the `class' keyword.  */
        /* Look for the `class' keyword.  */
-       cp_parser_require_keyword (parser, RID_CLASS, "`class'");
+       cp_parser_require_keyword (parser, RID_CLASS, "%<class%>");
+        /* If the next token is an ellipsis, we have a template
+           argument pack. */
+        if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+          {
+            /* Consume the `...' token. */
+            cp_lexer_consume_token (parser->lexer);
+            maybe_warn_variadic_templates ();
+
+            *is_parameter_pack = true;
+          }
        /* If the next token is an `=', then there is a
           default-argument.  If the next token is a `>', we are at
           the end of the parameter-list.  If the next token is a `,',
        /* If the next token is an `=', then there is a
           default-argument.  If the next token is a `>', we are at
           the end of the parameter-list.  If the next token is a `,',
@@ -8605,6 +9911,9 @@ cp_parser_type_parameter (cp_parser* parser)
            cp_lexer_consume_token (parser->lexer);
            /* Parse the id-expression.  */
            push_deferring_access_checks (dk_no_deferred);
            cp_lexer_consume_token (parser->lexer);
            /* Parse the id-expression.  */
            push_deferring_access_checks (dk_no_deferred);
+           /* save token before parsing the id-expression, for error
+              reporting */
+           token = cp_lexer_peek_token (parser->lexer);
            default_argument
              = cp_parser_id_expression (parser,
                                         /*template_keyword_p=*/false,
            default_argument
              = cp_parser_id_expression (parser,
                                         /*template_keyword_p=*/false,
@@ -8625,10 +9934,26 @@ cp_parser_type_parameter (cp_parser* parser)
                                         /*is_template=*/is_template,
                                         /*is_namespace=*/false,
                                         /*check_dependency=*/true,
                                         /*is_template=*/is_template,
                                         /*is_namespace=*/false,
                                         /*check_dependency=*/true,
-                                        /*ambiguous_decls=*/NULL);
+                                        /*ambiguous_decls=*/NULL,
+                                        token->location);
            /* See if the default argument is valid.  */
            default_argument
              = check_template_template_default_arg (default_argument);
            /* See if the default argument is valid.  */
            default_argument
              = check_template_template_default_arg (default_argument);
+
+            /* Template parameter packs cannot have default
+               arguments. */
+            if (*is_parameter_pack)
+              {
+                if (identifier)
+                  error ("%Htemplate parameter pack %qD cannot "
+                        "have a default argument",
+                        &token->location, identifier);
+                else
+                  error ("%Htemplate parameter packs cannot "
+                        "have default arguments",
+                        &token->location);
+                default_argument = NULL_TREE;
+              }
            pop_deferring_access_checks ();
          }
        else
            pop_deferring_access_checks ();
          }
        else
@@ -8668,12 +9993,14 @@ cp_parser_template_id (cp_parser *parser,
                       bool check_dependency_p,
                       bool is_declaration)
 {
                       bool check_dependency_p,
                       bool is_declaration)
 {
-  tree template;
+  int i;
+  tree templ;
   tree arguments;
   tree template_id;
   cp_token_position start_of_id = 0;
   tree arguments;
   tree template_id;
   cp_token_position start_of_id = 0;
-  tree access_check = NULL_TREE;
-  cp_token *next_token, *next_token_2;
+  deferred_access_check *chk;
+  VEC (deferred_access_check,gc) *access_check;
+  cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
   bool is_identifier;
 
   /* If the next token corresponds to a template-id, there is no need
   bool is_identifier;
 
   /* If the next token corresponds to a template-id, there is no need
@@ -8681,17 +10008,25 @@ cp_parser_template_id (cp_parser *parser,
   next_token = cp_lexer_peek_token (parser->lexer);
   if (next_token->type == CPP_TEMPLATE_ID)
     {
   next_token = cp_lexer_peek_token (parser->lexer);
   if (next_token->type == CPP_TEMPLATE_ID)
     {
-      tree value;
-      tree check;
+      struct tree_check *check_value;
 
       /* Get the stored value.  */
 
       /* Get the stored value.  */
-      value = cp_lexer_consume_token (parser->lexer)->value;
+      check_value = cp_lexer_consume_token (parser->lexer)->u.tree_check_value;
       /* Perform any access checks that were deferred.  */
       /* Perform any access checks that were deferred.  */
-      for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
-       perform_or_defer_access_check (TREE_PURPOSE (check),
-                                      TREE_VALUE (check));
+      access_check = check_value->checks;
+      if (access_check)
+       {
+         for (i = 0 ;
+              VEC_iterate (deferred_access_check, access_check, i, chk) ;
+              ++i)
+           {
+             perform_or_defer_access_check (chk->binfo,
+                                            chk->decl,
+                                            chk->diag_decl);
+           }
+       }
       /* Return the stored value.  */
       /* Return the stored value.  */
-      return TREE_VALUE (value);
+      return check_value->value;
     }
 
   /* Avoid performing name lookup if there is no possibility of
     }
 
   /* Avoid performing name lookup if there is no possibility of
@@ -8713,14 +10048,15 @@ cp_parser_template_id (cp_parser *parser,
 
   /* Parse the template-name.  */
   is_identifier = false;
 
   /* Parse the template-name.  */
   is_identifier = false;
-  template = cp_parser_template_name (parser, template_keyword_p,
-                                     check_dependency_p,
-                                     is_declaration,
-                                     &is_identifier);
-  if (template == error_mark_node || is_identifier)
+  token = cp_lexer_peek_token (parser->lexer);
+  templ = cp_parser_template_name (parser, template_keyword_p,
+                                  check_dependency_p,
+                                  is_declaration,
+                                  &is_identifier);
+  if (templ == error_mark_node || is_identifier)
     {
       pop_deferring_access_checks ();
     {
       pop_deferring_access_checks ();
-      return template;
+      return templ;
     }
 
   /* If we find the sequence `[:' after a template-name, it's probably
     }
 
   /* If we find the sequence `[:' after a template-name, it's probably
@@ -8739,6 +10075,7 @@ cp_parser_template_id (cp_parser *parser,
       /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
         CPP_LESS.  */
       cp_lexer_consume_token (parser->lexer);
       /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
         CPP_LESS.  */
       cp_lexer_consume_token (parser->lexer);
+
       /* Parse the arguments.  */
       arguments = cp_parser_enclosed_template_argument_list (parser);
       if (!cp_parser_parse_definitely (parser))
       /* Parse the arguments.  */
       arguments = cp_parser_enclosed_template_argument_list (parser);
       if (!cp_parser_parse_definitely (parser))
@@ -8753,15 +10090,17 @@ cp_parser_template_id (cp_parser *parser,
        }
       /* Otherwise, emit an error about the invalid digraph, but continue
         parsing because we got our argument list.  */
        }
       /* Otherwise, emit an error about the invalid digraph, but continue
         parsing because we got our argument list.  */
-      pedwarn ("%<<::%> cannot begin a template-argument list");
-      inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
-             "between %<<%> and %<::%>");
-      if (!flag_permissive)
+      if (permerror (next_token->location,
+                    "%<<::%> cannot begin a template-argument list"))
        {
        {
-         static bool hint;
-         if (!hint)
+         static bool hint = false;
+         inform (next_token->location,
+                 "%<<:%> is an alternate spelling for %<[%>."
+                 " Insert whitespace between %<<%> and %<::%>");
+         if (!hint && !flag_permissive)
            {
            {
-             inform ("(if you use -fpermissive G++ will accept your code)");
+             inform (next_token->location, "(if you use %<-fpermissive%>"
+                     " G++ will accept your code)");
              hint = true;
            }
        }
              hint = true;
            }
        }
@@ -8769,7 +10108,7 @@ cp_parser_template_id (cp_parser *parser,
   else
     {
       /* Look for the `<' that starts the template-argument-list.  */
   else
     {
       /* Look for the `<' that starts the template-argument-list.  */
-      if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+      if (!cp_parser_require (parser, CPP_LESS, "%<<%>"))
        {
          pop_deferring_access_checks ();
          return error_mark_node;
        {
          pop_deferring_access_checks ();
          return error_mark_node;
@@ -8779,10 +10118,10 @@ cp_parser_template_id (cp_parser *parser,
     }
 
   /* Build a representation of the specialization.  */
     }
 
   /* Build a representation of the specialization.  */
-  if (TREE_CODE (template) == IDENTIFIER_NODE)
-    template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
-  else if (DECL_CLASS_TEMPLATE_P (template)
-          || DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+  if (TREE_CODE (templ) == IDENTIFIER_NODE)
+    template_id = build_min_nt (TEMPLATE_ID_EXPR, templ, arguments);
+  else if (DECL_CLASS_TEMPLATE_P (templ)
+          || DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
     {
       bool entering_scope;
       /* In "template <typename T> ... A<T>::", A<T> is the abstract A
     {
       bool entering_scope;
       /* In "template <typename T> ... A<T>::", A<T> is the abstract A
@@ -8794,23 +10133,19 @@ cp_parser_template_id (cp_parser *parser,
                        && cp_lexer_next_token_is (parser->lexer,
                                                   CPP_SCOPE));
       template_id
                        && cp_lexer_next_token_is (parser->lexer,
                                                   CPP_SCOPE));
       template_id
-       = finish_template_type (template, arguments, entering_scope);
+       = finish_template_type (templ, arguments, entering_scope);
     }
   else
     {
       /* If it's not a class-template or a template-template, it should be
         a function-template.  */
     }
   else
     {
       /* If it's not a class-template or a template-template, it should be
         a function-template.  */
-      gcc_assert ((DECL_FUNCTION_TEMPLATE_P (template)
-                  || TREE_CODE (template) == OVERLOAD
-                  || BASELINK_P (template)));
+      gcc_assert ((DECL_FUNCTION_TEMPLATE_P (templ)
+                  || TREE_CODE (templ) == OVERLOAD
+                  || BASELINK_P (templ)));
 
 
-      template_id = lookup_template_function (template, arguments);
+      template_id = lookup_template_function (templ, arguments);
     }
 
     }
 
-  /* Retrieve any deferred checks.  Do not pop this access checks yet
-     so the memory will not be reclaimed during token replacing below.  */
-  access_check = get_deferred_access_checks ();
-
   /* If parsing tentatively, replace the sequence of tokens that makes
      up the template-id with a CPP_TEMPLATE_ID token.  That way,
      should we re-parse the token stream, we will not have to repeat
   /* If parsing tentatively, replace the sequence of tokens that makes
      up the template-id with a CPP_TEMPLATE_ID token.  That way,
      should we re-parse the token stream, we will not have to repeat
@@ -8823,7 +10158,11 @@ cp_parser_template_id (cp_parser *parser,
 
       /* Reset the contents of the START_OF_ID token.  */
       token->type = CPP_TEMPLATE_ID;
 
       /* Reset the contents of the START_OF_ID token.  */
       token->type = CPP_TEMPLATE_ID;
-      token->value = build_tree_list (access_check, template_id);
+      /* Retrieve any deferred checks.  Do not pop this access checks yet
+        so the memory will not be reclaimed during token replacing below.  */
+      token->u.tree_check_value = GGC_CNEW (struct tree_check);
+      token->u.tree_check_value->value = template_id;
+      token->u.tree_check_value->checks = get_deferred_access_checks ();
       token->keyword = RID_MAX;
 
       /* Purge all subsequent tokens.  */
       token->keyword = RID_MAX;
 
       /* Purge all subsequent tokens.  */
@@ -8834,7 +10173,8 @@ cp_parser_template_id (cp_parser *parser,
         user, as opposed to simply marking the tentative parse as
         failed?  */
       if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
         user, as opposed to simply marking the tentative parse as
         failed?  */
       if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
-       error ("parse error in template argument list");
+       error ("%Hparse error in template argument list",
+              &token->location);
     }
 
   pop_deferring_access_checks ();
     }
 
   pop_deferring_access_checks ();
@@ -8888,6 +10228,7 @@ cp_parser_template_name (cp_parser* parser,
   tree identifier;
   tree decl;
   tree fns;
   tree identifier;
   tree decl;
   tree fns;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* If the next token is `operator', then we have either an
      operator-function-id or a conversion-function-id.  */
 
   /* If the next token is `operator', then we have either an
      operator-function-id or a conversion-function-id.  */
@@ -8947,8 +10288,9 @@ cp_parser_template_name (cp_parser* parser,
          cp_token_position start = 0;
 
          /* Explain what went wrong.  */
          cp_token_position start = 0;
 
          /* Explain what went wrong.  */
-         error ("non-template %qD used as template", identifier);
-         inform ("use %<%T::template %D%> to indicate that it is a template",
+         error ("%Hnon-template %qD used as template",
+                &token->location, identifier);
+         inform (input_location, "use %<%T::template %D%> to indicate that it is a template",
                  parser->scope, identifier);
          /* If parsing tentatively, find the location of the "<" token.  */
          if (cp_parser_simulate_error (parser))
                  parser->scope, identifier);
          /* If parsing tentatively, find the location of the "<" token.  */
          if (cp_parser_simulate_error (parser))
@@ -8991,7 +10333,8 @@ cp_parser_template_name (cp_parser* parser,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
                                check_dependency_p,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
                                check_dependency_p,
-                               /*ambiguous_decls=*/NULL);
+                               /*ambiguous_decls=*/NULL,
+                               token->location);
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
@@ -9035,8 +10378,8 @@ cp_parser_template_name (cp_parser* parser,
 /* Parse a template-argument-list.
 
    template-argument-list:
 /* Parse a template-argument-list.
 
    template-argument-list:
-     template-argument
-     template-argument-list , template-argument
+     template-argument ... [opt]
+     template-argument-list , template-argument ... [opt]
 
    Returns a TREE_VEC containing the arguments.  */
 
 
    Returns a TREE_VEC containing the arguments.  */
 
@@ -9072,6 +10415,19 @@ cp_parser_template_argument_list (cp_parser* parser)
 
       /* Parse the template-argument.  */
       argument = cp_parser_template_argument (parser);
 
       /* Parse the template-argument.  */
       argument = cp_parser_template_argument (parser);
+
+      /* If the next token is an ellipsis, we're expanding a template
+         argument pack. */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+        {
+          /* Consume the `...' token. */
+          cp_lexer_consume_token (parser->lexer);
+
+          /* Make the argument into a TYPE_PACK_EXPANSION or
+             EXPR_PACK_EXPANSION. */
+          argument = make_pack_expansion (argument);
+        }
+
       if (n_args == alloced)
        {
          alloced *= 2;
       if (n_args == alloced)
        {
          alloced *= 2;
@@ -9124,7 +10480,7 @@ cp_parser_template_argument (cp_parser* parser)
   bool template_p;
   bool address_p;
   bool maybe_type_id = false;
   bool template_p;
   bool address_p;
   bool maybe_type_id = false;
-  cp_token *token;
+  cp_token *token = NULL, *argument_start_token = NULL;
   cp_id_kind idk;
 
   /* There's really no way to know what we're looking at, so we just
   cp_id_kind idk;
 
   /* There's really no way to know what we're looking at, so we just
@@ -9139,9 +10495,10 @@ cp_parser_template_argument (cp_parser* parser)
      Therefore, we try a type-id first.  */
   cp_parser_parse_tentatively (parser);
   argument = cp_parser_type_id (parser);
      Therefore, we try a type-id first.  */
   cp_parser_parse_tentatively (parser);
   argument = cp_parser_type_id (parser);
-  /* If there was no error parsing the type-id but the next token is a '>>',
-     we probably found a typo for '> >'. But there are type-id which are
-     also valid expressions. For instance:
+  /* If there was no error parsing the type-id but the next token is a
+     '>>', our behavior depends on which dialect of C++ we're
+     parsing. In C++98, we probably found a typo for '> >'. But there
+     are type-id which are also valid expressions. For instance:
 
      struct X { int operator >> (int); };
      template <int V> struct Foo {};
 
      struct X { int operator >> (int); };
      template <int V> struct Foo {};
@@ -9150,8 +10507,12 @@ cp_parser_template_argument (cp_parser* parser)
      Here 'X()' is a valid type-id of a function type, but the user just
      wanted to write the expression "X() >> 5". Thus, we remember that we
      found a valid type-id, but we still try to parse the argument as an
      Here 'X()' is a valid type-id of a function type, but the user just
      wanted to write the expression "X() >> 5". Thus, we remember that we
      found a valid type-id, but we still try to parse the argument as an
-     expression to see what happens.  */
+     expression to see what happens. 
+
+     In C++0x, the '>>' will be considered two separate '>'
+     tokens.  */
   if (!cp_parser_error_occurred (parser)
   if (!cp_parser_error_occurred (parser)
+      && cxx_dialect == cxx98
       && cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
     {
       maybe_type_id = true;
       && cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
     {
       maybe_type_id = true;
@@ -9171,6 +10532,7 @@ cp_parser_template_argument (cp_parser* parser)
   /* We're still not sure what the argument will be.  */
   cp_parser_parse_tentatively (parser);
   /* Try a template.  */
   /* We're still not sure what the argument will be.  */
   cp_parser_parse_tentatively (parser);
   /* Try a template.  */
+  argument_start_token = cp_lexer_peek_token (parser->lexer);
   argument = cp_parser_id_expression (parser,
                                      /*template_keyword_p=*/false,
                                      /*check_dependency_p=*/true,
   argument = cp_parser_id_expression (parser,
                                      /*template_keyword_p=*/false,
                                      /*check_dependency_p=*/true,
@@ -9193,7 +10555,8 @@ cp_parser_template_argument (cp_parser* parser)
                                          /*is_template=*/template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
                                          /*is_template=*/template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
-                                         /*ambiguous_decls=*/NULL);
+                                         /*ambiguous_decls=*/NULL,
+                                         argument_start_token->location);
       if (TREE_CODE (argument) != TEMPLATE_DECL
          && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
        cp_parser_error (parser, "expected template-name");
       if (TREE_CODE (argument) != TEMPLATE_DECL
          && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
        cp_parser_error (parser, "expected template-name");
@@ -9218,7 +10581,7 @@ cp_parser_template_argument (cp_parser* parser)
     {
       cp_parser_parse_tentatively (parser);
       argument = cp_parser_primary_expression (parser,
     {
       cp_parser_parse_tentatively (parser);
       argument = cp_parser_primary_expression (parser,
-                                              /*adress_p=*/false,
+                                              /*address_p=*/false,
                                               /*cast_p=*/false,
                                               /*template_arg_p=*/true,
                                               &idk);
                                               /*cast_p=*/false,
                                               /*template_arg_p=*/true,
                                               &idk);
@@ -9259,17 +10622,12 @@ cp_parser_template_argument (cp_parser* parser)
              argument = TREE_OPERAND (argument, 0);
            }
 
              argument = TREE_OPERAND (argument, 0);
            }
 
-         if (TREE_CODE (argument) == BASELINK)
-           /* We don't need the information about what class was used
-              to name the overloaded functions.  */
-           argument = BASELINK_FUNCTIONS (argument);
-
          if (TREE_CODE (argument) == VAR_DECL)
            {
              /* A variable without external linkage might still be a
                 valid constant-expression, so no error is issued here
                 if the external-linkage check fails.  */
          if (TREE_CODE (argument) == VAR_DECL)
            {
              /* A variable without external linkage might still be a
                 valid constant-expression, so no error is issued here
                 if the external-linkage check fails.  */
-             if (!DECL_EXTERNAL_LINKAGE_P (argument))
+             if (!address_p && !DECL_EXTERNAL_LINKAGE_P (argument))
                cp_parser_simulate_error (parser);
            }
          else if (is_overloaded_fn (argument))
                cp_parser_simulate_error (parser);
            }
          else if (is_overloaded_fn (argument))
@@ -9290,7 +10648,8 @@ cp_parser_template_argument (cp_parser* parser)
          if (cp_parser_parse_definitely (parser))
            {
              if (address_p)
          if (cp_parser_parse_definitely (parser))
            {
              if (address_p)
-               argument = build_x_unary_op (ADDR_EXPR, argument);
+               argument = build_x_unary_op (ADDR_EXPR, argument,
+                                             tf_warning_or_error);
              return argument;
            }
        }
              return argument;
            }
        }
@@ -9354,6 +10713,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   int declares_class_or_enum;
   cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
   int declares_class_or_enum;
   cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
+  cp_token *token;
 
   /* Look for an (optional) storage-class-specifier or
      function-specifier.  */
 
   /* Look for an (optional) storage-class-specifier or
      function-specifier.  */
@@ -9368,7 +10728,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     }
 
   /* Look for the `template' keyword.  */
     }
 
   /* Look for the `template' keyword.  */
-  cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
+  cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Let the front end know that we are processing an explicit
      instantiation.  */
   begin_explicit_instantiation ();
   /* Let the front end know that we are processing an explicit
      instantiation.  */
   begin_explicit_instantiation ();
@@ -9376,6 +10736,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
      control while processing explicit instantiation directives.  */
   push_deferring_access_checks (dk_no_check);
   /* Parse a decl-specifier-seq.  */
      control while processing explicit instantiation directives.  */
   push_deferring_access_checks (dk_no_check);
   /* Parse a decl-specifier-seq.  */
+  token = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
                                &decl_specifiers,
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
                                &decl_specifiers,
@@ -9408,7 +10769,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
                                /*member_p=*/false);
       if (declares_class_or_enum & 2)
        cp_parser_check_for_definition_in_return_type (declarator,
                                /*member_p=*/false);
       if (declares_class_or_enum & 2)
        cp_parser_check_for_definition_in_return_type (declarator,
-                                                      decl_specifiers.type);
+                                                      decl_specifiers.type,
+                                                      decl_specifiers.type_location);
       if (declarator != cp_error_declarator)
        {
          decl = grokdeclarator (declarator, &decl_specifiers,
       if (declarator != cp_error_declarator)
        {
          decl = grokdeclarator (declarator, &decl_specifiers,
@@ -9449,12 +10811,14 @@ static void
 cp_parser_explicit_specialization (cp_parser* parser)
 {
   bool need_lang_pop;
 cp_parser_explicit_specialization (cp_parser* parser)
 {
   bool need_lang_pop;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `template' keyword.  */
   /* Look for the `template' keyword.  */
-  cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
+  cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
   /* Look for the `<'.  */
   /* Look for the `<'.  */
-  cp_parser_require (parser, CPP_LESS, "`<'");
+  cp_parser_require (parser, CPP_LESS, "%<<%>");
   /* Look for the `>'.  */
   /* Look for the `>'.  */
-  cp_parser_require (parser, CPP_GREATER, "`>'");
+  cp_parser_require (parser, CPP_GREATER, "%<>%>");
   /* We have processed another parameter list.  */
   ++parser->num_template_parameter_lists;
   /* [temp]
   /* We have processed another parameter list.  */
   ++parser->num_template_parameter_lists;
   /* [temp]
@@ -9463,7 +10827,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
      linkage.  */
   if (current_lang_name == lang_name_c)
     {
      linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template specialization with C linkage");
+      error ("%Htemplate specialization with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
         front end.  */
       push_lang_context (lang_name_cplusplus);
       /* Give it C++ linkage to avoid confusing other parts of the
         front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -9472,7 +10836,13 @@ cp_parser_explicit_specialization (cp_parser* parser)
   else
     need_lang_pop = false;
   /* Let the front end know that we are beginning a specialization.  */
   else
     need_lang_pop = false;
   /* Let the front end know that we are beginning a specialization.  */
-  begin_specialization ();
+  if (!begin_specialization ())
+    {
+      end_specialization ();
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      return;
+    }
+
   /* If the next keyword is `template', we need to figure out whether
      or not we're looking a template-declaration.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
   /* If the next keyword is `template', we need to figure out whether
      or not we're looking a template-declaration.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
@@ -9487,8 +10857,9 @@ cp_parser_explicit_specialization (cp_parser* parser)
   else
     /* Parse the dependent declaration.  */
     cp_parser_single_declaration (parser,
   else
     /* Parse the dependent declaration.  */
     cp_parser_single_declaration (parser,
-                                 /*checks=*/NULL_TREE,
+                                 /*checks=*/NULL,
                                  /*member_p=*/false,
                                  /*member_p=*/false,
+                                  /*explicit_specialization_p=*/true,
                                  /*friend_p=*/NULL);
   /* We're done with the specialization.  */
   end_specialization ();
                                  /*friend_p=*/NULL);
   /* We're done with the specialization.  */
   end_specialization ();
@@ -9571,6 +10942,7 @@ cp_parser_type_specifier (cp_parser* parser,
          if (decl_specs)
            cp_parser_set_decl_spec_type (decl_specs,
                                          type_spec,
          if (decl_specs)
            cp_parser_set_decl_spec_type (decl_specs,
                                          type_spec,
+                                         token->location,
                                          /*user_defined_p=*/true);
          return type_spec;
        }
                                          /*user_defined_p=*/true);
          return type_spec;
        }
@@ -9595,6 +10967,7 @@ cp_parser_type_specifier (cp_parser* parser,
          if (decl_specs)
            cp_parser_set_decl_spec_type (decl_specs,
                                          type_spec,
          if (decl_specs)
            cp_parser_set_decl_spec_type (decl_specs,
                                          type_spec,
+                                         token->location,
                                          /*user_defined_p=*/true);
          return type_spec;
        }
                                          /*user_defined_p=*/true);
          return type_spec;
        }
@@ -9616,6 +10989,7 @@ cp_parser_type_specifier (cp_parser* parser,
       if (decl_specs)
        cp_parser_set_decl_spec_type (decl_specs,
                                      type_spec,
       if (decl_specs)
        cp_parser_set_decl_spec_type (decl_specs,
                                      type_spec,
+                                     token->location,
                                      /*user_defined_p=*/true);
       return type_spec;
 
                                      /*user_defined_p=*/true);
       return type_spec;
 
@@ -9654,7 +11028,7 @@ cp_parser_type_specifier (cp_parser* parser,
          ++decl_specs->specs[(int)ds];
          decl_specs->any_specifiers_p = true;
        }
          ++decl_specs->specs[(int)ds];
          decl_specs->any_specifiers_p = true;
        }
-      return cp_lexer_consume_token (parser->lexer)->value;
+      return cp_lexer_consume_token (parser->lexer)->u.value;
     }
 
   /* If we do not already have a type-specifier, assume we are looking
     }
 
   /* If we do not already have a type-specifier, assume we are looking
@@ -9691,6 +11065,14 @@ cp_parser_type_specifier (cp_parser* parser,
      double
      void
 
      double
      void
 
+   C++0x Extension:
+
+   simple-type-specifier:
+     auto
+     decltype ( expression )   
+     char16_t
+     char32_t
+
    GNU Extension:
 
    simple-type-specifier:
    GNU Extension:
 
    simple-type-specifier:
@@ -9719,6 +11101,12 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        decl_specs->explicit_char_p = true;
       type = char_type_node;
       break;
        decl_specs->explicit_char_p = true;
       type = char_type_node;
       break;
+    case RID_CHAR16:
+      type = char16_type_node;
+      break;
+    case RID_CHAR32:
+      type = char32_type_node;
+      break;
     case RID_WCHAR:
       type = wchar_type_node;
       break;
     case RID_WCHAR:
       type = wchar_type_node;
       break;
@@ -9759,6 +11147,22 @@ cp_parser_simple_type_specifier (cp_parser* parser,
     case RID_VOID:
       type = void_type_node;
       break;
     case RID_VOID:
       type = void_type_node;
       break;
+      
+    case RID_AUTO:
+      maybe_warn_cpp0x ("C++0x auto");
+      type = make_auto ();
+      break;
+
+    case RID_DECLTYPE:
+      /* Parse the `decltype' type.  */
+      type = cp_parser_decltype (parser);
+
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     token->location,
+                                     /*user_defined_p=*/true);
+
+      return type;
 
     case RID_TYPEOF:
       /* Consume the `typeof' token.  */
 
     case RID_TYPEOF:
       /* Consume the `typeof' token.  */
@@ -9771,6 +11175,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
       if (decl_specs)
        cp_parser_set_decl_spec_type (decl_specs, type,
 
       if (decl_specs)
        cp_parser_set_decl_spec_type (decl_specs, type,
+                                     token->location,
                                      /*user_defined_p=*/true);
 
       return type;
                                      /*user_defined_p=*/true);
 
       return type;
@@ -9792,17 +11197,18 @@ cp_parser_simple_type_specifier (cp_parser* parser,
              && token->keyword != RID_LONG))
        cp_parser_set_decl_spec_type (decl_specs,
                                      type,
              && token->keyword != RID_LONG))
        cp_parser_set_decl_spec_type (decl_specs,
                                      type,
+                                     token->location,
                                      /*user_defined=*/false);
       if (decl_specs)
        decl_specs->any_specifiers_p = true;
 
       /* Consume the token.  */
                                      /*user_defined=*/false);
       if (decl_specs)
        decl_specs->any_specifiers_p = true;
 
       /* Consume the token.  */
-      id = cp_lexer_consume_token (parser->lexer)->value;
+      id = cp_lexer_consume_token (parser->lexer)->u.value;
 
       /* There is no valid C++ program where a non-template type is
         followed by a "<".  That usually indicates that the user thought
         that the type was a template.  */
 
       /* There is no valid C++ program where a non-template type is
         followed by a "<".  That usually indicates that the user thought
         that the type was a template.  */
-      cp_parser_check_for_invalid_template_id (parser, type);
+      cp_parser_check_for_invalid_template_id (parser, type, token->location);
 
       return TYPE_NAME (type);
     }
 
       return TYPE_NAME (type);
     }
@@ -9831,6 +11237,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
                                                /*type_p=*/false,
                                                /*is_declaration=*/false)
           != NULL_TREE);
                                                /*type_p=*/false,
                                                /*is_declaration=*/false)
           != NULL_TREE);
+      token = cp_lexer_peek_token (parser->lexer);
       /* If we have seen a nested-name-specifier, and the next token
         is `template', then we are using the template-id production.  */
       if (parser->scope
       /* If we have seen a nested-name-specifier, and the next token
         is `template', then we are using the template-id production.  */
       if (parser->scope
@@ -9865,6 +11272,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        type = NULL_TREE;
       if (type && decl_specs)
        cp_parser_set_decl_spec_type (decl_specs, type,
        type = NULL_TREE;
       if (type && decl_specs)
        cp_parser_set_decl_spec_type (decl_specs, type,
+                                     token->location,
                                      /*user_defined=*/true);
     }
 
                                      /*user_defined=*/true);
     }
 
@@ -9897,7 +11305,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
          return qual_type;
        }
 
          return qual_type;
        }
 
-      cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+      cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type),
+                                              token->location);
     }
 
   return type;
     }
 
   return type;
@@ -9922,7 +11331,6 @@ static tree
 cp_parser_type_name (cp_parser* parser)
 {
   tree type_decl;
 cp_parser_type_name (cp_parser* parser)
 {
   tree type_decl;
-  tree identifier;
 
   /* We can't know yet whether it is a class-name or not.  */
   cp_parser_parse_tentatively (parser);
 
   /* We can't know yet whether it is a class-name or not.  */
   cp_parser_parse_tentatively (parser);
@@ -9938,59 +11346,80 @@ cp_parser_type_name (cp_parser* parser)
   if (!cp_parser_parse_definitely (parser))
     {
       /* It must be a typedef-name or an enum-name.  */
   if (!cp_parser_parse_definitely (parser))
     {
       /* It must be a typedef-name or an enum-name.  */
-      identifier = cp_parser_identifier (parser);
-      if (identifier == error_mark_node)
-       return error_mark_node;
-
-      /* Look up the type-name.  */
-      type_decl = cp_parser_lookup_name_simple (parser, identifier);
-
-      if (TREE_CODE (type_decl) != TYPE_DECL
-         && (objc_is_id (identifier) || objc_is_class_name (identifier)))
-       {
-         /* See if this is an Objective-C type.  */
-         tree protos = cp_parser_objc_protocol_refs_opt (parser);
-         tree type = objc_get_protocol_qualified_type (identifier, protos);
-         if (type)
-           type_decl = TYPE_NAME (type);
-       }
-
-      /* Issue an error if we did not find a type-name.  */
-      if (TREE_CODE (type_decl) != TYPE_DECL)
-       {
-         if (!cp_parser_simulate_error (parser))
-           cp_parser_name_lookup_error (parser, identifier, type_decl,
-                                        "is not a type");
-         type_decl = error_mark_node;
-       }
-      /* Remember that the name was used in the definition of the
-        current class so that we can check later to see if the
-        meaning would have been different after the class was
-        entirely defined.  */
-      else if (type_decl != error_mark_node
-              && !parser->scope)
-       maybe_note_name_used_in_class (identifier, type_decl);
+      return cp_parser_nonclass_name (parser);
     }
 
   return type_decl;
 }
 
     }
 
   return type_decl;
 }
 
+/* Parse a non-class type-name, that is, either an enum-name or a typedef-name.
 
 
-/* Parse an elaborated-type-specifier.  Note that the grammar given
-   here incorporates the resolution to DR68.
+   enum-name:
+     identifier
 
 
-   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
-     typename :: [opt] nested-name-specifier identifier
-     typename :: [opt] nested-name-specifier template [opt]
-       template-id
+   typedef-name:
+     identifier
 
 
-   GNU extension:
+   Returns a TYPE_DECL for the type.  */
 
 
-   elaborated-type-specifier:
-     class-key attributes :: [opt] nested-name-specifier [opt] identifier
+static tree
+cp_parser_nonclass_name (cp_parser* parser)
+{
+  tree type_decl;
+  tree identifier;
+
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  identifier = cp_parser_identifier (parser);
+  if (identifier == error_mark_node)
+    return error_mark_node;
+
+  /* Look up the type-name.  */
+  type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
+
+  if (TREE_CODE (type_decl) != TYPE_DECL
+      && (objc_is_id (identifier) || objc_is_class_name (identifier)))
+    {
+      /* See if this is an Objective-C type.  */
+      tree protos = cp_parser_objc_protocol_refs_opt (parser);
+      tree type = objc_get_protocol_qualified_type (identifier, protos);
+      if (type)
+       type_decl = TYPE_NAME (type);
+    }
+  
+  /* Issue an error if we did not find a type-name.  */
+  if (TREE_CODE (type_decl) != TYPE_DECL)
+    {
+      if (!cp_parser_simulate_error (parser))
+       cp_parser_name_lookup_error (parser, identifier, type_decl,
+                                    "is not a type", token->location);
+      return error_mark_node;
+    }
+  /* Remember that the name was used in the definition of the
+     current class so that we can check later to see if the
+     meaning would have been different after the class was
+     entirely defined.  */
+  else if (type_decl != error_mark_node
+          && !parser->scope)
+    maybe_note_name_used_in_class (identifier, type_decl);
+  
+  return type_decl;
+}
+
+/* Parse an elaborated-type-specifier.  Note that the grammar given
+   here incorporates the resolution to DR68.
+
+   elaborated-type-specifier:
+     class-key :: [opt] nested-name-specifier [opt] identifier
+     class-key :: [opt] nested-name-specifier [opt] template [opt] template-id
+     enum-key :: [opt] nested-name-specifier [opt] identifier
+     typename :: [opt] nested-name-specifier identifier
+     typename :: [opt] nested-name-specifier template [opt]
+       template-id
+
+   GNU extension:
+
+   elaborated-type-specifier:
+     class-key attributes :: [opt] nested-name-specifier [opt] identifier
      class-key attributes :: [opt] nested-name-specifier [opt]
               template [opt] template-id
      enum attributes :: [opt] nested-name-specifier [opt] identifier
      class-key attributes :: [opt] nested-name-specifier [opt]
               template [opt] template-id
      enum attributes :: [opt] nested-name-specifier [opt] identifier
@@ -10011,6 +11440,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
   tree identifier;
   tree type = NULL_TREE;
   tree attributes = NULL_TREE;
   tree identifier;
   tree type = NULL_TREE;
   tree attributes = NULL_TREE;
+  cp_token *token = NULL;
 
   /* See if we're looking at the `enum' keyword.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM))
 
   /* See if we're looking at the `enum' keyword.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM))
@@ -10019,6 +11449,17 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       cp_lexer_consume_token (parser->lexer);
       /* Remember that it's an enumeration type.  */
       tag_type = enum_type;
       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);
     }
       /* Parse the attributes.  */
       attributes = cp_parser_attributes_opt (parser);
     }
@@ -10032,7 +11473,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       tag_type = typename_type;
       /* The `typename' keyword is only allowed in templates.  */
       if (!processing_template_decl)
       tag_type = typename_type;
       /* The `typename' keyword is only allowed in templates.  */
       if (!processing_template_decl)
-       pedwarn ("using %<typename%> outside of template");
+       permerror (input_location, "using %<typename%> outside of template");
     }
   /* Otherwise it must be a class-key.  */
   else
     }
   /* Otherwise it must be a class-key.  */
   else
@@ -10066,8 +11507,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
                                         /*check_dependency_p=*/true,
                                         /*type_p=*/true,
                                         is_declaration);
                                         /*check_dependency_p=*/true,
                                         /*type_p=*/true,
                                         is_declaration);
-  /* For everything but enumeration types, consider a template-id.  */
-  /* For an enumeration type, consider only a plain identifier.  */
+ /* For everything but enumeration types, consider a template-id.
+    For an enumeration type, consider only a plain identifier.  */
   if (tag_type != enum_type)
     {
       bool template_p = false;
   if (tag_type != enum_type)
     {
       bool template_p = false;
@@ -10080,6 +11521,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (!template_p)
        cp_parser_parse_tentatively (parser);
       /* Parse the template-id.  */
       if (!template_p)
        cp_parser_parse_tentatively (parser);
       /* Parse the template-id.  */
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_template_id (parser, template_p,
                                    /*check_dependency_p=*/true,
                                    is_declaration);
       decl = cp_parser_template_id (parser, template_p,
                                    /*check_dependency_p=*/true,
                                    is_declaration);
@@ -10101,6 +11543,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
   if (!type)
     {
 
   if (!type)
     {
+      token = cp_lexer_peek_token (parser->lexer);
       identifier = cp_parser_identifier (parser);
 
       if (identifier == error_mark_node)
       identifier = cp_parser_identifier (parser);
 
       if (identifier == error_mark_node)
@@ -10113,18 +11556,26 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       if (tag_type == typename_type
          && TREE_CODE (parser->scope) != NAMESPACE_DECL)
        return cp_parser_make_typename_type (parser, parser->scope,
       if (tag_type == typename_type
          && TREE_CODE (parser->scope) != NAMESPACE_DECL)
        return cp_parser_make_typename_type (parser, parser->scope,
-                                            identifier);
+                                            identifier,
+                                            token->location);
       /* Look up a qualified name in the usual way.  */
       if (parser->scope)
        {
          tree decl;
       /* Look up a qualified name in the usual way.  */
       if (parser->scope)
        {
          tree decl;
+         tree ambiguous_decls;
 
          decl = cp_parser_lookup_name (parser, identifier,
                                        tag_type,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
                                        /*check_dependency=*/true,
 
          decl = cp_parser_lookup_name (parser, identifier,
                                        tag_type,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
                                        /*check_dependency=*/true,
-                                       /*ambiguous_decls=*/NULL);
+                                       &ambiguous_decls,
+                                       token->location);
+
+         /* If the lookup was ambiguous, an error will already have been
+            issued.  */
+         if (ambiguous_decls)
+           return error_mark_node;
 
          /* If we are parsing friend declaration, DECL may be a
             TEMPLATE_DECL tree node here.  However, we need to check
 
          /* If we are parsing friend declaration, DECL may be a
             TEMPLATE_DECL tree node here.  However, we need to check
@@ -10155,15 +11606,38 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
            {
              cp_parser_diagnose_invalid_type_name (parser,
                                                    parser->scope,
            {
              cp_parser_diagnose_invalid_type_name (parser,
                                                    parser->scope,
-                                                   identifier);
+                                                   identifier,
+                                                   token->location);
              return error_mark_node;
            }
 
          if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
              return error_mark_node;
            }
 
          if (TREE_CODE (TREE_TYPE (decl)) != TYPENAME_TYPE)
-           check_elaborated_type_specifier
-             (tag_type, decl,
-              (parser->num_template_parameter_lists
-               || DECL_SELF_REFERENCE_P (decl)));
+            {
+              bool allow_template = (parser->num_template_parameter_lists
+                                     || DECL_SELF_REFERENCE_P (decl));
+              type = check_elaborated_type_specifier (tag_type, decl, 
+                                                      allow_template);
+
+              if (type == error_mark_node)
+                return error_mark_node;
+            }
+
+          /* Forward declarations of nested types, such as
+
+               class C1::C2;
+               class C1::C2::C3;
+
+             are invalid unless all components preceding the final '::'
+             are complete.  If all enclosing types are complete, these
+             declarations become merely pointless.
+
+             Invalid forward declarations of nested types are errors
+             caught elsewhere in parsing.  Those that are pointless arrive
+             here.  */
+
+          if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+              && !is_friend && !processing_explicit_instantiation)
+            warning (0, "declaration %qD does not declare anything", decl);
 
          type = TREE_TYPE (decl);
        }
 
          type = TREE_TYPE (decl);
        }
@@ -10233,17 +11707,24 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
          /* An unqualified name was used to reference this type, so
             there were no qualifying templates.  */
          if (!cp_parser_check_template_parameters (parser,
          /* An unqualified name was used to reference this type, so
             there were no qualifying templates.  */
          if (!cp_parser_check_template_parameters (parser,
-                                                   /*num_templates=*/0))
+                                                   /*num_templates=*/0,
+                                                   token->location))
            return error_mark_node;
          type = xref_tag (tag_type, identifier, ts, template_p);
        }
     }
 
            return error_mark_node;
          type = xref_tag (tag_type, identifier, ts, template_p);
        }
     }
 
+  if (type == error_mark_node)
+    return error_mark_node;
+
   /* Allow attributes on forward declarations of classes.  */
   if (attributes)
     {
   /* Allow attributes on forward declarations of classes.  */
   if (attributes)
     {
-      if (tag_type != enum_type && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
-         && ! processing_explicit_instantiation)
+      if (TREE_CODE (type) == TYPENAME_TYPE)
+       warning (OPT_Wattributes,
+                "attributes ignored on uninstantiated type");
+      else if (tag_type != enum_type && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+              && ! processing_explicit_instantiation)
        warning (OPT_Wattributes,
                 "attributes ignored on template instantiation");
       else if (is_declaration && cp_parser_declares_only_class_p (parser))
        warning (OPT_Wattributes,
                 "attributes ignored on template instantiation");
       else if (is_declaration && cp_parser_declares_only_class_p (parser))
@@ -10258,7 +11739,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
   /* A "<" cannot follow an elaborated type specifier.  If that
      happens, the user was probably trying to form a template-id.  */
 
   /* A "<" cannot follow an elaborated type specifier.  If that
      happens, the user was probably trying to form a template-id.  */
-  cp_parser_check_for_invalid_template_id (parser, type);
+  cp_parser_check_for_invalid_template_id (parser, type, token->location);
 
   return type;
 }
 
   return type;
 }
@@ -10266,11 +11747,19 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 /* Parse an enum-specifier.
 
    enum-specifier:
 /* 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:
 
    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.  */
 
    Returns an ENUM_TYPE representing the enumeration, or NULL_TREE
    if the token stream isn't an enum-specifier after all.  */
@@ -10281,6 +11770,9 @@ cp_parser_enum_specifier (cp_parser* parser)
   tree identifier;
   tree type;
   tree attributes;
   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.  */
 
   /* Parse tentatively so that we can back up if we don't find a
      enum-specifier.  */
@@ -10292,6 +11784,20 @@ cp_parser_enum_specifier (cp_parser* parser)
      the enumeration being defined.  */
   cp_lexer_consume_token (parser->lexer);
 
      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))
   attributes = cp_parser_attributes_opt (parser);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
@@ -10299,21 +11805,57 @@ cp_parser_enum_specifier (cp_parser* parser)
   else
     identifier = make_anon_name ();
 
   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))
   /* 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.  */
     return NULL_TREE;
 
   /* Issue an error message if type-definitions are forbidden here.  */
-  cp_parser_check_type_definition (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);
-
+  if (!cp_parser_check_type_definition (parser))
+    type = error_mark_node;
+  else
+    /* Create the new type.  We do this before consuming the opening
+       brace so the enum will be recorded as being on the line of its
+       tag (or the 'enum' keyword, if there is no tag).  */
+    type = start_enum (identifier, underlying_type, scoped_enum_p);
+  
   /* Consume the opening brace.  */
   cp_lexer_consume_token (parser->lexer);
 
   /* Consume the opening brace.  */
   cp_lexer_consume_token (parser->lexer);
 
@@ -10328,7 +11870,7 @@ cp_parser_enum_specifier (cp_parser* parser)
     cp_parser_enumerator_list (parser, type);
 
   /* Consume the final '}'.  */
     cp_parser_enumerator_list (parser, type);
 
   /* Consume the final '}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 
   /* Look for trailing attributes to apply to this enumeration, and
      apply them if appropriate.  */
 
   /* Look for trailing attributes to apply to this enumeration, and
      apply them if appropriate.  */
@@ -10370,8 +11912,8 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
       /* If the next token is a `}', there is a trailing comma.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
        {
       /* If the next token is a `}', there is a trailing comma.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
        {
-         if (pedantic && !in_system_header)
-           pedwarn ("comma at end of enumerator list");
+         if (!in_system_header)
+           pedwarn (input_location, OPT_pedantic, "comma at end of enumerator list");
          break;
        }
     }
          break;
        }
     }
@@ -10429,6 +11971,8 @@ cp_parser_namespace_name (cp_parser* parser)
   tree identifier;
   tree namespace_decl;
 
   tree identifier;
   tree namespace_decl;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Get the name of the namespace.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
   /* Get the name of the namespace.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
@@ -10449,7 +11993,7 @@ cp_parser_namespace_name (cp_parser* parser)
        During the lookup of a name preceding the :: scope resolution
        operator, object, function, and enumerator names are ignored.
 
        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,
      function if the token after the name is the scope resolution
      operator.)  */
   namespace_decl = cp_parser_lookup_name (parser, identifier,
@@ -10457,13 +12001,14 @@ cp_parser_namespace_name (cp_parser* parser)
                                          /*is_template=*/false,
                                          /*is_namespace=*/true,
                                          /*check_dependency=*/true,
                                          /*is_template=*/false,
                                          /*is_namespace=*/true,
                                          /*check_dependency=*/true,
-                                         /*ambiguous_decls=*/NULL);
+                                         /*ambiguous_decls=*/NULL,
+                                         token->location);
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
     {
       if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
     {
       if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
-       error ("%qD is not a namespace-name", identifier);
+       error ("%H%qD is not a namespace-name", &token->location, identifier);
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
@@ -10494,9 +12039,19 @@ static void
 cp_parser_namespace_definition (cp_parser* parser)
 {
   tree identifier, attribs;
 cp_parser_namespace_definition (cp_parser* parser)
 {
   tree identifier, attribs;
+  bool has_visibility;
+  bool is_inline;
+
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE))
+    {
+      is_inline = true;
+      cp_lexer_consume_token (parser->lexer);
+    }
+  else
+    is_inline = false;
 
   /* Look for the `namespace' keyword.  */
 
   /* Look for the `namespace' keyword.  */
-  cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
 
   /* Get the name of the namespace.  We do not attempt to distinguish
      between an original-namespace-definition and an
 
   /* Get the name of the namespace.  We do not attempt to distinguish
      between an original-namespace-definition and an
@@ -10511,15 +12066,39 @@ cp_parser_namespace_definition (cp_parser* parser)
   attribs = cp_parser_attributes_opt (parser);
 
   /* Look for the `{' to start the namespace.  */
   attribs = cp_parser_attributes_opt (parser);
 
   /* Look for the `{' to start the namespace.  */
-  cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+  cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
   /* Start the namespace.  */
   /* Start the namespace.  */
-  push_namespace_with_attribs (identifier, attribs);
+  push_namespace (identifier);
+
+  /* "inline namespace" is equivalent to a stub namespace definition
+     followed by a strong using directive.  */
+  if (is_inline)
+    {
+      tree name_space = current_namespace;
+      /* Set up namespace association.  */
+      DECL_NAMESPACE_ASSOCIATIONS (name_space)
+       = tree_cons (CP_DECL_CONTEXT (name_space), NULL_TREE,
+                    DECL_NAMESPACE_ASSOCIATIONS (name_space));
+      /* Import the contents of the inline namespace.  */
+      pop_namespace ();
+      do_using_directive (name_space);
+      push_namespace (identifier);
+    }
+
+  has_visibility = handle_namespace_attrs (current_namespace, attribs);
+
   /* Parse the body of the namespace.  */
   cp_parser_namespace_body (parser);
   /* Parse the body of the namespace.  */
   cp_parser_namespace_body (parser);
+
+#ifdef HANDLE_PRAGMA_VISIBILITY
+  if (has_visibility)
+    pop_visibility ();
+#endif
+
   /* Finish the namespace.  */
   pop_namespace ();
   /* Look for the final `}'.  */
   /* Finish the namespace.  */
   pop_namespace ();
   /* Look for the final `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 }
 
 /* Parse a namespace-body.
 }
 
 /* Parse a namespace-body.
@@ -10544,19 +12123,31 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   tree identifier;
   tree namespace_specifier;
 
   tree identifier;
   tree namespace_specifier;
 
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
   /* Look for the `namespace' keyword.  */
   /* Look for the `namespace' keyword.  */
-  cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the identifier.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
     return;
   /* Look for the `=' token.  */
   /* Look for the identifier.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
     return;
   /* Look for the `=' token.  */
-  cp_parser_require (parser, CPP_EQ, "`='");
+  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);
+      /* Skip the definition.  */
+      cp_lexer_consume_token (parser->lexer);
+      if (cp_parser_skip_to_closing_brace (parser))
+       cp_lexer_consume_token (parser->lexer);
+      return;
+    }
+  cp_parser_require (parser, CPP_EQ, "%<=%>");
   /* Look for the qualified-namespace-specifier.  */
   namespace_specifier
     = cp_parser_qualified_namespace_specifier (parser);
   /* Look for the `;' token.  */
   /* Look for the qualified-namespace-specifier.  */
   namespace_specifier
     = cp_parser_qualified_namespace_specifier (parser);
   /* Look for the `;' token.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
   /* Register the alias in the symbol table.  */
   do_namespace_alias (identifier, namespace_specifier);
 
   /* Register the alias in the symbol table.  */
   do_namespace_alias (identifier, namespace_specifier);
@@ -10587,14 +12178,21 @@ cp_parser_qualified_namespace_specifier (cp_parser* parser)
   return cp_parser_namespace_name (parser);
 }
 
   return cp_parser_namespace_name (parser);
 }
 
-/* Parse a using-declaration.
+/* Parse a using-declaration, or, if ACCESS_DECLARATION_P is true, an
+   access declaration.
 
    using-declaration:
      using typename [opt] :: [opt] nested-name-specifier unqualified-id ;
 
    using-declaration:
      using typename [opt] :: [opt] nested-name-specifier unqualified-id ;
-     using :: unqualified-id ;  */
+     using :: unqualified-id ;  
 
 
-static void
-cp_parser_using_declaration (cp_parser* parser)
+   access-declaration:
+     qualified-id ;  
+
+   */
+
+static bool
+cp_parser_using_declaration (cp_parser* parser, 
+                            bool access_declaration_p)
 {
   cp_token *token;
   bool typename_p = false;
 {
   cp_token *token;
   bool typename_p = false;
@@ -10603,18 +12201,23 @@ cp_parser_using_declaration (cp_parser* parser)
   tree identifier;
   tree qscope;
 
   tree identifier;
   tree qscope;
 
-  /* Look for the `using' keyword.  */
-  cp_parser_require_keyword (parser, RID_USING, "`using'");
-
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  /* See if it's `typename'.  */
-  if (token->keyword == RID_TYPENAME)
+  if (access_declaration_p)
+    cp_parser_parse_tentatively (parser);
+  else
     {
     {
-      /* Remember that we've seen it.  */
-      typename_p = true;
-      /* Consume the `typename' token.  */
-      cp_lexer_consume_token (parser->lexer);
+      /* Look for the `using' keyword.  */
+      cp_parser_require_keyword (parser, RID_USING, "%<using%>");
+      
+      /* Peek at the next token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      /* See if it's `typename'.  */
+      if (token->keyword == RID_TYPENAME)
+       {
+         /* Remember that we've seen it.  */
+         typename_p = true;
+         /* Consume the `typename' token.  */
+         cp_lexer_consume_token (parser->lexer);
+       }
     }
 
   /* Look for the optional global scope qualification.  */
     }
 
   /* Look for the optional global scope qualification.  */
@@ -10641,6 +12244,13 @@ cp_parser_using_declaration (cp_parser* parser)
   if (!qscope)
     qscope = global_namespace;
 
   if (!qscope)
     qscope = global_namespace;
 
+  if (access_declaration_p && cp_parser_error_occurred (parser))
+    /* Something has already gone wrong; there's no need to parse
+       further.  Since an error has occurred, the return value of
+       cp_parser_parse_definitely will be false, as required.  */
+    return cp_parser_parse_definitely (parser);
+
+  token = cp_lexer_peek_token (parser->lexer);
   /* Parse the unqualified-id.  */
   identifier = cp_parser_unqualified_id (parser,
                                         /*template_keyword_p=*/false,
   /* Parse the unqualified-id.  */
   identifier = cp_parser_unqualified_id (parser,
                                         /*template_keyword_p=*/false,
@@ -10648,6 +12258,14 @@ cp_parser_using_declaration (cp_parser* parser)
                                         /*declarator_p=*/true,
                                         /*optional_p=*/false);
 
                                         /*declarator_p=*/true,
                                         /*optional_p=*/false);
 
+  if (access_declaration_p)
+    {
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       cp_parser_simulate_error (parser);
+      if (!cp_parser_parse_definitely (parser))
+       return false;
+    }
+
   /* The function we call to handle a using-declaration is different
      depending on what scope we are in.  */
   if (qscope == error_mark_node || identifier == error_mark_node)
   /* The function we call to handle a using-declaration is different
      depending on what scope we are in.  */
   if (qscope == error_mark_node || identifier == error_mark_node)
@@ -10657,21 +12275,32 @@ cp_parser_using_declaration (cp_parser* parser)
     /* [namespace.udecl]
 
        A using declaration shall not name a template-id.  */
     /* [namespace.udecl]
 
        A using declaration shall not name a template-id.  */
-    error ("a template-id may not appear in a using-declaration");
+    error ("%Ha template-id may not appear in a using-declaration",
+            &token->location);
   else
     {
       if (at_class_scope_p ())
        {
          /* Create the USING_DECL.  */
          decl = do_class_using_decl (parser->scope, identifier);
   else
     {
       if (at_class_scope_p ())
        {
          /* Create the USING_DECL.  */
          decl = do_class_using_decl (parser->scope, identifier);
-         /* Add it to the list of members in this class.  */
-         finish_member_declaration (decl);
+
+         if (check_for_bare_parameter_packs (decl))
+            return false;
+          else
+           /* Add it to the list of members in this class.  */
+           finish_member_declaration (decl);
        }
       else
        {
        }
       else
        {
-         decl = cp_parser_lookup_name_simple (parser, identifier);
+         decl = cp_parser_lookup_name_simple (parser,
+                                              identifier,
+                                              token->location);
          if (decl == error_mark_node)
          if (decl == error_mark_node)
-           cp_parser_name_lookup_error (parser, identifier, decl, NULL);
+           cp_parser_name_lookup_error (parser, identifier,
+                                        decl, NULL,
+                                        token->location);
+         else if (check_for_bare_parameter_packs (decl))
+           return false;
          else if (!at_namespace_scope_p ())
            do_local_using_decl (decl, qscope, identifier);
          else
          else if (!at_namespace_scope_p ())
            do_local_using_decl (decl, qscope, identifier);
          else
@@ -10680,7 +12309,9 @@ cp_parser_using_declaration (cp_parser* parser)
     }
 
   /* Look for the final `;'.  */
     }
 
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  
+  return true;
 }
 
 /* Parse a using-directive.
 }
 
 /* Parse a using-directive.
@@ -10696,9 +12327,9 @@ cp_parser_using_directive (cp_parser* parser)
   tree attribs;
 
   /* Look for the `using' keyword.  */
   tree attribs;
 
   /* Look for the `using' keyword.  */
-  cp_parser_require_keyword (parser, RID_USING, "`using'");
+  cp_parser_require_keyword (parser, RID_USING, "%<using%>");
   /* And the `namespace' keyword.  */
   /* And the `namespace' keyword.  */
-  cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
   /* And the optional nested-name-specifier.  */
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
   /* And the optional nested-name-specifier.  */
@@ -10714,7 +12345,7 @@ cp_parser_using_directive (cp_parser* parser)
   /* Update the symbol table.  */
   parse_using_directive (namespace_decl, attribs);
   /* Look for the final `;'.  */
   /* Update the symbol table.  */
   parse_using_directive (namespace_decl, attribs);
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 }
 
 /* Parse an asm-definition.
 }
 
 /* Parse an asm-definition.
@@ -10743,9 +12374,11 @@ cp_parser_asm_definition (cp_parser* parser)
   tree asm_stmt;
   bool volatile_p = false;
   bool extended_p = false;
   tree asm_stmt;
   bool volatile_p = false;
   bool extended_p = false;
+  bool invalid_inputs_p = false;
+  bool invalid_outputs_p = false;
 
   /* Look for the `asm' keyword.  */
 
   /* Look for the `asm' keyword.  */
-  cp_parser_require_keyword (parser, RID_ASM, "`asm'");
+  cp_parser_require_keyword (parser, RID_ASM, "%<asm%>");
   /* See if the next token is `volatile'.  */
   if (cp_parser_allow_gnu_extensions_p (parser)
       && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
   /* See if the next token is `volatile'.  */
   if (cp_parser_allow_gnu_extensions_p (parser)
       && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
@@ -10756,7 +12389,7 @@ cp_parser_asm_definition (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the opening `('.  */
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the opening `('.  */
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return;
   /* Look for the string.  */
   string = cp_parser_string_literal (parser, false, false);
     return;
   /* Look for the string.  */
   string = cp_parser_string_literal (parser, false, false);
@@ -10773,7 +12406,7 @@ cp_parser_asm_definition (cp_parser* parser)
      too.  Doing that means that we have to treat the `::' operator as
      two `:' tokens.  */
   if (cp_parser_allow_gnu_extensions_p (parser)
      too.  Doing that means that we have to treat the `::' operator as
      two `:' tokens.  */
   if (cp_parser_allow_gnu_extensions_p (parser)
-      && at_function_scope_p ()
+      && parser->in_function_body
       && (cp_lexer_next_token_is (parser->lexer, CPP_COLON)
          || cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)))
     {
       && (cp_lexer_next_token_is (parser->lexer, CPP_COLON)
          || cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)))
     {
@@ -10796,6 +12429,9 @@ cp_parser_asm_definition (cp_parser* parser)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            outputs = cp_parser_asm_operand_list (parser);
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            outputs = cp_parser_asm_operand_list (parser);
+
+           if (outputs == error_mark_node)
+             invalid_outputs_p = true;
        }
       /* If the next token is `::', there are no outputs, and the
         next token is the beginning of the inputs.  */
        }
       /* If the next token is `::', there are no outputs, and the
         next token is the beginning of the inputs.  */
@@ -10815,6 +12451,9 @@ cp_parser_asm_definition (cp_parser* parser)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            inputs = cp_parser_asm_operand_list (parser);
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            inputs = cp_parser_asm_operand_list (parser);
+
+           if (inputs == error_mark_node)
+             invalid_inputs_p = true;
        }
       else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
        /* The clobbers are coming next.  */
        }
       else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
        /* The clobbers are coming next.  */
@@ -10833,28 +12472,31 @@ cp_parser_asm_definition (cp_parser* parser)
        }
     }
   /* Look for the closing `)'.  */
        }
     }
   /* Look for the closing `)'.  */
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                           /*consume_paren=*/true);
     cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                           /*consume_paren=*/true);
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
 
-  /* Create the ASM_EXPR.  */
-  if (at_function_scope_p ())
+  if (!invalid_inputs_p && !invalid_outputs_p)
     {
     {
-      asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
-                                 inputs, clobbers);
-      /* If the extended syntax was not used, mark the ASM_EXPR.  */
-      if (!extended_p)
+      /* Create the ASM_EXPR.  */
+      if (parser->in_function_body)
        {
        {
-         tree temp = asm_stmt;
-         if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
-           temp = TREE_OPERAND (temp, 0);
+         asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
+                                     inputs, clobbers);
+         /* If the extended syntax was not used, mark the ASM_EXPR.  */
+         if (!extended_p)
+           {
+             tree temp = asm_stmt;
+             if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
+               temp = TREE_OPERAND (temp, 0);
 
 
-         ASM_INPUT_P (temp) = 1;
+             ASM_INPUT_P (temp) = 1;
+           }
        }
        }
+      else
+       cgraph_add_asm_node (string);
     }
     }
-  else
-    cgraph_add_asm_node (string);
 }
 
 /* Declarators [gram.dcl.decl] */
 }
 
 /* Declarators [gram.dcl.decl] */
@@ -10900,13 +12542,14 @@ cp_parser_asm_definition (cp_parser* parser)
 static tree
 cp_parser_init_declarator (cp_parser* parser,
                           cp_decl_specifier_seq *decl_specifiers,
 static tree
 cp_parser_init_declarator (cp_parser* parser,
                           cp_decl_specifier_seq *decl_specifiers,
-                          tree checks,
+                          VEC (deferred_access_check,gc)* checks,
                           bool function_definition_allowed_p,
                           bool member_p,
                           int declares_class_or_enum,
                           bool* function_definition_p)
 {
                           bool function_definition_allowed_p,
                           bool member_p,
                           int declares_class_or_enum,
                           bool* function_definition_p)
 {
-  cp_token *token;
+  cp_token *token = NULL, *asm_spec_start_token = NULL,
+           *attributes_start_token = NULL;
   cp_declarator *declarator;
   tree prefix_attributes;
   tree attributes;
   cp_declarator *declarator;
   tree prefix_attributes;
   tree attributes;
@@ -10914,12 +12557,12 @@ cp_parser_init_declarator (cp_parser* parser,
   tree initializer;
   tree decl = NULL_TREE;
   tree scope;
   tree initializer;
   tree decl = NULL_TREE;
   tree scope;
-  bool is_initialized;
+  int is_initialized;
   /* Only valid if IS_INITIALIZED is true.  In that case, CPP_EQ if
      initialized with "= ..", CPP_OPEN_PAREN if initialized with
      "(...)".  */
   enum cpp_ttype initialization_kind;
   /* Only valid if IS_INITIALIZED is true.  In that case, CPP_EQ if
      initialized with "= ..", CPP_OPEN_PAREN if initialized with
      "(...)".  */
   enum cpp_ttype initialization_kind;
-  bool is_parenthesized_init = false;
+  bool is_direct_init = false;
   bool is_non_constant_init;
   int ctor_dtor_or_conv_p;
   bool friend_p;
   bool is_non_constant_init;
   int ctor_dtor_or_conv_p;
   bool friend_p;
@@ -10940,6 +12583,7 @@ cp_parser_init_declarator (cp_parser* parser,
   resume_deferring_access_checks ();
 
   /* Parse the declarator.  */
   resume_deferring_access_checks ();
 
   /* Parse the declarator.  */
+  token = cp_lexer_peek_token (parser->lexer);
   declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                            &ctor_dtor_or_conv_p,
   declarator
     = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
                            &ctor_dtor_or_conv_p,
@@ -10953,9 +12597,15 @@ cp_parser_init_declarator (cp_parser* parser,
   if (declarator == cp_error_declarator)
     return error_mark_node;
 
   if (declarator == cp_error_declarator)
     return error_mark_node;
 
+  /* Check that the number of template-parameter-lists is OK.  */
+  if (!cp_parser_check_declarator_template_parameters (parser, declarator,
+                                                      token->location))
+    return error_mark_node;
+
   if (declares_class_or_enum & 2)
     cp_parser_check_for_definition_in_return_type (declarator,
   if (declares_class_or_enum & 2)
     cp_parser_check_for_definition_in_return_type (declarator,
-                                                  decl_specifiers->type);
+                                                  decl_specifiers->type,
+                                                  decl_specifiers->type_location);
 
   /* Figure out what scope the entity declared by the DECLARATOR is
      located in.  `grokdeclarator' sometimes changes the scope, so
 
   /* Figure out what scope the entity declared by the DECLARATOR is
      located in.  `grokdeclarator' sometimes changes the scope, so
@@ -10967,8 +12617,10 @@ cp_parser_init_declarator (cp_parser* parser,
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       /* Look for an asm-specification.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
     {
       /* Look for an asm-specification.  */
+      asm_spec_start_token = cp_lexer_peek_token (parser->lexer);
       asm_specification = cp_parser_asm_specification_opt (parser);
       /* And attributes.  */
       asm_specification = cp_parser_asm_specification_opt (parser);
       /* And attributes.  */
+      attributes_start_token = cp_lexer_peek_token (parser->lexer);
       attributes = cp_parser_attributes_opt (parser);
     }
   else
       attributes = cp_parser_attributes_opt (parser);
     }
   else
@@ -10981,7 +12633,8 @@ cp_parser_init_declarator (cp_parser* parser,
   token = cp_lexer_peek_token (parser->lexer);
   /* Check to see if the token indicates the start of a
      function-definition.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* Check to see if the token indicates the start of a
      function-definition.  */
-  if (cp_parser_token_starts_function_definition_p (token))
+  if (function_declarator_p (declarator)
+      && cp_parser_token_starts_function_definition_p (token))
     {
       if (!function_definition_allowed_p)
        {
     {
       if (!function_definition_allowed_p)
        {
@@ -10993,12 +12646,18 @@ cp_parser_init_declarator (cp_parser* parser,
        }
       else
        {
        }
       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)
          /* Neither attributes nor an asm-specification are allowed
             on a function-definition.  */
          if (asm_specification)
-           error ("an asm-specification is not allowed on a function-definition");
+           error ("%Han asm-specification is not allowed "
+                  "on a function-definition",
+                  &asm_spec_start_token->location);
          if (attributes)
          if (attributes)
-           error ("attributes are not allowed on a function-definition");
+           error ("%Hattributes are not allowed on a function-definition",
+                  &attributes_start_token->location);
          /* This is a function-definition.  */
          *function_definition_p = true;
 
          /* This is a function-definition.  */
          *function_definition_p = true;
 
@@ -11013,6 +12672,13 @@ cp_parser_init_declarator (cp_parser* parser,
              = (cp_parser_function_definition_from_specifiers_and_declarator
                 (parser, decl_specifiers, prefix_attributes, declarator));
 
              = (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;
        }
     }
          return decl;
        }
     }
@@ -11032,12 +12698,23 @@ cp_parser_init_declarator (cp_parser* parser,
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
-  /* An `=' or an `(' indicates an initializer.  */
+  /* An `=' or an `(', or an '{' in C++0x, indicates an initializer.  */
   if (token->type == CPP_EQ
   if (token->type == CPP_EQ
-      || token->type == CPP_OPEN_PAREN)
+      || token->type == CPP_OPEN_PAREN
+      || token->type == CPP_OPEN_BRACE)
     {
     {
-      is_initialized = true;
+      is_initialized = SD_INITIALIZED;
       initialization_kind = token->type;
       initialization_kind = token->type;
+
+      if (token->type == CPP_EQ
+         && function_declarator_p (declarator))
+       {
+         cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
+         if (t2->keyword == RID_DEFAULT)
+           is_initialized = SD_DEFAULTED;
+         else if (t2->keyword == RID_DELETE)
+           is_initialized = SD_DELETED;
+       }
     }
   else
     {
     }
   else
     {
@@ -11049,7 +12726,7 @@ cp_parser_init_declarator (cp_parser* parser,
          cp_parser_error (parser, "expected initializer");
          return error_mark_node;
        }
          cp_parser_error (parser, "expected initializer");
          return error_mark_node;
        }
-      is_initialized = false;
+      is_initialized = SD_UNINITIALIZED;
       initialization_kind = CPP_EOF;
     }
 
       initialization_kind = CPP_EOF;
     }
 
@@ -11072,10 +12749,6 @@ cp_parser_init_declarator (cp_parser* parser,
   /* Check to see whether or not this declaration is a friend.  */
   friend_p = cp_parser_friend_p (decl_specifiers);
 
   /* Check to see whether or not this declaration is a friend.  */
   friend_p = cp_parser_friend_p (decl_specifiers);
 
-  /* Check that the number of template-parameter-lists is OK.  */
-  if (!cp_parser_check_declarator_template_parameters (parser, declarator))
-    return error_mark_node;
-
   /* Enter the newly declared entry in the symbol table.  If we're
      processing a declaration in a class-specifier, we wait until
      after processing the initializer.  */
   /* Enter the newly declared entry in the symbol table.  If we're
      processing a declaration in a class-specifier, we wait until
      after processing the initializer.  */
@@ -11111,7 +12784,7 @@ cp_parser_init_declarator (cp_parser* parser,
       cp_parser_perform_template_parameter_access_checks (checks);
 
       /* Perform the access control checks for the declarator and the
       cp_parser_perform_template_parameter_access_checks (checks);
 
       /* Perform the access control checks for the declarator and the
-        the decl-specifiers.  */
+        decl-specifiers.  */
       perform_deferred_access_checks ();
 
       /* Restore the saved value.  */
       perform_deferred_access_checks ();
 
       /* Restore the saved value.  */
@@ -11121,17 +12794,32 @@ cp_parser_init_declarator (cp_parser* parser,
 
   /* Parse the initializer.  */
   initializer = NULL_TREE;
 
   /* Parse the initializer.  */
   initializer = NULL_TREE;
-  is_parenthesized_init = false;
+  is_direct_init = false;
   is_non_constant_init = true;
   if (is_initialized)
     {
   is_non_constant_init = true;
   if (is_initialized)
     {
-      if (declarator->kind == cdk_function
-         && declarator->declarator->kind == cdk_id
-         && initialization_kind == CPP_EQ)
-       initializer = cp_parser_pure_specifier (parser);
+      if (function_declarator_p (declarator))
+       {
+         cp_token *initializer_start_token = cp_lexer_peek_token (parser->lexer);
+          if (initialization_kind == CPP_EQ)
+            initializer = cp_parser_pure_specifier (parser);
+          else
+            {
+              /* If the declaration was erroneous, we don't really
+                 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);
+              cp_parser_skip_to_closing_parenthesis (parser,
+                                                     /*recovering=*/true,
+                                                     /*or_comma=*/false,
+                                                     /*consume_paren=*/true);
+            }
+       }
       else
        initializer = cp_parser_initializer (parser,
       else
        initializer = cp_parser_initializer (parser,
-                                            &is_parenthesized_init,
+                                            &is_direct_init,
                                             &is_non_constant_init);
     }
 
                                             &is_non_constant_init);
     }
 
@@ -11139,7 +12827,8 @@ cp_parser_init_declarator (cp_parser* parser,
      initializer.  Mark Mitchell proposed removing this functionality
      on the GCC mailing lists on 2002-08-13.  This parser accepts the
      attributes -- but ignores them.  */
      initializer.  Mark Mitchell proposed removing this functionality
      on the GCC mailing lists on 2002-08-13.  This parser accepts the
      attributes -- but ignores them.  */
-  if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init)
+  if (cp_parser_allow_gnu_extensions_p (parser)
+      && initialization_kind == CPP_OPEN_PAREN)
     if (cp_parser_attributes_opt (parser))
       warning (OPT_Wattributes,
               "attributes after parenthesized initializer ignored");
     if (cp_parser_attributes_opt (parser))
       warning (OPT_Wattributes,
               "attributes after parenthesized initializer ignored");
@@ -11172,9 +12861,17 @@ cp_parser_init_declarator (cp_parser* parser,
                         a direct-initialization, which means that an
                         `explicit' constructor is OK.  Otherwise, an
                         `explicit' constructor cannot be used.  */
                         a direct-initialization, which means that an
                         `explicit' constructor is OK.  Otherwise, an
                         `explicit' constructor cannot be used.  */
-                     ((is_parenthesized_init || !is_initialized)
-                    ? 0 : LOOKUP_ONLYCONVERTING));
+                     ((is_direct_init || !is_initialized)
+                      ? 0 : LOOKUP_ONLYCONVERTING));
     }
     }
+  else if ((cxx_dialect != cxx98) && friend_p
+          && decl && TREE_CODE (decl) == FUNCTION_DECL)
+    /* Core issue #226 (C++0x only): A default template-argument
+       shall not be specified in a friend class template
+       declaration. */
+    check_default_tmpl_args (decl, current_template_parms, /*is_primary=*/1, 
+                             /*is_partial=*/0, /*is_friend_decl=*/1);
+
   if (!friend_p && pushed_scope)
     pop_scope (pushed_scope);
 
   if (!friend_p && pushed_scope)
     pop_scope (pushed_scope);
 
@@ -11275,15 +12972,8 @@ cp_parser_declarator (cp_parser* parser,
          && !cp_parser_parse_definitely (parser))
        declarator = NULL;
 
          && !cp_parser_parse_definitely (parser))
        declarator = NULL;
 
-      /* Build the representation of the ptr-operator.  */
-      if (class_type)
-       declarator = make_ptrmem_declarator (cv_quals,
-                                            class_type,
-                                            declarator);
-      else if (code == INDIRECT_REF)
-       declarator = make_pointer_declarator (cv_quals, declarator);
-      else
-       declarator = make_reference_declarator (cv_quals, declarator);
+      declarator = cp_parser_make_indirect_declarator
+       (code, class_type, cv_quals, declarator);
     }
   /* Everything else is a direct-declarator.  */
   else
     }
   /* Everything else is a direct-declarator.  */
   else
@@ -11371,7 +13061,7 @@ cp_parser_direct_declarator (cp_parser* parser,
               int i (3);
 
             The first is the declaration of a function while the
               int i (3);
 
             The first is the declaration of a function while the
-            second is the definition of a variable, including its
+            second is the definition of a variable, including its
             initializer.
 
             Having seen only the parenthesis, we cannot know which of
             initializer.
 
             Having seen only the parenthesis, we cannot know which of
@@ -11389,8 +13079,10 @@ cp_parser_direct_declarator (cp_parser* parser,
 
          if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
            {
 
          if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
            {
-             cp_parameter_declarator *params;
+             tree params;
              unsigned saved_num_template_parameter_lists;
              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
 
              /* In a member-declarator, the only valid interpretation
                 of a parenthesis is the start of a
@@ -11417,6 +13109,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                = parser->num_template_parameter_lists;
              parser->num_template_parameter_lists = 0;
 
                = 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);
 
              /* Parse the parameter-declaration-clause.  */
              params = cp_parser_parameter_declaration_clause (parser);
 
@@ -11429,12 +13123,15 @@ cp_parser_direct_declarator (cp_parser* parser,
                {
                  cp_cv_quals cv_quals;
                  tree exception_specification;
                {
                  cp_cv_quals cv_quals;
                  tree exception_specification;
+                 tree late_return;
+
+                 is_declarator = true;
 
                  if (ctor_dtor_or_conv_p)
                    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
                  first = false;
                  /* Consume the `)'.  */
 
                  if (ctor_dtor_or_conv_p)
                    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
                  first = false;
                  /* Consume the `)'.  */
-                 cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+                 cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
                  /* Parse the cv-qualifier-seq.  */
                  cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
 
                  /* Parse the cv-qualifier-seq.  */
                  cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
@@ -11442,19 +13139,29 @@ cp_parser_direct_declarator (cp_parser* parser,
                  exception_specification
                    = cp_parser_exception_specification_opt (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,
                  /* 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;
                  /* 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
            }
 
          /* If this is the first, we can try a parenthesized
@@ -11478,7 +13185,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
              first = false;
              /* Expect a `)'.  */
              parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
              first = false;
              /* Expect a `)'.  */
-             if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+             if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
                declarator = cp_error_declarator;
              if (declarator == cp_error_declarator)
                break;
                declarator = cp_error_declarator;
              if (declarator == cp_error_declarator)
                break;
@@ -11520,16 +13227,17 @@ cp_parser_direct_declarator (cp_parser* parser,
              /* Normally, the array bound must be an integral constant
                 expression.  However, as an extension, we allow VLAs
                 in function scopes.  */
              /* Normally, the array bound must be an integral constant
                 expression.  However, as an extension, we allow VLAs
                 in function scopes.  */
-             else if (!at_function_scope_p ())
+             else if (!parser->in_function_body)
                {
                {
-                 error ("array bound is not an integer constant");
+                 error ("%Harray bound is not an integer constant",
+                        &token->location);
                  bounds = error_mark_node;
                }
            }
          else
            bounds = NULL_TREE;
          /* Look for the closing `]'.  */
                  bounds = error_mark_node;
                }
            }
          else
            bounds = NULL_TREE;
          /* Look for the closing `]'.  */
-         if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
+         if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"))
            {
              declarator = cp_error_declarator;
              break;
            {
              declarator = cp_error_declarator;
              break;
@@ -11543,17 +13251,49 @@ cp_parser_direct_declarator (cp_parser* parser,
          tree unqualified_name;
          special_function_kind sfk;
          bool abstract_ok;
          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)
 
          /* Parse a declarator-id */
          abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
          if (abstract_ok)
-           cp_parser_parse_tentatively (parser);
+            {
+              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);
+
+                  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)
            {
          unqualified_name
            = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
          qualifying_scope = parser->scope;
          if (abstract_ok)
            {
-             if (!cp_parser_parse_definitely (parser))
+              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
                unqualified_name = error_mark_node;
              else if (unqualified_name
                       && (qualifying_scope
@@ -11570,6 +13310,8 @@ cp_parser_direct_declarator (cp_parser* parser,
          if (unqualified_name == error_mark_node)
            {
              declarator = cp_error_declarator;
          if (unqualified_name == error_mark_node)
            {
              declarator = cp_error_declarator;
+              pack_expansion_p = false;
+              declarator->parameter_pack_p = false;
              break;
            }
 
              break;
            }
 
@@ -11598,14 +13340,16 @@ cp_parser_direct_declarator (cp_parser* parser,
              type = resolve_typename_type (qualifying_scope,
                                            /*only_current_p=*/false);
              /* If that failed, the declarator is invalid.  */
              type = resolve_typename_type (qualifying_scope,
                                            /*only_current_p=*/false);
              /* If that failed, the declarator is invalid.  */
-             if (type == error_mark_node)
-               error ("%<%T::%D%> is not a type",
+             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;
            }
 
          sfk = sfk_none;
                       TYPE_CONTEXT (qualifying_scope),
                       TYPE_IDENTIFIER (qualifying_scope));
              qualifying_scope = type;
            }
 
          sfk = sfk_none;
+
          if (unqualified_name)
            {
              tree class_type;
          if (unqualified_name)
            {
              tree class_type;
@@ -11624,8 +13368,9 @@ cp_parser_direct_declarator (cp_parser* parser,
                      if (qualifying_scope
                          && CLASSTYPE_USE_TEMPLATE (name_type))
                        {
                      if (qualifying_scope
                          && CLASSTYPE_USE_TEMPLATE (name_type))
                        {
-                         error ("invalid use of constructor as a template");
-                         inform ("use %<%T::%D%> instead of %<%T::%D%> to "
+                         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)),
                                  "name the constructor in a qualified name",
                                  class_type,
                                  DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
@@ -11673,6 +13418,10 @@ cp_parser_direct_declarator (cp_parser* parser,
                                           unqualified_name,
                                           sfk);
          declarator->id_loc = token->location;
                                           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);
 
        handle_declarator:;
          scope = get_scope_of_declarator (declarator);
@@ -11724,12 +13473,15 @@ cp_parser_direct_declarator (cp_parser* parser,
      & cv-qualifier-seq [opt]
 
    Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
      & cv-qualifier-seq [opt]
 
    Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
-   Returns ADDR_EXPR if a reference was used.  In the case of a
-   pointer-to-member, *TYPE is filled in with the TYPE containing the
-   member.  *CV_QUALS is filled in with the cv-qualifier-seq, or
-   TYPE_UNQUALIFIED, if there are no cv-qualifiers.  Returns
-   ERROR_MARK if an error occurred.  */
-
+   Returns ADDR_EXPR if a reference was used, or NON_LVALUE_EXPR for
+   an rvalue reference. In the case of a pointer-to-member, *TYPE is
+   filled in with the TYPE containing the member.  *CV_QUALS is
+   filled in with the cv-qualifier-seq, or TYPE_UNQUALIFIED, if there
+   are no cv-qualifiers.  Returns ERROR_MARK if an error occurred.
+   Note that the tree codes returned by this function have nothing
+   to do with the types of trees that will be eventually be created
+   to represent the pointer or reference type being parsed. They are
+   just constants with suggestive names. */
 static enum tree_code
 cp_parser_ptr_operator (cp_parser* parser,
                        tree* type,
 static enum tree_code
 cp_parser_ptr_operator (cp_parser* parser,
                        tree* type,
@@ -11745,13 +13497,19 @@ cp_parser_ptr_operator (cp_parser* parser,
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
-  /* If it's a `*' or `&' we have a pointer or reference.  */
-  if (token->type == CPP_MULT || token->type == CPP_AND)
-    {
-      /* Remember which ptr-operator we were processing.  */
-      code = (token->type == CPP_AND ? ADDR_EXPR : INDIRECT_REF);
 
 
-      /* Consume the `*' or `&'.  */
+  /* If it's a `*', `&' or `&&' we have a pointer or reference.  */
+  if (token->type == CPP_MULT)
+    code = INDIRECT_REF;
+  else if (token->type == CPP_AND)
+    code = ADDR_EXPR;
+  else if ((cxx_dialect != cxx98) &&
+          token->type == CPP_AND_AND) /* C++0x only */
+    code = NON_LVALUE_EXPR;
+
+  if (code != ERROR_MARK)
+    {
+      /* Consume the `*', `&' or `&&'.  */
       cp_lexer_consume_token (parser->lexer);
 
       /* A `*' can be followed by a cv-qualifier-seq, and so can a
       cp_lexer_consume_token (parser->lexer);
 
       /* A `*' can be followed by a cv-qualifier-seq, and so can a
@@ -11770,6 +13528,7 @@ cp_parser_ptr_operator (cp_parser* parser,
       cp_parser_global_scope_opt (parser,
                                  /*current_scope_valid_p=*/false);
       /* Look for the nested-name specifier.  */
       cp_parser_global_scope_opt (parser,
                                  /*current_scope_valid_p=*/false);
       /* Look for the nested-name specifier.  */
+      token = cp_lexer_peek_token (parser->lexer);
       cp_parser_nested_name_specifier (parser,
                                       /*typename_keyword_p=*/false,
                                       /*check_dependency_p=*/true,
       cp_parser_nested_name_specifier (parser,
                                       /*typename_keyword_p=*/false,
                                       /*check_dependency_p=*/true,
@@ -11778,13 +13537,13 @@ cp_parser_ptr_operator (cp_parser* parser,
       /* If we found it, and the next token is a `*', then we are
         indeed looking at a pointer-to-member operator.  */
       if (!cp_parser_error_occurred (parser)
       /* If we found it, and the next token is a `*', then we are
         indeed looking at a pointer-to-member operator.  */
       if (!cp_parser_error_occurred (parser)
-         && cp_parser_require (parser, CPP_MULT, "`*'"))
+         && cp_parser_require (parser, CPP_MULT, "%<*%>"))
        {
          /* Indicate that the `*' operator was used.  */
          code = INDIRECT_REF;
 
          if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
        {
          /* Indicate that the `*' operator was used.  */
          code = INDIRECT_REF;
 
          if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
-           error ("%qD is a namespace", parser->scope);
+           error ("%H%qD is a namespace", &token->location, parser->scope);
          else
            {
              /* The type of which the member is a member is given by the
          else
            {
              /* The type of which the member is a member is given by the
@@ -11859,7 +13618,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 
       if (cv_quals & cv_qualifier)
        {
 
       if (cv_quals & cv_qualifier)
        {
-         error ("duplicate cv-qualifier");
+         error ("%Hduplicate cv-qualifier", &token->location);
          cp_lexer_purge_token (parser->lexer);
        }
       else
          cp_lexer_purge_token (parser->lexer);
        }
       else
@@ -11872,6 +13631,30 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
   return cv_quals;
 }
 
   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:
 /* Parse a declarator-id.
 
    declarator-id:
@@ -11944,6 +13727,13 @@ cp_parser_type_id (cp_parser* parser)
   if (!cp_parser_parse_definitely (parser))
     abstract_declarator = NULL;
 
   if (!cp_parser_parse_definitely (parser))
     abstract_declarator = NULL;
 
+  if (type_specifier_seq.type
+      && type_uses_auto (type_specifier_seq.type))
+    {
+      error ("invalid use of %<auto%>");
+      return error_mark_node;
+    }
+  
   return groktypename (&type_specifier_seq, abstract_declarator);
 }
 
   return groktypename (&type_specifier_seq, abstract_declarator);
 }
 
@@ -11969,6 +13759,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 {
   bool seen_type_specifier = false;
   cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
 {
   bool seen_type_specifier = false;
   cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
+  cp_token *start_token = NULL;
 
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
 
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
@@ -11988,6 +13779,11 @@ cp_parser_type_specifier_seq (cp_parser* parser,
          continue;
        }
 
          continue;
        }
 
+      /* record the token of the beginning of the type specifier seq,
+         for error reporting purposes*/
+     if (!start_token)
+       start_token = cp_lexer_peek_token (parser->lexer);
+
       /* Look for the type-specifier.  */
       type_specifier = cp_parser_type_specifier (parser,
                                                 flags,
       /* Look for the type-specifier.  */
       type_specifier = cp_parser_type_specifier (parser,
                                                 flags,
@@ -12030,6 +13826,8 @@ cp_parser_type_specifier_seq (cp_parser* parser,
       if (is_condition && !is_cv_qualifier)
        flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
       if (is_condition && !is_cv_qualifier)
        flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
+
+  cp_parser_check_decl_spec (type_specifier_seq, start_token->location);
 }
 
 /* Parse a parameter-declaration-clause.
 }
 
 /* Parse a parameter-declaration-clause.
@@ -12042,10 +13840,10 @@ cp_parser_type_specifier_seq (cp_parser* parser,
    value of NULL indicates a parameter-declaration-clause consisting
    only of an ellipsis.  */
 
    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_parser_parameter_declaration_clause (cp_parser* parser)
 {
-  cp_parameter_declarator *parameters;
+  tree parameters;
   cp_token *token;
   bool ellipsis_p;
   bool is_error;
   cp_token *token;
   bool ellipsis_p;
   bool is_error;
@@ -12057,7 +13855,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     {
       /* Consume the `...' token.  */
       cp_lexer_consume_token (parser->lexer);
     {
       /* 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.  */
     }
   else if (token->type == CPP_CLOSE_PAREN)
     /* There are no parameters.  */
@@ -12065,10 +13863,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
 #ifndef NO_IMPLICIT_EXTERN_C
       if (in_system_header && current_class_type == NULL
          && current_lang_name == lang_name_c)
 #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
       else
 #endif
-       return no_parameters;
+       return void_list_node;
     }
   /* Check for `(void)', too, which is a special case.  */
   else if (token->keyword == RID_VOID
     }
   /* Check for `(void)', too, which is a special case.  */
   else if (token->keyword == RID_VOID
@@ -12078,7 +13876,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       /* Consume the `void' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* There are no parameters.  */
       /* 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.  */
     }
 
   /* Parse the parameter-declaration-list.  */
@@ -12098,7 +13896,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
       /* Expect an ellipsis.  */
       ellipsis_p
       cp_lexer_consume_token (parser->lexer);
       /* Expect an ellipsis.  */
       ellipsis_p
-       = (cp_parser_require (parser, CPP_ELLIPSIS, "`...'") != NULL);
+       = (cp_parser_require (parser, CPP_ELLIPSIS, "%<...%>") != NULL);
     }
   /* It might also be `...' if the optional trailing `,' was
      omitted.  */
     }
   /* It might also be `...' if the optional trailing `,' was
      omitted.  */
@@ -12113,8 +13911,8 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     ellipsis_p = false;
 
   /* Finish the parameter list.  */
     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;
 }
 
   return parameters;
 }
@@ -12130,11 +13928,11 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
    `void_list_node' is never appended to the list.  Upon return,
    *IS_ERROR will be true iff an error occurred.  */
 
    `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_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
-  cp_parameter_declarator *parameters = NULL;
-  cp_parameter_declarator **tail = &parameters;
+  tree parameters = NULL_TREE;
+  tree *tail = &parameters; 
   bool saved_in_unbraced_linkage_specification_p;
 
   /* Assume all will go well.  */
   bool saved_in_unbraced_linkage_specification_p;
 
   /* Assume all will go well.  */
@@ -12150,6 +13948,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   while (true)
     {
       cp_parameter_declarator *parameter;
   while (true)
     {
       cp_parameter_declarator *parameter;
+      tree decl = error_mark_node;
       bool parenthesized_p;
       /* Parse the parameter.  */
       parameter
       bool parenthesized_p;
       /* Parse the parameter.  */
       parameter
@@ -12157,17 +13956,38 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
                                           /*template_parm_p=*/false,
                                           &parenthesized_p);
 
                                           /*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 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;
        {
          *is_error = true;
-         parameters = NULL;
+         parameters = error_mark_node;
          break;
        }
          break;
        }
+
+      if (parameter->decl_specifiers.attributes)
+       cplus_decl_attributes (&decl,
+                              parameter->decl_specifiers.attributes,
+                              0);
+      if (DECL_NAME (decl))
+       decl = pushdecl (decl);
+
       /* Add the new parameter to the list.  */
       /* 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)
 
       /* Peek at the next token.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
@@ -12232,9 +14052,9 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 /* Parse a parameter declaration.
 
    parameter-declaration:
 /* Parse a parameter declaration.
 
    parameter-declaration:
-     decl-specifier-seq declarator
+     decl-specifier-seq ... [opt] declarator
      decl-specifier-seq declarator = assignment-expression
      decl-specifier-seq declarator = assignment-expression
-     decl-specifier-seq abstract-declarator [opt]
+     decl-specifier-seq ... [opt] abstract-declarator [opt]
      decl-specifier-seq abstract-declarator [opt] = assignment-expression
 
    If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
      decl-specifier-seq abstract-declarator [opt] = assignment-expression
 
    If TEMPLATE_PARM_P is TRUE, then this parameter-declaration
@@ -12256,7 +14076,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
   cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
   tree default_argument;
   cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
   tree default_argument;
-  cp_token *token;
+  cp_token *token = NULL, *declarator_token_start = NULL;
   const char *saved_message;
 
   /* In a template parameter, `>' is not an operator.
   const char *saved_message;
 
   /* In a template parameter, `>' is not an operator.
@@ -12289,12 +14109,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
+
   /* If the next token is a `)', `,', `=', `>', or `...', then there
   /* If the next token is a `)', `,', `=', `>', or `...', then there
-     is no declarator.  */
+     is no declarator. However, when variadic templates are enabled,
+     there may be a declarator following `...'.  */
   if (token->type == CPP_CLOSE_PAREN
       || token->type == CPP_COMMA
       || token->type == CPP_EQ
   if (token->type == CPP_CLOSE_PAREN
       || token->type == CPP_COMMA
       || token->type == CPP_EQ
-      || token->type == CPP_ELLIPSIS
       || token->type == CPP_GREATER)
     {
       declarator = NULL;
       || token->type == CPP_GREATER)
     {
       declarator = NULL;
@@ -12324,6 +14145,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
          && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
        cp_parser_commit_to_tentative_parse (parser);
       /* Parse the declarator.  */
          && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
        cp_parser_commit_to_tentative_parse (parser);
       /* Parse the declarator.  */
+      declarator_token_start = token;
       declarator = cp_parser_declarator (parser,
                                         CP_PARSER_DECLARATOR_EITHER,
                                         /*ctor_dtor_or_conv_p=*/NULL,
       declarator = cp_parser_declarator (parser,
                                         CP_PARSER_DECLARATOR_EITHER,
                                         /*ctor_dtor_or_conv_p=*/NULL,
@@ -12336,6 +14158,37 @@ cp_parser_parameter_declaration (cp_parser *parser,
                   cp_parser_attributes_opt (parser));
     }
 
                   cp_parser_attributes_opt (parser));
     }
 
+  /* If the next token is an ellipsis, and we have not seen a
+     declarator name, and the type of the declarator contains parameter
+     packs but it is not a TYPE_PACK_EXPANSION, then we actually have
+     a parameter pack expansion expression. Otherwise, leave the
+     ellipsis for a C-style variadic function. */
+  token = cp_lexer_peek_token (parser->lexer);
+  if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+    {
+      tree type = decl_specifiers.type;
+
+      if (type && DECL_P (type))
+        type = TREE_TYPE (type);
+
+      if (type
+         && TREE_CODE (type) != TYPE_PACK_EXPANSION
+         && declarator_can_be_parameter_pack (declarator)
+          && (!declarator || !declarator->parameter_pack_p)
+          && uses_parameter_packs (type))
+        {
+         /* Consume the `...'. */
+         cp_lexer_consume_token (parser->lexer);
+         maybe_warn_variadic_templates ();
+         
+         /* Build a pack expansion type */
+         if (declarator)
+           declarator->parameter_pack_p = true;
+         else
+           decl_specifiers.type = make_pack_expansion (type);
+       }
+    }
+
   /* The restriction on defining new types applies only to the type
      of the parameter, not to the default argument.  */
   parser->type_definition_forbidden_message = saved_message;
   /* The restriction on defining new types applies only to the type
      of the parameter, not to the default argument.  */
   parser->type_definition_forbidden_message = saved_message;
@@ -12343,7 +14196,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
   /* If the next token is `=', then process a default argument.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
     {
   /* If the next token is `=', then process a default argument.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
     {
-      bool saved_greater_than_is_operator_p;
       /* Consume the `='.  */
       cp_lexer_consume_token (parser->lexer);
 
       /* Consume the `='.  */
       cp_lexer_consume_token (parser->lexer);
 
@@ -12353,6 +14205,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
          && TYPE_BEING_DEFINED (current_class_type))
        {
          unsigned depth = 0;
          && TYPE_BEING_DEFINED (current_class_type))
        {
          unsigned depth = 0;
+         int maybe_template_id = 0;
          cp_token *first_token;
          cp_token *token;
 
          cp_token *first_token;
          cp_token *token;
 
@@ -12371,6 +14224,33 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  /* In valid code, a default argument must be
                     immediately followed by a `,' `)', or `...'.  */
                case CPP_COMMA:
                  /* In valid code, a default argument must be
                     immediately followed by a `,' `)', or `...'.  */
                case CPP_COMMA:
+                 if (depth == 0 && maybe_template_id)
+                   {
+                     /* If we've seen a '<', we might be in a
+                        template-argument-list.  Until Core issue 325 is
+                        resolved, we don't know how this situation ought
+                        to be handled, so try to DTRT.  We check whether
+                        what comes after the comma is a valid parameter
+                        declaration list.  If it is, then the comma ends
+                        the default argument; otherwise the default
+                        argument continues.  */
+                     bool error = false;
+
+                     /* Set ITALP so cp_parser_parameter_declaration_list
+                        doesn't decide to commit to this parse.  */
+                     bool saved_italp = parser->in_template_argument_list_p;
+                     parser->in_template_argument_list_p = true;
+
+                     cp_parser_parse_tentatively (parser);
+                     cp_lexer_consume_token (parser->lexer);
+                     cp_parser_parameter_declaration_list (parser, &error);
+                     if (!cp_parser_error_occurred (parser) && !error)
+                       done = true;
+                     cp_parser_abort_tentative_parse (parser);
+
+                     parser->in_template_argument_list_p = saved_italp;
+                     break;
+                   }
                case CPP_CLOSE_PAREN:
                case CPP_ELLIPSIS:
                  /* If we run into a non-nested `;', `}', or `]',
                case CPP_CLOSE_PAREN:
                case CPP_ELLIPSIS:
                  /* If we run into a non-nested `;', `}', or `]',
@@ -12394,18 +14274,37 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  ++depth;
                  break;
 
                  ++depth;
                  break;
 
+               case CPP_LESS:
+                 if (depth == 0)
+                   /* This might be the comparison operator, or it might
+                      start a template argument list.  */
+                   ++maybe_template_id;
+                 break;
+
+                case CPP_RSHIFT:
+                  if (cxx_dialect == cxx98)
+                    break;
+                  /* Fall through for C++0x, which treats the `>>'
+                     operator like two `>' tokens in certain
+                     cases.  */
+
                case CPP_GREATER:
                case CPP_GREATER:
-                 /* If we see a non-nested `>', and `>' is not an
-                    operator, then it marks the end of the default
-                    argument.  */
-                 if (!depth && !greater_than_is_operator_p)
-                   done = true;
+                 if (depth == 0)
+                   {
+                     /* This might be an operator, or it might close a
+                        template argument list.  But if a previous '<'
+                        started a template argument list, this will have
+                        closed it, so we can't be in one anymore.  */
+                     maybe_template_id -= 1 + (token->type == CPP_RSHIFT);
+                     if (maybe_template_id < 0)
+                       maybe_template_id = 0;
+                   }
                  break;
 
                  /* If we run out of tokens, issue an error message.  */
                case CPP_EOF:
                case CPP_PRAGMA_EOL:
                  break;
 
                  /* If we run out of tokens, issue an error message.  */
                case CPP_EOF:
                case CPP_PRAGMA_EOL:
-                 error ("file ends in default argument");
+                 error ("%Hfile ends in default argument", &token->location);
                  done = true;
                  break;
 
                  done = true;
                  break;
 
@@ -12432,7 +14331,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
              token = cp_lexer_consume_token (parser->lexer);
            }
 
              token = cp_lexer_consume_token (parser->lexer);
            }
 
-         /* Create a DEFAULT_ARG to represented the unparsed default
+         /* Create a DEFAULT_ARG to represent the unparsed default
             argument.  */
          default_argument = make_node (DEFAULT_ARG);
          DEFARG_TOKENS (default_argument)
             argument.  */
          default_argument = make_node (DEFAULT_ARG);
          DEFARG_TOKENS (default_argument)
@@ -12443,48 +14342,44 @@ cp_parser_parameter_declaration (cp_parser *parser,
         assignment-expression.  */
       else
        {
         assignment-expression.  */
       else
        {
-         bool saved_local_variables_forbidden_p;
-
-         /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
-            set correctly.  */
-         saved_greater_than_is_operator_p
-           = parser->greater_than_is_operator_p;
-         parser->greater_than_is_operator_p = greater_than_is_operator_p;
-         /* Local variable names (and the `this' keyword) may not
-            appear in a default argument.  */
-         saved_local_variables_forbidden_p
-           = parser->local_variables_forbidden_p;
-         parser->local_variables_forbidden_p = true;
-         /* The default argument expression may cause implicitly
-            defined member functions to be synthesized, which will
-            result in garbage collection.  We must treat this
-            situation as if we were within the body of function so as
-            to avoid collecting live data on the stack.  */
-         ++function_depth;
-         /* Parse the assignment-expression.  */
-         if (template_parm_p)
-           push_deferring_access_checks (dk_no_deferred);
-         default_argument
-           = cp_parser_assignment_expression (parser, /*cast_p=*/false);
-         if (template_parm_p)
-           pop_deferring_access_checks ();
-         /* Restore saved state.  */
-         --function_depth;
-         parser->greater_than_is_operator_p
-           = saved_greater_than_is_operator_p;
-         parser->local_variables_forbidden_p
-           = saved_local_variables_forbidden_p;
+         token = cp_lexer_peek_token (parser->lexer);
+         default_argument 
+           = cp_parser_default_argument (parser, template_parm_p);
        }
        }
+
       if (!parser->default_arg_ok_p)
        {
       if (!parser->default_arg_ok_p)
        {
-         if (!flag_pedantic_errors)
+         if (flag_permissive)
            warning (0, "deprecated use of default argument for parameter of non-function");
          else
            {
            warning (0, "deprecated use of default argument for parameter of non-function");
          else
            {
-             error ("default arguments are only permitted for function parameters");
+             error ("%Hdefault arguments are only "
+                    "permitted for function parameters",
+                    &token->location);
              default_argument = NULL_TREE;
            }
        }
              default_argument = NULL_TREE;
            }
        }
+      else if ((declarator && declarator->parameter_pack_p)
+              || (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);
+         else
+           error ("%H%sparameter pack cannot have a default argument",
+                  &declarator_token_start->location, kind);
+         
+         default_argument = NULL_TREE;
+       }
     }
   else
     default_argument = NULL_TREE;
     }
   else
     default_argument = NULL_TREE;
@@ -12494,10 +14389,50 @@ cp_parser_parameter_declaration (cp_parser *parser,
                                    default_argument);
 }
 
                                    default_argument);
 }
 
-/* Parse a function-body.
-
-   function-body:
-     compound_statement  */
+/* Parse a default argument and return it.
+
+   TEMPLATE_PARM_P is true if this is a default argument for a
+   non-type template parameter.  */
+static tree
+cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
+{
+  tree default_argument = NULL_TREE;
+  bool saved_greater_than_is_operator_p;
+  bool saved_local_variables_forbidden_p;
+
+  /* Make sure that PARSER->GREATER_THAN_IS_OPERATOR_P is
+     set correctly.  */
+  saved_greater_than_is_operator_p = parser->greater_than_is_operator_p;
+  parser->greater_than_is_operator_p = !template_parm_p;
+  /* Local variable names (and the `this' keyword) may not
+     appear in a default argument.  */
+  saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
+  parser->local_variables_forbidden_p = true;
+  /* The default argument expression may cause implicitly
+     defined member functions to be synthesized, which will
+     result in garbage collection.  We must treat this
+     situation as if we were within the body of function so as
+     to avoid collecting live data on the stack.  */
+  ++function_depth;
+  /* Parse the assignment-expression.  */
+  if (template_parm_p)
+    push_deferring_access_checks (dk_no_deferred);
+  default_argument
+    = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+  if (template_parm_p)
+    pop_deferring_access_checks ();
+  /* Restore saved state.  */
+  --function_depth;
+  parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
+  parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
+
+  return default_argument;
+}
+
+/* Parse a function-body.
+
+   function-body:
+     compound_statement  */
 
 static void
 cp_parser_function_body (cp_parser *parser)
 
 static void
 cp_parser_function_body (cp_parser *parser)
@@ -12535,14 +14470,14 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser)
    Returns an expression representing the initializer.  If no
    initializer is present, NULL_TREE is returned.
 
    Returns an expression representing the initializer.  If no
    initializer is present, NULL_TREE is returned.
 
-   *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )'
-   production is used, and zero otherwise.  *IS_PARENTHESIZED_INIT is
-   set to FALSE if there is no initializer present.  If there is an
+   *IS_DIRECT_INIT is set to FALSE if the `= initializer-clause'
+   production is used, and TRUE otherwise.  *IS_DIRECT_INIT is
+   set to TRUE if there is no initializer present.  If there is an
    initializer, and it is not a constant-expression, *NON_CONSTANT_P
    is set to true; otherwise it is set to false.  */
 
 static tree
    initializer, and it is not a constant-expression, *NON_CONSTANT_P
    is set to true; otherwise it is set to false.  */
 
 static tree
-cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
+cp_parser_initializer (cp_parser* parser, bool* is_direct_init,
                       bool* non_constant_p)
 {
   cp_token *token;
                       bool* non_constant_p)
 {
   cp_token *token;
@@ -12553,7 +14488,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
 
   /* Let our caller know whether or not this initializer was
      parenthesized.  */
 
   /* Let our caller know whether or not this initializer was
      parenthesized.  */
-  *is_parenthesized_init = (token->type == CPP_OPEN_PAREN);
+  *is_direct_init = (token->type != CPP_EQ);
   /* Assume that the initializer is constant.  */
   *non_constant_p = false;
 
   /* Assume that the initializer is constant.  */
   *non_constant_p = false;
 
@@ -12567,7 +14502,14 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
   else if (token->type == CPP_OPEN_PAREN)
     init = cp_parser_parenthesized_expression_list (parser, false,
                                                    /*cast_p=*/false,
   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);
                                                    non_constant_p);
+  else if (token->type == CPP_OPEN_BRACE)
+    {
+      maybe_warn_cpp0x ("extended initializer lists");
+      init = cp_parser_braced_list (parser, non_constant_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (init) = 1;
+    }
   else
     {
       /* Anything else is an error.  */
   else
     {
       /* Anything else is an error.  */
@@ -12582,20 +14524,14 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
 
    initializer-clause:
      assignment-expression
 
    initializer-clause:
      assignment-expression
-     { initializer-list , [opt] }
-     { }
+     braced-init-list
 
    Returns an expression representing the initializer.
 
    If the `assignment-expression' production is used the value
    returned is simply a representation for the expression.
 
 
    Returns an expression representing the initializer.
 
    If the `assignment-expression' production is used the value
    returned is simply a representation for the expression.
 
-   Otherwise, a CONSTRUCTOR is returned.  The CONSTRUCTOR_ELTS will be
-   the elements of the initializer-list (or NULL, if the last
-   production is used).  The TREE_TYPE for the CONSTRUCTOR will be
-   NULL_TREE.  There is no way to detect whether or not the optional
-   trailing `,' was provided.  NON_CONSTANT_P is as for
-   cp_parser_initializer.  */
+   Otherwise, calls cp_parser_braced_list.  */
 
 static tree
 cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
 
 static tree
 cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
@@ -12617,33 +14553,54 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
        initializer = fold_non_dependent_expr (initializer);
     }
   else
        initializer = fold_non_dependent_expr (initializer);
     }
   else
+    initializer = cp_parser_braced_list (parser, non_constant_p);
+
+  return initializer;
+}
+
+/* Parse a brace-enclosed initializer list.
+
+   braced-init-list:
+     { initializer-list , [opt] }
+     { }
+
+   Returns a CONSTRUCTOR.  The CONSTRUCTOR_ELTS will be
+   the elements of the initializer-list (or NULL, if the last
+   production is used).  The TREE_TYPE for the CONSTRUCTOR will be
+   NULL_TREE.  There is no way to detect whether or not the optional
+   trailing `,' was provided.  NON_CONSTANT_P is as for
+   cp_parser_initializer.  */     
+
+static tree
+cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
+{
+  tree initializer;
+
+  /* Consume the `{' token.  */
+  cp_lexer_consume_token (parser->lexer);
+  /* Create a CONSTRUCTOR to represent the braced-initializer.  */
+  initializer = make_node (CONSTRUCTOR);
+  /* If it's not a `}', then there is a non-trivial initializer.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
     {
     {
-      /* Consume the `{' token.  */
-      cp_lexer_consume_token (parser->lexer);
-      /* Create a CONSTRUCTOR to represent the braced-initializer.  */
-      initializer = make_node (CONSTRUCTOR);
-      /* If it's not a `}', then there is a non-trivial initializer.  */
-      if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
-       {
-         /* Parse the initializer list.  */
-         CONSTRUCTOR_ELTS (initializer)
-           = cp_parser_initializer_list (parser, non_constant_p);
-         /* A trailing `,' token is allowed.  */
-         if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
-           cp_lexer_consume_token (parser->lexer);
-       }
-      /* Now, there should be a trailing `}'.  */
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+      /* Parse the initializer list.  */
+      CONSTRUCTOR_ELTS (initializer)
+       = cp_parser_initializer_list (parser, non_constant_p);
+      /* A trailing `,' token is allowed.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
     }
     }
-
+  /* Now, there should be a trailing `}'.  */
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+  TREE_TYPE (initializer) = init_list_type_node;
   return initializer;
 }
 
 /* Parse an initializer-list.
 
    initializer-list:
   return initializer;
 }
 
 /* Parse an initializer-list.
 
    initializer-list:
-     initializer-clause
-     initializer-list , initializer-clause
+     initializer-clause ... [opt]
+     initializer-list , initializer-clause ... [opt]
 
    GNU Extension:
 
 
    GNU Extension:
 
@@ -12679,8 +14636,11 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          && cp_lexer_next_token_is (parser->lexer, CPP_NAME)
          && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
        {
          && cp_lexer_next_token_is (parser->lexer, CPP_NAME)
          && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
        {
+         /* Warn the user that they are using an extension.  */
+         pedwarn (input_location, OPT_pedantic, 
+                  "ISO C++ does not allow designated initializers");
          /* Consume the identifier.  */
          /* Consume the identifier.  */
-         identifier = cp_lexer_consume_token (parser->lexer)->value;
+         identifier = cp_lexer_consume_token (parser->lexer)->u.value;
          /* Consume the `:'.  */
          cp_lexer_consume_token (parser->lexer);
        }
          /* Consume the `:'.  */
          cp_lexer_consume_token (parser->lexer);
        }
@@ -12694,6 +14654,17 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
       if (clause_non_constant_p)
        *non_constant_p = true;
 
       if (clause_non_constant_p)
        *non_constant_p = true;
 
+      /* If we have an ellipsis, this is an initializer pack
+        expansion.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+        {
+          /* Consume the `...'.  */
+          cp_lexer_consume_token (parser->lexer);
+
+          /* Turn the initializer into an initializer expansion.  */
+          initializer = make_pack_expansion (initializer);
+        }
+
       /* Add it to the vector.  */
       CONSTRUCTOR_APPEND_ELT(v, identifier, initializer);
 
       /* Add it to the vector.  */
       CONSTRUCTOR_APPEND_ELT(v, identifier, initializer);
 
@@ -12749,6 +14720,7 @@ cp_parser_class_name (cp_parser *parser,
   tree scope;
   bool typename_p;
   cp_token *token;
   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);
 
   /* All class-names start with an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -12774,7 +14746,6 @@ cp_parser_class_name (cp_parser *parser,
       && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
     {
       cp_token *identifier_token;
       && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
     {
       cp_token *identifier_token;
-      tree identifier;
       bool ambiguous_p;
 
       /* Look for the identifier.  */
       bool ambiguous_p;
 
       /* Look for the identifier.  */
@@ -12816,10 +14787,12 @@ cp_parser_class_name (cp_parser *parser,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
                                        check_dependency_p,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
                                        check_dependency_p,
-                                       &ambiguous_decls);
+                                       &ambiguous_decls,
+                                       identifier_token->location);
          if (ambiguous_decls)
            {
          if (ambiguous_decls)
            {
-             error ("reference to %qD is ambiguous", identifier);
+             error ("%Hreference to %qD is ambiguous",
+                    &identifier_token->location, identifier);
              print_candidates (ambiguous_decls);
              if (cp_parser_parsing_tentatively (parser))
                {
              print_candidates (ambiguous_decls);
              if (cp_parser_parsing_tentatively (parser))
                {
@@ -12872,11 +14845,13 @@ cp_parser_class_name (cp_parser *parser,
     }
   else if (TREE_CODE (decl) != TYPE_DECL
           || TREE_TYPE (decl) == error_mark_node
     }
   else if (TREE_CODE (decl) != TYPE_DECL
           || TREE_TYPE (decl) == error_mark_node
-          || !IS_AGGR_TYPE (TREE_TYPE (decl)))
+          || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl)))
     decl = error_mark_node;
 
   if (decl == error_mark_node)
     cp_parser_error (parser, "expected class-name");
     decl = error_mark_node;
 
   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;
 }
 
   return decl;
 }
@@ -12897,15 +14872,19 @@ cp_parser_class_specifier (cp_parser* parser)
   int has_trailing_semicolon;
   bool nested_name_specifier_p;
   unsigned saved_num_template_parameter_lists;
   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 old_scope = NULL_TREE;
   tree scope = NULL_TREE;
+  tree bases;
 
   push_deferring_access_checks (dk_no_deferred);
 
   /* Parse the class-head.  */
   type = cp_parser_class_head (parser,
                               &nested_name_specifier_p,
 
   push_deferring_access_checks (dk_no_deferred);
 
   /* Parse the class-head.  */
   type = cp_parser_class_head (parser,
                               &nested_name_specifier_p,
-                              &attributes);
+                              &attributes,
+                              &bases);
   /* If the class-head was a semantic disaster, skip the entire body
      of the class.  */
   if (!type)
   /* If the class-head was a semantic disaster, skip the entire body
      of the class.  */
   if (!type)
@@ -12916,8 +14895,20 @@ cp_parser_class_specifier (cp_parser* parser)
     }
 
   /* Look for the `{'.  */
     }
 
   /* Look for the `{'.  */
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
+    {
+      pop_deferring_access_checks ();
+      return error_mark_node;
+    }
+
+  /* Process the base classes. If they're invalid, skip the 
+     entire class body.  */
+  if (!xref_basetypes (type, bases))
     {
     {
+      /* Consuming the closing brace yields better error messages
+         later on.  */
+      if (cp_parser_skip_to_closing_brace (parser))
+       cp_lexer_consume_token (parser->lexer);
       pop_deferring_access_checks ();
       return error_mark_node;
     }
       pop_deferring_access_checks ();
       return error_mark_node;
     }
@@ -12931,6 +14922,13 @@ cp_parser_class_specifier (cp_parser* parser)
   saved_num_template_parameter_lists
     = parser->num_template_parameter_lists;
   parser->num_template_parameter_lists = 0;
   saved_num_template_parameter_lists
     = parser->num_template_parameter_lists;
   parser->num_template_parameter_lists = 0;
+  /* 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)
 
   /* Start the class.  */
   if (nested_name_specifier_p)
@@ -12948,7 +14946,7 @@ cp_parser_class_specifier (cp_parser* parser)
     cp_parser_member_specification_opt (parser);
 
   /* Look for the trailing `}'.  */
     cp_parser_member_specification_opt (parser);
 
   /* Look for the trailing `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
   /* We get better error messages by noticing a common problem: a
      missing trailing `;'.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* We get better error messages by noticing a common problem: a
      missing trailing `;'.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -13039,9 +15037,12 @@ cp_parser_class_specifier (cp_parser* parser)
   /* Put back any saved access checks.  */
   pop_deferring_access_checks ();
 
   /* Put back any saved access checks.  */
   pop_deferring_access_checks ();
 
-  /* Restore the count of active template-parameter-lists.  */
+  /* Restore saved state.  */
+  parser->in_function_body = saved_in_function_body;
   parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
   parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
+  parser->in_unbraced_linkage_specification_p
+    = saved_in_unbraced_linkage_specification_p;
 
   return type;
 }
 
   return type;
 }
@@ -13060,6 +15061,10 @@ cp_parser_class_specifier (cp_parser* parser)
      class-key attributes nested-name-specifier [opt] template-id
        base-clause [opt]
 
      class-key attributes nested-name-specifier [opt] template-id
        base-clause [opt]
 
+   Upon return BASES is initialized to the list of base classes (or
+   NULL, if there are none) in the same form returned by
+   cp_parser_base_clause.
+
    Returns the TYPE of the indicated class.  Sets
    *NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions
    involving a nested-name-specifier was used, and FALSE otherwise.
    Returns the TYPE of the indicated class.  Sets
    *NESTED_NAME_SPECIFIER_P to TRUE iff one of the productions
    involving a nested-name-specifier was used, and FALSE otherwise.
@@ -13073,7 +15078,8 @@ cp_parser_class_specifier (cp_parser* parser)
 static tree
 cp_parser_class_head (cp_parser* parser,
                      bool* nested_name_specifier_p,
 static tree
 cp_parser_class_head (cp_parser* parser,
                      bool* nested_name_specifier_p,
-                     tree *attributes_p)
+                     tree *attributes_p,
+                     tree *bases)
 {
   tree nested_name_specifier;
   enum tag_types class_key;
 {
   tree nested_name_specifier;
   enum tag_types class_key;
@@ -13086,14 +15092,15 @@ cp_parser_class_head (cp_parser* parser,
   bool invalid_explicit_specialization_p = false;
   tree pushed_scope = NULL_TREE;
   unsigned num_templates;
   bool invalid_explicit_specialization_p = false;
   tree pushed_scope = NULL_TREE;
   unsigned num_templates;
-  tree bases;
-
+  cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL;
   /* Assume no nested-name-specifier will be present.  */
   *nested_name_specifier_p = false;
   /* Assume no template parameter lists will be used in defining the
      type.  */
   num_templates = 0;
 
   /* Assume no nested-name-specifier will be present.  */
   *nested_name_specifier_p = false;
   /* Assume no template parameter lists will be used in defining the
      type.  */
   num_templates = 0;
 
+  *bases = NULL_TREE;
+
   /* Look for the class-key.  */
   class_key = cp_parser_class_key (parser);
   if (class_key == none_type)
   /* Look for the class-key.  */
   class_key = cp_parser_class_key (parser);
   if (class_key == none_type)
@@ -13118,6 +15125,7 @@ cp_parser_class_head (cp_parser* parser,
 
   /* Determine the name of the class.  Begin by looking for an
      optional nested-name-specifier.  */
 
   /* Determine the name of the class.  Begin by looking for an
      optional nested-name-specifier.  */
+  nested_name_specifier_token_start = cp_lexer_peek_token (parser->lexer);
   nested_name_specifier
     = cp_parser_nested_name_specifier_opt (parser,
                                           /*typename_keyword_p=*/false,
   nested_name_specifier
     = cp_parser_nested_name_specifier_opt (parser,
                                           /*typename_keyword_p=*/false,
@@ -13128,6 +15136,7 @@ cp_parser_class_head (cp_parser* parser,
      identifier.  */
   if (nested_name_specifier)
     {
      identifier.  */
   if (nested_name_specifier)
     {
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       /* Although the grammar says `identifier', it really means
         `class-name' or `template-name'.  You are only allowed to
         define a class that has already been declared with this
       /* Although the grammar says `identifier', it really means
         `class-name' or `template-name'.  You are only allowed to
         define a class that has already been declared with this
@@ -13157,6 +15166,7 @@ cp_parser_class_head (cp_parser* parser,
       if (!cp_parser_parse_definitely (parser))
        {
          invalid_nested_name_p = true;
       if (!cp_parser_parse_definitely (parser))
        {
          invalid_nested_name_p = true;
+         type_start_token = cp_lexer_peek_token (parser->lexer);
          id = cp_parser_identifier (parser);
          if (id == error_mark_node)
            id = NULL_TREE;
          id = cp_parser_identifier (parser);
          if (id == error_mark_node)
            id = NULL_TREE;
@@ -13191,6 +15201,7 @@ cp_parser_class_head (cp_parser* parser,
         an identifier, or nothing at all.  */
       cp_parser_parse_tentatively (parser);
       /* Check for a template-id.  */
         an identifier, or nothing at all.  */
       cp_parser_parse_tentatively (parser);
       /* Check for a template-id.  */
+      type_start_token = cp_lexer_peek_token (parser->lexer);
       id = cp_parser_template_id (parser,
                                  /*template_keyword_p=*/false,
                                  /*check_dependency_p=*/true,
       id = cp_parser_template_id (parser,
                                  /*template_keyword_p=*/false,
                                  /*check_dependency_p=*/true,
@@ -13199,7 +15210,10 @@ cp_parser_class_head (cp_parser* parser,
       if (!cp_parser_parse_definitely (parser))
        {
          if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
       if (!cp_parser_parse_definitely (parser))
        {
          if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
-           id = cp_parser_identifier (parser);
+           {
+             type_start_token = cp_lexer_peek_token (parser->lexer);
+             id = cp_parser_identifier (parser);
+           }
          else
            id = NULL_TREE;
        }
          else
            id = NULL_TREE;
        }
@@ -13213,7 +15227,8 @@ cp_parser_class_head (cp_parser* parser,
   pop_deferring_access_checks ();
 
   if (id)
   pop_deferring_access_checks ();
 
   if (id)
-    cp_parser_check_for_invalid_template_id (parser, id);
+    cp_parser_check_for_invalid_template_id (parser, id,
+                                            type_start_token->location);
 
   /* If it's not a `:' or a `{' then we can't really be looking at a
      class-head, since a class-head only appears as part of a
 
   /* If it's not a `:' or a `{' then we can't really be looking at a
      class-head, since a class-head only appears as part of a
@@ -13230,11 +15245,17 @@ cp_parser_class_head (cp_parser* parser,
   cp_parser_commit_to_tentative_parse (parser);
   /* Issue the error about the overly-qualified name now.  */
   if (qualified_p)
   cp_parser_commit_to_tentative_parse (parser);
   /* Issue the error about the overly-qualified name now.  */
   if (qualified_p)
-    cp_parser_error (parser,
-                    "global qualification of class name is invalid");
+    {
+      cp_parser_error (parser,
+                      "global qualification of class name is invalid");
+      return error_mark_node;
+    }
   else if (invalid_nested_name_p)
   else if (invalid_nested_name_p)
-    cp_parser_error (parser,
-                    "qualified name does not name a class");
+    {
+      cp_parser_error (parser,
+                      "qualified name does not name a class");
+      return error_mark_node;
+    }
   else if (nested_name_specifier)
     {
       tree scope;
   else if (nested_name_specifier)
     {
       tree scope;
@@ -13242,7 +15263,8 @@ cp_parser_class_head (cp_parser* parser,
       /* Reject typedef-names in class heads.  */
       if (!DECL_IMPLICIT_TYPEDEF_P (type))
        {
       /* Reject typedef-names in class heads.  */
       if (!DECL_IMPLICIT_TYPEDEF_P (type))
        {
-         error ("invalid class name in declaration of %qD", type);
+         error ("%Hinvalid class name in declaration of %qD",
+                &type_start_token->location, type);
          type = NULL_TREE;
          goto done;
        }
          type = NULL_TREE;
          goto done;
        }
@@ -13253,20 +15275,28 @@ cp_parser_class_head (cp_parser* parser,
         class was originally declared, the program is invalid.  */
       if (scope && !is_ancestor (scope, nested_name_specifier))
        {
         class was originally declared, the program is invalid.  */
       if (scope && !is_ancestor (scope, nested_name_specifier))
        {
-         error ("declaration of %qD in %qD which does not enclose %qD",
-                type, 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);
+         else
+           error ("%Hdeclaration of %qD in %qD which does not enclose %qD",
+                  &type_start_token->location,
+                  type, scope, nested_name_specifier);
          type = NULL_TREE;
          goto done;
        }
       /* [dcl.meaning]
 
          type = NULL_TREE;
          goto done;
        }
       /* [dcl.meaning]
 
-        A declarator-id shall not be qualified exception of the
+        A declarator-id shall not be qualified except for the
         definition of a ... nested class outside of its class
         definition of a ... nested class outside of its class
-        ... [or] the definition or explicit instantiation of a
+        ... [or] the definition or explicit instantiation of a
         class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
        {
         class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
        {
-         pedwarn ("extra qualification ignored");
+         permerror (input_location, "%Hextra qualification not allowed",
+                    &nested_name_specifier_token_start->location);
          nested_name_specifier = NULL_TREE;
          num_templates = 0;
        }
          nested_name_specifier = NULL_TREE;
          num_templates = 0;
        }
@@ -13277,7 +15307,8 @@ cp_parser_class_head (cp_parser* parser,
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
       && parser->num_template_parameter_lists == 0
       && template_id_p)
     {
-      error ("an explicit specialization must be preceded by %<template <>%>");
+      error ("%Han explicit specialization must be preceded by %<template <>%>",
+            &type_start_token->location);
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
         cp_parser_explicit_specialization.  */
       invalid_explicit_specialization_p = true;
       /* Take the same action that would have been taken by
         cp_parser_explicit_specialization.  */
@@ -13289,7 +15320,8 @@ cp_parser_class_head (cp_parser* parser,
      use "goto done;" to return.  */
   /* Make sure that the right number of template parameters were
      present.  */
      use "goto done;" to return.  */
   /* Make sure that the right number of template parameters were
      present.  */
-  if (!cp_parser_check_template_parameters (parser, num_templates))
+  if (!cp_parser_check_template_parameters (parser, num_templates,
+                                           type_start_token->location))
     {
       /* If something went wrong, there is no point in even trying to
         process the class-definition.  */
     {
       /* If something went wrong, there is no point in even trying to
         process the class-definition.  */
@@ -13300,8 +15332,19 @@ cp_parser_class_head (cp_parser* parser,
   /* Look up the type.  */
   if (template_id_p)
     {
   /* Look up the type.  */
   if (template_id_p)
     {
-      type = TREE_TYPE (id);
-      maybe_process_partial_specialization (type);
+      if (TREE_CODE (id) == TEMPLATE_ID_EXPR
+         && (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);
+         type = error_mark_node;
+       }
+      else
+       {
+         type = TREE_TYPE (id);
+         type = maybe_process_partial_specialization (type);
+       }
       if (nested_name_specifier)
        pushed_scope = push_scope (nested_name_specifier);
     }
       if (nested_name_specifier)
        pushed_scope = push_scope (nested_name_specifier);
     }
@@ -13321,7 +15364,7 @@ cp_parser_class_head (cp_parser* parser,
        {
          class_type = resolve_typename_type (TREE_TYPE (type),
                                              /*only_current_p=*/false);
        {
          class_type = resolve_typename_type (TREE_TYPE (type),
                                              /*only_current_p=*/false);
-         if (class_type != error_mark_node)
+         if (TREE_CODE (class_type) != TYPENAME_TYPE)
            type = TYPE_NAME (class_type);
          else
            {
            type = TYPE_NAME (class_type);
          else
            {
@@ -13330,7 +15373,13 @@ cp_parser_class_head (cp_parser* parser,
            }
        }
 
            }
        }
 
-      maybe_process_partial_specialization (TREE_TYPE (type));
+      if (maybe_process_partial_specialization (TREE_TYPE (type))
+         == error_mark_node)
+       {
+         type = NULL_TREE;
+         goto done;
+       }
+
       class_type = current_class_type;
       /* Enter the scope indicated by the nested-name-specifier.  */
       pushed_scope = push_scope (nested_name_specifier);
       class_type = current_class_type;
       /* Enter the scope indicated by the nested-name-specifier.  */
       pushed_scope = push_scope (nested_name_specifier);
@@ -13369,11 +15418,15 @@ cp_parser_class_head (cp_parser* parser,
      that's an error.  */
   if (type != error_mark_node && COMPLETE_TYPE_P (type))
     {
      that's an error.  */
   if (type != error_mark_node && COMPLETE_TYPE_P (type))
     {
-      error ("redefinition of %q#T", type);
-      error ("previous definition of %q+#T", type);
+      error ("%Hredefinition of %q#T",
+            &type_start_token->location, type);
+      error ("%Hprevious definition of %q+#T",
+            &type_start_token->location, type);
       type = NULL_TREE;
       goto done;
     }
       type = NULL_TREE;
       goto done;
     }
+  else if (type == error_mark_node)
+    type = NULL_TREE;
 
   /* We will have entered the scope containing the class; the names of
      base classes should be looked up in that context.  For example:
 
   /* We will have entered the scope containing the class; the names of
      base classes should be looked up in that context.  For example:
@@ -13382,14 +15435,10 @@ cp_parser_class_head (cp_parser* parser,
        struct A::C : B {};
 
      is valid.  */
        struct A::C : B {};
 
      is valid.  */
-  bases = NULL_TREE;
 
   /* Get the list of base-classes, if there is one.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
 
   /* Get the list of base-classes, if there is one.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
-    bases = cp_parser_base_clause (parser);
-
-  /* Process the base classes.  */
-  xref_basetypes (type, bases);
+    *bases = cp_parser_base_clause (parser);
 
  done:
   /* Leave the scope given by the nested-name-specifier.  We will
 
  done:
   /* Leave the scope given by the nested-name-specifier.  We will
@@ -13466,9 +15515,9 @@ cp_parser_member_specification_opt (cp_parser* parser)
          /* Consume the access-specifier.  */
          cp_lexer_consume_token (parser->lexer);
          /* Remember which access-specifier is active.  */
          /* Consume the access-specifier.  */
          cp_lexer_consume_token (parser->lexer);
          /* Remember which access-specifier is active.  */
-         current_access_specifier = token->value;
+         current_access_specifier = token->u.value;
          /* Look for the `:'.  */
          /* Look for the `:'.  */
-         cp_parser_require (parser, CPP_COLON, "`:'");
+         cp_parser_require (parser, CPP_COLON, "%<:%>");
          break;
 
        default:
          break;
 
        default:
@@ -13512,7 +15561,12 @@ cp_parser_member_specification_opt (cp_parser* parser)
    member-declarator:
      declarator attributes [opt] pure-specifier [opt]
      declarator attributes [opt] constant-initializer [opt]
    member-declarator:
      declarator attributes [opt] pure-specifier [opt]
      declarator attributes [opt] constant-initializer [opt]
-     identifier [opt] attributes [opt] : constant-expression  */
+     identifier [opt] attributes [opt] : constant-expression  
+
+   C++0x Extensions:
+
+   member-declaration:
+     static_assert-declaration  */
 
 static void
 cp_parser_member_declaration (cp_parser* parser)
 
 static void
 cp_parser_member_declaration (cp_parser* parser)
@@ -13522,7 +15576,9 @@ cp_parser_member_declaration (cp_parser* parser)
   tree decl;
   int declares_class_or_enum;
   bool friend_p;
   tree decl;
   int declares_class_or_enum;
   bool friend_p;
-  cp_token *token;
+  cp_token *token = NULL;
+  cp_token *decl_spec_token_start = NULL;
+  cp_token *initializer_token_start = NULL;
   int saved_pedantic;
 
   /* Check for the `__extension__' keyword.  */
   int saved_pedantic;
 
   /* Check for the `__extension__' keyword.  */
@@ -13554,8 +15610,8 @@ cp_parser_member_declaration (cp_parser* parser)
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
     {
       /* Parse the using-declaration.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
     {
       /* Parse the using-declaration.  */
-      cp_parser_using_declaration (parser);
-
+      cp_parser_using_declaration (parser,
+                                  /*access_declaration_p=*/false);
       return;
     }
 
       return;
     }
 
@@ -13575,7 +15631,18 @@ cp_parser_member_declaration (cp_parser* parser)
       return;
     }
 
       return;
     }
 
+  /* If the next token is `static_assert' we have a static assertion.  */
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC_ASSERT))
+    {
+      cp_parser_static_assert (parser, /*member_p=*/true);
+      return;
+    }
+
+  if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
+    return;
+
   /* Parse the decl-specifier-seq.  */
   /* Parse the decl-specifier-seq.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
                                &decl_specifiers,
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
                                &decl_specifiers,
@@ -13602,8 +15669,8 @@ cp_parser_member_declaration (cp_parser* parser)
       if (!decl_specifiers.any_specifiers_p)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
       if (!decl_specifiers.any_specifiers_p)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
-         if (pedantic && !token->in_system_header)
-           pedwarn ("%Hextra %<;%>", &token->location);
+         if (!in_system_header_at (token->location))
+           pedwarn (token->location, OPT_pedantic, "extra %<;%>");
        }
       else
        {
        }
       else
        {
@@ -13621,7 +15688,8 @@ cp_parser_member_declaration (cp_parser* parser)
              /* If the `friend' keyword was present, the friend must
                 be introduced with a class-key.  */
               if (!declares_class_or_enum)
              /* If the `friend' keyword was present, the friend must
                 be introduced with a class-key.  */
               if (!declares_class_or_enum)
-                error ("a class-key must be used when declaring a friend");
+                error ("%Ha class-key must be used when declaring a friend",
+                        &decl_spec_token_start->location);
               /* In this case:
 
                    template <typename T> struct A {
               /* In this case:
 
                    template <typename T> struct A {
@@ -13635,8 +15703,8 @@ cp_parser_member_declaration (cp_parser* parser)
                   && TYPE_P (decl_specifiers.type))
                 type = decl_specifiers.type;
               if (!type || !TYPE_P (type))
                   && TYPE_P (decl_specifiers.type))
                 type = decl_specifiers.type;
               if (!type || !TYPE_P (type))
-                error ("friend declaration does not name a class or "
-                       "function");
+                error ("%Hfriend declaration does not name a class or "
+                       "function", &decl_spec_token_start->location);
               else
                 make_friend_class (current_class_type, type,
                                    /*complain=*/true);
               else
                 make_friend_class (current_class_type, type,
                                    /*complain=*/true);
@@ -13659,7 +15727,9 @@ cp_parser_member_declaration (cp_parser* parser)
              finish_member_declaration (decl);
            }
          else
              finish_member_declaration (decl);
            }
          else
-           cp_parser_check_access_in_redeclaration (TYPE_NAME (type));
+           cp_parser_check_access_in_redeclaration
+                                             (TYPE_NAME (type),
+                                              decl_spec_token_start->location);
        }
     }
   else
        }
     }
   else
@@ -13717,9 +15787,8 @@ cp_parser_member_declaration (cp_parser* parser)
                                                         sfk_none)
                                   : NULL,
                                   &decl_specifiers,
                                                         sfk_none)
                                   : NULL,
                                   &decl_specifiers,
-                                  width);
-             /* Apply the attributes.  */
-             cplus_decl_attributes (&decl, attributes, /*flags=*/0);
+                                  width,
+                                  attributes);
            }
          else
            {
            }
          else
            {
@@ -13754,7 +15823,8 @@ cp_parser_member_declaration (cp_parser* parser)
 
              if (declares_class_or_enum & 2)
                cp_parser_check_for_definition_in_return_type
 
              if (declares_class_or_enum & 2)
                cp_parser_check_for_definition_in_return_type
-                 (declarator, decl_specifiers.type);
+                                           (declarator, decl_specifiers.type,
+                                            decl_specifiers.type_location);
 
              /* Look for an asm-specification.  */
              asm_specification = cp_parser_asm_specification_opt (parser);
 
              /* Look for an asm-specification.  */
              asm_specification = cp_parser_asm_specification_opt (parser);
@@ -13788,8 +15858,8 @@ cp_parser_member_declaration (cp_parser* parser)
                     for a pure-specifier; otherwise, we look for a
                     constant-initializer.  When we call `grokfield', it will
                     perform more stringent semantics checks.  */
                     for a pure-specifier; otherwise, we look for a
                     constant-initializer.  When we call `grokfield', it will
                     perform more stringent semantics checks.  */
-                 if (declarator->kind == cdk_function
-                     && declarator->declarator->kind == cdk_id)
+                 initializer_token_start = cp_lexer_peek_token (parser->lexer);
+                 if (function_declarator_p (declarator))
                    initializer = cp_parser_pure_specifier (parser);
                  else
                    /* Parse the initializer.  */
                    initializer = cp_parser_pure_specifier (parser);
                  else
                    /* Parse the initializer.  */
@@ -13813,7 +15883,8 @@ cp_parser_member_declaration (cp_parser* parser)
                     standard, since a pure function may be defined
                     outside of the class-specifier.  */
                  if (initializer)
                     standard, since a pure function may be defined
                     outside of the class-specifier.  */
                  if (initializer)
-                   error ("pure-specifier on function-definition");
+                   error ("%Hpure-specifier on function-definition",
+                          &initializer_token_start->location);
                  decl = cp_parser_save_member_function_body (parser,
                                                              &decl_specifiers,
                                                              declarator,
                  decl = cp_parser_save_member_function_body (parser,
                                                              &decl_specifiers,
                                                              declarator,
@@ -13829,6 +15900,8 @@ cp_parser_member_declaration (cp_parser* parser)
                  return;
                }
              else
                  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,
                /* Create the declaration.  */
                decl = grokfield (declarator, &decl_specifiers,
                                  initializer, /*init_const_expr_p=*/true,
@@ -13873,7 +15946,7 @@ cp_parser_member_declaration (cp_parser* parser)
        }
     }
 
        }
     }
 
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 }
 
 /* Parse a pure-specifier.
 }
 
 /* Parse a pure-specifier.
@@ -13890,21 +15963,30 @@ cp_parser_pure_specifier (cp_parser* parser)
   cp_token *token;
 
   /* Look for the `=' token.  */
   cp_token *token;
 
   /* Look for the `=' token.  */
-  if (!cp_parser_require (parser, CPP_EQ, "`='"))
+  if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
     return error_mark_node;
   /* Look for the `0' token.  */
   token = cp_lexer_consume_token (parser->lexer);
     return error_mark_node;
   /* Look for the `0' token.  */
   token = cp_lexer_consume_token (parser->lexer);
+
+  /* Accept = default or = delete in c++0x mode.  */
+  if (token->keyword == RID_DEFAULT
+      || token->keyword == RID_DELETE)
+    {
+      maybe_warn_cpp0x ("defaulted and deleted functions");
+      return token->u.value;
+    }
+
   /* c_lex_with_flags marks a single digit '0' with PURE_ZERO.  */
   if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO))
     {
       cp_parser_error (parser,
   /* c_lex_with_flags marks a single digit '0' with PURE_ZERO.  */
   if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO))
     {
       cp_parser_error (parser,
-                      "invalid pure specifier (only `= 0' is allowed)");
+                      "invalid pure specifier (only %<= 0%> is allowed)");
       cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
       cp_parser_skip_to_end_of_statement (parser);
       return error_mark_node;
     }
   if (PROCESSING_REAL_TEMPLATE_DECL_P ())
     {
-      error ("templates may not be %<virtual%>");
+      error ("%Htemplates may not be %<virtual%>", &token->location);
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
@@ -13922,7 +16004,7 @@ static tree
 cp_parser_constant_initializer (cp_parser* parser)
 {
   /* Look for the `=' token.  */
 cp_parser_constant_initializer (cp_parser* parser)
 {
   /* Look for the `=' token.  */
-  if (!cp_parser_require (parser, CPP_EQ, "`='"))
+  if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
     return error_mark_node;
 
   /* It is invalid to write:
     return error_mark_node;
 
   /* It is invalid to write:
@@ -13939,7 +16021,7 @@ cp_parser_constant_initializer (cp_parser* parser)
       /* Skip the initializer.  */
       cp_parser_skip_to_closing_brace (parser);
       /* Look for the trailing `}'.  */
       /* Skip the initializer.  */
       cp_parser_skip_to_closing_brace (parser);
       /* Look for the trailing `}'.  */
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 
       return error_mark_node;
     }
 
       return error_mark_node;
     }
@@ -13957,8 +16039,8 @@ cp_parser_constant_initializer (cp_parser* parser)
      : base-specifier-list
 
    base-specifier-list:
      : base-specifier-list
 
    base-specifier-list:
-     base-specifier
-     base-specifier-list , base-specifier
+     base-specifier ... [opt]
+     base-specifier-list , base-specifier ... [opt]
 
    Returns a TREE_LIST representing the base-classes, in the order in
    which they were declared.  The representation of each node is as
 
    Returns a TREE_LIST representing the base-classes, in the order in
    which they were declared.  The representation of each node is as
@@ -13973,21 +16055,39 @@ cp_parser_base_clause (cp_parser* parser)
   tree bases = NULL_TREE;
 
   /* Look for the `:' that begins the list.  */
   tree bases = NULL_TREE;
 
   /* Look for the `:' that begins the list.  */
-  cp_parser_require (parser, CPP_COLON, "`:'");
+  cp_parser_require (parser, CPP_COLON, "%<:%>");
 
   /* Scan the base-specifier-list.  */
   while (true)
     {
       cp_token *token;
       tree base;
 
   /* Scan the base-specifier-list.  */
   while (true)
     {
       cp_token *token;
       tree base;
+      bool pack_expansion_p = false;
 
       /* Look for the base-specifier.  */
       base = cp_parser_base_specifier (parser);
 
       /* Look for the base-specifier.  */
       base = cp_parser_base_specifier (parser);
+      /* Look for the (optional) ellipsis. */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+        {
+          /* Consume the `...'. */
+          cp_lexer_consume_token (parser->lexer);
+
+          pack_expansion_p = true;
+        }
+
       /* Add BASE to the front of the list.  */
       if (base != error_mark_node)
        {
       /* Add BASE to the front of the list.  */
       if (base != error_mark_node)
        {
-         TREE_CHAIN (base) = bases;
-         bases = base;
+          if (pack_expansion_p)
+            /* Make this a pack expansion type. */
+            TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
+          
+
+          if (!check_for_bare_parameter_packs (TREE_VALUE (base)))
+            {
+              TREE_CHAIN (base) = bases;
+              bases = base;
+            }
        }
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
        }
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -14088,11 +16188,14 @@ cp_parser_base_specifier (cp_parser* parser)
      as base classes.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
      as base classes.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
     {
+      token = cp_lexer_peek_token (parser->lexer);
       if (!processing_template_decl)
       if (!processing_template_decl)
-       error ("keyword %<typename%> not allowed outside of templates");
+       error ("%Hkeyword %<typename%> not allowed outside of templates",
+              &token->location);
       else
       else
-       error ("keyword %<typename%> not allowed in this context "
-              "(the base class is implicitly a type)");
+       error ("%Hkeyword %<typename%> not allowed in this context "
+              "(the base class is implicitly a type)",
+              &token->location);
       cp_lexer_consume_token (parser->lexer);
     }
 
       cp_lexer_consume_token (parser->lexer);
     }
 
@@ -14161,7 +16264,7 @@ cp_parser_exception_specification_opt (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);
 
   /* Look for the `('.  */
   cp_lexer_consume_token (parser->lexer);
 
   /* Look for the `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -14183,7 +16286,7 @@ cp_parser_exception_specification_opt (cp_parser* parser)
     type_id_list = empty_except_spec;
 
   /* Look for the `)'.  */
     type_id_list = empty_except_spec;
 
   /* Look for the `)'.  */
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return type_id_list;
 }
 
   return type_id_list;
 }
@@ -14191,8 +16294,8 @@ cp_parser_exception_specification_opt (cp_parser* parser)
 /* Parse an (optional) type-id-list.
 
    type-id-list:
 /* Parse an (optional) type-id-list.
 
    type-id-list:
-     type-id
-     type-id-list , type-id
+     type-id ... [opt]
+     type-id-list , type-id ... [opt]
 
    Returns a TREE_LIST.  The TREE_VALUE of each node is a TYPE,
    in the order that the types were presented.  */
 
    Returns a TREE_LIST.  The TREE_VALUE of each node is a TYPE,
    in the order that the types were presented.  */
@@ -14209,6 +16312,15 @@ cp_parser_type_id_list (cp_parser* parser)
 
       /* Get the next type-id.  */
       type = cp_parser_type_id (parser);
 
       /* Get the next type-id.  */
       type = cp_parser_type_id (parser);
+      /* Parse the optional ellipsis. */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+        {
+          /* Consume the `...'. */
+          cp_lexer_consume_token (parser->lexer);
+
+          /* Turn the type into a pack expansion expression. */
+          type = make_pack_expansion (type);
+        }
       /* Add it to the list.  */
       types = add_exception_specifier (types, type, /*complain=*/1);
       /* Peek at the next token.  */
       /* Add it to the list.  */
       types = add_exception_specifier (types, type, /*complain=*/1);
       /* Peek at the next token.  */
@@ -14233,7 +16345,7 @@ cp_parser_try_block (cp_parser* parser)
 {
   tree try_block;
 
 {
   tree try_block;
 
-  cp_parser_require_keyword (parser, RID_TRY, "`try'");
+  cp_parser_require_keyword (parser, RID_TRY, "%<try%>");
   try_block = begin_try_block ();
   cp_parser_compound_statement (parser, NULL, true);
   finish_try_block (try_block);
   try_block = begin_try_block ();
   cp_parser_compound_statement (parser, NULL, true);
   finish_try_block (try_block);
@@ -14256,9 +16368,9 @@ cp_parser_function_try_block (cp_parser* parser)
   bool ctor_initializer_p;
 
   /* Look for the `try' keyword.  */
   bool ctor_initializer_p;
 
   /* Look for the `try' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_TRY, "`try'"))
+  if (!cp_parser_require_keyword (parser, RID_TRY, "%<try%>"))
     return false;
     return false;
-  /* Let the rest of the front-end know where we are.  */
+  /* Let the rest of the front end know where we are.  */
   try_block = begin_function_try_block (&compound_stmt);
   /* Parse the function-body.  */
   ctor_initializer_p
   try_block = begin_function_try_block (&compound_stmt);
   /* Parse the function-body.  */
   ctor_initializer_p
@@ -14306,12 +16418,12 @@ cp_parser_handler (cp_parser* parser)
   tree handler;
   tree declaration;
 
   tree handler;
   tree declaration;
 
-  cp_parser_require_keyword (parser, RID_CATCH, "`catch'");
+  cp_parser_require_keyword (parser, RID_CATCH, "%<catch%>");
   handler = begin_handler ();
   handler = begin_handler ();
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   declaration = cp_parser_exception_declaration (parser);
   finish_handler_parms (declaration, handler);
   declaration = cp_parser_exception_declaration (parser);
   finish_handler_parms (declaration, handler);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
   cp_parser_compound_statement (parser, NULL, false);
   finish_handler (handler);
 }
   cp_parser_compound_statement (parser, NULL, false);
   finish_handler (handler);
 }
@@ -14330,7 +16442,6 @@ cp_parser_handler (cp_parser* parser)
 static tree
 cp_parser_exception_declaration (cp_parser* parser)
 {
 static tree
 cp_parser_exception_declaration (cp_parser* parser)
 {
-  tree decl;
   cp_decl_specifier_seq type_specifiers;
   cp_declarator *declarator;
   const char *saved_message;
   cp_decl_specifier_seq type_specifiers;
   cp_declarator *declarator;
   const char *saved_message;
@@ -14363,16 +16474,10 @@ cp_parser_exception_declaration (cp_parser* parser)
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
 
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
 
-  if (type_specifiers.any_specifiers_p)
-    {
-      decl = grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
-      if (decl == NULL_TREE)
-       error ("invalid catch parameter");
-    }
-  else
-    decl = NULL_TREE;
+  if (!type_specifiers.any_specifiers_p)
+    return error_mark_node;
 
 
-  return decl;
+  return grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
 }
 
 /* Parse a throw-expression.
 }
 
 /* Parse a throw-expression.
@@ -14388,7 +16493,7 @@ cp_parser_throw_expression (cp_parser* parser)
   tree expression;
   cp_token* token;
 
   tree expression;
   cp_token* token;
 
-  cp_parser_require_keyword (parser, RID_THROW, "`throw'");
+  cp_parser_require_keyword (parser, RID_THROW, "%<throw%>");
   token = cp_lexer_peek_token (parser->lexer);
   /* Figure out whether or not there is an assignment-expression
      following the "throw" keyword.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* Figure out whether or not there is an assignment-expression
      following the "throw" keyword.  */
@@ -14433,13 +16538,13 @@ cp_parser_asm_specification_opt (cp_parser* parser)
   /* Consume the `asm' token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Look for the `('.  */
   /* Consume the `asm' token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Look for the `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
   /* Look for the string-literal.  */
   asm_specification = cp_parser_string_literal (parser, false, false);
 
   /* Look for the `)'.  */
 
   /* Look for the string-literal.  */
   asm_specification = cp_parser_string_literal (parser, false, false);
 
   /* Look for the `)'.  */
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`('");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return asm_specification;
 }
 
   return asm_specification;
 }
@@ -14458,12 +16563,14 @@ cp_parser_asm_specification_opt (cp_parser* parser)
    each node is the expression.  The TREE_PURPOSE is itself a
    TREE_LIST whose TREE_PURPOSE is a STRING_CST for the bracketed
    string-literal (or NULL_TREE if not present) and whose TREE_VALUE
    each node is the expression.  The TREE_PURPOSE is itself a
    TREE_LIST whose TREE_PURPOSE is a STRING_CST for the bracketed
    string-literal (or NULL_TREE if not present) and whose TREE_VALUE
-   is a STRING_CST for the string literal before the parenthesis.  */
+   is a STRING_CST for the string literal before the parenthesis. Returns
+   ERROR_MARK_NODE if any of the operands are invalid.  */
 
 static tree
 cp_parser_asm_operand_list (cp_parser* parser)
 {
   tree asm_operands = NULL_TREE;
 
 static tree
 cp_parser_asm_operand_list (cp_parser* parser)
 {
   tree asm_operands = NULL_TREE;
+  bool invalid_operands = false;
 
   while (true)
     {
 
   while (true)
     {
@@ -14481,7 +16588,7 @@ cp_parser_asm_operand_list (cp_parser* parser)
            name = build_string (IDENTIFIER_LENGTH (name),
                                 IDENTIFIER_POINTER (name));
          /* Look for the closing `]'.  */
            name = build_string (IDENTIFIER_LENGTH (name),
                                 IDENTIFIER_POINTER (name));
          /* Look for the closing `]'.  */
-         cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+         cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
        }
       else
        name = NULL_TREE;
        }
       else
        name = NULL_TREE;
@@ -14489,11 +16596,16 @@ cp_parser_asm_operand_list (cp_parser* parser)
       string_literal = cp_parser_string_literal (parser, false, false);
 
       /* Look for the `('.  */
       string_literal = cp_parser_string_literal (parser, false, false);
 
       /* Look for the `('.  */
-      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
       /* Parse the expression.  */
       expression = cp_parser_expression (parser, /*cast_p=*/false);
       /* Look for the `)'.  */
       /* Parse the expression.  */
       expression = cp_parser_expression (parser, /*cast_p=*/false);
       /* Look for the `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+
+      if (name == error_mark_node 
+         || string_literal == error_mark_node 
+         || expression == error_mark_node)
+        invalid_operands = true;
 
       /* Add this operand to the list.  */
       asm_operands = tree_cons (build_tree_list (name, string_literal),
 
       /* Add this operand to the list.  */
       asm_operands = tree_cons (build_tree_list (name, string_literal),
@@ -14507,7 +16619,7 @@ cp_parser_asm_operand_list (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
     }
 
       cp_lexer_consume_token (parser->lexer);
     }
 
-  return nreverse (asm_operands);
+  return invalid_operands ? error_mark_node : nreverse (asm_operands);
 }
 
 /* Parse an asm-clobber-list.
 }
 
 /* Parse an asm-clobber-list.
@@ -14572,8 +16684,8 @@ cp_parser_attributes_opt (cp_parser* parser)
       /* Consume the `__attribute__' keyword.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the two `(' tokens.  */
       /* Consume the `__attribute__' keyword.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the two `(' tokens.  */
-      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
-      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -14586,8 +16698,8 @@ cp_parser_attributes_opt (cp_parser* parser)
        attribute_list = NULL;
 
       /* Look for the two `)' tokens.  */
        attribute_list = NULL;
 
       /* Look for the two `)' tokens.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
       /* Add these new attributes to the list.  */
       attributes = chainon (attributes, attribute_list);
 
       /* Add these new attributes to the list.  */
       attributes = chainon (attributes, attribute_list);
@@ -14639,7 +16751,7 @@ cp_parser_attribute_list (cp_parser* parser)
 
          /* Save away the identifier that indicates which attribute
             this is.  */
 
          /* Save away the identifier that indicates which attribute
             this is.  */
-         identifier = token->value;
+         identifier = token->u.value;
          attribute = build_tree_list (identifier, NULL_TREE);
 
          /* Peek at the next token.  */
          attribute = build_tree_list (identifier, NULL_TREE);
 
          /* Peek at the next token.  */
@@ -14649,6 +16761,7 @@ cp_parser_attribute_list (cp_parser* parser)
            {
              arguments = cp_parser_parenthesized_expression_list
                          (parser, true, /*cast_p=*/false,
            {
              arguments = cp_parser_parenthesized_expression_list
                          (parser, true, /*cast_p=*/false,
+                           /*allow_expansion_p=*/false,
                           /*non_constant_p=*/NULL);
              /* Save the arguments away.  */
              TREE_VALUE (attribute) = arguments;
                           /*non_constant_p=*/NULL);
              /* Save the arguments away.  */
              TREE_VALUE (attribute) = arguments;
@@ -14716,7 +16829,7 @@ static void
 cp_parser_label_declaration (cp_parser* parser)
 {
   /* Look for the `__label__' keyword.  */
 cp_parser_label_declaration (cp_parser* parser)
 {
   /* Look for the `__label__' keyword.  */
-  cp_parser_require_keyword (parser, RID_LABEL, "`__label__'");
+  cp_parser_require_keyword (parser, RID_LABEL, "%<__label__%>");
 
   while (true)
     {
 
   while (true)
     {
@@ -14733,11 +16846,11 @@ cp_parser_label_declaration (cp_parser* parser)
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
        break;
       /* Look for the `,' separating the label declarations.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
        break;
       /* Look for the `,' separating the label declarations.  */
-      cp_parser_require (parser, CPP_COMMA, "`,'");
+      cp_parser_require (parser, CPP_COMMA, "%<,%>");
     }
 
   /* Look for the final `;'.  */
     }
 
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 }
 
 /* Support Functions */
 }
 
 /* Support Functions */
@@ -14783,7 +16896,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                       bool is_template,
                       bool is_namespace,
                       bool check_dependency,
                       bool is_template,
                       bool is_namespace,
                       bool check_dependency,
-                      tree *ambiguous_decls)
+                      tree *ambiguous_decls,
+                      location_t name_location)
 {
   int flags = 0;
   tree decl;
 {
   int flags = 0;
   tree decl;
@@ -14906,6 +17020,13 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
          decl = lookup_qualified_name (parser->scope, name,
                                        tag_type != none_type,
                                        /*complain=*/true);
          decl = lookup_qualified_name (parser->scope, name,
                                        tag_type != none_type,
                                        /*complain=*/true);
+
+         /* If we have a single function from a using decl, pull it out.  */
+         if (decl
+             && TREE_CODE (decl) == OVERLOAD
+             && !really_overloaded_fn (decl))
+           decl = OVL_FUNCTION (decl);
+
          if (pushed_scope)
            pop_scope (pushed_scope);
        }
          if (pushed_scope)
            pop_scope (pushed_scope);
        }
@@ -14957,7 +17078,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
         cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
        {
         cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
        {
-         error ("reference to %qD is ambiguous", name);
+         error ("%Hreference to %qD is ambiguous",
+                &name_location, name);
          print_candidates (decl);
        }
       return error_mark_node;
          print_candidates (decl);
        }
       return error_mark_node;
@@ -14987,14 +17109,15 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
    IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE.  */
 
 static tree
    IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE.  */
 
 static tree
-cp_parser_lookup_name_simple (cp_parser* parser, tree name)
+cp_parser_lookup_name_simple (cp_parser* parser, tree name, location_t location)
 {
   return cp_parser_lookup_name (parser, name,
                                none_type,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
                                /*check_dependency=*/true,
 {
   return cp_parser_lookup_name (parser, name,
                                none_type,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
                                /*check_dependency=*/true,
-                               /*ambiguous_decls=*/NULL);
+                               /*ambiguous_decls=*/NULL,
+                               location);
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
@@ -15047,7 +17170,8 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
 
 static bool
 cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 static bool
 cp_parser_check_declarator_template_parameters (cp_parser* parser,
-                                               cp_declarator *declarator)
+                                               cp_declarator *declarator,
+                                               location_t declarator_location)
 {
   unsigned num_templates;
 
 {
   unsigned num_templates;
 
@@ -15077,10 +17201,14 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
                 is correct; there shouldn't be a `template <>' for
                 the definition of `S<int>::f'.  */
 
                 is correct; there shouldn't be a `template <>' for
                 the definition of `S<int>::f'.  */
-             if (CLASSTYPE_TEMPLATE_INFO (scope)
-                 && (CLASSTYPE_TEMPLATE_INSTANTIATION (scope)
-                     || uses_template_parms (CLASSTYPE_TI_ARGS (scope)))
-                 && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
+             if (!CLASSTYPE_TEMPLATE_INFO (scope))
+               /* If SCOPE does not have template information of any
+                  kind, then it is not a template, nor is it nested
+                  within a template.  */
+               break;
+             if (explicit_class_specialization_p (scope))
+               break;
+             if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (scope)))
                ++num_templates;
 
              scope = TYPE_CONTEXT (scope);
                ++num_templates;
 
              scope = TYPE_CONTEXT (scope);
@@ -15093,7 +17221,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
        ++num_templates;
 
       return cp_parser_check_template_parameters (parser,
        ++num_templates;
 
       return cp_parser_check_template_parameters (parser,
-                                                 num_templates);
+                                                 num_templates,
+                                                 declarator_location);
 
     case cdk_function:
     case cdk_array:
 
     case cdk_function:
     case cdk_array:
@@ -15101,7 +17230,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
     case cdk_reference:
     case cdk_ptrmem:
       return (cp_parser_check_declarator_template_parameters
     case cdk_reference:
     case cdk_ptrmem:
       return (cp_parser_check_declarator_template_parameters
-             (parser, declarator->declarator));
+             (parser, declarator->declarator, declarator_location));
 
     case cdk_error:
       return true;
 
     case cdk_error:
       return true;
@@ -15118,7 +17247,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
-                                    unsigned num_templates)
+                                    unsigned num_templates,
+                                    location_t location)
 {
   /* If there are more template classes than parameter lists, we have
      something like:
 {
   /* If there are more template classes than parameter lists, we have
      something like:
@@ -15126,7 +17256,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      error ("too few template-parameter-lists");
+      error ("%Htoo few template-parameter-lists", &location);
       return false;
     }
   /* If there are the same number of template classes and parameter
       return false;
     }
   /* If there are the same number of template classes and parameter
@@ -15141,7 +17271,7 @@ cp_parser_check_template_parameters (cp_parser* parser,
      something like:
 
      template <class T> template <class U> void S::f();  */
      something like:
 
      template <class T> template <class U> void S::f();  */
-  error ("too many template-parameter-lists");
+  error ("%Htoo many template-parameter-lists", &location);
   return false;
 }
 
   return false;
 }
 
@@ -15197,7 +17327,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
   /* The common case is that this is not a constructor declarator, so
      try to avoid doing lots of work if at all possible.  It's not
      valid declare a constructor at function scope.  */
   /* The common case is that this is not a constructor declarator, so
      try to avoid doing lots of work if at all possible.  It's not
      valid declare a constructor at function scope.  */
-  if (at_function_scope_p ())
+  if (parser->in_function_body)
     return false;
   /* And only certain tokens can begin a constructor declarator.  */
   next_token = cp_lexer_peek_token (parser->lexer);
     return false;
   /* And only certain tokens can begin a constructor declarator.  */
   next_token = cp_lexer_peek_token (parser->lexer);
@@ -15267,15 +17397,14 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
      takes one parameter (of type `int') and returns a value of type
      `S::S'.  */
   if (constructor_p
      takes one parameter (of type `int') and returns a value of type
      `S::S'.  */
   if (constructor_p
-      && cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+      && cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     {
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
          /* A parameter declaration begins with a decl-specifier,
             which is either the "attribute" keyword, a storage class
             specifier, or (usually) a type-specifier.  */
     {
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
          /* A parameter declaration begins with a decl-specifier,
             which is either the "attribute" keyword, a storage class
             specifier, or (usually) a type-specifier.  */
-         && !cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)
-         && !cp_parser_storage_class_specifier_opt (parser))
+         && !cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer))
        {
          tree type;
          tree pushed_scope = NULL_TREE;
        {
          tree type;
          tree pushed_scope = NULL_TREE;
@@ -15292,7 +17421,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
                {
                  type = resolve_typename_type (type,
                                                /*only_current_p=*/false);
                {
                  type = resolve_typename_type (type,
                                                /*only_current_p=*/false);
-                 if (type == error_mark_node)
+                 if (TREE_CODE (type) == TYPENAME_TYPE)
                    {
                      cp_parser_abort_tentative_parse (parser);
                      return false;
                    {
                      cp_parser_abort_tentative_parse (parser);
                      return false;
@@ -15368,6 +17497,16 @@ cp_parser_function_definition_from_specifiers_and_declarator
       cp_parser_skip_to_end_of_block_or_statement (parser);
       fn = error_mark_node;
     }
       cp_parser_skip_to_end_of_block_or_statement (parser);
       fn = error_mark_node;
     }
+  else if (DECL_INITIAL (current_function_decl) != error_mark_node)
+    {
+      /* Seen already, skip it.  An error message has already been output.  */
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      fn = current_function_decl;
+      current_function_decl = NULL_TREE;
+      /* If this is a function from a class, pop the nested class.  */
+      if (current_class_name)
+       pop_nested_class ();
+    }
   else
     fn = cp_parser_function_definition_after_declarator (parser,
                                                         /*inline_p=*/false);
   else
     fn = cp_parser_function_definition_after_declarator (parser,
                                                         /*inline_p=*/false);
@@ -15388,11 +17527,16 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   tree fn;
   bool ctor_initializer_p = false;
   bool saved_in_unbraced_linkage_specification_p;
   tree fn;
   bool ctor_initializer_p = false;
   bool saved_in_unbraced_linkage_specification_p;
+  bool saved_in_function_body;
   unsigned saved_num_template_parameter_lists;
   unsigned saved_num_template_parameter_lists;
+  cp_token *token;
 
 
+  saved_in_function_body = parser->in_function_body;
+  parser->in_function_body = true;
   /* If the next token is `return', then the code may be trying to
      make use of the "named return value" extension that G++ used to
      support.  */
   /* If the next token is `return', then the code may be trying to
      make use of the "named return value" extension that G++ used to
      support.  */
+  token = cp_lexer_peek_token (parser->lexer);
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_RETURN))
     {
       /* Consume the `return' keyword.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_RETURN))
     {
       /* Consume the `return' keyword.  */
@@ -15401,7 +17545,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
         returned.  */
       cp_parser_identifier (parser);
       /* Issue an error message.  */
         returned.  */
       cp_parser_identifier (parser);
       /* Issue an error message.  */
-      error ("named return values are no longer supported");
+      error ("%Hnamed return values are no longer supported",
+            &token->location);
       /* Skip tokens until we reach the start of the function body.  */
       while (true)
        {
       /* Skip tokens until we reach the start of the function body.  */
       while (true)
        {
@@ -15443,6 +17588,7 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
     = saved_in_unbraced_linkage_specification_p;
   parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
     = saved_in_unbraced_linkage_specification_p;
   parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
+  parser->in_function_body = saved_in_function_body;
 
   return fn;
 }
 
   return fn;
 }
@@ -15455,24 +17601,36 @@ static void
 cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 {
   tree decl = NULL_TREE;
 cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 {
   tree decl = NULL_TREE;
-  tree checks;
+  VEC (deferred_access_check,gc) *checks;
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
+  cp_token *token;
 
   /* Look for the `template' keyword.  */
 
   /* Look for the `template' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"))
+  token = cp_lexer_peek_token (parser->lexer);
+  if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
     return;
 
   /* And the `<'.  */
     return;
 
   /* And the `<'.  */
-  if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+  if (!cp_parser_require (parser, CPP_LESS, "%<<%>"))
     return;
     return;
+  if (at_class_scope_p () && current_function_decl)
+    {
+      /* 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);
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      return;
+    }
   /* [temp]
 
      A template ... shall not have C linkage.  */
   if (current_lang_name == lang_name_c)
     {
   /* [temp]
 
      A template ... shall not have C linkage.  */
   if (current_lang_name == lang_name_c)
     {
-      error ("template with C linkage");
+      error ("%Htemplate with C linkage", &token->location);
       /* Give it C++ linkage to avoid confusing other parts of the
         front end.  */
       push_lang_context (lang_name_cplusplus);
       /* Give it C++ linkage to avoid confusing other parts of the
         front end.  */
       push_lang_context (lang_name_cplusplus);
@@ -15506,7 +17664,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   checks = get_deferred_access_checks ();
 
   /* Look for the `>'.  */
   checks = get_deferred_access_checks ();
 
   /* Look for the `>'.  */
-  cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
+  cp_parser_skip_to_end_of_template_parameter_list (parser);
   /* We just processed one more parameter list.  */
   ++parser->num_template_parameter_lists;
   /* If the next token is `template', there are more template
   /* We just processed one more parameter list.  */
   ++parser->num_template_parameter_lists;
   /* If the next token is `template', there are more template
@@ -15519,9 +17677,11 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* There are no access checks when parsing a template, as we do not
         know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
       /* There are no access checks when parsing a template, as we do not
         know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
+      token = cp_lexer_peek_token (parser->lexer);
       decl = cp_parser_single_declaration (parser,
                                           checks,
                                           member_p,
       decl = cp_parser_single_declaration (parser,
                                           checks,
                                           member_p,
+                                           /*explicit_specialization_p=*/false,
                                           &friend_p);
       pop_deferring_access_checks ();
 
                                           &friend_p);
       pop_deferring_access_checks ();
 
@@ -15530,7 +17690,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       if (member_p && !friend_p && decl)
        {
          if (TREE_CODE (decl) == TYPE_DECL)
       if (member_p && !friend_p && decl)
        {
          if (TREE_CODE (decl) == TYPE_DECL)
-           cp_parser_check_access_in_redeclaration (decl);
+           cp_parser_check_access_in_redeclaration (decl, token->location);
 
          decl = finish_member_template_decl (decl);
        }
 
          decl = finish_member_template_decl (decl);
        }
@@ -15569,7 +17729,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
    get_deferred_access_checks.  */
 
 static void
    get_deferred_access_checks.  */
 
 static void
-cp_parser_perform_template_parameter_access_checks (tree checks)
+cp_parser_perform_template_parameter_access_checks (VEC (deferred_access_check,gc)* checks)
 {
   ++processing_template_parmlist;
   perform_access_checks (checks);
 {
   ++processing_template_parmlist;
   perform_access_checks (checks);
@@ -15585,14 +17745,16 @@ cp_parser_perform_template_parameter_access_checks (tree checks)
 
 static tree
 cp_parser_single_declaration (cp_parser* parser,
 
 static tree
 cp_parser_single_declaration (cp_parser* parser,
-                             tree checks,
+                             VEC (deferred_access_check,gc)* checks,
                              bool member_p,
                              bool member_p,
+                              bool explicit_specialization_p,
                              bool* friend_p)
 {
   int declares_class_or_enum;
   tree decl = NULL_TREE;
   cp_decl_specifier_seq decl_specifiers;
   bool function_definition_p = false;
                              bool* friend_p)
 {
   int declares_class_or_enum;
   tree decl = NULL_TREE;
   cp_decl_specifier_seq decl_specifiers;
   bool function_definition_p = false;
+  cp_token *decl_spec_token_start;
 
   /* This function is only used when processing a template
      declaration.  */
 
   /* This function is only used when processing a template
      declaration.  */
@@ -15604,6 +17766,7 @@ cp_parser_single_declaration (cp_parser* parser,
 
   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
      alternative.  */
 
   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
      alternative.  */
+  decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
                                &decl_specifiers,
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
                                &decl_specifiers,
@@ -15614,7 +17777,8 @@ cp_parser_single_declaration (cp_parser* parser,
   /* There are no template typedefs.  */
   if (decl_specifiers.specs[(int) ds_typedef])
     {
   /* There are no template typedefs.  */
   if (decl_specifiers.specs[(int) ds_typedef])
     {
-      error ("template declaration of %qs", "typedef");
+      error ("%Htemplate declaration of %qs",
+            &decl_spec_token_start->location, "typedef");
       decl = error_mark_node;
     }
 
       decl = error_mark_node;
     }
 
@@ -15660,13 +17824,28 @@ cp_parser_single_declaration (cp_parser* parser,
   if (!decl
       && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
          || decl_specifiers.type != error_mark_node))
   if (!decl
       && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
          || decl_specifiers.type != error_mark_node))
-    decl = cp_parser_init_declarator (parser,
-                                     &decl_specifiers,
-                                     checks,
-                                     /*function_definition_allowed_p=*/true,
-                                     member_p,
-                                     declares_class_or_enum,
-                                     &function_definition_p);
+    {
+      decl = cp_parser_init_declarator (parser,
+                                       &decl_specifiers,
+                                       checks,
+                                       /*function_definition_allowed_p=*/true,
+                                       member_p,
+                                       declares_class_or_enum,
+                                       &function_definition_p);
+
+    /* 7.1.1-1 [dcl.stc]
+
+       A storage-class-specifier shall not be specified in an explicit
+       specialization...  */
+    if (decl
+        && explicit_specialization_p
+        && decl_specifiers.storage_class != sc_none)
+      {
+        error ("%Hexplicit template specialization cannot have a storage class",
+              &decl_spec_token_start->location);
+        decl = error_mark_node;
+      }
+    }
 
   pop_deferring_access_checks ();
 
 
   pop_deferring_access_checks ();
 
@@ -15678,7 +17857,7 @@ cp_parser_single_declaration (cp_parser* parser,
   /* Look for a trailing `;' after the declaration.  */
   if (!function_definition_p
       && (decl == error_mark_node
   /* Look for a trailing `;' after the declaration.  */
   if (!function_definition_p
       && (decl == error_mark_node
-         || !cp_parser_require (parser, CPP_SEMICOLON, "`;'")))
+         || !cp_parser_require (parser, CPP_SEMICOLON, "%<;%>")))
     cp_parser_skip_to_end_of_block_or_statement (parser);
 
   return decl;
     cp_parser_skip_to_end_of_block_or_statement (parser);
 
   return decl;
@@ -15701,24 +17880,35 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
 {
   tree expression_list;
   tree cast;
 {
   tree expression_list;
   tree cast;
+  bool nonconst_p;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      maybe_warn_cpp0x ("extended initializer lists");
+      expression_list = cp_parser_braced_list (parser, &nonconst_p);
+      CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
+      if (TREE_CODE (type) == TYPE_DECL)
+       type = TREE_TYPE (type);
+      return finish_compound_literal (type, expression_list);
+    }
 
   expression_list
     = cp_parser_parenthesized_expression_list (parser, false,
                                               /*cast_p=*/true,
 
   expression_list
     = cp_parser_parenthesized_expression_list (parser, false,
                                               /*cast_p=*/true,
+                                              /*allow_expansion_p=*/true,
                                               /*non_constant_p=*/NULL);
 
                                               /*non_constant_p=*/NULL);
 
-  cast = build_functional_cast (type, expression_list);
+  cast = build_functional_cast (type, expression_list,
+                                tf_warning_or_error);
   /* [expr.const]/1: In an integral constant expression "only type
      conversions to integral or enumeration type can be used".  */
   if (TREE_CODE (type) == TYPE_DECL)
     type = TREE_TYPE (type);
   /* [expr.const]/1: In an integral constant expression "only type
      conversions to integral or enumeration type can be used".  */
   if (TREE_CODE (type) == TYPE_DECL)
     type = TREE_TYPE (type);
-  if (cast != error_mark_node && !dependent_type_p (type)
-      && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-    {
-      if (cp_parser_non_integral_constant_expression
-         (parser, "a call to a constructor"))
-       return error_mark_node;
-    }
+  if (cast != error_mark_node
+      && !cast_valid_in_integral_constant_expression_p (type)
+      && (cp_parser_non_integral_constant_expression
+         (parser, "a call to a constructor")))
+    return error_mark_node;
   return cast;
 }
 
   return cast;
 }
 
@@ -15756,6 +17946,22 @@ cp_parser_save_member_function_body (cp_parser* parser,
   /* Save away the tokens that make up the body of the
      function.  */
   first = parser->lexer->next_token;
   /* Save away the tokens that make up the body of the
      function.  */
   first = parser->lexer->next_token;
+  /* We can have braced-init-list mem-initializers before the fn body.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      while (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
+            && cp_lexer_next_token_is_not_keyword (parser->lexer, RID_TRY))
+       {
+         /* cache_group will stop after an un-nested { } pair, too.  */
+         if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0))
+           break;
+
+         /* variadic mem-inits have ... after the ')'.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+           cp_lexer_consume_token (parser->lexer);
+       }
+    }
   cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0);
   /* Handle function try blocks.  */
   while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH))
   cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0);
   /* Handle function try blocks.  */
   while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH))
@@ -15814,7 +18020,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   saved_skip_evaluation = skip_evaluation;
   skip_evaluation = false;
   /* Parse the template-argument-list itself.  */
   saved_skip_evaluation = skip_evaluation;
   skip_evaluation = false;
   /* Parse the template-argument-list itself.  */
-  if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
+  if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER)
+      || cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
     arguments = NULL_TREE;
   else
     arguments = cp_parser_template_argument_list (parser);
     arguments = NULL_TREE;
   else
     arguments = cp_parser_template_argument_list (parser);
@@ -15822,7 +18029,28 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
      a '>>' instead, it's probably just a typo.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
     {
      a '>>' instead, it's probably just a typo.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
     {
-      if (!saved_greater_than_is_operator_p)
+      if (cxx_dialect != cxx98)
+        {
+          /* In C++0x, a `>>' in a template argument list or cast
+             expression is considered to be two separate `>'
+             tokens. So, change the current token to a `>', but don't
+             consume it: it will be consumed later when the outer
+             template argument list (or cast expression) is parsed.
+             Note that this replacement of `>' for `>>' is necessary
+             even if we are parsing tentatively: in the tentative
+             case, after calling
+             cp_parser_enclosed_template_argument_list we will always
+             throw away all of the template arguments and the first
+             closing `>', either because the template argument list
+             was erroneous or because we are replacing those tokens
+             with a CPP_TEMPLATE_ID token.  The second `>' (which will
+             not have been thrown away) is needed either to close an
+             outer template argument list or to complete a new-style
+             cast.  */
+         cp_token *token = cp_lexer_peek_token (parser->lexer);
+          token->type = CPP_GREATER;
+        }
+      else if (!saved_greater_than_is_operator_p)
        {
          /* If we're in a nested template argument list, the '>>' has
            to be a typo for '> >'. We emit the error message, but we
        {
          /* If we're in a nested template argument list, the '>>' has
            to be a typo for '> >'. We emit the error message, but we
@@ -15835,8 +18063,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
                 "within a nested template argument list",
                 &token->location);
 
                 "within a nested template argument list",
                 &token->location);
 
-         /* ??? Proper recovery should terminate two levels of
-            template argument list here.  */
          token->type = CPP_GREATER;
        }
       else
          token->type = CPP_GREATER;
        }
       else
@@ -15845,13 +18071,13 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
            is a typo for '>'. Emit an error message and continue.
            Same deal about the token location, but here we can get it
            right by consuming the '>>' before issuing the diagnostic.  */
            is a typo for '>'. Emit an error message and continue.
            Same deal about the token location, but here we can get it
            right by consuming the '>>' before issuing the diagnostic.  */
-         cp_lexer_consume_token (parser->lexer);
-         error ("spurious %<>>%>, use %<>%> to terminate "
-                "a template argument list");
+         cp_token *token = cp_lexer_consume_token (parser->lexer);
+         error ("%Hspurious %<>>%>, use %<>%> to terminate "
+                "a template argument list", &token->location);
        }
     }
   else
        }
     }
   else
-    cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
+    cp_parser_skip_to_end_of_template_parameter_list (parser);
   /* The `>' token might be a greater-than operator again now.  */
   parser->greater_than_is_operator_p
     = saved_greater_than_is_operator_p;
   /* The `>' token might be a greater-than operator again now.  */
   parser->greater_than_is_operator_p
     = saved_greater_than_is_operator_p;
@@ -15906,8 +18132,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
         function.  */
       function_scope = current_function_decl;
       if (function_scope)
         function.  */
       function_scope = current_function_decl;
       if (function_scope)
-       push_function_context_to (function_scope);
-
+       push_function_context ();
 
       /* Push the body of the function onto the lexer stack.  */
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
       /* Push the body of the function onto the lexer stack.  */
       cp_parser_push_lexer_for_tokens (parser, tokens);
@@ -15930,7 +18155,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
 
       /* Leave the scope of the containing function.  */
       if (function_scope)
 
       /* Leave the scope of the containing function.  */
       if (function_scope)
-       pop_function_context_from (function_scope);
+       pop_function_context ();
       cp_parser_pop_lexer (parser);
     }
 
       cp_parser_pop_lexer (parser);
     }
 
@@ -16051,26 +18276,21 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 static tree
 cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 {
 static tree
 cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 {
-  static const char *format;
   tree expr = NULL_TREE;
   const char *saved_message;
   tree expr = NULL_TREE;
   const char *saved_message;
+  char *tmp;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
-
-  /* Initialize FORMAT the first time we get here.  */
-  if (!format)
-    format = "types may not be defined in '%s' expressions";
+  bool pack_expansion_p = false;
 
   /* Types cannot be defined in a `sizeof' expression.  Save away the
      old message.  */
   saved_message = parser->type_definition_forbidden_message;
   /* And create the new one.  */
 
   /* Types cannot be defined in a `sizeof' expression.  Save away the
      old message.  */
   saved_message = parser->type_definition_forbidden_message;
   /* And create the new one.  */
-  parser->type_definition_forbidden_message
-    = XNEWVEC (const char, strlen (format)
-              + strlen (IDENTIFIER_POINTER (ridpointers[keyword]))
-              + 1 /* `\0' */);
-  sprintf ((char *) parser->type_definition_forbidden_message,
-          format, IDENTIFIER_POINTER (ridpointers[keyword]));
+  tmp = concat ("types may not be defined in %<",
+               IDENTIFIER_POINTER (ridpointers[keyword]),
+               "%> expressions", NULL);
+  parser->type_definition_forbidden_message = tmp;
 
   /* The restrictions on constant-expressions do not apply inside
      sizeof expressions.  */
 
   /* The restrictions on constant-expressions do not apply inside
      sizeof expressions.  */
@@ -16080,6 +18300,19 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
     = parser->non_integral_constant_expression_p;
   parser->integral_constant_expression_p = false;
 
     = parser->non_integral_constant_expression_p;
   parser->integral_constant_expression_p = false;
 
+  /* If it's a `...', then we are computing the length of a parameter
+     pack.  */
+  if (keyword == RID_SIZEOF
+      && cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+    {
+      /* Consume the `...'.  */
+      cp_lexer_consume_token (parser->lexer);
+      maybe_warn_variadic_templates ();
+
+      /* Note that this is an expansion.  */
+      pack_expansion_p = true;
+    }
+
   /* Do not actually evaluate the expression.  */
   ++skip_evaluation;
   /* If it's a `(', then we might be looking at the type-id
   /* Do not actually evaluate the expression.  */
   ++skip_evaluation;
   /* If it's a `(', then we might be looking at the type-id
@@ -16124,11 +18357,16 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   if (!expr)
     expr = cp_parser_unary_expression (parser, /*address_p=*/false,
                                       /*cast_p=*/false);
   if (!expr)
     expr = cp_parser_unary_expression (parser, /*address_p=*/false,
                                       /*cast_p=*/false);
+
+  if (pack_expansion_p)
+    /* Build a pack expansion. */
+    expr = make_pack_expansion (expr);
+
   /* Go back to evaluating expressions.  */
   --skip_evaluation;
 
   /* Free the message we created.  */
   /* Go back to evaluating expressions.  */
   --skip_evaluation;
 
   /* Free the message we created.  */
-  free ((char *) parser->type_definition_forbidden_message);
+  free (tmp);
   /* And restore the old one.  */
   parser->type_definition_forbidden_message = saved_message;
   parser->integral_constant_expression_p
   /* And restore the old one.  */
   parser->type_definition_forbidden_message = saved_message;
   parser->integral_constant_expression_p
@@ -16156,26 +18394,27 @@ cp_parser_declares_only_class_p (cp_parser *parser)
 static void
 cp_parser_set_storage_class (cp_parser *parser,
                             cp_decl_specifier_seq *decl_specs,
 static void
 cp_parser_set_storage_class (cp_parser *parser,
                             cp_decl_specifier_seq *decl_specs,
-                            enum rid keyword)
+                            enum rid keyword,
+                            location_t location)
 {
   cp_storage_class storage_class;
 
   if (parser->in_unbraced_linkage_specification_p)
     {
 {
   cp_storage_class storage_class;
 
   if (parser->in_unbraced_linkage_specification_p)
     {
-      error ("invalid use of %qD in linkage specification",
-            ridpointers[keyword]);
+      error ("%Hinvalid use of %qD in linkage specification",
+            &location, ridpointers[keyword]);
       return;
     }
   else if (decl_specs->storage_class != sc_none)
     {
       return;
     }
   else if (decl_specs->storage_class != sc_none)
     {
-      decl_specs->multiple_storage_classes_p = true;
+      decl_specs->conflicting_specifiers_p = true;
       return;
     }
 
   if ((keyword == RID_EXTERN || keyword == RID_STATIC)
       && decl_specs->specs[(int) ds_thread])
     {
       return;
     }
 
   if ((keyword == RID_EXTERN || keyword == RID_STATIC)
       && decl_specs->specs[(int) ds_thread])
     {
-      error ("%<__thread%> before %qD", ridpointers[keyword]);
+      error ("%H%<__thread%> before %qD", &location, ridpointers[keyword]);
       decl_specs->specs[(int) ds_thread] = 0;
     }
 
       decl_specs->specs[(int) ds_thread] = 0;
     }
 
@@ -16200,6 +18439,13 @@ cp_parser_set_storage_class (cp_parser *parser,
       gcc_unreachable ();
     }
   decl_specs->storage_class = storage_class;
       gcc_unreachable ();
     }
   decl_specs->storage_class = storage_class;
+
+  /* A storage class specifier cannot be applied alongside a typedef 
+     specifier. If there is a typedef specifier present then set 
+     conflicting_specifiers_p which will trigger an error later
+     on in grokdeclarator. */
+  if (decl_specs->specs[(int)ds_typedef])
+    decl_specs->conflicting_specifiers_p = true;
 }
 
 /* Update the DECL_SPECS to reflect the TYPE_SPEC.  If USER_DEFINED_P
 }
 
 /* Update the DECL_SPECS to reflect the TYPE_SPEC.  If USER_DEFINED_P
@@ -16209,17 +18455,21 @@ cp_parser_set_storage_class (cp_parser *parser,
 static void
 cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
                              tree type_spec,
 static void
 cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
                              tree type_spec,
+                             location_t location,
                              bool user_defined_p)
 {
   decl_specs->any_specifiers_p = true;
 
                              bool user_defined_p)
 {
   decl_specs->any_specifiers_p = true;
 
-  /* If the user tries to redeclare bool or wchar_t (with, for
-     example, in "typedef int wchar_t;") we remember that this is what
-     happened.  In system headers, we ignore these declarations so
-     that G++ can work with system headers that are not C++-safe.  */
+  /* If the user tries to redeclare bool, char16_t, char32_t, or wchar_t
+     (with, for example, in "typedef int wchar_t;") we remember that
+     this is what happened.  In system headers, we ignore these
+     declarations so that G++ can work with system headers that are not
+     C++-safe.  */
   if (decl_specs->specs[(int) ds_typedef]
       && !user_defined_p
       && (type_spec == boolean_type_node
   if (decl_specs->specs[(int) ds_typedef]
       && !user_defined_p
       && (type_spec == boolean_type_node
+         || type_spec == char16_type_node
+         || type_spec == char32_type_node
          || type_spec == wchar_type_node)
       && (decl_specs->type
          || decl_specs->specs[(int) ds_long]
          || type_spec == wchar_type_node)
       && (decl_specs->type
          || decl_specs->specs[(int) ds_long]
@@ -16232,6 +18482,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
        {
          decl_specs->type = type_spec;
          decl_specs->user_defined_type_p = false;
        {
          decl_specs->type = type_spec;
          decl_specs->user_defined_type_p = false;
+         decl_specs->type_location = location;
        }
     }
   else if (decl_specs->type)
        }
     }
   else if (decl_specs->type)
@@ -16241,6 +18492,7 @@ cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
       decl_specs->type = type_spec;
       decl_specs->user_defined_type_p = user_defined_p;
       decl_specs->redefined_builtin_type = NULL_TREE;
       decl_specs->type = type_spec;
       decl_specs->user_defined_type_p = user_defined_p;
       decl_specs->redefined_builtin_type = NULL_TREE;
+      decl_specs->type_location = location;
     }
 }
 
     }
 }
 
@@ -16279,54 +18531,78 @@ cp_parser_require (cp_parser* parser,
     }
 }
 
     }
 }
 
-/* Like cp_parser_require, except that tokens will be skipped until
-   the desired token is found.  An error message is still produced if
-   the next token is not as expected.  */
+/* An error message is produced if the next token is not '>'.
+   All further tokens are skipped until the desired token is
+   found or '{', '}', ';' or an unbalanced ')' or ']'.  */
 
 static void
 
 static void
-cp_parser_skip_until_found (cp_parser* parser,
-                           enum cpp_ttype type,
-                           const char* token_desc)
+cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
 {
 {
-  cp_token *token;
+  /* Current level of '< ... >'.  */
+  unsigned level = 0;
+  /* Ignore '<' and '>' nested inside '( ... )' or '[ ... ]'.  */
   unsigned nesting_depth = 0;
 
   unsigned nesting_depth = 0;
 
-  if (cp_parser_require (parser, type, token_desc))
+  /* Are we ready, yet?  If not, issue error message.  */
+  if (cp_parser_require (parser, CPP_GREATER, "%<>%>"))
     return;
 
   /* Skip tokens until the desired token is found.  */
   while (true)
     {
       /* Peek at the next token.  */
     return;
 
   /* Skip tokens until the desired token is found.  */
   while (true)
     {
       /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-
-      /* If we've reached the token we want, consume it and stop.  */
-      if (token->type == type && !nesting_depth)
+      switch (cp_lexer_peek_token (parser->lexer)->type)
        {
        {
-         cp_lexer_consume_token (parser->lexer);
-         return;
-       }
+       case CPP_LESS:
+         if (!nesting_depth)
+           ++level;
+         break;
 
 
-      switch (token->type)
-       {
-       case CPP_EOF:
-       case CPP_PRAGMA_EOL:
-         /* If we've run out of tokens, stop.  */
-         return;
+        case CPP_RSHIFT:
+          if (cxx_dialect == cxx98)
+            /* C++0x views the `>>' operator as two `>' tokens, but
+               C++98 does not. */
+            break;
+          else if (!nesting_depth && level-- == 0)
+           {
+              /* We've hit a `>>' where the first `>' closes the
+                 template argument list, and the second `>' is
+                 spurious.  Just consume the `>>' and stop; we've
+                 already produced at least one error.  */
+             cp_lexer_consume_token (parser->lexer);
+             return;
+           }
+          /* Fall through for C++0x, so we handle the second `>' in
+             the `>>'.  */
+
+       case CPP_GREATER:
+         if (!nesting_depth && level-- == 0)
+           {
+             /* We've reached the token we want, consume it and stop.  */
+             cp_lexer_consume_token (parser->lexer);
+             return;
+           }
+         break;
 
 
-       case CPP_OPEN_BRACE:
        case CPP_OPEN_PAREN:
        case CPP_OPEN_SQUARE:
          ++nesting_depth;
          break;
 
        case CPP_OPEN_PAREN:
        case CPP_OPEN_SQUARE:
          ++nesting_depth;
          break;
 
-       case CPP_CLOSE_BRACE:
        case CPP_CLOSE_PAREN:
        case CPP_CLOSE_SQUARE:
          if (nesting_depth-- == 0)
            return;
          break;
 
        case CPP_CLOSE_PAREN:
        case CPP_CLOSE_SQUARE:
          if (nesting_depth-- == 0)
            return;
          break;
 
+       case CPP_EOF:
+       case CPP_PRAGMA_EOL:
+       case CPP_SEMICOLON:
+       case CPP_OPEN_BRACE:
+       case CPP_CLOSE_BRACE:
+         /* The '>' was probably forgotten, don't look further.  */
+         return;
+
        default:
          break;
        }
        default:
          break;
        }
@@ -16393,8 +18669,8 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser)
   return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
 }
 
   return (token->type == CPP_OPEN_BRACE || token->type == CPP_COLON);
 }
 
-/* Returns TRUE iff the next token is the "," or ">" ending a
-   template-argument.  */
+/* Returns TRUE iff the next token is the "," or ">" (or `>>', in
+   C++0x) ending a template-argument.  */
 
 static bool
 cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
 
 static bool
 cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
@@ -16402,7 +18678,10 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
   cp_token *token;
 
   token = cp_lexer_peek_token (parser->lexer);
   cp_token *token;
 
   token = cp_lexer_peek_token (parser->lexer);
-  return (token->type == CPP_COMMA || token->type == CPP_GREATER);
+  return (token->type == CPP_COMMA 
+          || token->type == CPP_GREATER
+          || token->type == CPP_ELLIPSIS
+         || ((cxx_dialect != cxx98) && token->type == CPP_RSHIFT));
 }
 
 /* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the
 }
 
 /* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the
@@ -16456,7 +18735,7 @@ static void
 cp_parser_check_class_key (enum tag_types class_key, tree type)
 {
   if ((TREE_CODE (type) == UNION_TYPE) != (class_key == union_type))
 cp_parser_check_class_key (enum tag_types class_key, tree type)
 {
   if ((TREE_CODE (type) == UNION_TYPE) != (class_key == union_type))
-    pedwarn ("%qs tag used in naming %q#T",
+    permerror (input_location, "%qs tag used in naming %q#T",
            class_key == union_type ? "union"
             : class_key == record_type ? "struct" : "class",
             type);
            class_key == union_type ? "union"
             : class_key == record_type ? "struct" : "class",
             type);
@@ -16468,16 +18747,16 @@ cp_parser_check_class_key (enum tag_types class_key, tree type)
    [class.mem/1].  */
 
 static void
    [class.mem/1].  */
 
 static void
-cp_parser_check_access_in_redeclaration (tree decl)
+cp_parser_check_access_in_redeclaration (tree decl, location_t location)
 {
 {
-  if (!CLASS_TYPE_P (TREE_TYPE (decl)))
+  if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl)))
     return;
 
   if ((TREE_PRIVATE (decl)
        != (current_access_specifier == access_private_node))
       || (TREE_PROTECTED (decl)
          != (current_access_specifier == access_protected_node)))
     return;
 
   if ((TREE_PRIVATE (decl)
        != (current_access_specifier == access_private_node))
       || (TREE_PROTECTED (decl)
          != (current_access_specifier == access_protected_node)))
-    error ("%qD redeclared with different access", decl);
+    error ("%H%qD redeclared with different access", &location, decl);
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
 }
 
 /* Look for the `template' keyword, as a syntactic disambiguator.
@@ -16494,8 +18773,9 @@ cp_parser_optional_template_keyword (cp_parser *parser)
         template and what is not.  */
       if (!processing_template_decl)
        {
         template and what is not.  */
       if (!processing_template_decl)
        {
-         error ("%<template%> (as a disambiguator) is only allowed "
-                "within templates");
+         cp_token *token = cp_lexer_peek_token (parser->lexer);
+         error ("%H%<template%> (as a disambiguator) is only allowed "
+                "within templates", &token->location);
          /* If this part of the token stream is rescanned, the same
             error message would be generated.  So, we purge the token
             from the stream.  */
          /* If this part of the token stream is rescanned, the same
             error message would be generated.  So, we purge the token
             from the stream.  */
@@ -16519,55 +18799,80 @@ cp_parser_optional_template_keyword (cp_parser *parser)
 static void
 cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
 {
 static void
 cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
 {
-  tree value;
-  tree check;
+  int i;
+  struct tree_check *check_value;
+  deferred_access_check *chk;
+  VEC (deferred_access_check,gc) *checks;
 
   /* Get the stored value.  */
 
   /* Get the stored value.  */
-  value = cp_lexer_consume_token (parser->lexer)->value;
+  check_value = cp_lexer_consume_token (parser->lexer)->u.tree_check_value;
   /* Perform any access checks that were deferred.  */
   /* Perform any access checks that were deferred.  */
-  for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
-    perform_or_defer_access_check (TREE_PURPOSE (check), TREE_VALUE (check));
+  checks = check_value->checks;
+  if (checks)
+    {
+      for (i = 0 ;
+          VEC_iterate (deferred_access_check, checks, i, chk) ;
+          ++i)
+       {
+         perform_or_defer_access_check (chk->binfo,
+                                        chk->decl,
+                                        chk->diag_decl);
+       }
+    }
   /* Set the scope from the stored value.  */
   /* Set the scope from the stored value.  */
-  parser->scope = TREE_VALUE (value);
-  parser->qualifying_scope = TREE_TYPE (value);
+  parser->scope = check_value->value;
+  parser->qualifying_scope = check_value->qualifying_scope;
   parser->object_scope = NULL_TREE;
 }
 
   parser->object_scope = NULL_TREE;
 }
 
-/* Consume tokens up through a non-nested END token.  */
+/* Consume tokens up through a non-nested END token.  Returns TRUE if we
+   encounter the end of a block before what we were looking for.  */
 
 
-static void
+static bool
 cp_parser_cache_group (cp_parser *parser,
                       enum cpp_ttype end,
                       unsigned depth)
 {
   while (true)
     {
 cp_parser_cache_group (cp_parser *parser,
                       enum cpp_ttype end,
                       unsigned depth)
 {
   while (true)
     {
-      cp_token *token;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
 
 
-      /* Abort a parenthesized expression if we encounter a brace.  */
+      /* Abort a parenthesized expression if we encounter a semicolon.  */
       if ((end == CPP_CLOSE_PAREN || depth == 0)
       if ((end == CPP_CLOSE_PAREN || depth == 0)
-         && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
-       return;
+         && token->type == CPP_SEMICOLON)
+       return true;
       /* If we've reached the end of the file, stop.  */
       /* If we've reached the end of the file, stop.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)
+      if (token->type == CPP_EOF
          || (end != CPP_PRAGMA_EOL
          || (end != CPP_PRAGMA_EOL
-             && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL)))
-       return;
-      /* Consume the next token.  */
-      token = cp_lexer_consume_token (parser->lexer);
+             && token->type == CPP_PRAGMA_EOL))
+       return true;
+      if (token->type == CPP_CLOSE_BRACE && depth == 0)
+       /* We've hit the end of an enclosing block, so there's been some
+          kind of syntax error.  */
+       return true;
+
+      /* Consume the token.  */
+      cp_lexer_consume_token (parser->lexer);
       /* See if it starts a new group.  */
       if (token->type == CPP_OPEN_BRACE)
        {
          cp_parser_cache_group (parser, CPP_CLOSE_BRACE, depth + 1);
       /* See if it starts a new group.  */
       if (token->type == CPP_OPEN_BRACE)
        {
          cp_parser_cache_group (parser, CPP_CLOSE_BRACE, depth + 1);
+         /* In theory this should probably check end == '}', but
+            cp_parser_save_member_function_body needs it to exit
+            after either '}' or ')' when called with ')'.  */
          if (depth == 0)
          if (depth == 0)
-           return;
+           return false;
        }
       else if (token->type == CPP_OPEN_PAREN)
        }
       else if (token->type == CPP_OPEN_PAREN)
-       cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1);
+       {
+         cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1);
+         if (depth == 0 && end == CPP_CLOSE_PAREN)
+           return false;
+       }
       else if (token->type == CPP_PRAGMA)
        cp_parser_cache_group (parser, CPP_PRAGMA_EOL, depth + 1);
       else if (token->type == end)
       else if (token->type == CPP_PRAGMA)
        cp_parser_cache_group (parser, CPP_PRAGMA_EOL, depth + 1);
       else if (token->type == end)
-       return;
+       return false;
     }
 }
 
     }
 }
 
@@ -16717,7 +19022,7 @@ cp_parser_objc_expression (cp_parser* parser)
 
     case CPP_OBJC_STRING:
       kwd = cp_lexer_consume_token (parser->lexer);
 
     case CPP_OBJC_STRING:
       kwd = cp_lexer_consume_token (parser->lexer);
-      return objc_build_string_object (kwd->value);
+      return objc_build_string_object (kwd->u.value);
 
     case CPP_KEYWORD:
       switch (kwd->keyword)
 
     case CPP_KEYWORD:
       switch (kwd->keyword)
@@ -16735,7 +19040,8 @@ cp_parser_objc_expression (cp_parser* parser)
          break;
        }
     default:
          break;
        }
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+            &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -16757,7 +19063,7 @@ cp_parser_objc_message_expression (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '['.  */
   receiver = cp_parser_objc_message_receiver (parser);
   messageargs = cp_parser_objc_message_args (parser);
   cp_lexer_consume_token (parser->lexer);  /* Eat '['.  */
   receiver = cp_parser_objc_message_receiver (parser);
   messageargs = cp_parser_objc_message_args (parser);
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
 
   return objc_build_message_expr (build_tree_list (receiver, messageargs));
 }
 
   return objc_build_message_expr (build_tree_list (receiver, messageargs));
 }
@@ -16829,7 +19135,7 @@ cp_parser_objc_message_args (cp_parser* parser)
        return build_tree_list (selector, NULL_TREE);
 
       maybe_unary_selector_p = false;
        return build_tree_list (selector, NULL_TREE);
 
       maybe_unary_selector_p = false;
-      cp_parser_require (parser, CPP_COLON, "`:'");
+      cp_parser_require (parser, CPP_COLON, "%<:%>");
       arg = cp_parser_assignment_expression (parser, false);
 
       sel_args
       arg = cp_parser_assignment_expression (parser, false);
 
       sel_args
@@ -16868,15 +19174,18 @@ static tree
 cp_parser_objc_encode_expression (cp_parser* parser)
 {
   tree type;
 cp_parser_objc_encode_expression (cp_parser* parser)
 {
   tree type;
+  cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  token = cp_lexer_peek_token (parser->lexer);
   type = complete_type (cp_parser_type_id (parser));
   type = complete_type (cp_parser_type_id (parser));
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   if (!type)
     {
 
   if (!type)
     {
-      error ("%<@encode%> must specify a type as an argument");
+      error ("%H%<@encode%> must specify a type as an argument",
+            &token->location);
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
@@ -16891,9 +19200,9 @@ cp_parser_objc_defs_expression (cp_parser *parser)
   tree name;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@defs'.  */
   tree name;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@defs'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   name = cp_parser_identifier (parser);
   name = cp_parser_identifier (parser);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return objc_get_class_ivars (name);
 }
 
   return objc_get_class_ivars (name);
 }
@@ -16911,9 +19220,9 @@ cp_parser_objc_protocol_expression (cp_parser* parser)
   tree proto;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
   tree proto;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   proto = cp_parser_identifier (parser);
   proto = cp_parser_identifier (parser);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return objc_build_protocol_expr (proto);
 }
 
   return objc_build_protocol_expr (proto);
 }
@@ -16941,7 +19250,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
   cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@selector'.  */
   cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@selector'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   token = cp_lexer_peek_token (parser->lexer);
 
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
   token = cp_lexer_peek_token (parser->lexer);
 
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
@@ -16988,7 +19297,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
     }
 
  finish_selector:
     }
 
  finish_selector:
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   return objc_build_selector_expr (sel_seq);
 }
 
   return objc_build_selector_expr (sel_seq);
 }
@@ -17024,7 +19333,7 @@ cp_parser_objc_identifier_list (cp_parser* parser)
    objc-alias-declaration:
      @compatibility_alias identifier identifier ;
 
    objc-alias-declaration:
      @compatibility_alias identifier identifier ;
 
-   This function registers the alias mapping with the Objective-C front-end.
+   This function registers the alias mapping with the Objective-C front end.
    It returns nothing.  */
 
 static void
    It returns nothing.  */
 
 static void
@@ -17045,7 +19354,7 @@ cp_parser_objc_alias_declaration (cp_parser* parser)
      @class objc-identifier-list ;
 
    The function registers the forward declarations with the Objective-C
      @class objc-identifier-list ;
 
    The function registers the forward declarations with the Objective-C
-   front-end.  It returns nothing.  */
+   front end.  It returns nothing.  */
 
 static void
 cp_parser_objc_class_declaration (cp_parser* parser)
 
 static void
 cp_parser_objc_class_declaration (cp_parser* parser)
@@ -17074,7 +19383,7 @@ cp_parser_objc_protocol_refs_opt (cp_parser* parser)
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '<'.  */
       protorefs = cp_parser_objc_identifier_list (parser);
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '<'.  */
       protorefs = cp_parser_objc_identifier_list (parser);
-      cp_parser_require (parser, CPP_GREATER, "`>'");
+      cp_parser_require (parser, CPP_GREATER, "%<>%>");
     }
 
   return protorefs;
     }
 
   return protorefs;
@@ -17125,7 +19434,7 @@ cp_parser_objc_protocol_qualifiers (cp_parser* parser)
   tree quals = NULL_TREE, node;
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   tree quals = NULL_TREE, node;
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
-  node = token->value;
+  node = token->u.value;
 
   while (node && TREE_CODE (node) == IDENTIFIER_NODE
         && (node == ridpointers [(int) RID_IN]
 
   while (node && TREE_CODE (node) == IDENTIFIER_NODE
         && (node == ridpointers [(int) RID_IN]
@@ -17138,7 +19447,7 @@ cp_parser_objc_protocol_qualifiers (cp_parser* parser)
       quals = tree_cons (NULL_TREE, node, quals);
       cp_lexer_consume_token (parser->lexer);
       token = cp_lexer_peek_token (parser->lexer);
       quals = tree_cons (NULL_TREE, node, quals);
       cp_lexer_consume_token (parser->lexer);
       token = cp_lexer_peek_token (parser->lexer);
-      node = token->value;
+      node = token->u.value;
     }
 
   return quals;
     }
 
   return quals;
@@ -17149,7 +19458,7 @@ cp_parser_objc_protocol_qualifiers (cp_parser* parser)
 static tree
 cp_parser_objc_typename (cp_parser* parser)
 {
 static tree
 cp_parser_objc_typename (cp_parser* parser)
 {
-  tree typename = NULL_TREE;
+  tree type_name = NULL_TREE;
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
@@ -17163,11 +19472,11 @@ cp_parser_objc_typename (cp_parser* parser)
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
        cp_type = cp_parser_type_id (parser);
 
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
        cp_type = cp_parser_type_id (parser);
 
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
-      typename = build_tree_list (proto_quals, cp_type);
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      type_name = build_tree_list (proto_quals, cp_type);
     }
 
     }
 
-  return typename;
+  return type_name;
 }
 
 /* Check to see if TYPE refers to an Objective-C selector name.  */
 }
 
 /* Check to see if TYPE refers to an Objective-C selector name.  */
@@ -17191,7 +19500,7 @@ cp_parser_objc_selector (cp_parser* parser)
 
   if (!cp_parser_objc_selector_p (token->type))
     {
 
   if (!cp_parser_objc_selector_p (token->type))
     {
-      error ("invalid Objective-C++ selector name");
+      error ("%Hinvalid Objective-C++ selector name", &token->location);
       return error_mark_node;
     }
 
       return error_mark_node;
     }
 
@@ -17209,7 +19518,7 @@ cp_parser_objc_selector (cp_parser* parser)
     case CPP_OR_EQ: return get_identifier ("or_eq");
     case CPP_XOR: return get_identifier ("xor");
     case CPP_XOR_EQ: return get_identifier ("xor_eq");
     case CPP_OR_EQ: return get_identifier ("or_eq");
     case CPP_XOR: return get_identifier ("xor");
     case CPP_XOR_EQ: return get_identifier ("xor_eq");
-    default: return token->value;
+    default: return token->u.value;
     }
 }
 
     }
 }
 
@@ -17224,7 +19533,7 @@ cp_parser_objc_method_keyword_params (cp_parser* parser)
 
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
     {
 
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
     {
-      tree selector = NULL_TREE, typename, identifier;
+      tree selector = NULL_TREE, type_name, identifier;
 
       if (token->type != CPP_COLON)
        selector = cp_parser_objc_selector (parser);
 
       if (token->type != CPP_COLON)
        selector = cp_parser_objc_selector (parser);
@@ -17235,14 +19544,14 @@ cp_parser_objc_method_keyword_params (cp_parser* parser)
        return selector;
 
       maybe_unary_selector_p = false;
        return selector;
 
       maybe_unary_selector_p = false;
-      cp_parser_require (parser, CPP_COLON, "`:'");
-      typename = cp_parser_objc_typename (parser);
+      cp_parser_require (parser, CPP_COLON, "%<:%>");
+      type_name = cp_parser_objc_typename (parser);
       identifier = cp_parser_identifier (parser);
 
       params
        = chainon (params,
                   objc_build_keyword_decl (selector,
       identifier = cp_parser_identifier (parser);
 
       params
        = chainon (params,
                   objc_build_keyword_decl (selector,
-                                           typename,
+                                           type_name,
                                            identifier));
 
       token = cp_lexer_peek_token (parser->lexer);
                                            identifier));
 
       token = cp_lexer_peek_token (parser->lexer);
@@ -17472,11 +19781,10 @@ cp_parser_objc_class_ivars (cp_parser* parser)
          attributes = chainon (prefix_attributes, attributes);
 
          if (width)
          attributes = chainon (prefix_attributes, attributes);
 
          if (width)
-           {
              /* Create the bitfield declaration.  */
              /* Create the bitfield declaration.  */
-             decl = grokbitfield (declarator, &declspecs, width);
-             cplus_decl_attributes (&decl, attributes, /*flags=*/0);
-           }
+             decl = grokbitfield (declarator, &declspecs,
+                                  width,
+                                  attributes);
          else
            decl = grokfield (declarator, &declspecs,
                              NULL_TREE, /*init_const_expr_p=*/false,
          else
            decl = grokfield (declarator, &declspecs,
                              NULL_TREE, /*init_const_expr_p=*/false,
@@ -17522,7 +19830,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
     {
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
     {
-      error ("identifier expected after %<@protocol%>");
+      tok = cp_lexer_peek_token (parser->lexer);
+      error ("%Hidentifier expected after %<@protocol%>", &tok->location);
       goto finish;
     }
 
       goto finish;
     }
 
@@ -17565,7 +19874,7 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
       *categ = cp_parser_identifier (parser);
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
       *categ = cp_parser_identifier (parser);
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
     }
 }
 
     }
 }
 
@@ -17658,7 +19967,8 @@ cp_parser_objc_declaration (cp_parser* parser)
       cp_parser_objc_end_implementation (parser);
       break;
     default:
       cp_parser_objc_end_implementation (parser);
       break;
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+            &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 }
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 }
@@ -17685,7 +19995,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
   location_t location;
   tree stmt;
 
   location_t location;
   tree stmt;
 
-  cp_parser_require_keyword (parser, RID_AT_TRY, "`@try'");
+  cp_parser_require_keyword (parser, RID_AT_TRY, "%<@try%>");
   location = cp_lexer_peek_token (parser->lexer)->location;
   /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
      node, lest it get absorbed into the surrounding block.  */
   location = cp_lexer_peek_token (parser->lexer)->location;
   /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
      node, lest it get absorbed into the surrounding block.  */
@@ -17699,13 +20009,13 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
       tree parm;
 
       cp_lexer_consume_token (parser->lexer);
       tree parm;
 
       cp_lexer_consume_token (parser->lexer);
-      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
       parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
       parm = grokdeclarator (parmdecl->declarator,
                             &parmdecl->decl_specifiers,
                             PARM, /*initialized=*/0,
                             /*attrlist=*/NULL);
       parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
       parm = grokdeclarator (parmdecl->declarator,
                             &parmdecl->decl_specifiers,
                             PARM, /*initialized=*/0,
                             /*attrlist=*/NULL);
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
       objc_begin_catch_clause (parm);
       cp_parser_compound_statement (parser, NULL, false);
       objc_finish_catch_clause ();
       objc_begin_catch_clause (parm);
       cp_parser_compound_statement (parser, NULL, false);
       objc_finish_catch_clause ();
@@ -17737,12 +20047,12 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
   location_t location;
   tree lock, stmt;
 
   location_t location;
   tree lock, stmt;
 
-  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "`@synchronized'");
+  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "%<@synchronized%>");
 
   location = cp_lexer_peek_token (parser->lexer)->location;
 
   location = cp_lexer_peek_token (parser->lexer)->location;
-  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
   lock = cp_parser_expression (parser, false);
   lock = cp_parser_expression (parser, false);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
      node, lest it get absorbed into the surrounding block.  */
 
   /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
      node, lest it get absorbed into the surrounding block.  */
@@ -17763,7 +20073,7 @@ static tree
 cp_parser_objc_throw_statement (cp_parser *parser) {
   tree expr = NULL_TREE;
 
 cp_parser_objc_throw_statement (cp_parser *parser) {
   tree expr = NULL_TREE;
 
-  cp_parser_require_keyword (parser, RID_AT_THROW, "`@throw'");
+  cp_parser_require_keyword (parser, RID_AT_THROW, "%<@throw%>");
 
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     expr = cp_parser_assignment_expression (parser, false);
 
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     expr = cp_parser_assignment_expression (parser, false);
@@ -17789,7 +20099,8 @@ cp_parser_objc_statement (cp_parser * parser) {
     case RID_AT_THROW:
       return cp_parser_objc_throw_statement (parser);
     default:
     case RID_AT_THROW:
       return cp_parser_objc_throw_statement (parser);
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+            &kwd->location, kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -17798,25 +20109,6 @@ cp_parser_objc_statement (cp_parser * parser) {
 \f
 /* OpenMP 2.5 parsing routines.  */
 
 \f
 /* OpenMP 2.5 parsing routines.  */
 
-/* All OpenMP clauses.  OpenMP 2.5.  */
-typedef enum pragma_omp_clause {
-  PRAGMA_OMP_CLAUSE_NONE = 0,
-
-  PRAGMA_OMP_CLAUSE_COPYIN,
-  PRAGMA_OMP_CLAUSE_COPYPRIVATE,
-  PRAGMA_OMP_CLAUSE_DEFAULT,
-  PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
-  PRAGMA_OMP_CLAUSE_IF,
-  PRAGMA_OMP_CLAUSE_LASTPRIVATE,
-  PRAGMA_OMP_CLAUSE_NOWAIT,
-  PRAGMA_OMP_CLAUSE_NUM_THREADS,
-  PRAGMA_OMP_CLAUSE_ORDERED,
-  PRAGMA_OMP_CLAUSE_PRIVATE,
-  PRAGMA_OMP_CLAUSE_REDUCTION,
-  PRAGMA_OMP_CLAUSE_SCHEDULE,
-  PRAGMA_OMP_CLAUSE_SHARED
-} pragma_omp_clause;
-
 /* Returns name of the next clause.
    If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
    the token is not consumed.  Otherwise appropriate pragma_omp_clause is
 /* Returns name of the next clause.
    If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
    the token is not consumed.  Otherwise appropriate pragma_omp_clause is
@@ -17835,13 +20127,15 @@ cp_parser_omp_clause_name (cp_parser *parser)
     result = PRAGMA_OMP_CLAUSE_PRIVATE;
   else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
     result = PRAGMA_OMP_CLAUSE_PRIVATE;
   else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
-      tree id = cp_lexer_peek_token (parser->lexer)->value;
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
 
       switch (p[0])
        {
        case 'c':
       const char *p = IDENTIFIER_POINTER (id);
 
       switch (p[0])
        {
        case 'c':
-         if (!strcmp ("copyin", p))
+         if (!strcmp ("collapse", p))
+           result = PRAGMA_OMP_CLAUSE_COLLAPSE;
+         else if (!strcmp ("copyin", p))
            result = PRAGMA_OMP_CLAUSE_COPYIN;
          else if (!strcmp ("copyprivate", p))
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
            result = PRAGMA_OMP_CLAUSE_COPYIN;
          else if (!strcmp ("copyprivate", p))
            result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
@@ -17874,6 +20168,10 @@ cp_parser_omp_clause_name (cp_parser *parser)
          else if (!strcmp ("shared", p))
            result = PRAGMA_OMP_CLAUSE_SHARED;
          break;
          else if (!strcmp ("shared", p))
            result = PRAGMA_OMP_CLAUSE_SHARED;
          break;
+       case 'u':
+         if (!strcmp ("untied", p))
+           result = PRAGMA_OMP_CLAUSE_UNTIED;
+         break;
        }
     }
 
        }
     }
 
@@ -17886,14 +20184,15 @@ cp_parser_omp_clause_name (cp_parser *parser)
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
-check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
+                          const char *name, location_t location)
 {
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
 {
   tree c;
 
   for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
     if (OMP_CLAUSE_CODE (c) == code)
       {
-       error ("too many %qs clauses", name);
+       error ("%Htoo many %qs clauses", &location, name);
        break;
       }
 }
        break;
       }
 }
@@ -17916,10 +20215,12 @@ static tree
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
                                tree list)
 {
 cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
                                tree list)
 {
+  cp_token *token;
   while (1)
     {
       tree name, decl;
 
   while (1)
     {
       tree name, decl;
 
+      token = cp_lexer_peek_token (parser->lexer);
       name = cp_parser_id_expression (parser, /*template_p=*/false,
                                      /*check_dependency_p=*/true,
                                      /*template_p=*/NULL,
       name = cp_parser_id_expression (parser, /*template_p=*/false,
                                      /*check_dependency_p=*/true,
                                      /*template_p=*/NULL,
@@ -17928,9 +20229,9 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       if (name == error_mark_node)
        goto skip_comma;
 
       if (name == error_mark_node)
        goto skip_comma;
 
-      decl = cp_parser_lookup_name_simple (parser, name);
+      decl = cp_parser_lookup_name_simple (parser, name, token->location);
       if (decl == error_mark_node)
       if (decl == error_mark_node)
-       cp_parser_name_lookup_error (parser, name, decl, NULL);
+       cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
       else if (kind != 0)
        {
          tree u = build_omp_clause (kind);
       else if (kind != 0)
        {
          tree u = build_omp_clause (kind);
@@ -17947,7 +20248,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       cp_lexer_consume_token (parser->lexer);
     }
 
       cp_lexer_consume_token (parser->lexer);
     }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     {
       int ending;
 
     {
       int ending;
 
@@ -17971,28 +20272,70 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 static tree
 cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
 {
 static tree
 cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
 {
-  if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return cp_parser_omp_var_list_no_open (parser, kind, list);
   return list;
 }
 
     return cp_parser_omp_var_list_no_open (parser, kind, list);
   return list;
 }
 
-/* OpenMP 2.5:
-   default ( shared | none ) */
+/* OpenMP 3.0:
+   collapse ( constant-expression ) */
 
 static tree
 
 static tree
-cp_parser_omp_clause_default (cp_parser *parser, tree list)
+cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location)
 {
 {
-  enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
-  tree c;
+  tree c, num;
+  location_t loc;
+  HOST_WIDE_INT n;
 
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
     return list;
-  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
-    {
-      tree id = cp_lexer_peek_token (parser->lexer)->value;
-      const char *p = IDENTIFIER_POINTER (id);
 
 
-      switch (p[0])
+  num = cp_parser_constant_expression (parser, false, NULL);
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  if (num == error_mark_node)
+    return list;
+  num = fold_non_dependent_expr (num);
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
+      || !host_integerp (num, 0)
+      || (n = tree_low_cst (num, 0)) <= 0
+      || (int) n != n)
+    {
+      error ("%Hcollapse argument needs positive constant integer expression",
+            &loc);
+      return list;
+    }
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
+  c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
+  OMP_CLAUSE_CHAIN (c) = list;
+  OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
+
+  return c;
+}
+
+/* OpenMP 2.5:
+   default ( shared | none ) */
+
+static tree
+cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
+{
+  enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+  tree c;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+    return list;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      switch (p[0])
        {
        case 'n':
          if (strcmp ("none", p) != 0)
        {
        case 'n':
          if (strcmp ("none", p) != 0)
@@ -18018,7 +20361,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
       cp_parser_error (parser, "expected %<none%> or %<shared%>");
     }
 
       cp_parser_error (parser, "expected %<none%> or %<shared%>");
     }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
@@ -18026,7 +20369,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
   if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
     return list;
 
   if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
     return list;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
   c = build_omp_clause (OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
   c = build_omp_clause (OMP_CLAUSE_DEFAULT);
   OMP_CLAUSE_CHAIN (c) = list;
   OMP_CLAUSE_DEFAULT_KIND (c) = kind;
@@ -18038,22 +20381,22 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
    if ( expression ) */
 
 static tree
    if ( expression ) */
 
 static tree
-cp_parser_omp_clause_if (cp_parser *parser, tree list)
+cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
 {
   tree t, c;
 
 {
   tree t, c;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
   t = cp_parser_condition (parser);
 
   if (t == error_mark_node
     return list;
 
   t = cp_parser_condition (parser);
 
   if (t == error_mark_node
-      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
 
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
 
   c = build_omp_clause (OMP_CLAUSE_IF);
   OMP_CLAUSE_IF_EXPR (c) = t;
 
   c = build_omp_clause (OMP_CLAUSE_IF);
   OMP_CLAUSE_IF_EXPR (c) = t;
@@ -18066,11 +20409,12 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list)
    nowait */
 
 static tree
    nowait */
 
 static tree
-cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED,
+                            tree list, location_t location)
 {
   tree c;
 
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait", location);
 
   c = build_omp_clause (OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
 
   c = build_omp_clause (OMP_CLAUSE_NOWAIT);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -18081,22 +20425,24 @@ cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
    num_threads ( expression ) */
 
 static tree
    num_threads ( expression ) */
 
 static tree
-cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
+cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
+                                 location_t location)
 {
   tree t, c;
 
 {
   tree t, c;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
   t = cp_parser_expression (parser, false);
 
   if (t == error_mark_node
     return list;
 
   t = cp_parser_expression (parser, false);
 
   if (t == error_mark_node
-      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
 
     cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                           /*or_comma=*/false,
                                           /*consume_paren=*/true);
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
+                            "num_threads", location);
 
   c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
   OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
 
   c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
   OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
@@ -18109,11 +20455,13 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
    ordered */
 
 static tree
    ordered */
 
 static tree
-cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
+                             tree list, location_t location)
 {
   tree c;
 
 {
   tree c;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED,
+                            "ordered", location);
 
   c = build_omp_clause (OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
 
   c = build_omp_clause (OMP_CLAUSE_ORDERED);
   OMP_CLAUSE_CHAIN (c) = list;
@@ -18132,7 +20480,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
   enum tree_code code;
   tree nlist, c;
 
   enum tree_code code;
   tree nlist, c;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
   switch (cp_lexer_peek_token (parser->lexer)->type)
     return list;
 
   switch (cp_lexer_peek_token (parser->lexer)->type)
@@ -18162,7 +20510,8 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
       code = TRUTH_ORIF_EXPR;
       break;
     default:
       code = TRUTH_ORIF_EXPR;
       break;
     default:
-      cp_parser_error (parser, "`+', `*', `-', `&', `^', `|', `&&', or `||'");
+      cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, "
+                              "%<|%>, %<&&%>, or %<||%>");
     resync_fail:
       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                             /*or_comma=*/false,
     resync_fail:
       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                             /*or_comma=*/false,
@@ -18171,7 +20520,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
     }
   cp_lexer_consume_token (parser->lexer);
 
     }
   cp_lexer_consume_token (parser->lexer);
 
-  if (!cp_parser_require (parser, CPP_COLON, "`:'"))
+  if (!cp_parser_require (parser, CPP_COLON, "%<:%>"))
     goto resync_fail;
 
   nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list);
     goto resync_fail;
 
   nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list);
@@ -18186,21 +20535,21 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
    schedule ( schedule-kind , expression )
 
    schedule-kind:
    schedule ( schedule-kind , expression )
 
    schedule-kind:
-     static | dynamic | guided | runtime  */
+     static | dynamic | guided | runtime | auto  */
 
 static tree
 
 static tree
-cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
+cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location)
 {
   tree c, t;
 
 {
   tree c, t;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
   c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
     return list;
 
   c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
-      tree id = cp_lexer_peek_token (parser->lexer)->value;
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
 
       switch (p[0])
       const char *p = IDENTIFIER_POINTER (id);
 
       switch (p[0])
@@ -18229,31 +20578,38 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
     }
   else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
     OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
     }
   else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
     OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
+  else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
+    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
   else
     goto invalid_kind;
   cp_lexer_consume_token (parser->lexer);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
     {
   else
     goto invalid_kind;
   cp_lexer_consume_token (parser->lexer);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
     {
+      cp_token *token;
       cp_lexer_consume_token (parser->lexer);
 
       cp_lexer_consume_token (parser->lexer);
 
+      token = cp_lexer_peek_token (parser->lexer);
       t = cp_parser_assignment_expression (parser, false);
 
       if (t == error_mark_node)
        goto resync_fail;
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
       t = cp_parser_assignment_expression (parser, false);
 
       if (t == error_mark_node)
        goto resync_fail;
       else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
-       error ("schedule %<runtime%> does not take "
-              "a %<chunk_size%> parameter");
+       error ("%Hschedule %<runtime%> does not take "
+              "a %<chunk_size%> parameter", &token->location);
+      else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
+       error ("%Hschedule %<auto%> does not take "
+              "a %<chunk_size%> parameter", &token->location);
       else
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
       else
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
-      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
        goto resync_fail;
     }
        goto resync_fail;
     }
-  else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`,' or `)'"))
+  else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<,%> or %<)%>"))
     goto resync_fail;
 
     goto resync_fail;
 
-  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
   OMP_CLAUSE_CHAIN (c) = list;
   return c;
 
@@ -18266,6 +20622,22 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
   return list;
 }
 
   return list;
 }
 
+/* OpenMP 3.0:
+   untied */
+
+static tree
+cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED,
+                            tree list, location_t location)
+{
+  tree c;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
+
+  c = build_omp_clause (OMP_CLAUSE_UNTIED);
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
 /* Parse all OpenMP clauses.  The set clauses allowed by the directive
    is a bitmask in MASK.  Return the list of clauses found; the result
    of clause default goes in *pdefault.  */
 /* Parse all OpenMP clauses.  The set clauses allowed by the directive
    is a bitmask in MASK.  Return the list of clauses found; the result
    of clause default goes in *pdefault.  */
@@ -18275,15 +20647,29 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
                           const char *where, cp_token *pragma_tok)
 {
   tree clauses = NULL;
                           const char *where, cp_token *pragma_tok)
 {
   tree clauses = NULL;
+  bool first = true;
+  cp_token *token = NULL;
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
 
   while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
     {
-      pragma_omp_clause c_kind = cp_parser_omp_clause_name (parser);
+      pragma_omp_clause c_kind;
       const char *c_name;
       tree prev = clauses;
 
       const char *c_name;
       tree prev = clauses;
 
+      if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+
+      token = cp_lexer_peek_token (parser->lexer);
+      c_kind = cp_parser_omp_clause_name (parser);
+      first = false;
+
       switch (c_kind)
        {
       switch (c_kind)
        {
+       case PRAGMA_OMP_CLAUSE_COLLAPSE:
+         clauses = cp_parser_omp_clause_collapse (parser, clauses,
+                                                  token->location);
+         c_name = "collapse";
+         break;
        case PRAGMA_OMP_CLAUSE_COPYIN:
          clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYIN, clauses);
          c_name = "copyin";
        case PRAGMA_OMP_CLAUSE_COPYIN:
          clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYIN, clauses);
          c_name = "copyin";
@@ -18294,7 +20680,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
          c_name = "copyprivate";
          break;
        case PRAGMA_OMP_CLAUSE_DEFAULT:
          c_name = "copyprivate";
          break;
        case PRAGMA_OMP_CLAUSE_DEFAULT:
-         clauses = cp_parser_omp_clause_default (parser, clauses);
+         clauses = cp_parser_omp_clause_default (parser, clauses,
+                                                 token->location);
          c_name = "default";
          break;
        case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
          c_name = "default";
          break;
        case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
@@ -18303,7 +20690,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
          c_name = "firstprivate";
          break;
        case PRAGMA_OMP_CLAUSE_IF:
          c_name = "firstprivate";
          break;
        case PRAGMA_OMP_CLAUSE_IF:
-         clauses = cp_parser_omp_clause_if (parser, clauses);
+         clauses = cp_parser_omp_clause_if (parser, clauses, token->location);
          c_name = "if";
          break;
        case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
          c_name = "if";
          break;
        case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
@@ -18312,15 +20699,17 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
          c_name = "lastprivate";
          break;
        case PRAGMA_OMP_CLAUSE_NOWAIT:
          c_name = "lastprivate";
          break;
        case PRAGMA_OMP_CLAUSE_NOWAIT:
-         clauses = cp_parser_omp_clause_nowait (parser, clauses);
+         clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
          c_name = "nowait";
          break;
        case PRAGMA_OMP_CLAUSE_NUM_THREADS:
          c_name = "nowait";
          break;
        case PRAGMA_OMP_CLAUSE_NUM_THREADS:
-         clauses = cp_parser_omp_clause_num_threads (parser, clauses);
+         clauses = cp_parser_omp_clause_num_threads (parser, clauses,
+                                                     token->location);
          c_name = "num_threads";
          break;
        case PRAGMA_OMP_CLAUSE_ORDERED:
          c_name = "num_threads";
          break;
        case PRAGMA_OMP_CLAUSE_ORDERED:
-         clauses = cp_parser_omp_clause_ordered (parser, clauses);
+         clauses = cp_parser_omp_clause_ordered (parser, clauses,
+                                                 token->location);
          c_name = "ordered";
          break;
        case PRAGMA_OMP_CLAUSE_PRIVATE:
          c_name = "ordered";
          break;
        case PRAGMA_OMP_CLAUSE_PRIVATE:
@@ -18333,7 +20722,8 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
          c_name = "reduction";
          break;
        case PRAGMA_OMP_CLAUSE_SCHEDULE:
          c_name = "reduction";
          break;
        case PRAGMA_OMP_CLAUSE_SCHEDULE:
-         clauses = cp_parser_omp_clause_schedule (parser, clauses);
+         clauses = cp_parser_omp_clause_schedule (parser, clauses,
+                                                  token->location);
          c_name = "schedule";
          break;
        case PRAGMA_OMP_CLAUSE_SHARED:
          c_name = "schedule";
          break;
        case PRAGMA_OMP_CLAUSE_SHARED:
@@ -18341,6 +20731,11 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
                                            clauses);
          c_name = "shared";
          break;
                                            clauses);
          c_name = "shared";
          break;
+       case PRAGMA_OMP_CLAUSE_UNTIED:
+         clauses = cp_parser_omp_clause_untied (parser, clauses,
+                                                token->location);
+         c_name = "nowait";
+         break;
        default:
          cp_parser_error (parser, "expected %<#pragma omp%> clause");
          goto saw_error;
        default:
          cp_parser_error (parser, "expected %<#pragma omp%> clause");
          goto saw_error;
@@ -18351,7 +20746,7 @@ cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
          /* Remove the invalid clause(s) from the list to avoid
             confusing the rest of the compiler.  */
          clauses = prev;
          /* Remove the invalid clause(s) from the list to avoid
             confusing the rest of the compiler.  */
          clauses = prev;
-         error ("%qs is not valid for %qs", c_name, where);
+         error ("%H%qs is not valid for %qs", &token->location, c_name, where);
        }
     }
  saw_error:
        }
     }
  saw_error:
@@ -18398,7 +20793,7 @@ cp_parser_omp_structured_block (cp_parser *parser)
   tree stmt = begin_omp_structured_block ();
   unsigned int save = cp_parser_begin_omp_structured_block (parser);
 
   tree stmt = begin_omp_structured_block ();
   unsigned int save = cp_parser_begin_omp_structured_block (parser);
 
-  cp_parser_statement (parser, NULL_TREE, false);
+  cp_parser_statement (parser, NULL_TREE, false, NULL);
 
   cp_parser_end_omp_structured_block (parser, save);
   return finish_omp_structured_block (stmt);
 
   cp_parser_end_omp_structured_block (parser, save);
   return finish_omp_structured_block (stmt);
@@ -18521,7 +20916,7 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
       name = cp_parser_identifier (parser);
 
       if (name == error_mark_node
       name = cp_parser_identifier (parser);
 
       if (name == error_mark_node
-         || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+         || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
        cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                               /*or_comma=*/false,
                                               /*consume_paren=*/true);
        cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
                                               /*or_comma=*/false,
                                               /*consume_paren=*/true);
@@ -18550,91 +20945,490 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
   finish_omp_flush ();
 }
 
   finish_omp_flush ();
 }
 
-/* Parse the restricted form of the for statment allowed by OpenMP.  */
+/* Helper function, to parse omp for increment expression.  */
 
 static tree
 
 static tree
-cp_parser_omp_for_loop (cp_parser *parser)
+cp_parser_omp_for_cond (cp_parser *parser, tree decl)
 {
 {
-  tree init, cond, incr, body, decl, pre_body;
-  location_t loc;
+  tree lhs = cp_parser_cast_expression (parser, false, false), rhs;
+  enum tree_code op;
+  cp_token *token;
 
 
-  if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+  if (lhs != decl)
     {
     {
-      cp_parser_error (parser, "for statement expected");
-      return NULL;
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
     }
     }
-  loc = cp_lexer_consume_token (parser->lexer)->location;
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
-    return NULL;
 
 
-  init = decl = NULL;
-  pre_body = push_stmt_list ();
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+  token = cp_lexer_peek_token (parser->lexer);
+  op = binops_by_token [token->type].tree_type;
+  switch (op)
     {
     {
-      cp_decl_specifier_seq type_specifiers;
+    case LT_EXPR:
+    case LE_EXPR:
+    case GT_EXPR:
+    case GE_EXPR:
+      break;
+    default:
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+
+  cp_lexer_consume_token (parser->lexer);
+  rhs = cp_parser_binary_expression (parser, false,
+                                    PREC_RELATIONAL_EXPRESSION);
+  if (rhs == error_mark_node
+      || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
 
 
-      /* First, try to parse as an initialized declaration.  See
-        cp_parser_condition, from whence the bulk of this is copied.  */
+  return build2 (op, boolean_type_node, lhs, rhs);
+}
 
 
-      cp_parser_parse_tentatively (parser);
-      cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
-                                   &type_specifiers);
-      if (!cp_parser_error_occurred (parser))
+/* Helper function, to parse omp for increment expression.  */
+
+static tree
+cp_parser_omp_for_incr (cp_parser *parser, tree decl)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  enum tree_code op;
+  tree lhs, rhs;
+  cp_id_kind idk;
+  bool decl_first;
+
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    {
+      op = (token->type == CPP_PLUS_PLUS
+           ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
+      cp_lexer_consume_token (parser->lexer);
+      lhs = cp_parser_cast_expression (parser, false, false);
+      if (lhs != decl)
+       return error_mark_node;
+      return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+    }
+
+  lhs = cp_parser_primary_expression (parser, false, false, false, &idk);
+  if (lhs != decl)
+    return error_mark_node;
+
+  token = cp_lexer_peek_token (parser->lexer);
+  if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+    {
+      op = (token->type == CPP_PLUS_PLUS
+           ? POSTINCREMENT_EXPR : POSTDECREMENT_EXPR);
+      cp_lexer_consume_token (parser->lexer);
+      return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+    }
+
+  op = cp_parser_assignment_operator_opt (parser);
+  if (op == ERROR_MARK)
+    return error_mark_node;
+
+  if (op != NOP_EXPR)
+    {
+      rhs = cp_parser_assignment_expression (parser, false);
+      rhs = build2 (op, TREE_TYPE (decl), decl, rhs);
+      return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+    }
+
+  lhs = cp_parser_binary_expression (parser, false,
+                                    PREC_ADDITIVE_EXPRESSION);
+  token = cp_lexer_peek_token (parser->lexer);
+  decl_first = lhs == decl;
+  if (decl_first)
+    lhs = NULL_TREE;
+  if (token->type != CPP_PLUS
+      && token->type != CPP_MINUS)
+    return error_mark_node;
+
+  do
+    {
+      op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
+      cp_lexer_consume_token (parser->lexer);
+      rhs = cp_parser_binary_expression (parser, false,
+                                        PREC_ADDITIVE_EXPRESSION);
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
        {
        {
-         tree asm_specification, attributes;
-         cp_declarator *declarator;
-
-         declarator = cp_parser_declarator (parser,
-                                            CP_PARSER_DECLARATOR_NAMED,
-                                            /*ctor_dtor_or_conv_p=*/NULL,
-                                            /*parenthesized_p=*/NULL,
-                                            /*member_p=*/false);
-         attributes = cp_parser_attributes_opt (parser);
-         asm_specification = cp_parser_asm_specification_opt (parser);
+         if (lhs == NULL_TREE)
+           {
+             if (op == PLUS_EXPR)
+               lhs = rhs;
+             else
+               lhs = build_x_unary_op (NEGATE_EXPR, rhs, tf_warning_or_error);
+           }
+         else
+           lhs = build_x_binary_op (op, lhs, ERROR_MARK, rhs, ERROR_MARK,
+                                    NULL, tf_warning_or_error);
+       }
+    }
+  while (token->type == CPP_PLUS || token->type == CPP_MINUS);
 
 
-         cp_parser_require (parser, CPP_EQ, "`='");
+  if (!decl_first)
+    {
+      if (rhs != decl || op == MINUS_EXPR)
+       return error_mark_node;
+      rhs = build2 (op, TREE_TYPE (decl), lhs, decl);
+    }
+  else
+    rhs = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, lhs);
+
+  return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+}
+
+/* Parse the restricted form of the for statement allowed by OpenMP.  */
+
+static tree
+cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
+{
+  tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
+  tree for_block = NULL_TREE, real_decl, initv, condv, incrv, declv;
+  tree this_pre_body, cl;
+  location_t loc_first;
+  bool collapse_err = false;
+  int i, collapse = 1, nbraces = 0;
+
+  for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
+    if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
+      collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
+
+  gcc_assert (collapse >= 1);
+
+  declv = make_tree_vec (collapse);
+  initv = make_tree_vec (collapse);
+  condv = make_tree_vec (collapse);
+  incrv = make_tree_vec (collapse);
+
+  loc_first = cp_lexer_peek_token (parser->lexer)->location;
+
+  for (i = 0; i < collapse; i++)
+    {
+      int bracecount = 0;
+      bool add_private_clause = false;
+      location_t loc;
+
+      if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+       {
+         cp_parser_error (parser, "for statement expected");
+         return NULL;
+       }
+      loc = cp_lexer_consume_token (parser->lexer)->location;
+
+      if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+       return NULL;
+
+      init = decl = real_decl = NULL;
+      this_pre_body = push_stmt_list ();
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       {
+         /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
+
+            init-expr:
+                      var = lb
+                      integer-type var = lb
+                      random-access-iterator-type var = lb
+                      pointer-type var = lb
+         */
+         cp_decl_specifier_seq type_specifiers;
+
+         /* First, try to parse as an initialized declaration.  See
+            cp_parser_condition, from whence the bulk of this is copied.  */
+
+         cp_parser_parse_tentatively (parser);
+         cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+                                       &type_specifiers);
          if (cp_parser_parse_definitely (parser))
            {
          if (cp_parser_parse_definitely (parser))
            {
-             tree pushed_scope;
+             /* If parsing a type specifier seq succeeded, then this
+                MUST be a initialized declaration.  */
+             tree asm_specification, attributes;
+             cp_declarator *declarator;
+
+             declarator = cp_parser_declarator (parser,
+                                                CP_PARSER_DECLARATOR_NAMED,
+                                                /*ctor_dtor_or_conv_p=*/NULL,
+                                                /*parenthesized_p=*/NULL,
+                                                /*member_p=*/false);
+             attributes = cp_parser_attributes_opt (parser);
+             asm_specification = cp_parser_asm_specification_opt (parser);
 
 
-             decl = start_decl (declarator, &type_specifiers,
-                                /*initialized_p=*/false, attributes,
-                                /*prefix_attributes=*/NULL_TREE,
-                                &pushed_scope);
+             if (declarator == cp_error_declarator) 
+               cp_parser_skip_to_end_of_statement (parser);
 
 
-             init = cp_parser_assignment_expression (parser, false);
+             else 
+               {
+                 tree pushed_scope, auto_node;
 
 
-             cp_finish_decl (decl, NULL_TREE, /*init_const_expr_p=*/false,
-                             asm_specification, LOOKUP_ONLYCONVERTING);
+                 decl = start_decl (declarator, &type_specifiers,
+                                    SD_INITIALIZED, attributes,
+                                    /*prefix_attributes=*/NULL_TREE,
+                                    &pushed_scope);
 
 
-             if (pushed_scope)
-               pop_scope (pushed_scope);
+                 auto_node = type_uses_auto (TREE_TYPE (decl));
+                 if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+                   {
+                     if (cp_lexer_next_token_is (parser->lexer, 
+                                                 CPP_OPEN_PAREN))
+                       error ("parenthesized initialization is not allowed in "
+                              "OpenMP %<for%> loop");
+                     else
+                       /* Trigger an error.  */
+                       cp_parser_require (parser, CPP_EQ, "%<=%>");
+
+                     init = error_mark_node;
+                     cp_parser_skip_to_end_of_statement (parser);
+                   }
+                 else if (CLASS_TYPE_P (TREE_TYPE (decl))
+                          || type_dependent_expression_p (decl)
+                          || auto_node)
+                   {
+                     bool is_direct_init, is_non_constant_init;
+
+                     init = cp_parser_initializer (parser,
+                                                   &is_direct_init,
+                                                   &is_non_constant_init);
+
+                     if (auto_node && describable_type (init))
+                       {
+                         TREE_TYPE (decl)
+                           = do_auto_deduction (TREE_TYPE (decl), init,
+                                                auto_node);
+
+                         if (!CLASS_TYPE_P (TREE_TYPE (decl))
+                             && !type_dependent_expression_p (decl))
+                           goto non_class;
+                       }
+                     
+                     cp_finish_decl (decl, init, !is_non_constant_init,
+                                     asm_specification,
+                                     LOOKUP_ONLYCONVERTING);
+                     if (CLASS_TYPE_P (TREE_TYPE (decl)))
+                       {
+                         for_block
+                           = tree_cons (NULL, this_pre_body, for_block);
+                         init = NULL_TREE;
+                       }
+                     else
+                       init = pop_stmt_list (this_pre_body);
+                     this_pre_body = NULL_TREE;
+                   }
+                 else
+                   {
+                     /* Consume '='.  */
+                     cp_lexer_consume_token (parser->lexer);
+                     init = cp_parser_assignment_expression (parser, false);
+
+                   non_class:
+                     if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+                       init = error_mark_node;
+                     else
+                       cp_finish_decl (decl, NULL_TREE,
+                                       /*init_const_expr_p=*/false,
+                                       asm_specification,
+                                       LOOKUP_ONLYCONVERTING);
+                   }
+
+                 if (pushed_scope)
+                   pop_scope (pushed_scope);
+               }
+           }
+         else 
+           {
+             cp_id_kind idk;
+             /* If parsing a type specifier sequence failed, then
+                this MUST be a simple expression.  */
+             cp_parser_parse_tentatively (parser);
+             decl = cp_parser_primary_expression (parser, false, false,
+                                                  false, &idk);
+             if (!cp_parser_error_occurred (parser)
+                 && decl
+                 && DECL_P (decl)
+                 && CLASS_TYPE_P (TREE_TYPE (decl)))
+               {
+                 tree rhs;
+
+                 cp_parser_parse_definitely (parser);
+                 cp_parser_require (parser, CPP_EQ, "%<=%>");
+                 rhs = cp_parser_assignment_expression (parser, false);
+                 finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR,
+                                                        rhs,
+                                                        tf_warning_or_error));
+                 add_private_clause = true;
+               }
+             else
+               {
+                 decl = NULL;
+                 cp_parser_abort_tentative_parse (parser);
+                 init = cp_parser_expression (parser, false);
+                 if (init)
+                   {
+                     if (TREE_CODE (init) == MODIFY_EXPR
+                         || TREE_CODE (init) == MODOP_EXPR)
+                       real_decl = TREE_OPERAND (init, 0);
+                   }
+               }
            }
        }
            }
        }
-      else
-       cp_parser_abort_tentative_parse (parser);
+      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+      if (this_pre_body)
+       {
+         this_pre_body = pop_stmt_list (this_pre_body);
+         if (pre_body)
+           {
+             tree t = pre_body;
+             pre_body = push_stmt_list ();
+             add_stmt (t);
+             add_stmt (this_pre_body);
+             pre_body = pop_stmt_list (pre_body);
+           }
+         else
+           pre_body = this_pre_body;
+       }
 
 
-      /* If parsing as an initialized declaration failed, try again as
-        a simple expression.  */
-      if (decl == NULL)
-       init = cp_parser_expression (parser, false);
-    }
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
-  pre_body = pop_stmt_list (pre_body);
+      if (decl)
+       real_decl = decl;
+      if (par_clauses != NULL && real_decl != NULL_TREE)
+       {
+         tree *c;
+         for (c = par_clauses; *c ; )
+           if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE
+               && OMP_CLAUSE_DECL (*c) == real_decl)
+             {
+               error ("%Hiteration variable %qD should not be firstprivate",
+                      &loc, real_decl);
+               *c = OMP_CLAUSE_CHAIN (*c);
+             }
+           else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE
+                    && OMP_CLAUSE_DECL (*c) == real_decl)
+             {
+               /* Add lastprivate (decl) clause to OMP_FOR_CLAUSES,
+                  change it to shared (decl) in OMP_PARALLEL_CLAUSES.  */
+               tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+               OMP_CLAUSE_DECL (l) = real_decl;
+               OMP_CLAUSE_CHAIN (l) = clauses;
+               CP_OMP_CLAUSE_INFO (l) = CP_OMP_CLAUSE_INFO (*c);
+               clauses = l;
+               OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
+               CP_OMP_CLAUSE_INFO (*c) = NULL;
+               add_private_clause = false;
+             }
+           else
+             {
+               if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE
+                   && OMP_CLAUSE_DECL (*c) == real_decl)
+                 add_private_clause = false;
+               c = &OMP_CLAUSE_CHAIN (*c);
+             }
+       }
 
 
-  cond = NULL;
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    cond = cp_parser_condition (parser);
-  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+      if (add_private_clause)
+       {
+         tree c;
+         for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+           {
+             if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+                  || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+                 && OMP_CLAUSE_DECL (c) == decl)
+               break;
+             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+                      && OMP_CLAUSE_DECL (c) == decl)
+               error ("%Hiteration variable %qD should not be firstprivate",
+                      &loc, decl);
+             else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+                      && OMP_CLAUSE_DECL (c) == decl)
+               error ("%Hiteration variable %qD should not be reduction",
+                      &loc, decl);
+           }
+         if (c == NULL)
+           {
+             c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+             OMP_CLAUSE_DECL (c) = decl;
+             c = finish_omp_clauses (c);
+             if (c)
+               {
+                 OMP_CLAUSE_CHAIN (c) = clauses;
+                 clauses = c;
+               }
+           }
+       }
 
 
-  incr = NULL;
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
-    incr = cp_parser_expression (parser, false);
+      cond = NULL;
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       {
+         /* If decl is an iterator, preserve LHS and RHS of the relational
+            expr until finish_omp_for.  */
+         if (decl
+             && (type_dependent_expression_p (decl)
+                 || CLASS_TYPE_P (TREE_TYPE (decl))))
+           cond = cp_parser_omp_for_cond (parser, decl);
+         else
+           cond = cp_parser_condition (parser);
+       }
+      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
 
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
-    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
-                                          /*or_comma=*/false,
-                                          /*consume_paren=*/true);
+      incr = NULL;
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+       {
+         /* If decl is an iterator, preserve the operator on decl
+            until finish_omp_for.  */
+         if (decl
+             && (type_dependent_expression_p (decl)
+                 || CLASS_TYPE_P (TREE_TYPE (decl))))
+           incr = cp_parser_omp_for_incr (parser, decl);
+         else
+           incr = cp_parser_expression (parser, false);
+       }
+
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                              /*or_comma=*/false,
+                                              /*consume_paren=*/true);
+
+      TREE_VEC_ELT (declv, i) = decl;
+      TREE_VEC_ELT (initv, i) = init;
+      TREE_VEC_ELT (condv, i) = cond;
+      TREE_VEC_ELT (incrv, i) = incr;
+
+      if (i == collapse - 1)
+       break;
+
+      /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
+        in between the collapsed for loops to be still considered perfectly
+        nested.  Hopefully the final version clarifies this.
+        For now handle (multiple) {'s and empty statements.  */
+      cp_parser_parse_tentatively (parser);
+      do
+       {
+         if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+           break;
+         else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+           {
+             cp_lexer_consume_token (parser->lexer);
+             bracecount++;
+           }
+         else if (bracecount
+                  && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+           cp_lexer_consume_token (parser->lexer);
+         else
+           {
+             loc = cp_lexer_peek_token (parser->lexer)->location;
+             error ("%Hnot enough collapsed for loops", &loc);
+             collapse_err = true;
+             cp_parser_abort_tentative_parse (parser);
+             declv = NULL_TREE;
+             break;
+           }
+       }
+      while (1);
+
+      if (declv)
+       {
+         cp_parser_parse_definitely (parser);
+         nbraces += bracecount;
+       }
+    }
 
   /* Note that we saved the original contents of this flag when we entered
      the structured block, and so we don't need to re-save it here.  */
 
   /* Note that we saved the original contents of this flag when we entered
      the structured block, and so we don't need to re-save it here.  */
@@ -18643,10 +21437,44 @@ cp_parser_omp_for_loop (cp_parser *parser)
   /* Note that the grammar doesn't call for a structured block here,
      though the loop as a whole is a structured block.  */
   body = push_stmt_list ();
   /* Note that the grammar doesn't call for a structured block here,
      though the loop as a whole is a structured block.  */
   body = push_stmt_list ();
-  cp_parser_statement (parser, NULL_TREE, false);
+  cp_parser_statement (parser, NULL_TREE, false, NULL);
   body = pop_stmt_list (body);
 
   body = pop_stmt_list (body);
 
-  return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
+  if (declv == NULL_TREE)
+    ret = NULL_TREE;
+  else
+    ret = finish_omp_for (loc_first, declv, initv, condv, incrv, body,
+                         pre_body, clauses);
+
+  while (nbraces)
+    {
+      if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         nbraces--;
+       }
+      else if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+       cp_lexer_consume_token (parser->lexer);
+      else
+       {
+         if (!collapse_err)
+           {
+             location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+             error ("%Hcollapsed loops not perfectly nested", &loc);
+           }
+         collapse_err = true;
+         cp_parser_statement_seq_opt (parser, NULL);
+         cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+       }
+    }
+
+  while (for_block)
+    {
+      add_stmt (pop_stmt_list (TREE_VALUE (for_block)));
+      for_block = TREE_CHAIN (for_block);
+    }
+
+  return ret;
 }
 
 /* OpenMP 2.5:
 }
 
 /* OpenMP 2.5:
@@ -18660,7 +21488,8 @@ cp_parser_omp_for_loop (cp_parser *parser)
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
        | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
        | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
        | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
        | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
-       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT)              \
+       | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE))
 
 static tree
 cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
 
 static tree
 cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
@@ -18674,9 +21503,7 @@ cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
   sb = begin_omp_structured_block ();
   save = cp_parser_begin_omp_structured_block (parser);
 
   sb = begin_omp_structured_block ();
   save = cp_parser_begin_omp_structured_block (parser);
 
-  ret = cp_parser_omp_for_loop (parser);
-  if (ret)
-    OMP_FOR_CLAUSES (ret) = clauses;
+  ret = cp_parser_omp_for_loop (parser, clauses, NULL);
 
   cp_parser_end_omp_structured_block (parser, save);
   add_stmt (finish_omp_structured_block (sb));
 
   cp_parser_end_omp_structured_block (parser, save);
   add_stmt (finish_omp_structured_block (sb));
@@ -18722,7 +21549,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
   bool error_suppress = false;
   cp_token *tok;
 
   bool error_suppress = false;
   cp_token *tok;
 
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
     return NULL_TREE;
 
   stmt = push_stmt_list ();
     return NULL_TREE;
 
   stmt = push_stmt_list ();
@@ -18736,7 +21563,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
 
       while (1)
        {
 
       while (1)
        {
-         cp_parser_statement (parser, NULL_TREE, false);
+         cp_parser_statement (parser, NULL_TREE, false, NULL);
 
          tok = cp_lexer_peek_token (parser->lexer);
          if (tok->pragma_kind == PRAGMA_OMP_SECTION)
 
          tok = cp_lexer_peek_token (parser->lexer);
          if (tok->pragma_kind == PRAGMA_OMP_SECTION)
@@ -18777,7 +21604,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
 
   substmt = pop_stmt_list (stmt);
 
 
   substmt = pop_stmt_list (stmt);
 
@@ -18849,7 +21676,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
     }
   else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
     }
   else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
-      tree id = cp_lexer_peek_token (parser->lexer)->value;
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
       const char *p = IDENTIFIER_POINTER (id);
       if (strcmp (p, "sections") == 0)
        {
       const char *p = IDENTIFIER_POINTER (id);
       if (strcmp (p, "sections") == 0)
        {
@@ -18868,15 +21695,13 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
   switch (p_kind)
     {
     case PRAGMA_OMP_PARALLEL:
   switch (p_kind)
     {
     case PRAGMA_OMP_PARALLEL:
-      cp_parser_already_scoped_statement (parser);
+      cp_parser_statement (parser, NULL_TREE, false, NULL);
       par_clause = clauses;
       break;
 
     case PRAGMA_OMP_PARALLEL_FOR:
       c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
       par_clause = clauses;
       break;
 
     case PRAGMA_OMP_PARALLEL_FOR:
       c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
-      stmt = cp_parser_omp_for_loop (parser);
-      if (stmt)
-       OMP_FOR_CLAUSES (stmt) = ws_clause;
+      cp_parser_omp_for_loop (parser, ws_clause, &par_clause);
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
       break;
 
     case PRAGMA_OMP_PARALLEL_SECTIONS:
@@ -18921,6 +21746,43 @@ cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
   return add_stmt (stmt);
 }
 
   return add_stmt (stmt);
 }
 
+/* OpenMP 3.0:
+   # pragma omp task task-clause[optseq] new-line
+     structured-block  */
+
+#define OMP_TASK_CLAUSE_MASK                           \
+       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
+       | (1u << PRAGMA_OMP_CLAUSE_UNTIED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
+       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+
+static tree
+cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree clauses, block;
+  unsigned int save;
+
+  clauses = cp_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
+                                      "#pragma omp task", pragma_tok);
+  block = begin_omp_task ();
+  save = cp_parser_begin_omp_structured_block (parser);
+  cp_parser_statement (parser, NULL_TREE, false, NULL);
+  cp_parser_end_omp_structured_block (parser, save);
+  return finish_omp_task (clauses, block);
+}
+
+/* OpenMP 3.0:
+   # pragma omp taskwait new-line  */
+
+static void
+cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
+{
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+  finish_omp_taskwait ();
+}
+
 /* OpenMP 2.5:
    # pragma omp threadprivate (variable-list) */
 
 /* OpenMP 2.5:
    # pragma omp threadprivate (variable-list) */
 
@@ -18932,9 +21794,6 @@ cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok)
   vars = cp_parser_omp_var_list (parser, 0, NULL);
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
   vars = cp_parser_omp_var_list (parser, 0, NULL);
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
-  if (!targetm.have_tls)
-    sorry ("threadprivate variables not supported in this target");
-
   finish_omp_threadprivate (vars);
 }
 
   finish_omp_threadprivate (vars);
 }
 
@@ -18971,6 +21830,9 @@ cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
     case PRAGMA_OMP_SINGLE:
       stmt = cp_parser_omp_single (parser, pragma_tok);
       break;
     case PRAGMA_OMP_SINGLE:
       stmt = cp_parser_omp_single (parser, pragma_tok);
       break;
+    case PRAGMA_OMP_TASK:
+      stmt = cp_parser_omp_task (parser, pragma_tok);
+      break;
     default:
       gcc_unreachable ();
     }
     default:
       gcc_unreachable ();
     }
@@ -19005,14 +21867,15 @@ cp_parser_initial_pragma (cp_token *first_token)
   cp_lexer_get_preprocessor_token (NULL, first_token);
   if (first_token->type == CPP_STRING)
     {
   cp_lexer_get_preprocessor_token (NULL, first_token);
   if (first_token->type == CPP_STRING)
     {
-      name = first_token->value;
+      name = first_token->u.value;
 
       cp_lexer_get_preprocessor_token (NULL, first_token);
       if (first_token->type != CPP_PRAGMA_EOL)
 
       cp_lexer_get_preprocessor_token (NULL, first_token);
       if (first_token->type != CPP_PRAGMA_EOL)
-       error ("junk at end of %<#pragma GCC pch_preprocess%>");
+       error ("%Hjunk at end of %<#pragma GCC pch_preprocess%>",
+               &first_token->location);
     }
   else
     }
   else
-    error ("expected string literal");
+    error ("%Hexpected string literal", &first_token->location);
 
   /* Skip to the end of the pragma.  */
   while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
 
   /* Skip to the end of the pragma.  */
   while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
@@ -19045,7 +21908,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
   switch (id)
     {
     case PRAGMA_GCC_PCH_PREPROCESS:
   switch (id)
     {
     case PRAGMA_GCC_PCH_PREPROCESS:
-      error ("%<#pragma GCC pch_preprocess%> must be first");
+      error ("%H%<#pragma GCC pch_preprocess%> must be first",
+             &pragma_tok->location);
       break;
 
     case PRAGMA_OMP_BARRIER:
       break;
 
     case PRAGMA_OMP_BARRIER:
@@ -19055,8 +21919,8 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
          cp_parser_omp_barrier (parser, pragma_tok);
          return false;
        case pragma_stmt:
          cp_parser_omp_barrier (parser, pragma_tok);
          return false;
        case pragma_stmt:
-         error ("%<#pragma omp barrier%> may only be "
-                "used in compound statements");
+         error ("%H%<#pragma omp barrier%> may only be "
+                "used in compound statements", &pragma_tok->location);
          break;
        default:
          goto bad_stmt;
          break;
        default:
          goto bad_stmt;
@@ -19070,8 +21934,24 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
          cp_parser_omp_flush (parser, pragma_tok);
          return false;
        case pragma_stmt:
          cp_parser_omp_flush (parser, pragma_tok);
          return false;
        case pragma_stmt:
-         error ("%<#pragma omp flush%> may only be "
-                "used in compound statements");
+         error ("%H%<#pragma omp flush%> may only be "
+                "used in compound statements", &pragma_tok->location);
+         break;
+       default:
+         goto bad_stmt;
+       }
+      break;
+
+    case PRAGMA_OMP_TASKWAIT:
+      switch (context)
+       {
+       case pragma_compound:
+         cp_parser_omp_taskwait (parser, pragma_tok);
+         return false;
+       case pragma_stmt:
+         error ("%H%<#pragma omp taskwait%> may only be "
+                "used in compound statements",
+                &pragma_tok->location);
          break;
        default:
          goto bad_stmt;
          break;
        default:
          goto bad_stmt;
@@ -19090,14 +21970,15 @@ cp_parser_pragma (cp_parser *parser, enum pragma_context context)
     case PRAGMA_OMP_PARALLEL:
     case PRAGMA_OMP_SECTIONS:
     case PRAGMA_OMP_SINGLE:
     case PRAGMA_OMP_PARALLEL:
     case PRAGMA_OMP_SECTIONS:
     case PRAGMA_OMP_SINGLE:
+    case PRAGMA_OMP_TASK:
       if (context == pragma_external)
        goto bad_stmt;
       cp_parser_omp_construct (parser, pragma_tok);
       return true;
 
     case PRAGMA_OMP_SECTION:
       if (context == pragma_external)
        goto bad_stmt;
       cp_parser_omp_construct (parser, pragma_tok);
       return true;
 
     case PRAGMA_OMP_SECTION:
-      error ("%<#pragma omp section%> may only be used in "
-            "%<#pragma omp sections%> construct");
+      error ("%H%<#pragma omp section%> may only be used in "
+            "%<#pragma omp sections%> construct", &pragma_tok->location);
       break;
 
     default:
       break;
 
     default:
@@ -19125,7 +22006,7 @@ pragma_lex (tree *value)
   tok = cp_lexer_peek_token (the_parser->lexer);
 
   ret = tok->type;
   tok = cp_lexer_peek_token (the_parser->lexer);
 
   ret = tok->type;
-  *value = tok->value;
+  *value = tok->u.value;
 
   if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
     ret = CPP_EOF;
 
   if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
     ret = CPP_EOF;
@@ -19166,8 +22047,4 @@ c_parse_file (void)
   the_parser = NULL;
 }
 
   the_parser = NULL;
 }
 
-/* This variable must be provided by every front end.  */
-
-int yydebug;
-
 #include "gt-cp-parser.h"
 #include "gt-cp-parser.h"