OSDN Git Service

* doc/invoke.texi (Warning Options): Document that -Wempty-body
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 82ee887..4599aca 100644 (file)
 /* 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 (())
@@ -69,7 +83,12 @@ typedef struct cp_token GTY (())
   /* The input file stack index at which this token was found.  */
   unsigned input_file_stack_index : INPUT_FILE_STACK_BITS;
   /* 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;
@@ -81,7 +100,7 @@ DEF_VEC_ALLOC_P (cp_token_position,heap);
 
 static const cp_token eof_token =
 {
-  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, 0, NULL_TREE,
+  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, 0, { NULL },
 #if USE_MAPPED_LOCATION
   0
 #else
@@ -394,7 +413,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
 
    /* 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);
   token->input_file_stack_index = input_file_stack_tick;
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
@@ -410,20 +429,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)
     {
-      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.  */
-         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'.  */
-         token->value = ridpointers[token->keyword];
+         token->u.value = ridpointers[token->keyword];
        }
       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_RID_CODE (token->u.value) = RID_MAX;
+            }
+
          token->ambiguous_p = false;
          token->keyword = RID_MAX;
        }
@@ -432,7 +466,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
   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;
@@ -442,14 +476,14 @@ 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;
-       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.  */
-      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;
     }
 }
 
@@ -641,7 +675,7 @@ cp_lexer_purge_token (cp_lexer *lexer)
   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
@@ -675,7 +709,7 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
     {
       tok->type = CPP_PURGED;
       tok->location = UNKNOWN_LOCATION;
-      tok->value = NULL_TREE;
+      tok->u.value = NULL_TREE;
       tok->keyword = RID_MAX;
     }
 }
@@ -753,16 +787,16 @@ 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.  */
-      if (TREE_CODE (token->value) != IDENTIFIER_NODE)
+      if (TREE_CODE (token->u.value) != IDENTIFIER_NODE)
        break;
       /* else fall through */
     case CPP_NAME:
-      fputs (IDENTIFIER_POINTER (token->value), stream);
+      fputs (IDENTIFIER_POINTER (token->u.value), stream);
       break;
 
     case CPP_STRING:
     case CPP_WSTRING:
-      fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->value));
+      fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
       break;
 
     default:
@@ -857,6 +891,7 @@ make_declarator (cp_declarator_kind kind)
   declarator->kind = kind;
   declarator->attributes = NULL_TREE;
   declarator->declarator = NULL;
+  declarator->parameter_pack_p = false;
 
   return declarator;
 }
@@ -894,7 +929,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;
-
+  
   return declarator;
 }
 
@@ -911,6 +946,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;
+  if (target)
+    {
+      declarator->parameter_pack_p = target->parameter_pack_p;
+      target->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
 
   return declarator;
 }
@@ -926,6 +968,13 @@ make_reference_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;
+  if (target)
+    {
+      declarator->parameter_pack_p = target->parameter_pack_p;
+      target->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
 
   return declarator;
 }
@@ -944,6 +993,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;
 
+  if (pointee)
+    {
+      declarator->parameter_pack_p = pointee->parameter_pack_p;
+      pointee->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
+
   return declarator;
 }
 
@@ -965,6 +1022,13 @@ make_call_declarator (cp_declarator *target,
   declarator->u.function.parameters = parms;
   declarator->u.function.qualifiers = cv_qualifiers;
   declarator->u.function.exception_specification = exception_specification;
+  if (target)
+    {
+      declarator->parameter_pack_p = target->parameter_pack_p;
+      target->parameter_pack_p = false;
+    }
+  else
+    declarator->parameter_pack_p = false;
 
   return declarator;
 }
@@ -980,10 +1044,47 @@ make_array_declarator (cp_declarator *element, tree 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;
 }
 
+/* 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_error:
+       case cdk_array:
+       case cdk_ptrmem:
+         found = true;
+         break;
+         
+       default:
+         declarator = declarator->declarator;
+         break;
+       }
+    }
+
+  return !found;
+}
+
 cp_parameter_declarator *no_parameters;
 
 /* Create a parameter declarator with the indicated DECL_SPECIFIERS,
@@ -1158,8 +1259,15 @@ typedef enum cp_parser_status_kind
 
 typedef struct cp_parser_expression_stack_entry
 {
+  /* Left hand side of the binary operation we are currently
+     parsing.  */
   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;
+  /* Precedence of the binary operation we are parsing.  */
   int prec;
 } cp_parser_expression_stack_entry;
 
@@ -1322,7 +1430,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
-     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
@@ -1369,6 +1479,7 @@ typedef struct cp_parser GTY(())
 #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.
@@ -1476,7 +1587,7 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
 static tree cp_parser_parenthesized_expression_list
-  (cp_parser *, 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
@@ -1517,7 +1628,7 @@ static tree cp_parser_builtin_offsetof
 /* Statements [gram.stmt.stmt]  */
 
 static void cp_parser_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
@@ -1527,7 +1638,7 @@ static tree cp_parser_compound_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
@@ -1540,7 +1651,7 @@ static void cp_parser_declaration_statement
   (cp_parser *);
 
 static tree cp_parser_implicitly_scoped_statement
-  (cp_parser *);
+  (cp_parser *, bool *);
 static void cp_parser_already_scoped_statement
   (cp_parser *);
 
@@ -1599,7 +1710,7 @@ static void cp_parser_static_assert
 /* 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
@@ -1689,9 +1800,9 @@ static void cp_parser_template_declaration
 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
-  (cp_parser *);
+  (cp_parser *, bool *);
 static tree cp_parser_template_id
   (cp_parser *, bool, bool, bool);
 static tree cp_parser_template_name
@@ -1799,9 +1910,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
-  (tree);
+  (VEC (deferred_access_check,gc)*);
 static tree cp_parser_single_declaration
-  (cp_parser *, tree, bool, bool *);
+  (cp_parser *, VEC (deferred_access_check,gc)*, bool, bool *);
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
@@ -1816,6 +1927,8 @@ static void cp_parser_late_parsing_default_args
   (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
@@ -1955,7 +2068,7 @@ cp_parser_error (cp_parser* parser, const char* message)
                        CPP_KEYWORD, keywords are treated like
                        identifiers.  */
                     (token->type == CPP_KEYWORD ? CPP_NAME : token->type),
-                    token->value);
+                    token->u.value);
     }
 }
 
@@ -1975,26 +2088,26 @@ cp_parser_name_lookup_error (cp_parser* parser,
   if (decl == error_mark_node)
     {
       if (parser->scope && parser->scope != global_namespace)
-       error ("%<%D::%D%> has not been declared",
+       error ("%<%E::%E%> has not been declared",
               parser->scope, name);
       else if (parser->scope == global_namespace)
-       error ("%<::%D%> has not been declared", name);
+       error ("%<::%E%> has not been declared", name);
       else if (parser->object_scope
               && !CLASS_TYPE_P (parser->object_scope))
-       error ("request for member %qD in non-class type %qT",
+       error ("request for member %qE in non-class type %qT",
               name, parser->object_scope);
       else if (parser->object_scope)
-       error ("%<%T::%D%> has not been declared",
+       error ("%<%T::%E%> has not been declared",
               parser->object_scope, name);
       else
-       error ("%qD has not been declared", name);
+       error ("%qE has not been declared", name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error ("%<%D::%D%> %s", parser->scope, name, desired);
+    error ("%<%E::%E%> %s", parser->scope, name, desired);
   else if (parser->scope == global_namespace)
-    error ("%<::%D%> %s", name, desired);
+    error ("%<::%E%> %s", name, desired);
   else
-    error ("%qD %s", name, desired);
+    error ("%qE %s", name, desired);
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -2264,12 +2377,13 @@ 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)
-         && dependent_type_p (parser->scope)))
+         && dependent_type_p (parser->scope))
+      || TREE_CODE (id) == TYPE_DECL)
     {
       cp_parser_abort_tentative_parse (parser);
       return false;
     }
-  if (!cp_parser_parse_definitely (parser) || TREE_CODE (id) == TYPE_DECL)
+  if (!cp_parser_parse_definitely (parser))
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
@@ -2696,7 +2810,7 @@ cp_parser_identifier (cp_parser* parser)
   /* 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
@@ -2737,8 +2851,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
     {
       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;
       if (tok->type == CPP_WSTRING)
        wide = true;
@@ -2754,8 +2868,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
        {
          cp_lexer_consume_token (parser->lexer);
          count++;
-         str.text = (unsigned char *)TREE_STRING_POINTER (tok->value);
-         str.len = TREE_STRING_LENGTH (tok->value);
+         str.text = (unsigned char *)TREE_STRING_POINTER (tok->u.value);
+         str.len = TREE_STRING_LENGTH (tok->u.value);
          if (tok->type == CPP_WSTRING)
            wide = true;
 
@@ -2877,6 +2991,25 @@ cp_parser_translation_unit (cp_parser* parser)
      __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:
@@ -2922,7 +3055,7 @@ cp_parser_primary_expression (cp_parser *parser,
       /* 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)
        {
@@ -2947,6 +3080,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
+                     || parser->greater_than_is_operator_p)
+                 /* C++0x only: A ">>" treated like two ">" tokens,
+                     in a template-argument-list.  */
+                 && (next_token->type != CPP_RSHIFT
+                      || !flag_cpp0x
                      || parser->greater_than_is_operator_p))
                cast_p = false;
            }
@@ -2959,7 +3097,7 @@ cp_parser_primary_expression (cp_parser *parser,
            cp_parser_non_integral_constant_expression
              (parser, "floating-point literal");
        }
-      return token->value;
+      return token->u.value;
 
     case CPP_STRING:
     case CPP_WSTRING:
@@ -2998,13 +3136,20 @@ cp_parser_primary_expression (cp_parser *parser,
 
               at class or namespace scope.  */
            if (!parser->in_function_body)
-             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);
+             {
+               error ("statement-expressions are allowed only inside functions");
+               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
          {
@@ -3075,7 +3220,7 @@ cp_parser_primary_expression (cp_parser *parser,
             Consume the token.  */
          token = cp_lexer_consume_token (parser->lexer);
          /* Look up the name.  */
-         return finish_fname (token->value);
+         return finish_fname (token->u.value);
 
        case RID_VA_ARG:
          {
@@ -3107,7 +3252,26 @@ cp_parser_primary_expression (cp_parser *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:
@@ -3224,9 +3388,11 @@ cp_parser_primary_expression (cp_parser *parser,
 
       /* 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 ()
-         && (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");
@@ -3512,7 +3678,7 @@ cp_parser_unqualified_id (cp_parser* parser,
            && 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);
@@ -3813,7 +3979,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                      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,
@@ -3824,13 +3990,13 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                      else if (ambiguous_decls)
                        {
                          error ("reference to %qD is ambiguous",
-                                token->value);
+                                token->u.value);
                          print_candidates (ambiguous_decls);
                          decl = error_mark_node;
                        }
                      else
                        cp_parser_name_lookup_error
-                         (parser, token->value, decl,
+                         (parser, token->u.value, decl,
                           "is not a class or namespace");
                    }
                  parser->scope = error_mark_node;
@@ -3889,17 +4055,17 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
   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.  */
-      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.  */
@@ -4255,6 +4421,21 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                   allowed in standard C++.  */
                if (pedantic)
                  pedwarn ("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
                  = finish_compound_literal (type, initializer_list);
@@ -4317,7 +4498,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,
-                    /*cast_p=*/false,
+                    /*cast_p=*/false, /*allow_expansion_p=*/true,
                     /*non_constant_p=*/NULL));
            if (is_builtin_constant_p)
              {
@@ -4393,8 +4574,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                        || 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;
                  }
 
@@ -4714,6 +4894,9 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 
    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.
@@ -4728,6 +4911,7 @@ static tree
 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;
@@ -4757,7 +4941,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
            /* Consume the identifier.  */
            token = cp_lexer_consume_token (parser->lexer);
            /* Save the identifier.  */
-           identifier = token->value;
+           identifier = token->u.value;
          }
        else
          {
@@ -4777,6 +4961,18 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
            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
@@ -5226,7 +5422,7 @@ cp_parser_new_placement (cp_parser* parser)
 
   /* 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;
@@ -5431,7 +5627,7 @@ cp_parser_new_initializer (cp_parser* parser)
   tree 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));
   if (!expression_list)
     expression_list = void_zero_node;
@@ -5673,10 +5869,12 @@ 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.  */
 
-#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                          \
+   || (flag_cpp0x && token->type == CPP_RSHIFT))       \
+  && !parser->greater_than_is_operator_p)              \
+ ? PREC_NOT_OPERATOR                                   \
+ : binops_by_token[token->type].prec)
 
 static tree
 cp_parser_binary_expression (cp_parser* parser, bool cast_p)
@@ -5685,18 +5883,30 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
   cp_parser_expression_stack_entry *sp = &stack[0];
   tree lhs, rhs;
   cp_token *token;
-  enum tree_code tree_type;
+  enum tree_code tree_type, lhs_type, rhs_type;
   enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
   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);
 
+      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);
 
       /* Popping an entry off the stack means we completed a subexpression:
@@ -5723,6 +5933,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);
+      rhs_type = ERROR_MARK;
 
       /* Get another operator token.  Look up its precedence to avoid
         building a useless (immediately popped) stack entry for common
@@ -5738,8 +5949,10 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
          sp->prec = prec;
          sp->tree_type = tree_type;
          sp->lhs = lhs;
+         sp->lhs_type = lhs_type;
          sp++;
          lhs = rhs;
+         lhs_type = rhs_type;
          prec = new_prec;
          new_prec = lookahead_prec;
          goto get_rhs;
@@ -5756,11 +5969,15 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
          prec = sp->prec;
          tree_type = sp->tree_type;
          rhs = lhs;
+         rhs_type = lhs_type;
          lhs = sp->lhs;
+         lhs_type = sp->lhs_type;
        }
 
       overloaded_p = false;
-      lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p);
+      lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
+                              &overloaded_p);
+      lhs_type = tree_type;
 
       /* If the binary operator required the use of an overloaded operator,
         then this expression cannot be an integral constant-expression.
@@ -6162,6 +6379,112 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   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);
+
+  /* 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);
+
+      /* 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 expr, which may mean either processing the
+     static assert now or saving it for template instantiation.  */
+  return finish_trait_expr (kind, type1, type2);
+}
+
 /* Statements [gram.stmt.stmt]  */
 
 /* Parse a statement.
@@ -6177,17 +6500,23 @@ cp_parser_builtin_offsetof (cp_parser *parser)
      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,
-                    bool in_compound)
+                    bool in_compound, bool *if_p)
 {
   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.  */
@@ -6212,7 +6541,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
 
        case RID_IF:
        case RID_SWITCH:
-         statement = cp_parser_selection_statement (parser);
+         statement = cp_parser_selection_statement (parser, if_p);
          break;
 
        case RID_WHILE:
@@ -6241,6 +6570,11 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
          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.  */
@@ -6475,9 +6809,22 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
          || 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 ("%<else%> without a previous %<if%>");
+           }
+       }
 
       /* Parse the statement.  */
-      cp_parser_statement (parser, in_statement_expr, true);
+      cp_parser_statement (parser, in_statement_expr, true, NULL);
     }
 }
 
@@ -6488,14 +6835,22 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
      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
-cp_parser_selection_statement (cp_parser* parser)
+cp_parser_selection_statement (cp_parser* parser, bool *if_p)
 {
   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");
 
@@ -6531,11 +6886,18 @@ cp_parser_selection_statement (cp_parser* parser)
 
        if (keyword == RID_IF)
          {
+           bool nested_if;
+           unsigned char in_statement;
+
            /* 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;
+           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.  */
@@ -6546,8 +6908,28 @@ cp_parser_selection_statement (cp_parser* parser)
                cp_lexer_consume_token (parser->lexer);
                begin_else_clause (statement);
                /* Parse the else-clause.  */
-               cp_parser_implicitly_scoped_statement (parser);
+               cp_parser_implicitly_scoped_statement (parser, NULL);
                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.  */
@@ -6566,7 +6948,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;
-           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;
 
@@ -6683,6 +7065,51 @@ cp_parser_condition (cp_parser* parser)
   return cp_parser_expression (parser, /*cast_p=*/false);
 }
 
+/* We check for a ) immediately followed by ; with no whitespacing
+   between.  This is used to issue a warning for:
+
+     while (...);
+
+   and:
+
+     for (...);
+
+   as the semicolon is probably extraneous.
+
+   On parse errors, the next token might not be a ), so do nothing in
+   that case. */
+
+static void
+check_empty_body (cp_parser* parser, const char* type)
+{
+  cp_token *token;
+  cp_token *close_paren;
+  expanded_location close_loc;
+  expanded_location semi_loc;
+  
+  close_paren = cp_lexer_peek_token (parser->lexer);
+  if (close_paren->type != CPP_CLOSE_PAREN)
+    return;
+
+  close_loc = expand_location (close_paren->location);
+  token = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+  if (token->type != CPP_SEMICOLON
+      || (token->flags & PREV_WHITE))
+    return;
+
+  semi_loc =  expand_location (token->location);
+  if (close_loc.line == semi_loc.line
+#ifdef USE_MAPPED_LOCATION
+      && close_loc.column+1 == semi_loc.column
+#endif
+      )
+    warning (OPT_Wempty_body,
+            "suggest a space before %<;%> or explicit braces around empty "
+            "body in %<%s%> statement",
+            type);
+}
+
 /* Parse an iteration-statement.
 
    iteration-statement:
@@ -6725,6 +7152,7 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        finish_while_stmt_cond (condition, statement);
+       check_empty_body (parser, "while");
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
        /* Parse the dependent statement.  */
@@ -6744,7 +7172,7 @@ cp_parser_iteration_statement (cp_parser* parser)
        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.  */
@@ -6786,6 +7214,7 @@ cp_parser_iteration_statement (cp_parser* parser)
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
          expression = cp_parser_expression (parser, /*cast_p=*/false);
        finish_for_expr (expression, statement);
+       check_empty_body (parser, "for");
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
@@ -6861,6 +7290,7 @@ cp_parser_jump_statement (cp_parser* parser)
   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");
@@ -6872,14 +7302,15 @@ cp_parser_jump_statement (cp_parser* parser)
   switch (keyword)
     {
     case RID_BREAK:
-      switch (parser->in_statement)
+      in_statement = parser->in_statement & ~IN_IF_STMT;      
+      switch (in_statement)
        {
        case 0:
          error ("break statement not within loop or switch");
          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:
@@ -6893,7 +7324,7 @@ cp_parser_jump_statement (cp_parser* parser)
       break;
 
     case RID_CONTINUE:
-      switch (parser->in_statement & ~IN_SWITCH_STMT)
+      switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
        {
        case 0:
          error ("continue statement not within a loop");
@@ -6986,13 +7417,21 @@ cp_parser_declaration_statement (cp_parser* parser)
    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
-cp_parser_implicitly_scoped_statement (cp_parser* parser)
+cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p)
 {
   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))
     {
@@ -7008,7 +7447,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
       /* 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);
     }
@@ -7027,7 +7466,7 @@ 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))
-    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
@@ -7392,7 +7831,7 @@ cp_parser_simple_declaration (cp_parser* parser,
 
       /* 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,
@@ -7730,7 +8169,7 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
     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;
@@ -7778,7 +8217,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
     }
 
   /* Consume the token.  */
-  return cp_lexer_consume_token (parser->lexer)->value;
+  return cp_lexer_consume_token (parser->lexer)->u.value;
 }
 
 /* Parse a linkage-specification.
@@ -8067,8 +8506,8 @@ cp_parser_ctor_initializer_opt (cp_parser* parser)
 /* 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)
@@ -8087,6 +8526,26 @@ cp_parser_mem_initializer_list (cp_parser* 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 ("cannot expand initializer for member %<%D%>", 
+                     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)
        {
@@ -8142,6 +8601,7 @@ cp_parser_mem_initializer (cp_parser* parser)
   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;
@@ -8545,14 +9005,18 @@ cp_parser_template_parameter_list (cp_parser* parser)
       tree parameter;
       cp_token *token;
       bool is_non_type;
+      bool is_parameter_pack;
 
       /* 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,
-                                               is_non_type);
+                                               is_non_type,
+                                                is_parameter_pack);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
@@ -8581,10 +9045,12 @@ 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
-   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
-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;
@@ -8592,11 +9058,13 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
 
   /* 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)
-    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:
 
@@ -8614,6 +9082,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);
+      /* 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);
@@ -8622,7 +9094,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)
-       return cp_parser_type_parameter (parser);
+       return cp_parser_type_parameter (parser, is_parameter_pack);
     }
 
   /* Otherwise, it is a non-type parameter.
@@ -8637,12 +9109,40 @@ 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);
+
+  /* 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;
+    }
+
   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);
 }
 
@@ -8657,12 +9157,20 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
      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
-   the declaration of the parameter.  */
+   the declaration of the parameter.
+
+   Sets *IS_PARAMETER_PACK if this is a template parameter pack. */
 
 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;
@@ -8681,6 +9189,17 @@ cp_parser_type_parameter (cp_parser* parser)
        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))
@@ -8699,6 +9218,18 @@ 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);
+
+            /* Template parameter packs cannot have default
+               arguments. */
+            if (*is_parameter_pack)
+              {
+                if (identifier)
+                  error ("template parameter pack %qD cannot have a default argument", 
+                         identifier);
+                else
+                  error ("template parameter packs cannot have default arguments");
+                default_argument = NULL_TREE;
+              }
            pop_deferring_access_checks ();
          }
        else
@@ -8724,6 +9255,16 @@ cp_parser_type_parameter (cp_parser* parser)
        cp_parser_require (parser, CPP_GREATER, "`>'");
        /* Look for the `class' keyword.  */
        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 `,',
@@ -8778,6 +9319,18 @@ cp_parser_type_parameter (cp_parser* parser)
            /* 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 ("template parameter pack %qD cannot have a default argument", 
+                         identifier);
+                else
+                  error ("template parameter packs cannot have default arguments");
+                default_argument = NULL_TREE;
+              }
            pop_deferring_access_checks ();
          }
        else
@@ -8817,11 +9370,13 @@ cp_parser_template_id (cp_parser *parser,
                       bool check_dependency_p,
                       bool is_declaration)
 {
+  int i;
   tree template;
   tree arguments;
   tree template_id;
   cp_token_position start_of_id = 0;
-  tree access_check = NULL_TREE;
+  deferred_access_check *chk;
+  VEC (deferred_access_check,gc) *access_check;
   cp_token *next_token, *next_token_2;
   bool is_identifier;
 
@@ -8830,18 +9385,25 @@ cp_parser_template_id (cp_parser *parser,
   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.  */
-      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.  */
-      for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
-       perform_or_defer_access_check (TREE_PURPOSE (check),
-                                      TREE_VALUE (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 TREE_VALUE (value);
+      return check_value->value;
     }
 
   /* Avoid performing name lookup if there is no possibility of
@@ -8957,10 +9519,6 @@ cp_parser_template_id (cp_parser *parser,
       template_id = lookup_template_function (template, 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
@@ -8973,7 +9531,11 @@ cp_parser_template_id (cp_parser *parser,
 
       /* 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.  */
@@ -9185,8 +9747,8 @@ cp_parser_template_name (cp_parser* parser,
 /* 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.  */
 
@@ -9222,6 +9784,19 @@ cp_parser_template_argument_list (cp_parser* 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;
@@ -9638,7 +10213,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
   else
     /* Parse the dependent declaration.  */
     cp_parser_single_declaration (parser,
-                                 /*checks=*/NULL_TREE,
+                                 /*checks=*/NULL,
                                  /*member_p=*/false,
                                  /*friend_p=*/NULL);
   /* We're done with the specialization.  */
@@ -9805,7 +10380,7 @@ cp_parser_type_specifier (cp_parser* parser,
          ++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
@@ -9948,7 +10523,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        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
@@ -10217,8 +10792,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
                                         /*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;
@@ -10311,10 +10886,15 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
            }
 
          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;
+            }
 
          type = TREE_TYPE (decl);
        }
@@ -10709,6 +11289,16 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   if (identifier == error_mark_node)
     return;
   /* Look for the `=' token.  */
+  if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
+      && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)) 
+    {
+      error ("%<namespace%> definition is not allowed here");
+      /* Skip the definition.  */
+      cp_lexer_consume_token (parser->lexer);
+      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
@@ -11086,7 +11676,7 @@ cp_parser_asm_definition (cp_parser* parser)
 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,
@@ -11139,6 +11729,10 @@ cp_parser_init_declarator (cp_parser* parser,
   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))
+    return error_mark_node;
+
   if (declares_class_or_enum & 2)
     cp_parser_check_for_definition_in_return_type (declarator,
                                                   decl_specifiers->type);
@@ -11258,10 +11852,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 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.  */
@@ -11311,9 +11901,23 @@ cp_parser_init_declarator (cp_parser* parser,
   is_non_constant_init = true;
   if (is_initialized)
     {
-      if (function_declarator_p (declarator)
-         && initialization_kind == CPP_EQ)
-       initializer = cp_parser_pure_specifier (parser);
+      if (function_declarator_p (declarator))
+       {
+          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 ("initializer provided for function");
+              cp_parser_skip_to_closing_parenthesis (parser,
+                                                     /*recovering=*/true,
+                                                     /*or_comma=*/false,
+                                                     /*consume_paren=*/true);
+            }
+       }
       else
        initializer = cp_parser_initializer (parser,
                                             &is_parenthesized_init,
@@ -11360,6 +11964,13 @@ cp_parser_init_declarator (cp_parser* parser,
                      ((is_parenthesized_init || !is_initialized)
                     ? 0 : LOOKUP_ONLYCONVERTING));
     }
+  else if (flag_cpp0x && 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);
 
@@ -11728,17 +12339,47 @@ cp_parser_direct_declarator (cp_parser* parser,
          tree unqualified_name;
          special_function_kind sfk;
          bool abstract_ok;
+          bool pack_expansion_p = false;
 
          /* Parse a declarator-id */
          abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
          if (abstract_ok)
-           cp_parser_parse_tentatively (parser);
+            {
+              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;
+                }
+            }
+
          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
@@ -11755,6 +12396,8 @@ cp_parser_direct_declarator (cp_parser* parser,
          if (unqualified_name == error_mark_node)
            {
              declarator = cp_error_declarator;
+              pack_expansion_p = false;
+              declarator->parameter_pack_p = false;
              break;
            }
 
@@ -11784,13 +12427,14 @@ cp_parser_direct_declarator (cp_parser* parser,
                                            /*only_current_p=*/false);
              /* If that failed, the declarator is invalid.  */
              if (type == error_mark_node)
-               error ("%<%T::%D%> is not a type",
+               error ("%<%T::%E%> is not a type",
                       TYPE_CONTEXT (qualifying_scope),
                       TYPE_IDENTIFIER (qualifying_scope));
              qualifying_scope = type;
            }
 
          sfk = sfk_none;
+
          if (unqualified_name)
            {
              tree class_type;
@@ -11858,6 +12502,10 @@ cp_parser_direct_declarator (cp_parser* parser,
                                           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);
@@ -12419,9 +13067,9 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 /* Parse a parameter declaration.
 
    parameter-declaration:
-     decl-specifier-seq declarator
+     decl-specifier-seq ... [opt] declarator
      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
@@ -12476,12 +13124,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
+
   /* 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
-      || token->type == CPP_ELLIPSIS
       || token->type == CPP_GREATER)
     {
       declarator = NULL;
@@ -12523,6 +13172,37 @@ cp_parser_parameter_declaration (cp_parser *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;
@@ -12581,6 +13261,13 @@ cp_parser_parameter_declaration (cp_parser *parser,
                  ++depth;
                  break;
 
+                case CPP_RSHIFT:
+                  if (!flag_cpp0x)
+                    break;
+                  /* Fall through for C++0x, which treats the `>>'
+                     operator like two `>' tokens in certain
+                     cases.  */
+
                case CPP_GREATER:
                  /* If we see a non-nested `>', and `>' is not an
                     operator, then it marks the end of the default
@@ -12754,6 +13441,7 @@ 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,
+                                                    /*allow_expansion_p=*/true,
                                                    non_constant_p);
   else
     {
@@ -12829,8 +13517,8 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
 /* Parse an initializer-list.
 
    initializer-list:
-     initializer-clause
-     initializer-list , initializer-clause
+     initializer-clause ... [opt]
+     initializer-list , initializer-clause ... [opt]
 
    GNU Extension:
 
@@ -12870,7 +13558,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          if (pedantic)
            pedwarn ("ISO C++ does not allow designated initializers");
          /* 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);
        }
@@ -12884,6 +13572,17 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
       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);
 
@@ -13270,6 +13969,10 @@ cp_parser_class_specifier (cp_parser* parser)
      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.
@@ -13304,6 +14007,8 @@ cp_parser_class_head (cp_parser* parser,
      type.  */
   num_templates = 0;
 
+  *bases = NULL_TREE;
+
   /* Look for the class-key.  */
   class_key = cp_parser_class_key (parser);
   if (class_key == none_type)
@@ -13594,7 +14299,6 @@ cp_parser_class_head (cp_parser* parser,
        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))
@@ -13675,7 +14379,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
          /* 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 `:'.  */
          cp_parser_require (parser, CPP_COLON, "`:'");
          break;
@@ -14048,7 +14752,11 @@ cp_parser_member_declaration (cp_parser* parser)
                  token = cp_lexer_peek_token (parser->lexer);
                  /* If the next token is a semicolon, consume it.  */
                  if (token->type == CPP_SEMICOLON)
-                   cp_lexer_consume_token (parser->lexer);
+                   {
+                     if (pedantic && !in_system_header)
+                       pedwarn ("extra %<;%>");
+                     cp_lexer_consume_token (parser->lexer);
+                   }
                  return;
                }
              else
@@ -14180,8 +14888,8 @@ cp_parser_constant_initializer (cp_parser* parser)
      : 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
@@ -14203,12 +14911,28 @@ cp_parser_base_clause (cp_parser* parser)
     {
       cp_token *token;
       tree base;
+      bool pack_expansion_p = false;
 
       /* 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)
        {
+          if (pack_expansion_p)
+            /* Make this a pack expansion type. */
+            TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
+          else
+            check_for_bare_parameter_packs (TREE_VALUE (base));
+
          TREE_CHAIN (base) = bases;
          bases = base;
        }
@@ -14414,8 +15138,8 @@ cp_parser_exception_specification_opt (cp_parser* parser)
 /* 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.  */
@@ -14432,6 +15156,15 @@ cp_parser_type_id_list (cp_parser* 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.  */
@@ -14481,7 +15214,7 @@ cp_parser_function_try_block (cp_parser* parser)
   /* Look for the `try' keyword.  */
   if (!cp_parser_require_keyword (parser, RID_TRY, "`try'"))
     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
@@ -14855,7 +15588,7 @@ cp_parser_attribute_list (cp_parser* parser)
 
          /* 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.  */
@@ -14865,6 +15598,7 @@ cp_parser_attribute_list (cp_parser* parser)
            {
              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;
@@ -15293,10 +16027,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'.  */
-             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);
@@ -15684,7 +16422,7 @@ static void
 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;
@@ -15807,7 +16545,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
    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);
@@ -15823,7 +16561,7 @@ cp_parser_perform_template_parameter_access_checks (tree checks)
 
 static tree
 cp_parser_single_declaration (cp_parser* parser,
-                             tree checks,
+                             VEC (deferred_access_check,gc)* checks,
                              bool member_p,
                              bool* friend_p)
 {
@@ -15943,6 +16681,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
   expression_list
     = cp_parser_parenthesized_expression_list (parser, false,
                                               /*cast_p=*/true,
+                                               /*allow_expansion_p=*/true,
                                               /*non_constant_p=*/NULL);
 
   cast = build_functional_cast (type, expression_list);
@@ -16050,7 +16789,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   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);
@@ -16058,7 +16798,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))
     {
-      if (!saved_greater_than_is_operator_p)
+      if (flag_cpp0x)
+        {
+          /* 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
@@ -16071,8 +16832,6 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
                 "within a nested template argument list",
                 &token->location);
 
-         /* ??? Proper recovery should terminate two levels of
-            template argument list here.  */
          token->type = CPP_GREATER;
        }
       else
@@ -16292,6 +17051,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   const char *saved_message;
   bool saved_integral_constant_expression_p;
   bool saved_non_integral_constant_expression_p;
+  bool pack_expansion_p = false;
 
   /* Initialize FORMAT the first time we get here.  */
   if (!format)
@@ -16316,6 +17076,19 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
     = 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
@@ -16360,6 +17133,11 @@ 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 (pack_expansion_p)
+    /* Build a pack expansion. */
+    expr = make_pack_expansion (expr);
+
   /* Go back to evaluating expressions.  */
   --skip_evaluation;
 
@@ -16549,6 +17327,23 @@ cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
            ++level;
          break;
 
+        case CPP_RSHIFT:
+          if (!flag_cpp0x)
+            /* 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)
            {
@@ -16643,8 +17438,8 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser)
   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)
@@ -16652,7 +17447,10 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
   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
+         || (flag_cpp0x && token->type == CPP_RSHIFT));
 }
 
 /* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the
@@ -16769,19 +17567,29 @@ cp_parser_optional_template_keyword (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.  */
-  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.  */
-  for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
-    perform_or_defer_access_check (TREE_PURPOSE (check),
-                                  TREE_VALUE (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.  */
-  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;
 }
 
@@ -16969,7 +17777,7 @@ cp_parser_objc_expression (cp_parser* parser)
 
     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)
@@ -16987,7 +17795,7 @@ cp_parser_objc_expression (cp_parser* parser)
          break;
        }
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -17276,7 +18084,7 @@ cp_parser_objc_identifier_list (cp_parser* parser)
    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
@@ -17297,7 +18105,7 @@ cp_parser_objc_alias_declaration (cp_parser* parser)
      @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)
@@ -17377,7 +18185,7 @@ cp_parser_objc_protocol_qualifiers (cp_parser* parser)
   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]
@@ -17390,7 +18198,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);
-      node = token->value;
+      node = token->u.value;
     }
 
   return quals;
@@ -17461,7 +18269,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");
-    default: return token->value;
+    default: return token->u.value;
     }
 }
 
@@ -17910,7 +18718,7 @@ cp_parser_objc_declaration (cp_parser* parser)
       cp_parser_objc_end_implementation (parser);
       break;
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 }
@@ -18041,7 +18849,7 @@ cp_parser_objc_statement (cp_parser * parser) {
     case RID_AT_THROW:
       return cp_parser_objc_throw_statement (parser);
     default:
-      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
       cp_parser_skip_to_end_of_block_or_statement (parser);
     }
 
@@ -18050,25 +18858,6 @@ cp_parser_objc_statement (cp_parser * parser) {
 \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
@@ -18087,7 +18876,7 @@ cp_parser_omp_clause_name (cp_parser *parser)
     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])
@@ -18241,7 +19030,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
     return list;
   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])
@@ -18452,7 +19241,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
 
   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])
@@ -18650,7 +19439,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);
 
-  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);
@@ -18895,7 +19684,7 @@ 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 ();
-  cp_parser_statement (parser, NULL_TREE, false);
+  cp_parser_statement (parser, NULL_TREE, false, NULL);
   body = pop_stmt_list (body);
 
   return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
@@ -18988,7 +19777,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
 
       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)
@@ -19101,7 +19890,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
     }
   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)
        {
@@ -19184,9 +19973,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);
 
-  if (!targetm.have_tls)
-    sorry ("threadprivate variables not supported in this target");
-
   finish_omp_threadprivate (vars);
 }
 
@@ -19257,7 +20043,7 @@ cp_parser_initial_pragma (cp_token *first_token)
   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)
@@ -19377,7 +20163,7 @@ pragma_lex (tree *value)
   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;
@@ -19418,8 +20204,4 @@ c_parse_file (void)
   the_parser = NULL;
 }
 
-/* This variable must be provided by every front end.  */
-
-int yydebug;
-
 #include "gt-cp-parser.h"