OSDN Git Service

Index: gcc/cp/ChangeLog
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index bba4d25..b8af4d2 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 (())
@@ -66,8 +80,15 @@ typedef struct cp_token GTY (())
      KEYWORD is RID_MAX) iff this name was looked up and found to be
      ambiguous.  An error has already been reported.  */
   BOOL_BITFIELD ambiguous_p : 1;
+  /* The 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;
@@ -79,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, NULL_TREE,
+  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, 0, { NULL },
 #if USE_MAPPED_LOCATION
   0
 #else
@@ -205,7 +226,7 @@ static void cp_parser_initial_pragma
   (cp_token *);
 
 /* Manifest constants.  */
-#define CP_LEXER_BUFFER_SIZE 10000
+#define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
 #define CP_SAVED_TOKEN_STACK 5
 
 /* A token type for keywords, as opposed to ordinary identifiers.  */
@@ -392,7 +413,8 @@ 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;
   token->in_system_header = in_system_header;
@@ -407,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;
        }
@@ -429,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;
@@ -439,18 +476,19 @@ 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;
     }
 }
 
-/* Update the globals input_location and in_system_header from TOKEN.  */
+/* Update the globals input_location and in_system_header and the
+   input file stack from TOKEN.  */
 static inline void
 cp_lexer_set_source_position_from_token (cp_token *token)
 {
@@ -458,6 +496,7 @@ cp_lexer_set_source_position_from_token (cp_token *token)
     {
       input_location = token->location;
       in_system_header = token->in_system_header;
+      restore_input_file_stack (token->input_file_stack_index);
     }
 }
 
@@ -500,6 +539,51 @@ cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
   return cp_lexer_peek_token (lexer)->keyword == keyword;
 }
 
+/* Return true if the next token is a keyword for a decl-specifier.  */
+
+static bool
+cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
+{
+  cp_token *token;
+
+  token = cp_lexer_peek_token (lexer);
+  switch (token->keyword) 
+    {
+      /* Storage classes.  */
+    case RID_AUTO:
+    case RID_REGISTER:
+    case RID_STATIC:
+    case RID_EXTERN:
+    case RID_MUTABLE:
+    case RID_THREAD:
+      /* Elaborated type specifiers.  */
+    case RID_ENUM:
+    case RID_CLASS:
+    case RID_STRUCT:
+    case RID_UNION:
+    case RID_TYPENAME:
+      /* Simple type specifiers.  */
+    case RID_CHAR:
+    case RID_WCHAR:
+    case RID_BOOL:
+    case RID_SHORT:
+    case RID_INT:
+    case RID_LONG:
+    case RID_SIGNED:
+    case RID_UNSIGNED:
+    case RID_FLOAT:
+    case RID_DOUBLE:
+    case RID_VOID:
+      /* GNU extensions.  */ 
+    case RID_ATTRIBUTE:
+    case RID_TYPEOF:
+      return true;
+
+    default:
+      return false;
+    }
+}
+
 /* Return a pointer to the Nth token in the token stream.  If N is 1,
    then this is precisely equivalent to cp_lexer_peek_token (except
    that it is not inline).  One would like to disallow that case, but
@@ -513,7 +597,7 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
 
   /* N is 1-based, not zero-based.  */
   gcc_assert (n > 0);
-  
+
   if (cp_lexer_debugging_p (lexer))
     fprintf (cp_lexer_debug_stream,
             "cp_lexer: peeking ahead %ld at token: ", (long)n);
@@ -591,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
@@ -625,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;
     }
 }
@@ -703,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:
@@ -780,7 +864,8 @@ static cp_parameter_declarator *make_parameter_declarator
 static cp_declarator *make_ptrmem_declarator
   (cp_cv_quals, tree, cp_declarator *);
 
-cp_declarator *cp_error_declarator;
+/* An erroneous declarator.  */
+static cp_declarator *cp_error_declarator;
 
 /* The obstack on which declarators and related data structures are
    allocated.  */
@@ -959,6 +1044,24 @@ make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers,
   return parameter;
 }
 
+/* Returns true iff DECLARATOR  is a declaration for a function.  */
+
+static bool
+function_declarator_p (const cp_declarator *declarator)
+{
+  while (declarator)
+    {
+      if (declarator->kind == cdk_function
+         && declarator->declarator->kind == cdk_id)
+       return true;
+      if (declarator->kind == cdk_id
+         || declarator->kind == cdk_error)
+       return false;
+      declarator = declarator->declarator;
+    }
+  return false;
+}
 /* The parser.  */
 
 /* Overview
@@ -1089,8 +1192,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;
 
@@ -1149,8 +1259,6 @@ static const cp_parser_binary_operations_map_node binops[] = {
   { CPP_GREATER, GT_EXPR, PREC_RELATIONAL_EXPRESSION },
   { CPP_LESS_EQ, LE_EXPR, PREC_RELATIONAL_EXPRESSION },
   { CPP_GREATER_EQ, GE_EXPR, PREC_RELATIONAL_EXPRESSION },
-  { CPP_MIN, MIN_EXPR, PREC_RELATIONAL_EXPRESSION },
-  { CPP_MAX, MAX_EXPR, PREC_RELATIONAL_EXPRESSION },
 
   { CPP_EQ_EQ, EQ_EXPR, PREC_EQUALITY_EXPRESSION },
   { CPP_NOT_EQ, NE_EXPR, PREC_EQUALITY_EXPRESSION },
@@ -1293,12 +1401,21 @@ typedef struct cp_parser GTY(())
   /* TRUE if we are presently parsing a template-argument-list.  */
   bool in_template_argument_list_p;
 
-  /* TRUE if we are presently parsing the body of an
-     iteration-statement.  */
-  bool in_iteration_statement_p;
-
-  /* TRUE if we are presently parsing the body of a switch
-     statement.  */
+  /* Set to IN_ITERATION_STMT if parsing an iteration-statement,
+     to IN_OMP_BLOCK if parsing OpenMP structured block and
+     IN_OMP_FOR if parsing OpenMP loop.  If parsing a switch statement,
+     this is bitwise ORed with IN_SWITCH_STMT, unless parsing an
+     iteration-statement, OpenMP block or loop within that switch.  */
+#define IN_SWITCH_STMT         1
+#define IN_ITERATION_STMT      2
+#define IN_OMP_BLOCK           4
+#define IN_OMP_FOR             8
+  unsigned char in_statement;
+
+  /* TRUE if we are presently parsing the body of a switch statement.
+     Note that this doesn't quite overlap with in_statement above.
+     The difference relates to giving the right sets of error messages:
+     "case not in switch" vs "break statement used with OpenMP...".  */
   bool in_switch_statement_p;
 
   /* TRUE if we are parsing a type-id in an expression context.  In
@@ -1314,6 +1431,10 @@ typedef struct cp_parser GTY(())
      character set.  */
   bool translate_strings_p;
 
+  /* TRUE if we are presently parsing the body of a function, but not
+     a local class.  */
+  bool in_function_body;
+
   /* If non-NULL, then we are parsing a construct where new type
      definitions are not permitted.  The string stored here will be
      issued as an error message if a type is defined.  */
@@ -1380,9 +1501,9 @@ static bool cp_parser_translation_unit
 static tree cp_parser_primary_expression
   (cp_parser *, bool, bool, bool, cp_id_kind *);
 static tree cp_parser_id_expression
-  (cp_parser *, bool, bool, bool *, bool);
+  (cp_parser *, bool, bool, bool *, bool, bool);
 static tree cp_parser_unqualified_id
-  (cp_parser *, bool, bool, bool);
+  (cp_parser *, bool, bool, bool, bool);
 static tree cp_parser_nested_name_specifier_opt
   (cp_parser *, bool, bool, bool, bool);
 static tree cp_parser_nested_name_specifier
@@ -1437,9 +1558,9 @@ static tree cp_parser_builtin_offsetof
 /* Statements [gram.stmt.stmt]  */
 
 static void cp_parser_statement
-  (cp_parser *, tree, bool);
-static tree cp_parser_labeled_statement
-  (cp_parser *, tree, bool);
+  (cp_parser *, tree, bool, bool *);
+static void cp_parser_label_for_labeled_statement
+  (cp_parser *);
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
@@ -1447,7 +1568,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
@@ -1460,7 +1581,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 *);
 
@@ -1505,19 +1626,21 @@ static tree cp_parser_qualified_namespace_specifier
   (cp_parser *);
 static void cp_parser_namespace_alias_definition
   (cp_parser *);
-static void cp_parser_using_declaration
-  (cp_parser *);
+static bool cp_parser_using_declaration
+  (cp_parser *, bool);
 static void cp_parser_using_directive
   (cp_parser *);
 static void cp_parser_asm_definition
   (cp_parser *);
 static void cp_parser_linkage_specification
   (cp_parser *);
+static void cp_parser_static_assert
+  (cp_parser *, bool);
 
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
-  (cp_parser *, cp_decl_specifier_seq *, 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
@@ -1527,7 +1650,7 @@ static enum tree_code cp_parser_ptr_operator
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
 static tree cp_parser_declarator_id
-  (cp_parser *);
+  (cp_parser *, bool);
 static tree cp_parser_type_id
   (cp_parser *);
 static void cp_parser_type_specifier_seq
@@ -1557,7 +1680,7 @@ static tree cp_parser_class_name
 static tree cp_parser_class_specifier
   (cp_parser *);
 static tree cp_parser_class_head
-  (cp_parser *, bool *, tree *);
+  (cp_parser *, bool *, tree *, tree *);
 static enum tag_types cp_parser_class_key
   (cp_parser *);
 static void cp_parser_member_specification_opt
@@ -1716,8 +1839,10 @@ static tree cp_parser_function_definition_after_declarator
   (cp_parser *, bool);
 static void cp_parser_template_declaration_after_export
   (cp_parser *, bool);
+static void cp_parser_perform_template_parameter_access_checks
+  (VEC (deferred_access_check,gc)*);
 static tree cp_parser_single_declaration
-  (cp_parser *, 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
@@ -1735,7 +1860,7 @@ static tree cp_parser_sizeof_operand
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
 static void cp_parser_set_storage_class
-  (cp_decl_specifier_seq *, cp_storage_class);
+  (cp_parser *, cp_decl_specifier_seq *, enum rid);
 static void cp_parser_set_decl_spec_type
   (cp_decl_specifier_seq *, tree, bool);
 static bool cp_parser_friend_p
@@ -1782,7 +1907,7 @@ static void cp_parser_name_lookup_error
   (cp_parser *, tree, tree, const char *);
 static bool cp_parser_simulate_error
   (cp_parser *);
-static void cp_parser_check_type_definition
+static bool cp_parser_check_type_definition
   (cp_parser *);
 static void cp_parser_check_for_definition_in_return_type
   (cp_declarator *, tree);
@@ -1804,8 +1929,8 @@ static void cp_parser_skip_to_end_of_block_or_statement
   (cp_parser *);
 static void cp_parser_skip_to_closing_brace
   (cp_parser *);
-static void cp_parser_skip_until_found
-  (cp_parser *, enum cpp_ttype, const char *);
+static void cp_parser_skip_to_end_of_template_parameter_list
+  (cp_parser *);
 static void cp_parser_skip_to_pragma_eol
   (cp_parser*, cp_token *);
 static bool cp_parser_error_occurred
@@ -1843,16 +1968,6 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword)
   return token->keyword == keyword;
 }
 
-/* A minimum or maximum operator has been seen.  As these are
-   deprecated, issue a warning.  */
-
-static inline void
-cp_parser_warn_min_max (void)
-{
-  if (warn_deprecated && !in_system_header)
-    warning (OPT_Wdeprecated, "minimum/maximum operators are deprecated");
-}
-
 /* If not parsing tentatively, issue a diagnostic of the form
       FILE:LINE: MESSAGE before TOKEN
    where TOKEN is the next token in the input stream.  MESSAGE
@@ -1881,7 +1996,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);
     }
 }
 
@@ -1938,18 +2053,65 @@ cp_parser_simulate_error (cp_parser* parser)
   return false;
 }
 
+/* Check for repeated decl-specifiers.  */
+
+static void
+cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
+{
+  cp_decl_spec ds;
+
+  for (ds = ds_first; ds != ds_last; ++ds)
+    {
+      unsigned count = decl_specs->specs[(int)ds];
+      if (count < 2)
+       continue;
+      /* The "long" specifier is a special case because of "long long".  */
+      if (ds == ds_long)
+       {
+         if (count > 2)
+           error ("%<long long long%> is too long for GCC");
+         else if (pedantic && !in_system_header && warn_long_long)
+           pedwarn ("ISO C++ does not support %<long long%>");
+       }
+      else if (count > 1)
+       {
+         static const char *const decl_spec_names[] = {
+           "signed",
+           "unsigned",
+           "short",
+           "long",
+           "const",
+           "volatile",
+           "restrict",
+           "inline",
+           "virtual",
+           "explicit",
+           "friend",
+           "typedef",
+           "__complex",
+           "__thread"
+         };
+         error ("duplicate %qs", decl_spec_names[(int)ds]);
+       }
+    }
+}
+
 /* This function is called when a type is defined.  If type
    definitions are forbidden at this point, an error message is
    issued.  */
 
-static void
+static bool
 cp_parser_check_type_definition (cp_parser* parser)
 {
   /* If types are forbidden here, issue a message.  */
   if (parser->type_definition_forbidden_message)
-    /* Use `%s' to print the string in case there are any escape
-       characters in the message.  */
-    error ("%s", parser->type_definition_forbidden_message);
+    {
+      /* Use `%s' to print the string in case there are any escape
+        characters in the message.  */
+      error ("%s", parser->type_definition_forbidden_message);
+      return false;
+    }
+  return true;
 }
 
 /* This function is called when the DECLARATOR is processed.  The TYPE
@@ -2050,8 +2212,12 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
   /* If the lookup found a template-name, it means that the user forgot
   to specify an argument list. Emit a useful error message.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
-    error ("invalid use of template-name %qE without an argument list",
-      decl);
+    error ("invalid use of template-name %qE without an argument list", decl);
+  else if (TREE_CODE (id) == BIT_NOT_EXPR)
+    error ("invalid use of destructor %qD as a type", id);
+  else if (TREE_CODE (decl) == TYPE_DECL)
+    /* Something like 'unsigned A a;'  */
+    error ("invalid combination of multiple type-specifiers");
   else if (!parser->scope)
     {
       /* Issue an error message.  */
@@ -2120,8 +2286,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
    form `ID a', where `ID' is an id-expression and `a' is a plain identifier.
    Usually, `ID' should name a type, but if we got here it means that it
    does not. We try to emit the best possible error message depending on
-   how exactly the id-expression looks like.
-*/
+   how exactly the id-expression looks like.  */
 
 static bool
 cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
@@ -2133,7 +2298,8 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
                                /*template_keyword_p=*/false,
                                /*check_dependency_p=*/true,
                                /*template_p=*/NULL,
-                               /*declarator_p=*/true);
+                               /*declarator_p=*/true,
+                               /*optional_p=*/false);
   /* After the id-expression, there should be a plain identifier,
      otherwise this is not a simple variable declaration. Also, if
      the scope is dependent, we cannot do much.  */
@@ -2144,8 +2310,7 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
       cp_parser_abort_tentative_parse (parser);
       return false;
     }
-  if (!cp_parser_parse_definitely (parser)
-      || TREE_CODE (id) != IDENTIFIER_NODE)
+  if (!cp_parser_parse_definitely (parser) || TREE_CODE (id) == TYPE_DECL)
     return false;
 
   /* Emit a diagnostic for the invalid type.  */
@@ -2420,6 +2585,17 @@ cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok)
   cp_lexer_purge_tokens_after (parser->lexer, pragma_tok);
 }
 
+/* Require pragma end of line, resyncing with it as necessary.  The
+   arguments are as for cp_parser_skip_to_pragma_eol.  */
+
+static void
+cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok)
+{
+  parser->lexer->in_pragma = false;
+  if (!cp_parser_require (parser, CPP_PRAGMA_EOL, "end of line"))
+    cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+}
+
 /* This is a simple wrapper around make_typename_type. When the id is
    an unresolved identifier node, we can provide a superior diagnostic
    using cp_parser_diagnose_invalid_type_name.  */
@@ -2431,7 +2607,7 @@ cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
   if (TREE_CODE (id) == IDENTIFIER_NODE)
     {
       result = make_typename_type (scope, id, typename_type,
-                                   /*complain=*/tf_none);
+                                  /*complain=*/tf_none);
       if (result == error_mark_node)
        cp_parser_diagnose_invalid_type_name (parser, scope, id);
       return result;
@@ -2489,7 +2665,7 @@ cp_parser_new (void)
   parser->in_template_argument_list_p = false;
 
   /* We are not in an iteration statement.  */
-  parser->in_iteration_statement_p = false;
+  parser->in_statement = 0;
 
   /* We are not in a switch statement.  */
   parser->in_switch_statement_p = false;
@@ -2503,6 +2679,9 @@ cp_parser_new (void)
   /* String literals should be translated to the execution character set.  */
   parser->translate_strings_p = true;
 
+  /* We are not parsing a function body.  */
+  parser->in_function_body = false;
+
   /* The unparsed function queue is empty.  */
   parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
 
@@ -2558,7 +2737,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
@@ -2599,8 +2778,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;
@@ -2616,8 +2795,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;
 
@@ -2687,25 +2866,25 @@ cp_parser_translation_unit (cp_parser* parser)
     }
 
   cp_parser_declaration_seq_opt (parser);
-  
+
   /* If there are no tokens left then all went well.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
     {
       /* Get rid of the token array; we don't need it any more.  */
       cp_lexer_destroy (parser->lexer);
       parser->lexer = NULL;
-      
+
       /* This file might have been a context that's implicitly extern
-         "C".  If so, pop the lang context.  (Only relevant for PCH.) */
+        "C".  If so, pop the lang context.  (Only relevant for PCH.) */
       if (parser->implicit_extern_c)
-        {
-          pop_lang_context ();
-          parser->implicit_extern_c = false;
-        }
-      
+       {
+         pop_lang_context ();
+         parser->implicit_extern_c = false;
+       }
+
       /* Finish up.  */
       finish_translation_unit ();
-      
+
       success = true;
     }
   else
@@ -2713,7 +2892,7 @@ cp_parser_translation_unit (cp_parser* parser)
       cp_parser_error (parser, "expected declaration");
       success = false;
     }
-  
+
   /* Make sure the declarator obstack was fully cleaned up.  */
   gcc_assert (obstack_next_free (&declarator_obstack)
              == declarator_obstack_base);
@@ -2784,7 +2963,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)
        {
@@ -2821,7 +3000,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:
@@ -2859,14 +3038,21 @@ cp_parser_primary_expression (cp_parser *parser,
                 int i = ({ int j = 3; j + 1; });
 
               at class or namespace scope.  */
-           if (!at_function_scope_p ())
-             error ("statement-expressions are allowed only inside functions");
-           /* Start the statement-expression.  */
-           expr = begin_stmt_expr ();
-           /* Parse the compound-statement.  */
-           cp_parser_compound_statement (parser, expr, false);
-           /* Finish up.  */
-           expr = finish_stmt_expr (expr, false);
+           if (!parser->in_function_body)
+             {
+               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
          {
@@ -2937,7 +3123,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:
          {
@@ -3001,7 +3187,8 @@ cp_parser_primary_expression (cp_parser *parser,
                                     /*template_keyword_p=*/false,
                                     /*check_dependency_p=*/true,
                                     &template_p,
-                                    /*declarator_p=*/false);
+                                    /*declarator_p=*/false,
+                                    /*optional_p=*/false);
        if (id_expression == error_mark_node)
          return error_mark_node;
        token = cp_lexer_peek_token (parser->lexer);
@@ -3069,7 +3256,7 @@ cp_parser_primary_expression (cp_parser *parser,
              }
          }
 
-       decl = (finish_id_expression 
+       decl = (finish_id_expression
                (id_expression, decl, parser->scope,
                 idk,
                 parser->integral_constant_expression_p,
@@ -3085,9 +3272,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");
@@ -3134,7 +3323,8 @@ cp_parser_id_expression (cp_parser *parser,
                         bool template_keyword_p,
                         bool check_dependency_p,
                         bool *template_p,
-                        bool declarator_p)
+                        bool declarator_p,
+                        bool optional_p)
 {
   bool global_scope_p;
   bool nested_name_specifier_p;
@@ -3177,7 +3367,8 @@ cp_parser_id_expression (cp_parser *parser,
       /* Process the final unqualified-id.  */
       unqualified_id = cp_parser_unqualified_id (parser, *template_p,
                                                 check_dependency_p,
-                                                declarator_p);
+                                                declarator_p,
+                                                /*optional_p=*/false);
       /* Restore the SAVED_SCOPE for our caller.  */
       parser->scope = saved_scope;
       parser->object_scope = saved_object_scope;
@@ -3235,7 +3426,8 @@ cp_parser_id_expression (cp_parser *parser,
   else
     return cp_parser_unqualified_id (parser, template_keyword_p,
                                     /*check_dependency_p=*/true,
-                                    declarator_p);
+                                    declarator_p,
+                                    optional_p);
 }
 
 /* Parse an unqualified-id.
@@ -3264,7 +3456,8 @@ static tree
 cp_parser_unqualified_id (cp_parser* parser,
                          bool template_keyword_p,
                          bool check_dependency_p,
-                         bool declarator_p)
+                         bool declarator_p,
+                         bool optional_p)
 {
   cp_token *token;
 
@@ -3345,13 +3538,31 @@ cp_parser_unqualified_id (cp_parser* parser,
        object_scope = parser->object_scope;
        qualifying_scope = parser->qualifying_scope;
 
+       /* Check for invalid scopes.  */
+       if (scope == error_mark_node)
+         {
+           if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+             cp_lexer_consume_token (parser->lexer);
+           return error_mark_node;
+         }
+       if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
+         {
+           if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
+             error ("scope %qT before %<~%> is not a class-name", scope);
+           cp_parser_simulate_error (parser);
+           if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+             cp_lexer_consume_token (parser->lexer);
+           return error_mark_node;
+         }
+       gcc_assert (!scope || TYPE_P (scope));
+
        /* If the name is of the form "X::~X" it's OK.  */
-       if (scope && TYPE_P (scope)
-           && cp_lexer_next_token_is (parser->lexer, CPP_NAME)
+       token = cp_lexer_peek_token (parser->lexer);
+       if (scope
+           && token->type == CPP_NAME
            && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
                == CPP_OPEN_PAREN)
-           && (cp_lexer_peek_token (parser->lexer)->value
-               == TYPE_IDENTIFIER (scope)))
+           && constructor_name_p (token->u.value, scope))
          {
            cp_lexer_consume_token (parser->lexer);
            return build_nt (BIT_NOT_EXPR, scope);
@@ -3429,7 +3640,7 @@ cp_parser_unqualified_id (cp_parser* parser,
           destructor is the same as the name of the qualifying
           class.  That allows us to keep parsing after running
           into ill-formed destructor names.  */
-       if (type_decl == error_mark_node && scope && TYPE_P (scope))
+       if (type_decl == error_mark_node && scope)
          return build_nt (BIT_NOT_EXPR, scope);
        else if (type_decl == error_mark_node)
          return error_mark_node;
@@ -3440,6 +3651,7 @@ cp_parser_unqualified_id (cp_parser* parser,
            if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
              error ("declaration of %<~%T%> as member of %qT",
                     type_decl, scope);
+           cp_parser_simulate_error (parser);
            return error_mark_node;
          }
 
@@ -3485,6 +3697,8 @@ cp_parser_unqualified_id (cp_parser* parser,
       /* Fall through.  */
 
     default:
+      if (optional_p)
+       return NULL_TREE;
       cp_parser_error (parser, "expected unqualified-id");
       return error_mark_node;
     }
@@ -3520,20 +3734,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
   cp_token_position start = 0;
   cp_token *token;
 
-  /* If the next token corresponds to a nested name specifier, there
-     is no need to reparse it.  However, if CHECK_DEPENDENCY_P is
-     false, it may have been true before, in which case something
-     like `A<X>::B<Y>::C' may have resulted in a nested-name-specifier
-     of `A<X>::', where it should now be `A<X>::B<Y>::'.  So, when
-     CHECK_DEPENDENCY_P is false, we have to fall through into the
-     main loop.  */
-  if (check_dependency_p
-      && cp_lexer_next_token_is (parser->lexer, CPP_NESTED_NAME_SPECIFIER))
-    {
-      cp_parser_pre_parsed_nested_name_specifier (parser);
-      return parser->scope;
-    }
-
   /* Remember where the nested-name-specifier starts.  */
   if (cp_parser_uncommitted_to_tentative_parse_p (parser))
     {
@@ -3558,6 +3758,17 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
        {
          /* Grab the nested-name-specifier and continue the loop.  */
          cp_parser_pre_parsed_nested_name_specifier (parser);
+         /* If we originally encountered this nested-name-specifier
+            with IS_DECLARATION set to false, we will not have
+            resolved TYPENAME_TYPEs, so we must do so here.  */
+         if (is_declaration
+             && TREE_CODE (parser->scope) == TYPENAME_TYPE)
+           {
+             new_scope = resolve_typename_type (parser->scope,
+                                                /*only_current_p=*/false);
+             if (new_scope != error_mark_node)
+               parser->scope = new_scope;
+           }
          success = true;
          continue;
        }
@@ -3633,6 +3844,8 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
             class-or-namespace-name.  */
          parser->scope = old_scope;
          parser->qualifying_scope = saved_qualifying_scope;
+         if (cp_parser_uncommitted_to_tentative_parse_p (parser))
+           break;
          /* If the next token is an identifier, and the one after
             that is a `::', then any valid interpretation would have
             found a class-or-namespace-name.  */
@@ -3650,7 +3863,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,
@@ -3660,14 +3873,14 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                        error ("%qD used without template parameters", decl);
                      else if (ambiguous_decls)
                        {
-                         error ("reference to %qD is ambiguous", 
-                                token->value);
+                         error ("reference to %qD is ambiguous",
+                                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;
@@ -3726,23 +3939,23 @@ 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.  */
       cp_lexer_purge_tokens_after (parser->lexer, start);
     }
-  
+
   if (start)
     pop_to_parent_deferring_access_checks ();
 
@@ -3936,9 +4149,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
 
        /* Only type conversions to integral or enumeration types
           can be used in constant-expressions.  */
-       if (parser->integral_constant_expression_p
-           && !dependent_type_p (type)
-           && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+       if (!cast_valid_in_integral_constant_expression_p (type)
            && (cp_parser_non_integral_constant_expression
                (parser,
                 "a cast to a type other than an integral or "
@@ -4010,12 +4221,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
            /* Look for the `)' token.  */
            cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
          }
+       /* Restore the saved message.  */
+       parser->type_definition_forbidden_message = saved_message;
        /* `typeid' may not appear in an integral constant expression.  */
        if (cp_parser_non_integral_constant_expression(parser,
                                                       "`typeid' operator"))
          return error_mark_node;
-       /* Restore the saved message.  */
-       parser->type_definition_forbidden_message = saved_message;
       }
       break;
 
@@ -4102,8 +4313,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
          }
 
        /* It must be a primary-expression.  */
-       postfix_expression 
-         = cp_parser_primary_expression (parser, address_p, cast_p, 
+       postfix_expression
+         = cp_parser_primary_expression (parser, address_p, cast_p,
                                          /*template_arg_p=*/false,
                                          &idk);
       }
@@ -4232,8 +4443,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;
                  }
 
@@ -4242,7 +4452,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
                    = (build_new_method_call
                       (instance, fn, args, NULL_TREE,
                        (idk == CP_ID_KIND_QUALIFIED
-                        ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL)));
+                        ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
+                       /*fn_p=*/NULL));
                else
                  postfix_expression
                    = finish_call_expr (postfix_expression, args,
@@ -4475,12 +4686,13 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
         pseudo-destructor-name.  */
       bool template_p;
       /* Parse the id-expression.  */
-      name = (cp_parser_id_expression 
-             (parser, 
+      name = (cp_parser_id_expression
+             (parser,
               cp_parser_optional_template_keyword (parser),
               /*check_dependency_p=*/true,
               &template_p,
-              /*declarator_p=*/false));
+              /*declarator_p=*/false,
+              /*optional_p=*/false));
       /* In general, build a SCOPE_REF if the member name is qualified.
         However, if the name was not dependent and has already been
         resolved; there is no need to build the SCOPE_REF.  For example;
@@ -4517,7 +4729,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
            }
          if (scope && name && BASELINK_P (name))
            adjust_result_of_qualified_name_lookup
-             (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
+             (name, BINFO_TYPE (BASELINK_ACCESS_BINFO (name)), scope);
          postfix_expression
            = finish_class_member_access_expr (postfix_expression, name,
                                               template_p);
@@ -4594,7 +4806,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
          {
@@ -5420,9 +5632,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
 
          /* Only type conversions to integral or enumeration types
             can be used in constant-expressions.  */
-         if (parser->integral_constant_expression_p
-             && !dependent_type_p (type)
-             && !INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+         if (!cast_valid_in_integral_constant_expression_p (type)
              && (cp_parser_non_integral_constant_expression
                  (parser,
                   "a cast to a type other than an integral or "
@@ -5524,19 +5734,18 @@ 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 (token->type == CPP_MIN || token->type == CPP_MAX)
-       cp_parser_warn_min_max ();
 
       new_prec = TOKEN_PRECEDENCE (token);
 
@@ -5564,6 +5773,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
@@ -5579,8 +5789,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;
@@ -5597,11 +5809,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.
@@ -5791,16 +6007,6 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
       op = BIT_IOR_EXPR;
       break;
 
-    case CPP_MIN_EQ:
-      op = MIN_EXPR;
-      cp_parser_warn_min_max ();
-      break;
-
-    case CPP_MAX_EQ:
-      op = MAX_EXPR;
-      cp_parser_warn_min_max ();
-      break;
-
     default:
       /* Nothing else is an assignment operator.  */
       op = ERROR_MARK;
@@ -5936,8 +6142,7 @@ cp_parser_constant_expression (cp_parser* parser,
    offsetof-member-designator:
      id-expression
      | offsetof-member-designator "." id-expression
-     | offsetof-member-designator "[" expression "]"
-*/
+     | offsetof-member-designator "[" expression "]"  */
 
 static tree
 cp_parser_builtin_offsetof (cp_parser *parser)
@@ -6005,7 +6210,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   if (processing_template_decl)
     expr = build1 (OFFSETOF_EXPR, size_type_node, expr);
   else
-    expr = fold_offsetof (expr);
+    expr = finish_offsetof (expr);
 
  failure:
   parser->integral_constant_expression_p = save_ice_p;
@@ -6028,18 +6233,24 @@ cp_parser_builtin_offsetof (cp_parser *parser)
      declaration-statement
      try-block
 
-  IN_COMPOUND is true when the statement is nested inside a 
-  cp_parser_compound_statement; this matters for certain pragmas.  */
+  IN_COMPOUND is true when the statement is nested inside a
+  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.  */
@@ -6056,13 +6267,15 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
        {
        case RID_CASE:
        case RID_DEFAULT:
-         statement = cp_parser_labeled_statement (parser, in_statement_expr,
-                                                  in_compound);
-         break;
+         /* Looks like a labeled-statement with a case label.
+            Parse the label, and then use tail recursion to parse
+            the statement.  */
+         cp_parser_label_for_labeled_statement (parser);
+         goto restart;
 
        case RID_IF:
        case RID_SWITCH:
-         statement = cp_parser_selection_statement (parser);
+         statement = cp_parser_selection_statement (parser, if_p);
          break;
 
        case RID_WHILE:
@@ -6103,8 +6316,13 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
         labeled-statement.  */
       token = cp_lexer_peek_nth_token (parser->lexer, 2);
       if (token->type == CPP_COLON)
-       statement = cp_parser_labeled_statement (parser, in_statement_expr,
-                                                in_compound);
+       {
+         /* Looks like a labeled-statement with an ordinary label.
+            Parse the label, and then use tail recursion to parse
+            the statement.  */
+         cp_parser_label_for_labeled_statement (parser);
+         goto restart;
+       }
     }
   /* Anything that starts with a `{' must be a compound-statement.  */
   else if (token->type == CPP_OPEN_BRACE)
@@ -6116,7 +6334,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
       /* Only certain OpenMP pragmas are attached to statements, and thus
         are considered statements themselves.  All others are not.  In
         the context of a compound, accept the pragma as a "statement" and
-        return so that we can check for a close brace.  Otherwise we 
+        return so that we can check for a close brace.  Otherwise we
         require a real statement and must go back and read one.  */
       if (in_compound)
        cp_parser_pragma (parser, pragma_compound);
@@ -6154,30 +6372,23 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
     SET_EXPR_LOCATION (statement, statement_location);
 }
 
-/* Parse a labeled-statement.
+/* Parse the label for a labeled-statement, i.e.
 
-   labeled-statement:
-     identifier : statement
-     case constant-expression : statement
-     default : statement
+   identifier :
+   case constant-expression :
+   default :
 
    GNU Extension:
+   case constant-expression ... constant-expression : statement
 
-   labeled-statement:
-     case constant-expression ... constant-expression : statement
-
-   Returns the new CASE_LABEL_EXPR, for a `case' or `default' label.
-   For an ordinary label, returns a LABEL_EXPR.
+   When a label is parsed without errors, the label is added to the
+   parse tree by the finish_* functions, so this function doesn't
+   have to return the label.  */
 
-   IN_COMPOUND is as for cp_parser_statement: true when we're nested
-   inside a compound.  */
-
-static tree
-cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
-                            bool in_compound)
+static void
+cp_parser_label_for_labeled_statement (cp_parser* parser)
 {
   cp_token *token;
-  tree statement = error_mark_node;
 
   /* The next token should be an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -6185,7 +6396,7 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
       && token->type != CPP_KEYWORD)
     {
       cp_parser_error (parser, "expected labeled-statement");
-      return error_mark_node;
+      return;
     }
 
   switch (token->keyword)
@@ -6218,7 +6429,7 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
          expr_hi = NULL_TREE;
 
        if (parser->in_switch_statement_p)
-         statement = finish_case_label (expr, expr_hi);
+         finish_case_label (expr, expr_hi);
        else
          error ("case label %qE not within a switch statement", expr);
       }
@@ -6229,24 +6440,19 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
       cp_lexer_consume_token (parser->lexer);
 
       if (parser->in_switch_statement_p)
-       statement = finish_case_label (NULL_TREE, NULL_TREE);
+       finish_case_label (NULL_TREE, NULL_TREE);
       else
        error ("case label not within a switch statement");
       break;
 
     default:
       /* Anything else must be an ordinary label.  */
-      statement = finish_label_stmt (cp_parser_identifier (parser));
+      finish_label_stmt (cp_parser_identifier (parser));
       break;
     }
 
   /* Require the `:' token.  */
   cp_parser_require (parser, CPP_COLON, "`:'");
-  /* Parse the labeled statement.  */
-  cp_parser_statement (parser, in_statement_expr, in_compound);
-
-  /* Return the label, in the case of a `case' or `default' label.  */
-  return statement;
 }
 
 /* Parse an expression-statement.
@@ -6334,7 +6540,7 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
        break;
 
       /* Parse the statement.  */
-      cp_parser_statement (parser, in_statement_expr, true);
+      cp_parser_statement (parser, in_statement_expr, true, NULL);
     }
 }
 
@@ -6345,14 +6551,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");
 
@@ -6388,11 +6602,13 @@ cp_parser_selection_statement (cp_parser* parser)
 
        if (keyword == RID_IF)
          {
+           bool nested_if;
+
            /* Add the condition.  */
            finish_if_stmt_cond (condition, statement);
 
            /* Parse the then-clause.  */
-           cp_parser_implicitly_scoped_statement (parser);
+           cp_parser_implicitly_scoped_statement (parser, &nested_if);
            finish_then_clause (statement);
 
            /* If the next token is `else', parse the else-clause.  */
@@ -6403,8 +6619,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.  */
@@ -6413,15 +6649,19 @@ cp_parser_selection_statement (cp_parser* parser)
        else
          {
            bool in_switch_statement_p;
+           unsigned char in_statement;
 
            /* Add the condition.  */
            finish_switch_cond (condition, statement);
 
            /* Parse the body of the switch-statement.  */
            in_switch_statement_p = parser->in_switch_statement_p;
+           in_statement = parser->in_statement;
            parser->in_switch_statement_p = true;
-           cp_parser_implicitly_scoped_statement (parser);
+           parser->in_statement |= IN_SWITCH_STMT;
+           cp_parser_implicitly_scoped_statement (parser, NULL);
            parser->in_switch_statement_p = in_switch_statement_p;
+           parser->in_statement = in_statement;
 
            /* Now we're all done with the switch-statement.  */
            finish_switch_stmt (statement);
@@ -6500,6 +6740,7 @@ cp_parser_condition (cp_parser* parser)
       if (cp_parser_parse_definitely (parser))
        {
          tree pushed_scope;
+         bool non_constant_p;
 
          /* Create the declaration.  */
          decl = start_decl (declarator, &type_specifiers,
@@ -6507,12 +6748,16 @@ cp_parser_condition (cp_parser* parser)
                             attributes, /*prefix_attributes=*/NULL_TREE,
                             &pushed_scope);
          /* Parse the assignment-expression.  */
-         initializer = cp_parser_assignment_expression (parser,
-                                                        /*cast_p=*/false);
+         initializer
+           = cp_parser_constant_expression (parser,
+                                            /*allow_non_constant_p=*/true,
+                                            &non_constant_p);
+         if (!non_constant_p)
+           initializer = fold_non_dependent_expr (initializer);
 
          /* Process the initializer.  */
          cp_finish_decl (decl,
-                         initializer,
+                         initializer, !non_constant_p,
                          asm_specification,
                          LOOKUP_ONLYCONVERTING);
 
@@ -6547,8 +6792,7 @@ cp_parser_iteration_statement (cp_parser* parser)
   cp_token *token;
   enum rid keyword;
   tree statement;
-  bool in_iteration_statement_p;
-
+  unsigned char in_statement;
 
   /* Peek at the next token.  */
   token = cp_parser_require (parser, CPP_KEYWORD, "iteration-statement");
@@ -6557,7 +6801,7 @@ cp_parser_iteration_statement (cp_parser* parser)
 
   /* Remember whether or not we are already within an iteration
      statement.  */
-  in_iteration_statement_p = parser->in_iteration_statement_p;
+  in_statement = parser->in_statement;
 
   /* See what kind of keyword it is.  */
   keyword = token->keyword;
@@ -6577,9 +6821,9 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
        /* Parse the dependent statement.  */
-       parser->in_iteration_statement_p = true;
+       parser->in_statement = IN_ITERATION_STMT;
        cp_parser_already_scoped_statement (parser);
-       parser->in_iteration_statement_p = in_iteration_statement_p;
+       parser->in_statement = in_statement;
        /* We're done with the while-statement.  */
        finish_while_stmt (statement);
       }
@@ -6592,9 +6836,9 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Begin the do-statement.  */
        statement = begin_do_stmt ();
        /* Parse the body of the do-statement.  */
-       parser->in_iteration_statement_p = true;
-       cp_parser_implicitly_scoped_statement (parser);
-       parser->in_iteration_statement_p = in_iteration_statement_p;
+       parser->in_statement = IN_ITERATION_STMT;
+       cp_parser_implicitly_scoped_statement (parser, NULL);
+       parser->in_statement = in_statement;
        finish_do_body (statement);
        /* Look for the `while' keyword.  */
        cp_parser_require_keyword (parser, RID_WHILE, "`while'");
@@ -6639,9 +6883,9 @@ cp_parser_iteration_statement (cp_parser* parser)
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
        /* Parse the body of the for-statement.  */
-       parser->in_iteration_statement_p = true;
+       parser->in_statement = IN_ITERATION_STMT;
        cp_parser_already_scoped_statement (parser);
-       parser->in_iteration_statement_p = in_iteration_statement_p;
+       parser->in_statement = in_statement;
 
        /* We're done with the for-statement.  */
        finish_for_stmt (statement);
@@ -6721,25 +6965,42 @@ cp_parser_jump_statement (cp_parser* parser)
   switch (keyword)
     {
     case RID_BREAK:
-      if (!parser->in_switch_statement_p
-         && !parser->in_iteration_statement_p)
+      switch (parser->in_statement)
        {
+       case 0:
          error ("break statement not within loop or switch");
-         statement = error_mark_node;
+         break;
+       default:
+         gcc_assert ((parser->in_statement & IN_SWITCH_STMT)
+                     || parser->in_statement == IN_ITERATION_STMT);
+         statement = finish_break_stmt ();
+         break;
+       case IN_OMP_BLOCK:
+         error ("invalid exit from OpenMP structured block");
+         break;
+       case IN_OMP_FOR:
+         error ("break statement used with OpenMP for loop");
+         break;
        }
-      else
-       statement = finish_break_stmt ();
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       break;
 
     case RID_CONTINUE:
-      if (!parser->in_iteration_statement_p)
+      switch (parser->in_statement & ~IN_SWITCH_STMT)
        {
+       case 0:
          error ("continue statement not within a loop");
-         statement = error_mark_node;
+         break;
+       case IN_ITERATION_STMT:
+       case IN_OMP_FOR:
+         statement = finish_continue_stmt ();
+         break;
+       case IN_OMP_BLOCK:
+         error ("invalid exit from OpenMP structured block");
+         break;
+       default:
+         gcc_unreachable ();
        }
-      else
-       statement = finish_continue_stmt ();
       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
       break;
 
@@ -6818,13 +7079,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))
     {
@@ -6840,7 +7109,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);
     }
@@ -6859,7 +7128,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
@@ -7019,9 +7288,10 @@ cp_parser_declaration (cp_parser* parser)
           && (/* A named namespace definition.  */
               (token2.type == CPP_NAME
                && (cp_lexer_peek_nth_token (parser->lexer, 3)->type
-                   == CPP_OPEN_BRACE))
+                   != CPP_EQ))
               /* An unnamed namespace definition.  */
-              || token2.type == CPP_OPEN_BRACE))
+              || token2.type == CPP_OPEN_BRACE
+              || token2.keyword == RID_ATTRIBUTE))
     cp_parser_namespace_definition (parser);
   /* Objective-C++ declaration/definition.  */
   else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
@@ -7051,6 +7321,11 @@ cp_parser_declaration (cp_parser* parser)
      __extension__ block-declaration
      label-declaration
 
+   C++0x Extension:
+
+   block-declaration:
+     static_assert-declaration
+
    If STATEMENT_P is TRUE, then this block-declaration is occurring as
    part of a declaration-statement.  */
 
@@ -7102,7 +7377,8 @@ cp_parser_block_declaration (cp_parser *parser,
        cp_parser_using_directive (parser);
       /* Otherwise, it's a using-declaration.  */
       else
-       cp_parser_using_declaration (parser);
+       cp_parser_using_declaration (parser,
+                                    /*access_declaration_p=*/false);
     }
   /* If the next keyword is `__label__' we have a label declaration.  */
   else if (token1->keyword == RID_LABEL)
@@ -7111,6 +7387,9 @@ cp_parser_block_declaration (cp_parser *parser,
        cp_parser_commit_to_tentative_parse (parser);
       cp_parser_label_declaration (parser);
     }
+  /* If the next token is `static_assert' we have a static assertion.  */
+  else if (token1->keyword == RID_STATIC_ASSERT)
+    cp_parser_static_assert (parser, /*member_p=*/false);
   /* Anything else must be a simple-declaration.  */
   else
     cp_parser_simple_declaration (parser, !statement_p);
@@ -7214,6 +7493,7 @@ cp_parser_simple_declaration (cp_parser* parser,
 
       /* Parse the init-declarator.  */
       decl = cp_parser_init_declarator (parser, &decl_specifiers,
+                                       /*checks=*/NULL,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
                                        declares_class_or_enum,
@@ -7364,10 +7644,17 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
          /* decl-specifier:
               friend  */
        case RID_FRIEND:
-         if (decl_specs->specs[(int) ds_friend]++)
-           error ("duplicate %<friend%>");
-         /* Consume the token.  */
-         cp_lexer_consume_token (parser->lexer);
+         if (!at_class_scope_p ())
+           {
+             error ("%<friend%> used outside of class");
+             cp_lexer_purge_token (parser->lexer);
+           }
+         else
+           {
+             ++decl_specs->specs[(int) ds_friend];
+             /* Consume the token.  */
+             cp_lexer_consume_token (parser->lexer);
+           }
          break;
 
          /* function-specifier:
@@ -7391,6 +7678,9 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
          /* The "typedef" keyword can only occur in a declaration; we
             may as well commit at this point.  */
          cp_parser_commit_to_tentative_parse (parser);
+
+          if (decl_specs->storage_class != sc_none)
+            decl_specs->conflicting_specifiers_p = true;
          break;
 
          /* storage-class-specifier:
@@ -7403,39 +7693,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
             GNU Extension:
               thread  */
        case RID_AUTO:
-         /* Consume the token.  */
-         cp_lexer_consume_token (parser->lexer);
-         cp_parser_set_storage_class (decl_specs, sc_auto);
-         break;
        case RID_REGISTER:
-         /* Consume the token.  */
-         cp_lexer_consume_token (parser->lexer);
-         cp_parser_set_storage_class (decl_specs, sc_register);
-         break;
        case RID_STATIC:
-         /* Consume the token.  */
-         cp_lexer_consume_token (parser->lexer);
-         if (decl_specs->specs[(int) ds_thread])
-           {
-             error ("%<__thread%> before %<static%>");
-             decl_specs->specs[(int) ds_thread] = 0;
-           }
-         cp_parser_set_storage_class (decl_specs, sc_static);
-         break;
        case RID_EXTERN:
-         /* Consume the token.  */
-         cp_lexer_consume_token (parser->lexer);
-         if (decl_specs->specs[(int) ds_thread])
-           {
-             error ("%<__thread%> before %<extern%>");
-             decl_specs->specs[(int) ds_thread] = 0;
-           }
-         cp_parser_set_storage_class (decl_specs, sc_extern);
-         break;
        case RID_MUTABLE:
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
-         cp_parser_set_storage_class (decl_specs, sc_mutable);
+         cp_parser_set_storage_class (parser, decl_specs, token->keyword);
          break;
        case RID_THREAD:
          /* Consume the token.  */
@@ -7531,6 +7795,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
+  cp_parser_check_decl_spec (decl_specs);
+
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
@@ -7565,7 +7831,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;
@@ -7594,7 +7860,12 @@ cp_parser_function_specifier_opt (cp_parser* parser,
       break;
 
     case RID_VIRTUAL:
-      if (decl_specs)
+      /* 14.5.2.3 [temp.mem]
+
+        A member function template shall not be virtual.  */
+      if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+       error ("templates may not be %<virtual%>");
+      else if (decl_specs)
        ++decl_specs->specs[(int) ds_virtual];
       break;
 
@@ -7608,7 +7879,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.
@@ -7663,9 +7934,7 @@ cp_parser_linkage_specification (cp_parser* parser)
       saved_in_unbraced_linkage_specification_p
        = parser->in_unbraced_linkage_specification_p;
       parser->in_unbraced_linkage_specification_p = true;
-      have_extern_spec = true;
       cp_parser_declaration (parser);
-      have_extern_spec = false;
       parser->in_unbraced_linkage_specification_p
        = saved_in_unbraced_linkage_specification_p;
     }
@@ -7674,6 +7943,68 @@ cp_parser_linkage_specification (cp_parser* parser)
   pop_lang_context ();
 }
 
+/* Parse a static_assert-declaration.
+
+   static_assert-declaration:
+     static_assert ( constant-expression , string-literal ) ; 
+
+   If MEMBER_P, this static_assert is a class member.  */
+
+static void 
+cp_parser_static_assert(cp_parser *parser, bool member_p)
+{
+  tree condition;
+  tree message;
+  cp_token *token;
+  location_t saved_loc;
+
+  /* Peek at the `static_assert' token so we can keep track of exactly
+     where the static assertion started.  */
+  token = cp_lexer_peek_token (parser->lexer);
+  saved_loc = token->location;
+
+  /* Look for the `static_assert' keyword.  */
+  if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, 
+                                  "`static_assert'"))
+    return;
+
+  /*  We know we are in a static assertion; commit to any tentative
+      parse.  */
+  if (cp_parser_parsing_tentatively (parser))
+    cp_parser_commit_to_tentative_parse (parser);
+
+  /* Parse the `(' starting the static assertion condition.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+
+  /* Parse the constant-expression.  */
+  condition = 
+    cp_parser_constant_expression (parser,
+                                   /*allow_non_constant_p=*/false,
+                                   /*non_constant_p=*/NULL);
+
+  /* Parse the separating `,'.  */
+  cp_parser_require (parser, CPP_COMMA, "`,'");
+
+  /* Parse the string-literal message.  */
+  message = cp_parser_string_literal (parser, 
+                                      /*translate=*/false,
+                                      /*wide_ok=*/true);
+
+  /* A `)' completes the static assertion.  */
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+    cp_parser_skip_to_closing_parenthesis (parser, 
+                                           /*recovering=*/true, 
+                                           /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  /* A semicolon terminates the declaration.  */
+  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+
+  /* Complete the static assertion, which may mean either processing 
+     the static assert now or saving it for template instantiation.  */
+  finish_static_assert (condition, message, saved_loc, member_p);
+}
+
 /* Special member functions [gram.special] */
 
 /* Parse a conversion-function-id.
@@ -8240,27 +8571,6 @@ cp_parser_operator (cp_parser* parser)
       cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
       return ansi_opname (ARRAY_REF);
 
-      /* Extensions.  */
-    case CPP_MIN:
-      id = ansi_opname (MIN_EXPR);
-      cp_parser_warn_min_max ();
-      break;
-
-    case CPP_MAX:
-      id = ansi_opname (MAX_EXPR);
-      cp_parser_warn_min_max ();
-      break;
-
-    case CPP_MIN_EQ:
-      id = ansi_assopname (MIN_EXPR);
-      cp_parser_warn_min_max ();
-      break;
-
-    case CPP_MAX_EQ:
-      id = ansi_assopname (MAX_EXPR);
-      cp_parser_warn_min_max ();
-      break;
-
     default:
       /* Anything else is an error.  */
       break;
@@ -8344,6 +8654,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
        parameter_list = process_template_parm (parameter_list,
                                                parameter,
                                                is_non_type);
+      else
+       {
+         tree err_parm = build_tree_list (parameter, parameter);
+         TREE_VALUE (err_parm) = error_mark_node;
+         parameter_list = chainon (parameter_list, err_parm);
+       }
+
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
       /* If it's not a `,', we're done.  */
@@ -8481,7 +8798,9 @@ cp_parser_type_parameter (cp_parser* parser)
            /* Consume the `=' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Parse the default-argument.  */
+           push_deferring_access_checks (dk_no_deferred);
            default_argument = cp_parser_type_id (parser);
+           pop_deferring_access_checks ();
          }
        else
          default_argument = NULL_TREE;
@@ -8535,12 +8854,14 @@ cp_parser_type_parameter (cp_parser* parser)
            /* Consume the `='.  */
            cp_lexer_consume_token (parser->lexer);
            /* Parse the id-expression.  */
+           push_deferring_access_checks (dk_no_deferred);
            default_argument
              = cp_parser_id_expression (parser,
                                         /*template_keyword_p=*/false,
                                         /*check_dependency_p=*/true,
                                         /*template_p=*/&is_template,
-                                        /*declarator_p=*/false);
+                                        /*declarator_p=*/false,
+                                        /*optional_p=*/false);
            if (TREE_CODE (default_argument) == TYPE_DECL)
              /* If the id-expression was a template-id that refers to
                 a template-class, we already have the declaration here,
@@ -8558,6 +8879,7 @@ cp_parser_type_parameter (cp_parser* parser)
            /* See if the default argument is valid.  */
            default_argument
              = check_template_template_default_arg (default_argument);
+           pop_deferring_access_checks ();
          }
        else
          default_argument = NULL_TREE;
@@ -8596,11 +8918,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;
 
@@ -8609,17 +8933,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));
+      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
@@ -8711,10 +9043,19 @@ cp_parser_template_id (cp_parser *parser,
     template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
   else if (DECL_CLASS_TEMPLATE_P (template)
           || DECL_TEMPLATE_TEMPLATE_PARM_P (template))
-    template_id
-      = finish_template_type (template, arguments,
-                             cp_lexer_next_token_is (parser->lexer,
-                                                     CPP_SCOPE));
+    {
+      bool entering_scope;
+      /* In "template <typename T> ... A<T>::", A<T> is the abstract A
+        template (rather than some instantiation thereof) only if
+        is not nested within some other construct.  For example, in
+        "template <typename T> void f(T) { A<T>::", A<T> is just an
+        instantiation of A.  */
+      entering_scope = (template_parm_scope_p ()
+                       && cp_lexer_next_token_is (parser->lexer,
+                                                  CPP_SCOPE));
+      template_id
+       = finish_template_type (template, arguments, entering_scope);
+    }
   else
     {
       /* If it's not a class-template or a template-template, it should be
@@ -8726,10 +9067,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
@@ -8742,7 +9079,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.  */
@@ -8974,8 +9315,8 @@ cp_parser_template_argument_list (cp_parser* parser)
   saved_in_template_argument_list_p = parser->in_template_argument_list_p;
   parser->in_template_argument_list_p = true;
   /* Even if the template-id appears in an integral
-     constant-expression, the contents of the argument list do 
-     not.  */ 
+     constant-expression, the contents of the argument list do
+     not.  */
   saved_ice_p = parser->integral_constant_expression_p;
   parser->integral_constant_expression_p = false;
   saved_non_ice_p = parser->non_integral_constant_expression_p;
@@ -9094,7 +9435,8 @@ cp_parser_template_argument (cp_parser* parser)
                                      /*template_keyword_p=*/false,
                                      /*check_dependency_p=*/true,
                                      &template_p,
-                                     /*declarator_p=*/false);
+                                     /*declarator_p=*/false,
+                                     /*optional_p=*/false);
   /* If the next token isn't a `,' or a `>', then this argument wasn't
      really finished.  */
   if (!cp_parser_next_token_ends_template_argument_p (parser))
@@ -9177,17 +9519,12 @@ cp_parser_template_argument (cp_parser* parser)
              argument = TREE_OPERAND (argument, 0);
            }
 
-         if (TREE_CODE (argument) == BASELINK)
-           /* We don't need the information about what class was used
-              to name the overloaded functions.  */  
-           argument = BASELINK_FUNCTIONS (argument);
-
          if (TREE_CODE (argument) == VAR_DECL)
            {
              /* A variable without external linkage might still be a
                 valid constant-expression, so no error is issued here
                 if the external-linkage check fails.  */
-             if (!DECL_EXTERNAL_LINKAGE_P (argument))
+             if (!address_p && !DECL_EXTERNAL_LINKAGE_P (argument))
                cp_parser_simulate_error (parser);
            }
          else if (is_overloaded_fn (argument))
@@ -9311,7 +9648,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
       pop_deferring_access_checks ();
       if (type)
        do_type_instantiation (type, extension_specifier,
-                               /*complain=*/tf_error);
+                              /*complain=*/tf_error);
     }
   else
     {
@@ -9330,7 +9667,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
       if (declarator != cp_error_declarator)
        {
          decl = grokdeclarator (declarator, &decl_specifiers,
-                                NORMAL, 0, NULL);
+                                NORMAL, 0, &decl_specifiers.attributes);
          /* Turn access control back on for names used during
             template instantiation.  */
          pop_deferring_access_checks ();
@@ -9376,9 +9713,9 @@ cp_parser_explicit_specialization (cp_parser* parser)
   /* We have processed another parameter list.  */
   ++parser->num_template_parameter_lists;
   /* [temp]
-   
+
      A template ... explicit specialization ... shall not have C
-     linkage.  */ 
+     linkage.  */
   if (current_lang_name == lang_name_c)
     {
       error ("template specialization with C linkage");
@@ -9390,7 +9727,13 @@ cp_parser_explicit_specialization (cp_parser* parser)
   else
     need_lang_pop = false;
   /* Let the front end know that we are beginning a specialization.  */
-  begin_specialization ();
+  if (!begin_specialization ())
+    {
+      end_specialization ();
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      return;
+    }
+
   /* If the next keyword is `template', we need to figure out whether
      or not we're looking a template-declaration.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
@@ -9405,6 +9748,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
   else
     /* Parse the dependent declaration.  */
     cp_parser_single_declaration (parser,
+                                 /*checks=*/NULL,
                                  /*member_p=*/false,
                                  /*friend_p=*/NULL);
   /* We're done with the specialization.  */
@@ -9478,22 +9822,11 @@ cp_parser_type_specifier (cp_parser* parser,
   switch (keyword)
     {
     case RID_ENUM:
-      /* 'enum' [identifier] '{' introduces an enum-specifier;
-        'enum' <anything else> introduces an elaborated-type-specifier.  */
-      if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE
-         || (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME
-             && cp_lexer_peek_nth_token (parser->lexer, 3)->type
-                == CPP_OPEN_BRACE))
+      /* Look for the enum-specifier.  */
+      type_spec = cp_parser_enum_specifier (parser);
+      /* If that worked, we're done.  */
+      if (type_spec)
        {
-         if (parser->num_template_parameter_lists)
-           {
-             error ("template declaration of %qs", "enum");
-             cp_parser_skip_to_end_of_block_or_statement (parser);
-             type_spec = error_mark_node;
-           }
-         else
-           type_spec = cp_parser_enum_specifier (parser);
-
          if (declares_class_or_enum)
            *declares_class_or_enum = 2;
          if (decl_specs)
@@ -9582,7 +9915,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
@@ -9725,7 +10058,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
@@ -9994,7 +10327,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 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;
@@ -10026,7 +10360,6 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
        type = TREE_TYPE (decl);
     }
 
-  /* For an enumeration type, consider only a plain identifier.  */
   if (!type)
     {
       identifier = cp_parser_identifier (parser);
@@ -10088,10 +10421,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);
        }
@@ -10154,23 +10492,39 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
          else
            ts = ts_global;
 
-         /* Warn about attributes. They are ignored.  */
-         if (attributes)
-           warning (OPT_Wattributes,
-                    "type attributes are honored only at type definition");
-
-         template_p = 
+         template_p =
            (parser->num_template_parameter_lists
             && (cp_parser_next_token_starts_class_definition_p (parser)
                 || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)));
          /* An unqualified name was used to reference this type, so
             there were no qualifying templates.  */
-         if (!cp_parser_check_template_parameters (parser, 
+         if (!cp_parser_check_template_parameters (parser,
                                                    /*num_templates=*/0))
            return error_mark_node;
          type = xref_tag (tag_type, identifier, ts, template_p);
        }
     }
+
+  if (type == error_mark_node)
+    return error_mark_node;
+
+  /* Allow attributes on forward declarations of classes.  */
+  if (attributes)
+    {
+      if (TREE_CODE (type) == TYPENAME_TYPE)
+       warning (OPT_Wattributes,
+                "attributes ignored on uninstantiated type");
+      else if (tag_type != enum_type && CLASSTYPE_TEMPLATE_INSTANTIATION (type)
+              && ! processing_explicit_instantiation)
+       warning (OPT_Wattributes,
+                "attributes ignored on template instantiation");
+      else if (is_declaration && cp_parser_declares_only_class_p (parser))
+       cplus_decl_attributes (&type, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
+      else
+       warning (OPT_Wattributes,
+                "attributes ignored on elaborated-type-specifier that is not a forward declaration");
+    }
+
   if (tag_type != enum_type)
     cp_parser_check_class_key (tag_type, type);
 
@@ -10187,15 +10541,22 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
      enum identifier [opt] { enumerator-list [opt] }
 
    GNU Extensions:
-     enum identifier [opt] { enumerator-list [opt] } attributes
+     enum attributes[opt] identifier [opt] { enumerator-list [opt] }
+       attributes[opt]
 
-   Returns an ENUM_TYPE representing the enumeration.  */
+   Returns an ENUM_TYPE representing the enumeration, or NULL_TREE
+   if the token stream isn't an enum-specifier after all.  */
 
 static tree
 cp_parser_enum_specifier (cp_parser* parser)
 {
   tree identifier;
   tree type;
+  tree attributes;
+
+  /* Parse tentatively so that we can back up if we don't find a
+     enum-specifier.  */
+  cp_parser_parse_tentatively (parser);
 
   /* Caller guarantees that the current token is 'enum', an identifier
      possibly follows, and the token after that is an opening brace.
@@ -10203,22 +10564,38 @@ cp_parser_enum_specifier (cp_parser* parser)
      the enumeration being defined.  */
   cp_lexer_consume_token (parser->lexer);
 
+  attributes = cp_parser_attributes_opt (parser);
+
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     identifier = cp_parser_identifier (parser);
   else
     identifier = make_anon_name ();
 
-  /* Issue an error message if type-definitions are forbidden here.  */
-  cp_parser_check_type_definition (parser);
+  /* Look for the `{' but don't consume it yet.  */
+  if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    cp_parser_simulate_error (parser);
 
-  /* Create the new type.  We do this before consuming the opening brace
-     so the enum will be recorded as being on the line of its tag (or the
-     'enum' keyword, if there is no tag).  */
-  type = start_enum (identifier);
+  if (!cp_parser_parse_definitely (parser))
+    return NULL_TREE;
 
+  /* Issue an error message if type-definitions are forbidden here.  */
+  if (!cp_parser_check_type_definition (parser))
+    type = error_mark_node;
+  else
+    /* Create the new type.  We do this before consuming the opening
+       brace so the enum will be recorded as being on the line of its
+       tag (or the 'enum' keyword, if there is no tag).  */
+    type = start_enum (identifier);
+  
   /* Consume the opening brace.  */
   cp_lexer_consume_token (parser->lexer);
 
+  if (type == error_mark_node)
+    {
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      return error_mark_node;
+    }
+
   /* If the next token is not '}', then there are some enumerators.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
     cp_parser_enumerator_list (parser, type);
@@ -10389,7 +10766,7 @@ cp_parser_namespace_name (cp_parser* parser)
 static void
 cp_parser_namespace_definition (cp_parser* parser)
 {
-  tree identifier;
+  tree identifier, attribs;
 
   /* Look for the `namespace' keyword.  */
   cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
@@ -10403,10 +10780,13 @@ cp_parser_namespace_definition (cp_parser* parser)
   else
     identifier = NULL_TREE;
 
+  /* Parse any specified attributes.  */
+  attribs = cp_parser_attributes_opt (parser);
+
   /* Look for the `{' to start the namespace.  */
   cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
   /* Start the namespace.  */
-  push_namespace (identifier);
+  push_namespace_with_attribs (identifier, attribs);
   /* Parse the body of the namespace.  */
   cp_parser_namespace_body (parser);
   /* Finish the namespace.  */
@@ -10480,14 +10860,21 @@ cp_parser_qualified_namespace_specifier (cp_parser* parser)
   return cp_parser_namespace_name (parser);
 }
 
-/* Parse a using-declaration.
+/* Parse a using-declaration, or, if ACCESS_DECLARATION_P is true, an
+   access declaration.
 
    using-declaration:
      using typename [opt] :: [opt] nested-name-specifier unqualified-id ;
-     using :: unqualified-id ;  */
+     using :: unqualified-id ;  
 
-static void
-cp_parser_using_declaration (cp_parser* parser)
+   access-declaration:
+     qualified-id ;  
+
+   */
+
+static bool
+cp_parser_using_declaration (cp_parser* parser, 
+                            bool access_declaration_p)
 {
   cp_token *token;
   bool typename_p = false;
@@ -10496,18 +10883,23 @@ cp_parser_using_declaration (cp_parser* parser)
   tree identifier;
   tree qscope;
 
-  /* Look for the `using' keyword.  */
-  cp_parser_require_keyword (parser, RID_USING, "`using'");
-
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  /* See if it's `typename'.  */
-  if (token->keyword == RID_TYPENAME)
+  if (access_declaration_p)
+    cp_parser_parse_tentatively (parser);
+  else
     {
-      /* Remember that we've seen it.  */
-      typename_p = true;
-      /* Consume the `typename' token.  */
-      cp_lexer_consume_token (parser->lexer);
+      /* Look for the `using' keyword.  */
+      cp_parser_require_keyword (parser, RID_USING, "`using'");
+      
+      /* Peek at the next token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      /* See if it's `typename'.  */
+      if (token->keyword == RID_TYPENAME)
+       {
+         /* Remember that we've seen it.  */
+         typename_p = true;
+         /* Consume the `typename' token.  */
+         cp_lexer_consume_token (parser->lexer);
+       }
     }
 
   /* Look for the optional global scope qualification.  */
@@ -10534,11 +10926,26 @@ cp_parser_using_declaration (cp_parser* parser)
   if (!qscope)
     qscope = global_namespace;
 
+  if (access_declaration_p && cp_parser_error_occurred (parser))
+    /* Something has already gone wrong; there's no need to parse
+       further.  Since an error has occurred, the return value of
+       cp_parser_parse_definitely will be false, as required.  */
+    return cp_parser_parse_definitely (parser);
+
   /* Parse the unqualified-id.  */
   identifier = cp_parser_unqualified_id (parser,
                                         /*template_keyword_p=*/false,
                                         /*check_dependency_p=*/true,
-                                        /*declarator_p=*/true);
+                                        /*declarator_p=*/true,
+                                        /*optional_p=*/false);
+
+  if (access_declaration_p)
+    {
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       cp_parser_simulate_error (parser);
+      if (!cp_parser_parse_definitely (parser))
+       return false;
+    }
 
   /* The function we call to handle a using-declaration is different
      depending on what scope we are in.  */
@@ -10573,6 +10980,8 @@ cp_parser_using_declaration (cp_parser* parser)
 
   /* Look for the final `;'.  */
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  
+  return true;
 }
 
 /* Parse a using-directive.
@@ -10665,7 +11074,7 @@ cp_parser_asm_definition (cp_parser* parser)
      too.  Doing that means that we have to treat the `::' operator as
      two `:' tokens.  */
   if (cp_parser_allow_gnu_extensions_p (parser)
-      && at_function_scope_p ()
+      && parser->in_function_body
       && (cp_lexer_next_token_is (parser->lexer, CPP_COLON)
          || cp_lexer_next_token_is (parser->lexer, CPP_SCOPE)))
     {
@@ -10731,7 +11140,7 @@ cp_parser_asm_definition (cp_parser* parser)
   cp_parser_require (parser, CPP_SEMICOLON, "`;'");
 
   /* Create the ASM_EXPR.  */
-  if (at_function_scope_p ())
+  if (parser->in_function_body)
     {
       asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
                                  inputs, clobbers);
@@ -10771,10 +11180,14 @@ cp_parser_asm_definition (cp_parser* parser)
    function-definition:
      __extension__ function-definition
 
-   The DECL_SPECIFIERS and PREFIX_ATTRIBUTES apply to this declarator.
-   Returns a representation of the entity declared.  If MEMBER_P is TRUE,
-   then this declarator appears in a class scope.  The new DECL created
-   by this declarator is returned.
+   The DECL_SPECIFIERS apply to this declarator.  Returns a
+   representation of the entity declared.  If MEMBER_P is TRUE, then
+   this declarator appears in a class scope.  The new DECL created by
+   this declarator is returned.
+
+   The CHECKS are access checks that should be performed once we know
+   what entity is being declared (and, therefore, what classes have
+   befriended it).
 
    If FUNCTION_DEFINITION_ALLOWED_P then we handle the declarator and
    for a function-definition here as well.  If the declarator is a
@@ -10788,6 +11201,7 @@ cp_parser_asm_definition (cp_parser* parser)
 static tree
 cp_parser_init_declarator (cp_parser* parser,
                           cp_decl_specifier_seq *decl_specifiers,
+                          VEC (deferred_access_check,gc)* checks,
                           bool function_definition_allowed_p,
                           bool member_p,
                           int declares_class_or_enum,
@@ -10802,7 +11216,11 @@ cp_parser_init_declarator (cp_parser* parser,
   tree decl = NULL_TREE;
   tree scope;
   bool is_initialized;
-  bool is_parenthesized_init;
+  /* Only valid if IS_INITIALIZED is true.  In that case, CPP_EQ if
+     initialized with "= ..", CPP_OPEN_PAREN if initialized with
+     "(...)".  */
+  enum cpp_ttype initialization_kind;
+  bool is_parenthesized_init = false;
   bool is_non_constant_init;
   int ctor_dtor_or_conv_p;
   bool friend_p;
@@ -10836,6 +11254,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);
@@ -10916,16 +11338,24 @@ cp_parser_init_declarator (cp_parser* parser,
     }
 
   /* An `=' or an `(' indicates an initializer.  */
-  is_initialized = (token->type == CPP_EQ
-                    || token->type == CPP_OPEN_PAREN);
-  /* If the init-declarator isn't initialized and isn't followed by a
-     `,' or `;', it's not a valid init-declarator.  */
-  if (!is_initialized
-      && token->type != CPP_COMMA
-      && token->type != CPP_SEMICOLON)
+  if (token->type == CPP_EQ
+      || token->type == CPP_OPEN_PAREN)
     {
-      cp_parser_error (parser, "expected initializer");
-      return error_mark_node;
+      is_initialized = true;
+      initialization_kind = token->type;
+    }
+  else
+    {
+      /* If the init-declarator isn't initialized and isn't followed by a
+        `,' or `;', it's not a valid init-declarator.  */
+      if (token->type != CPP_COMMA
+         && token->type != CPP_SEMICOLON)
+       {
+         cp_parser_error (parser, "expected initializer");
+         return error_mark_node;
+       }
+      is_initialized = false;
+      initialization_kind = CPP_EOF;
     }
 
   /* Because start_decl has side-effects, we should only call it if we
@@ -10947,20 +11377,13 @@ 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.  */
   if (!member_p)
     {
       if (parser->in_unbraced_linkage_specification_p)
-       {
-         decl_specifiers->storage_class = sc_extern;
-         have_extern_spec = false;
-       }
+       decl_specifiers->storage_class = sc_extern;
       decl = start_decl (declarator, decl_specifiers,
                         is_initialized, attributes, prefix_attributes,
                         &pushed_scope);
@@ -10985,6 +11408,9 @@ cp_parser_init_declarator (cp_parser* parser,
          current_function_decl = decl;
        }
 
+      /* Perform access checks for template parameters.  */
+      cp_parser_perform_template_parameter_access_checks (checks);
+
       /* Perform the access control checks for the declarator and the
         the decl-specifiers.  */
       perform_deferred_access_checks ();
@@ -10995,15 +11421,32 @@ cp_parser_init_declarator (cp_parser* parser,
     }
 
   /* Parse the initializer.  */
+  initializer = NULL_TREE;
+  is_parenthesized_init = false;
+  is_non_constant_init = true;
   if (is_initialized)
-    initializer = cp_parser_initializer (parser,
-                                        &is_parenthesized_init,
-                                        &is_non_constant_init);
-  else
     {
-      initializer = NULL_TREE;
-      is_parenthesized_init = false;
-      is_non_constant_init = true;
+      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,
+                                            &is_non_constant_init);
     }
 
   /* The old parser allows attributes to appear after a parenthesized
@@ -11025,7 +11468,8 @@ cp_parser_init_declarator (cp_parser* parser,
          pushed_scope = false;
        }
       decl = grokfield (declarator, decl_specifiers,
-                       initializer, /*asmspec=*/NULL_TREE,
+                       initializer, !is_non_constant_init,
+                       /*asmspec=*/NULL_TREE,
                        prefix_attributes);
       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
        cp_parser_save_default_args (parser, decl);
@@ -11036,7 +11480,7 @@ cp_parser_init_declarator (cp_parser* parser,
   if (!friend_p && decl && decl != error_mark_node)
     {
       cp_finish_decl (decl,
-                     initializer,
+                     initializer, !is_non_constant_init,
                      asm_specification,
                      /* If the initializer is in parentheses, then this is
                         a direct-initialization, which means that an
@@ -11048,12 +11492,6 @@ cp_parser_init_declarator (cp_parser* parser,
   if (!friend_p && pushed_scope)
     pop_scope (pushed_scope);
 
-  /* Remember whether or not variables were initialized by
-     constant-expressions.  */
-  if (decl && TREE_CODE (decl) == VAR_DECL
-      && is_initialized && !is_non_constant_init)
-    DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
-
   return decl;
 }
 
@@ -11172,7 +11610,7 @@ cp_parser_declarator (cp_parser* parser,
                                                member_p);
     }
 
-  if (attributes && declarator != cp_error_declarator)
+  if (attributes && declarator && declarator != cp_error_declarator)
     declarator->attributes = attributes;
 
   return declarator;
@@ -11396,7 +11834,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              /* Normally, the array bound must be an integral constant
                 expression.  However, as an extension, we allow VLAs
                 in function scopes.  */
-             else if (!at_function_scope_p ())
+             else if (!parser->in_function_body)
                {
                  error ("array bound is not an integer constant");
                  bounds = error_mark_node;
@@ -11418,25 +11856,31 @@ cp_parser_direct_declarator (cp_parser* parser,
          tree qualifying_scope;
          tree unqualified_name;
          special_function_kind sfk;
+         bool abstract_ok;
 
          /* Parse a declarator-id */
-         if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
+         abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
+         if (abstract_ok)
            cp_parser_parse_tentatively (parser);
-         unqualified_name = cp_parser_declarator_id (parser);
+         unqualified_name
+           = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
          qualifying_scope = parser->scope;
-         if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
+         if (abstract_ok)
            {
              if (!cp_parser_parse_definitely (parser))
                unqualified_name = error_mark_node;
-             else if (qualifying_scope
-                      || (TREE_CODE (unqualified_name)
-                          != IDENTIFIER_NODE))
+             else if (unqualified_name
+                      && (qualifying_scope
+                          || (TREE_CODE (unqualified_name)
+                              != IDENTIFIER_NODE)))
                {
                  cp_parser_error (parser, "expected unqualified-id");
                  unqualified_name = error_mark_node;
                }
            }
 
+         if (!unqualified_name)
+           return NULL;
          if (unqualified_name == error_mark_node)
            {
              declarator = cp_error_declarator;
@@ -11539,7 +11983,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                    *ctor_dtor_or_conv_p = -1;
                }
            }
-         declarator = make_id_declarator (qualifying_scope, 
+         declarator = make_id_declarator (qualifying_scope,
                                           unqualified_name,
                                           sfk);
          declarator->id_loc = token->location;
@@ -11650,17 +12094,23 @@ cp_parser_ptr_operator (cp_parser* parser,
       if (!cp_parser_error_occurred (parser)
          && cp_parser_require (parser, CPP_MULT, "`*'"))
        {
-         /* The type of which the member is a member is given by the
-            current SCOPE.  */
-         *type = parser->scope;
-         /* The next name will not be qualified.  */
-         parser->scope = NULL_TREE;
-         parser->qualifying_scope = NULL_TREE;
-         parser->object_scope = NULL_TREE;
          /* Indicate that the `*' operator was used.  */
          code = INDIRECT_REF;
-         /* Look for the optional cv-qualifier-seq.  */
-         *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
+
+         if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
+           error ("%qD is a namespace", parser->scope);
+         else
+           {
+             /* The type of which the member is a member is given by the
+                current SCOPE.  */
+             *type = parser->scope;
+             /* The next name will not be qualified.  */
+             parser->scope = NULL_TREE;
+             parser->qualifying_scope = NULL_TREE;
+             parser->object_scope = NULL_TREE;
+             /* Look for the optional cv-qualifier-seq.  */
+             *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
+           }
        }
       /* If that didn't work we don't have a ptr-operator.  */
       if (!cp_parser_parse_definitely (parser))
@@ -11750,7 +12200,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
    unqualified-id.  */
 
 static tree
-cp_parser_declarator_id (cp_parser* parser)
+cp_parser_declarator_id (cp_parser* parser, bool optional_p)
 {
   tree id;
   /* The expression must be an id-expression.  Assume that qualified
@@ -11771,8 +12221,9 @@ cp_parser_declarator_id (cp_parser* parser)
                                /*template_keyword_p=*/false,
                                /*check_dependency_p=*/false,
                                /*template_p=*/NULL,
-                               /*declarator_p=*/true);
-  if (BASELINK_P (id))
+                               /*declarator_p=*/true,
+                               optional_p);
+  if (id && BASELINK_P (id))
     id = BASELINK_FUNCTIONS (id);
   return id;
 }
@@ -11893,6 +12344,8 @@ cp_parser_type_specifier_seq (cp_parser* parser,
       if (is_condition && !is_cv_qualifier)
        flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
+
+  cp_parser_check_decl_spec (type_specifier_seq);
 }
 
 /* Parse a parameter-declaration-clause.
@@ -11998,9 +12451,16 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
   cp_parameter_declarator *parameters = NULL;
   cp_parameter_declarator **tail = &parameters;
+  bool saved_in_unbraced_linkage_specification_p;
 
   /* Assume all will go well.  */
   *is_error = false;
+  /* The special considerations that apply to a function within an
+     unbraced linkage specifications do not apply to the parameters
+     to the function.  */
+  saved_in_unbraced_linkage_specification_p 
+    = parser->in_unbraced_linkage_specification_p;
+  parser->in_unbraced_linkage_specification_p = false;
 
   /* Look for more parameters.  */
   while (true)
@@ -12079,6 +12539,9 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
        }
     }
 
+  parser->in_unbraced_linkage_specification_p
+    = saved_in_unbraced_linkage_specification_p;
+
   return parameters;
 }
 
@@ -12308,10 +12771,21 @@ cp_parser_parameter_declaration (cp_parser *parser,
          saved_local_variables_forbidden_p
            = parser->local_variables_forbidden_p;
          parser->local_variables_forbidden_p = true;
+         /* The default argument expression may cause implicitly
+            defined member functions to be synthesized, which will
+            result in garbage collection.  We must treat this
+            situation as if we were within the body of function so as
+            to avoid collecting live data on the stack.  */
+         ++function_depth;
          /* Parse the assignment-expression.  */
+         if (template_parm_p)
+           push_deferring_access_checks (dk_no_deferred);
          default_argument
            = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+         if (template_parm_p)
+           pop_deferring_access_checks ();
          /* Restore saved state.  */
+         --function_depth;
          parser->greater_than_is_operator_p
            = saved_greater_than_is_operator_p;
          parser->local_variables_forbidden_p
@@ -12521,8 +12995,11 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          && cp_lexer_next_token_is (parser->lexer, CPP_NAME)
          && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
        {
+         /* Warn the user that they are using an extension.  */
+         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);
        }
@@ -12688,7 +13165,7 @@ cp_parser_class_name (cp_parser *parser,
   if (typename_p && decl != error_mark_node)
     {
       decl = make_typename_type (scope, decl, typename_type,
-                                 /*complain=*/tf_error);
+                                /*complain=*/tf_error);
       if (decl != error_mark_node)
        decl = TYPE_NAME (decl);
     }
@@ -12707,15 +13184,18 @@ cp_parser_class_name (cp_parser *parser,
        standard does not seem to be definitive, but there is no other
        valid interpretation of the following `::'.  Therefore, those
        names are considered class-names.  */
-    decl = TYPE_NAME (make_typename_type (scope, decl, tag_type, tf_error));
-  else if (decl == error_mark_node
-          || TREE_CODE (decl) != TYPE_DECL
-          || TREE_TYPE (decl) == error_mark_node
-          || !IS_AGGR_TYPE (TREE_TYPE (decl)))
     {
-      cp_parser_error (parser, "expected class-name");
-      return error_mark_node;
+      decl = make_typename_type (scope, decl, tag_type, tf_error);
+      if (decl != error_mark_node)
+       decl = TYPE_NAME (decl);
     }
+  else if (TREE_CODE (decl) != TYPE_DECL
+          || TREE_TYPE (decl) == error_mark_node
+          || !IS_AGGR_TYPE (TREE_TYPE (decl)))
+    decl = error_mark_node;
+
+  if (decl == error_mark_node)
+    cp_parser_error (parser, "expected class-name");
 
   return decl;
 }
@@ -12736,15 +13216,18 @@ cp_parser_class_specifier (cp_parser* parser)
   int has_trailing_semicolon;
   bool nested_name_specifier_p;
   unsigned saved_num_template_parameter_lists;
+  bool saved_in_function_body;
   tree old_scope = NULL_TREE;
   tree scope = NULL_TREE;
+  tree bases;
 
   push_deferring_access_checks (dk_no_deferred);
 
   /* Parse the class-head.  */
   type = cp_parser_class_head (parser,
                               &nested_name_specifier_p,
-                              &attributes);
+                              &attributes,
+                              &bases);
   /* If the class-head was a semantic disaster, skip the entire body
      of the class.  */
   if (!type)
@@ -12761,6 +13244,19 @@ cp_parser_class_specifier (cp_parser* parser)
       return error_mark_node;
     }
 
+  /* Process the base classes. If they're invalid, skip the 
+     entire class body.  */
+  if (!xref_basetypes (type, bases))
+    {
+      cp_parser_skip_to_closing_brace (parser);
+
+      /* Consuming the closing brace yields better error messages
+         later on.  */
+      cp_lexer_consume_token (parser->lexer);
+      pop_deferring_access_checks ();
+      return error_mark_node;
+    }
+
   /* Issue an error message if type-definitions are forbidden here.  */
   cp_parser_check_type_definition (parser);
   /* Remember that we are defining one more class.  */
@@ -12770,6 +13266,9 @@ cp_parser_class_specifier (cp_parser* parser)
   saved_num_template_parameter_lists
     = parser->num_template_parameter_lists;
   parser->num_template_parameter_lists = 0;
+  /* We are not in a function body.  */
+  saved_in_function_body = parser->in_function_body;
+  parser->in_function_body = false;
 
   /* Start the class.  */
   if (nested_name_specifier_p)
@@ -12777,7 +13276,7 @@ cp_parser_class_specifier (cp_parser* parser)
       scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));
       old_scope = push_inner_scope (scope);
     }
-  type = begin_class_definition (type);
+  type = begin_class_definition (type, attributes);
 
   if (type == error_mark_node)
     /* If the type is erroneous, skip the entire body of the class.  */
@@ -12794,10 +13293,7 @@ cp_parser_class_specifier (cp_parser* parser)
   has_trailing_semicolon = (token->type == CPP_SEMICOLON);
   /* Look for trailing attributes to apply to this class.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
-    {
-      tree sub_attr = cp_parser_attributes_opt (parser);
-      attributes = chainon (attributes, sub_attr);
-    }
+    attributes = cp_parser_attributes_opt (parser);
   if (type != error_mark_node)
     type = finish_struct (type, attributes);
   if (nested_name_specifier_p)
@@ -12828,7 +13324,7 @@ cp_parser_class_specifier (cp_parser* parser)
       tree fn;
       tree class_type = NULL_TREE;
       tree pushed_scope = NULL_TREE;
+
       /* In a first pass, parse default arguments to the functions.
         Then, in a second pass, parse the bodies of the functions.
         This two-phased approach handles cases like:
@@ -12881,7 +13377,8 @@ cp_parser_class_specifier (cp_parser* parser)
   /* Put back any saved access checks.  */
   pop_deferring_access_checks ();
 
-  /* Restore the count of active template-parameter-lists.  */
+  /* Restore saved state.  */
+  parser->in_function_body = saved_in_function_body;
   parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
 
@@ -12902,6 +13399,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.
@@ -12915,7 +13416,8 @@ cp_parser_class_specifier (cp_parser* parser)
 static tree
 cp_parser_class_head (cp_parser* parser,
                      bool* nested_name_specifier_p,
-                     tree *attributes_p)
+                     tree *attributes_p,
+                     tree *bases)
 {
   tree nested_name_specifier;
   enum tag_types class_key;
@@ -12928,7 +13430,6 @@ cp_parser_class_head (cp_parser* parser,
   bool invalid_explicit_specialization_p = false;
   tree pushed_scope = NULL_TREE;
   unsigned num_templates;
-  tree bases;
 
   /* Assume no nested-name-specifier will be present.  */
   *nested_name_specifier_p = false;
@@ -12936,6 +13437,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)
@@ -12975,7 +13478,7 @@ cp_parser_class_head (cp_parser* parser,
         define a class that has already been declared with this
         syntax.
 
-        The proposed resolution for Core Issue 180 says that whever
+        The proposed resolution for Core Issue 180 says that wherever
         you see `class T::X' you should treat `X' as a type-name.
 
         It is OK to define an inaccessible class; for example:
@@ -13143,7 +13646,7 @@ cp_parser_class_head (cp_parser* parser,
   if (template_id_p)
     {
       type = TREE_TYPE (id);
-      maybe_process_partial_specialization (type);
+      type = maybe_process_partial_specialization (type);
       if (nested_name_specifier)
        pushed_scope = push_scope (nested_name_specifier);
     }
@@ -13216,6 +13719,8 @@ cp_parser_class_head (cp_parser* parser,
       type = NULL_TREE;
       goto done;
     }
+  else if (type == error_mark_node)
+    type = NULL_TREE;
 
   /* We will have entered the scope containing the class; the names of
      base classes should be looked up in that context.  For example:
@@ -13224,14 +13729,10 @@ 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))
-    bases = cp_parser_base_clause (parser);
-
-  /* Process the base classes.  */
-  xref_basetypes (type, bases);
+    *bases = cp_parser_base_clause (parser);
 
  done:
   /* Leave the scope given by the nested-name-specifier.  We will
@@ -13308,7 +13809,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;
@@ -13354,7 +13855,12 @@ cp_parser_member_specification_opt (cp_parser* parser)
    member-declarator:
      declarator attributes [opt] pure-specifier [opt]
      declarator attributes [opt] constant-initializer [opt]
-     identifier [opt] attributes [opt] : constant-expression  */
+     identifier [opt] attributes [opt] : constant-expression  
+
+   C++0x Extensions:
+
+   member-declaration:
+     static_assert-declaration  */
 
 static void
 cp_parser_member_declaration (cp_parser* parser)
@@ -13396,8 +13902,8 @@ cp_parser_member_declaration (cp_parser* parser)
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
     {
       /* Parse the using-declaration.  */
-      cp_parser_using_declaration (parser);
-
+      cp_parser_using_declaration (parser,
+                                  /*access_declaration_p=*/false);
       return;
     }
 
@@ -13417,6 +13923,16 @@ cp_parser_member_declaration (cp_parser* parser)
       return;
     }
 
+  /* If the next token is `static_assert' we have a static assertion.  */
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC_ASSERT))
+    {
+      cp_parser_static_assert (parser, /*member_p=*/true);
+      return;
+    }
+
+  if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
+    return;
+
   /* Parse the decl-specifier-seq.  */
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
@@ -13630,7 +14146,7 @@ cp_parser_member_declaration (cp_parser* parser)
                     for a pure-specifier; otherwise, we look for a
                     constant-initializer.  When we call `grokfield', it will
                     perform more stringent semantics checks.  */
-                 if (declarator->kind == cdk_function)
+                 if (function_declarator_p (declarator))
                    initializer = cp_parser_pure_specifier (parser);
                  else
                    /* Parse the initializer.  */
@@ -13670,16 +14186,11 @@ cp_parser_member_declaration (cp_parser* parser)
                  return;
                }
              else
-               {
-                 /* Create the declaration.  */
-                 decl = grokfield (declarator, &decl_specifiers,
-                                   initializer, asm_specification,
-                                   attributes);
-                 /* Any initialization must have been from a
-                    constant-expression.  */
-                 if (decl && TREE_CODE (decl) == VAR_DECL && initializer)
-                   DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
-               }
+               /* Create the declaration.  */
+               decl = grokfield (declarator, &decl_specifiers,
+                                 initializer, /*init_const_expr_p=*/true,
+                                 asm_specification,
+                                 attributes);
            }
 
          /* Reset PREFIX_ATTRIBUTES.  */
@@ -13741,12 +14252,20 @@ cp_parser_pure_specifier (cp_parser* parser)
   /* Look for the `0' token.  */
   token = cp_lexer_consume_token (parser->lexer);
   /* c_lex_with_flags marks a single digit '0' with PURE_ZERO.  */
-  if (token->type == CPP_NUMBER && (token->flags & PURE_ZERO))
-    return integer_zero_node;
+  if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO))
+    {
+      cp_parser_error (parser,
+                      "invalid pure specifier (only `= 0' is allowed)");
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
+  if (PROCESSING_REAL_TEMPLATE_DECL_P ())
+    {
+      error ("templates may not be %<virtual%>");
+      return error_mark_node;
+    }
 
-  cp_parser_error (parser, "invalid pure specifier (only `= 0' is allowed)");
-  cp_parser_skip_to_end_of_statement (parser);
-  return error_mark_node;
+  return integer_zero_node;
 }
 
 /* Parse a constant-initializer.
@@ -14089,14 +14608,15 @@ cp_parser_try_block (cp_parser* parser)
 static bool
 cp_parser_function_try_block (cp_parser* parser)
 {
+  tree compound_stmt;
   tree try_block;
   bool ctor_initializer_p;
 
   /* 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.  */
-  try_block = begin_function_try_block ();
+  /* 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
     = cp_parser_ctor_initializer_opt_and_function_body (parser);
@@ -14105,7 +14625,7 @@ cp_parser_function_try_block (cp_parser* parser)
   /* Parse the handlers.  */
   cp_parser_handler_seq (parser);
   /* We're done with the handlers.  */
-  finish_function_handler_sequence (try_block);
+  finish_function_handler_sequence (try_block, compound_stmt);
 
   return ctor_initializer_p;
 }
@@ -14167,7 +14687,6 @@ cp_parser_handler (cp_parser* parser)
 static tree
 cp_parser_exception_declaration (cp_parser* parser)
 {
-  tree decl;
   cp_decl_specifier_seq type_specifiers;
   cp_declarator *declarator;
   const char *saved_message;
@@ -14200,16 +14719,10 @@ cp_parser_exception_declaration (cp_parser* parser)
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
 
-  if (type_specifiers.any_specifiers_p)
-    {
-      decl = grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
-      if (decl == NULL_TREE)
-       error ("invalid catch parameter");
-    }
-  else
-    decl = NULL_TREE;
+  if (!type_specifiers.any_specifiers_p)
+    return error_mark_node;
 
-  return decl;
+  return grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
 }
 
 /* Parse a throw-expression.
@@ -14469,12 +14982,14 @@ cp_parser_attribute_list (cp_parser* parser)
       if (token->type == CPP_NAME
          || token->type == CPP_KEYWORD)
        {
+         tree arguments = NULL_TREE;
+
          /* Consume the token.  */
          token = cp_lexer_consume_token (parser->lexer);
 
          /* 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.  */
@@ -14482,18 +14997,19 @@ cp_parser_attribute_list (cp_parser* parser)
          /* If it's an `(', then parse the attribute arguments.  */
          if (token->type == CPP_OPEN_PAREN)
            {
-             tree arguments;
-
-             arguments = (cp_parser_parenthesized_expression_list
-                          (parser, true, /*cast_p=*/false,
-                           /*non_constant_p=*/NULL));
-             /* Save the identifier and arguments away.  */
+             arguments = cp_parser_parenthesized_expression_list
+                         (parser, true, /*cast_p=*/false,
+                          /*non_constant_p=*/NULL);
+             /* Save the arguments away.  */
              TREE_VALUE (attribute) = arguments;
            }
 
-         /* Add this attribute to the list.  */
-         TREE_CHAIN (attribute) = attribute_list;
-         attribute_list = attribute;
+         if (arguments != error_mark_node)
+           {
+             /* Add this attribute to the list.  */
+             TREE_CHAIN (attribute) = attribute_list;
+             attribute_list = attribute;
+           }
 
          token = cp_lexer_peek_token (parser->lexer);
        }
@@ -14609,12 +15125,12 @@ cp_parser_label_declaration (cp_parser* parser)
 
    If AMBIGUOUS_DECLS is non-NULL, *AMBIGUOUS_DECLS is set to a
    TREE_LIST of candidates if name-lookup results in an ambiguity, and
-   NULL_TREE otherwise.  */ 
+   NULL_TREE otherwise.  */
 
 static tree
 cp_parser_lookup_name (cp_parser *parser, tree name,
                       enum tag_types tag_type,
-                      bool is_template, 
+                      bool is_template,
                       bool is_namespace,
                       bool check_dependency,
                       tree *ambiguous_decls)
@@ -14911,10 +15427,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);
@@ -15031,7 +15551,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
   /* The common case is that this is not a constructor declarator, so
      try to avoid doing lots of work if at all possible.  It's not
      valid declare a constructor at function scope.  */
-  if (at_function_scope_p ())
+  if (parser->in_function_body)
     return false;
   /* And only certain tokens can begin a constructor declarator.  */
   next_token = cp_lexer_peek_token (parser->lexer);
@@ -15108,8 +15628,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
          /* A parameter declaration begins with a decl-specifier,
             which is either the "attribute" keyword, a storage class
             specifier, or (usually) a type-specifier.  */
-         && !cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE)
-         && !cp_parser_storage_class_specifier_opt (parser))
+         && !cp_lexer_next_token_is_decl_specifier_keyword (parser->lexer))
        {
          tree type;
          tree pushed_scope = NULL_TREE;
@@ -15199,10 +15718,19 @@ cp_parser_function_definition_from_specifiers_and_declarator
   if (!success_p)
     {
       /* Skip the entire function.  */
-      error ("invalid function declaration");
       cp_parser_skip_to_end_of_block_or_statement (parser);
       fn = error_mark_node;
     }
+  else if (DECL_INITIAL (current_function_decl) != error_mark_node)
+    {
+      /* Seen already, skip it.  An error message has already been output.  */
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      fn = current_function_decl;
+      current_function_decl = NULL_TREE;
+      /* If this is a function from a class, pop the nested class.  */
+      if (current_class_name)
+       pop_nested_class ();
+    }
   else
     fn = cp_parser_function_definition_after_declarator (parser,
                                                         /*inline_p=*/false);
@@ -15223,8 +15751,11 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   tree fn;
   bool ctor_initializer_p = false;
   bool saved_in_unbraced_linkage_specification_p;
+  bool saved_in_function_body;
   unsigned saved_num_template_parameter_lists;
 
+  saved_in_function_body = parser->in_function_body;
+  parser->in_function_body = true;
   /* If the next token is `return', then the code may be trying to
      make use of the "named return value" extension that G++ used to
      support.  */
@@ -15278,6 +15809,7 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
     = saved_in_unbraced_linkage_specification_p;
   parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
+  parser->in_function_body = saved_in_function_body;
 
   return fn;
 }
@@ -15290,6 +15822,7 @@ static void
 cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 {
   tree decl = NULL_TREE;
+  VEC (deferred_access_check,gc) *checks;
   tree parameter_list;
   bool friend_p = false;
   bool need_lang_pop;
@@ -15301,8 +15834,17 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   /* And the `<'.  */
   if (!cp_parser_require (parser, CPP_LESS, "`<'"))
     return;
+  if (at_class_scope_p () && current_function_decl)
+    {
+      /* 14.5.2.2 [temp.mem]
+
+         A local class shall not have member templates.  */
+      error ("invalid declaration of member template in local class");
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+      return;
+    }
   /* [temp]
-   
+
      A template ... shall not have C linkage.  */
   if (current_lang_name == lang_name_c)
     {
@@ -15314,6 +15856,12 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
     }
   else
     need_lang_pop = false;
+
+  /* We cannot perform access checks on the template parameter
+     declarations until we know what is being declared, just as we
+     cannot check the decl-specifier list.  */
+  push_deferring_access_checks (dk_deferred);
+
   /* If the next token is `>', then we have an invalid
      specialization.  Rather than complain about an invalid template
      parameter, issue an error message here.  */
@@ -15327,8 +15875,14 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
     /* Parse the template parameters.  */
     parameter_list = cp_parser_template_parameter_list (parser);
 
+  /* Get the deferred access checks from the parameter list.  These
+     will be checked once we know what is being declared, as for a
+     member template the checks must be performed in the scope of the
+     class containing the member.  */
+  checks = get_deferred_access_checks ();
+
   /* Look for the `>'.  */
-  cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
+  cp_parser_skip_to_end_of_template_parameter_list (parser);
   /* We just processed one more parameter list.  */
   ++parser->num_template_parameter_lists;
   /* If the next token is `template', there are more template
@@ -15341,11 +15895,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       /* There are no access checks when parsing a template, as we do not
         know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
-
       decl = cp_parser_single_declaration (parser,
+                                          checks,
                                           member_p,
                                           &friend_p);
-
       pop_deferring_access_checks ();
 
       /* If this is a member template declaration, let the front
@@ -15364,6 +15917,8 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   /* We are done with the current parameter list.  */
   --parser->num_template_parameter_lists;
 
+  pop_deferring_access_checks ();
+
   /* Finish up.  */
   finish_template_decl (parameter_list);
 
@@ -15385,6 +15940,18 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
                   TREE_VALUE (parser->unparsed_functions_queues));
 }
 
+/* Perform the deferred access checks from a template-parameter-list.
+   CHECKS is a TREE_LIST of access checks, as returned by
+   get_deferred_access_checks.  */
+
+static void
+cp_parser_perform_template_parameter_access_checks (VEC (deferred_access_check,gc)* checks)
+{
+  ++processing_template_parmlist;
+  perform_access_checks (checks);
+  --processing_template_parmlist;
+}
+
 /* Parse a `decl-specifier-seq [opt] init-declarator [opt] ;' or
    `function-definition' sequence.  MEMBER_P is true, this declaration
    appears in a class scope.
@@ -15394,6 +15961,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 
 static tree
 cp_parser_single_declaration (cp_parser* parser,
+                             VEC (deferred_access_check,gc)* checks,
                              bool member_p,
                              bool* friend_p)
 {
@@ -15455,6 +16023,9 @@ cp_parser_single_declaration (cp_parser* parser,
            decl = TYPE_NAME (decl);
          else
            decl = error_mark_node;
+
+         /* Perform access checks for template parameters.  */
+         cp_parser_perform_template_parameter_access_checks (checks);
        }
     }
   /* If it's not a template class, try for a template function.  If
@@ -15467,6 +16038,7 @@ cp_parser_single_declaration (cp_parser* parser,
          || decl_specifiers.type != error_mark_node))
     decl = cp_parser_init_declarator (parser,
                                      &decl_specifiers,
+                                     checks,
                                      /*function_definition_allowed_p=*/true,
                                      member_p,
                                      declares_class_or_enum,
@@ -15516,13 +16088,11 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
      conversions to integral or enumeration type can be used".  */
   if (TREE_CODE (type) == TYPE_DECL)
     type = TREE_TYPE (type);
-  if (cast != error_mark_node && !dependent_type_p (type)
-      && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
-    {
-      if (cp_parser_non_integral_constant_expression
-         (parser, "a call to a constructor"))
-       return error_mark_node;
-    }
+  if (cast != error_mark_node
+      && !cast_valid_in_integral_constant_expression_p (type)
+      && (cp_parser_non_integral_constant_expression
+         (parser, "a call to a constructor")))
+    return error_mark_node;
   return cast;
 }
 
@@ -15655,7 +16225,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
        }
     }
   else
-    cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
+    cp_parser_skip_to_end_of_template_parameter_list (parser);
   /* The `>' token might be a greater-than operator again now.  */
   parser->greater_than_is_operator_p
     = saved_greater_than_is_operator_p;
@@ -15818,7 +16388,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 
       if (!processing_template_decl)
        parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg);
-      
+
       TREE_PURPOSE (parm) = parsed_arg;
 
       /* Update any instantiations we've already created.  */
@@ -15954,16 +16524,63 @@ cp_parser_declares_only_class_p (cp_parser *parser)
          || cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
 }
 
-/* Update the DECL_SPECS to reflect the STORAGE_CLASS.  */
+/* Update the DECL_SPECS to reflect the storage class indicated by
+   KEYWORD.  */
 
 static void
-cp_parser_set_storage_class (cp_decl_specifier_seq *decl_specs,
-                            cp_storage_class storage_class)
+cp_parser_set_storage_class (cp_parser *parser,
+                            cp_decl_specifier_seq *decl_specs,
+                            enum rid keyword)
 {
-  if (decl_specs->storage_class != sc_none)
-    decl_specs->multiple_storage_classes_p = true;
-  else
-    decl_specs->storage_class = storage_class;
+  cp_storage_class storage_class;
+
+  if (parser->in_unbraced_linkage_specification_p)
+    {
+      error ("invalid use of %qD in linkage specification",
+            ridpointers[keyword]);
+      return;
+    }
+  else if (decl_specs->storage_class != sc_none)
+    {
+      decl_specs->conflicting_specifiers_p = true;
+      return;
+    }
+
+  if ((keyword == RID_EXTERN || keyword == RID_STATIC)
+      && decl_specs->specs[(int) ds_thread])
+    {
+      error ("%<__thread%> before %qD", ridpointers[keyword]);
+      decl_specs->specs[(int) ds_thread] = 0;
+    }
+
+  switch (keyword)
+    {
+    case RID_AUTO:
+      storage_class = sc_auto;
+      break;
+    case RID_REGISTER:
+      storage_class = sc_register;
+      break;
+    case RID_STATIC:
+      storage_class = sc_static;
+      break;
+    case RID_EXTERN:
+      storage_class = sc_extern;
+      break;
+    case RID_MUTABLE:
+      storage_class = sc_mutable;
+      break;
+    default:
+      gcc_unreachable ();
+    }
+  decl_specs->storage_class = storage_class;
+
+  /* A storage class specifier cannot be applied alongside a typedef 
+     specifier. If there is a typedef specifier present then set 
+     conflicting_specifiers_p which will trigger an error later
+     on in grokdeclarator. */
+  if (decl_specs->specs[(int)ds_typedef])
+    decl_specs->conflicting_specifiers_p = true;
 }
 
 /* Update the DECL_SPECS to reflect the TYPE_SPEC.  If USER_DEFINED_P
@@ -16043,54 +16660,61 @@ cp_parser_require (cp_parser* parser,
     }
 }
 
-/* Like cp_parser_require, except that tokens will be skipped until
-   the desired token is found.  An error message is still produced if
-   the next token is not as expected.  */
+/* An error message is produced if the next token is not '>'.
+   All further tokens are skipped until the desired token is
+   found or '{', '}', ';' or an unbalanced ')' or ']'.  */
 
 static void
-cp_parser_skip_until_found (cp_parser* parser,
-                           enum cpp_ttype type,
-                           const char* token_desc)
+cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
 {
-  cp_token *token;
+  /* Current level of '< ... >'.  */
+  unsigned level = 0;
+  /* Ignore '<' and '>' nested inside '( ... )' or '[ ... ]'.  */
   unsigned nesting_depth = 0;
 
-  if (cp_parser_require (parser, type, token_desc))
+  /* Are we ready, yet?  If not, issue error message.  */
+  if (cp_parser_require (parser, CPP_GREATER, "%<>%>"))
     return;
 
   /* Skip tokens until the desired token is found.  */
   while (true)
     {
       /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-
-      /* If we've reached the token we want, consume it and stop.  */
-      if (token->type == type && !nesting_depth)
+      switch (cp_lexer_peek_token (parser->lexer)->type)
        {
-         cp_lexer_consume_token (parser->lexer);
-         return;
-       }
+       case CPP_LESS:
+         if (!nesting_depth)
+           ++level;
+         break;
 
-      switch (token->type)
-       {
-       case CPP_EOF:
-       case CPP_PRAGMA_EOL:
-         /* If we've run out of tokens, stop.  */
-         return;
+       case CPP_GREATER:
+         if (!nesting_depth && level-- == 0)
+           {
+             /* We've reached the token we want, consume it and stop.  */
+             cp_lexer_consume_token (parser->lexer);
+             return;
+           }
+         break;
 
-       case CPP_OPEN_BRACE:
        case CPP_OPEN_PAREN:
        case CPP_OPEN_SQUARE:
          ++nesting_depth;
          break;
 
-       case CPP_CLOSE_BRACE:
        case CPP_CLOSE_PAREN:
        case CPP_CLOSE_SQUARE:
          if (nesting_depth-- == 0)
            return;
          break;
 
+       case CPP_EOF:
+       case CPP_PRAGMA_EOL:
+       case CPP_SEMICOLON:
+       case CPP_OPEN_BRACE:
+       case CPP_CLOSE_BRACE:
+         /* The '>' was probably forgotten, don't look further.  */
+         return;
+
        default:
          break;
        }
@@ -16283,17 +16907,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));
+  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;
 }
 
@@ -16481,7 +17117,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)
@@ -16499,7 +17135,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);
     }
 
@@ -16709,7 +17345,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
   token = cp_lexer_peek_token (parser->lexer);
 
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
-         || token->type == CPP_SCOPE)
+        || token->type == CPP_SCOPE)
     {
       tree selector = NULL_TREE;
 
@@ -16718,7 +17354,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
        selector = cp_parser_objc_selector (parser);
 
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
-          && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
+         && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
        {
          /* Detect if we have a unary selector.  */
          if (maybe_unary_selector_p)
@@ -16733,9 +17369,9 @@ cp_parser_objc_selector_expression (cp_parser* parser)
        }
       maybe_unary_selector_p = false;
       token = cp_lexer_consume_token (parser->lexer);
-      
+
       if (token->type == CPP_SCOPE)
-        {
+       {
          sel_seq
            = chainon (sel_seq,
                       build_tree_list (selector, NULL_TREE));
@@ -16788,7 +17424,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
@@ -16809,7 +17445,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)
@@ -16889,7 +17525,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]
@@ -16902,7 +17538,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;
@@ -16973,7 +17609,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;
     }
 }
 
@@ -17242,7 +17878,8 @@ cp_parser_objc_class_ivars (cp_parser* parser)
              cplus_decl_attributes (&decl, attributes, /*flags=*/0);
            }
          else
-           decl = grokfield (declarator, &declspecs, NULL_TREE,
+           decl = grokfield (declarator, &declspecs,
+                             NULL_TREE, /*init_const_expr_p=*/false,
                              NULL_TREE, attributes);
 
          /* Add the instance variable.  */
@@ -17421,7 +18058,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);
     }
 }
@@ -17552,143 +18189,1359 @@ 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);
     }
 
   return error_mark_node;
 }
-/* The parser.  */
-
-static GTY (()) cp_parser *the_parser;
-
 \f
-/* Special handling for the first token or line in the file.  The first
-   thing in the file might be #pragma GCC pch_preprocess, which loads a
-   PCH file, which is a GC collection point.  So we need to handle this
-   first pragma without benefit of an existing lexer structure.
+/* OpenMP 2.5 parsing routines.  */
 
-   Always returns one token to the caller in *FIRST_TOKEN.  This is 
-   either the true first token of the file, or the first token after
-   the initial pragma.  */
+/* 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
+   returned and the token is consumed.  */
 
-static void
-cp_parser_initial_pragma (cp_token *first_token)
+static pragma_omp_clause
+cp_parser_omp_clause_name (cp_parser *parser)
 {
-  tree name = NULL;
-
-  cp_lexer_get_preprocessor_token (NULL, first_token);
-  if (first_token->pragma_kind != PRAGMA_GCC_PCH_PREPROCESS)
-    return;
+  pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
 
-  cp_lexer_get_preprocessor_token (NULL, first_token);
-  if (first_token->type == CPP_STRING)
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_IF))
+    result = PRAGMA_OMP_CLAUSE_IF;
+  else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_DEFAULT))
+    result = PRAGMA_OMP_CLAUSE_DEFAULT;
+  else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_PRIVATE))
+    result = PRAGMA_OMP_CLAUSE_PRIVATE;
+  else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
-      name = first_token->value;
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
 
-      cp_lexer_get_preprocessor_token (NULL, first_token);
-      if (first_token->type != CPP_PRAGMA_EOL)
-       error ("junk at end of %<#pragma GCC pch_preprocess%>");
+      switch (p[0])
+       {
+       case 'c':
+         if (!strcmp ("copyin", p))
+           result = PRAGMA_OMP_CLAUSE_COPYIN;
+         else if (!strcmp ("copyprivate", p))
+           result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
+         break;
+       case 'f':
+         if (!strcmp ("firstprivate", p))
+           result = PRAGMA_OMP_CLAUSE_FIRSTPRIVATE;
+         break;
+       case 'l':
+         if (!strcmp ("lastprivate", p))
+           result = PRAGMA_OMP_CLAUSE_LASTPRIVATE;
+         break;
+       case 'n':
+         if (!strcmp ("nowait", p))
+           result = PRAGMA_OMP_CLAUSE_NOWAIT;
+         else if (!strcmp ("num_threads", p))
+           result = PRAGMA_OMP_CLAUSE_NUM_THREADS;
+         break;
+       case 'o':
+         if (!strcmp ("ordered", p))
+           result = PRAGMA_OMP_CLAUSE_ORDERED;
+         break;
+       case 'r':
+         if (!strcmp ("reduction", p))
+           result = PRAGMA_OMP_CLAUSE_REDUCTION;
+         break;
+       case 's':
+         if (!strcmp ("schedule", p))
+           result = PRAGMA_OMP_CLAUSE_SCHEDULE;
+         else if (!strcmp ("shared", p))
+           result = PRAGMA_OMP_CLAUSE_SHARED;
+         break;
+       }
     }
-  else
-    error ("expected string literal");
 
-  /* Skip to the end of the pragma.  */
-  while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
-    cp_lexer_get_preprocessor_token (NULL, first_token);
+  if (result != PRAGMA_OMP_CLAUSE_NONE)
+    cp_lexer_consume_token (parser->lexer);
 
-  /* Read one more token to return to our caller.  */
-  cp_lexer_get_preprocessor_token (NULL, first_token);
+  return result;
+}
 
-  /* Now actually load the PCH file.  */
-  if (name)
-    c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
+/* Validate that a clause of the given type does not already exist.  */
+
+static void
+check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+{
+  tree c;
+
+  for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+    if (OMP_CLAUSE_CODE (c) == code)
+      {
+       error ("too many %qs clauses", name);
+       break;
+      }
 }
 
-/* Normal parsing of a pragma token.  Here we can (and must) use the
-   regular lexer.  */
+/* OpenMP 2.5:
+   variable-list:
+     identifier
+     variable-list , identifier
 
-static bool
-cp_parser_pragma (cp_parser *parser, enum pragma_context context ATTRIBUTE_UNUSED)
+   In addition, we match a closing parenthesis.  An opening parenthesis
+   will have been consumed by the caller.
+
+   If KIND is nonzero, create the appropriate node and install the decl
+   in OMP_CLAUSE_DECL and add the node to the head of the list.
+
+   If KIND is zero, create a TREE_LIST with the decl in TREE_PURPOSE;
+   return the list created.  */
+
+static tree
+cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
+                               tree list)
 {
-  cp_token *pragma_tok;
-  unsigned int id;
+  while (1)
+    {
+      tree name, decl;
 
-  pragma_tok = cp_lexer_consume_token (parser->lexer);
-  gcc_assert (pragma_tok->type == CPP_PRAGMA);
-  parser->lexer->in_pragma = true;
+      name = cp_parser_id_expression (parser, /*template_p=*/false,
+                                     /*check_dependency_p=*/true,
+                                     /*template_p=*/NULL,
+                                     /*declarator_p=*/false,
+                                     /*optional_p=*/false);
+      if (name == error_mark_node)
+       goto skip_comma;
 
-  id = pragma_tok->pragma_kind;
-  switch (id)
+      decl = cp_parser_lookup_name_simple (parser, name);
+      if (decl == error_mark_node)
+       cp_parser_name_lookup_error (parser, name, decl, NULL);
+      else if (kind != 0)
+       {
+         tree u = build_omp_clause (kind);
+         OMP_CLAUSE_DECL (u) = decl;
+         OMP_CLAUSE_CHAIN (u) = list;
+         list = u;
+       }
+      else
+       list = tree_cons (decl, NULL_TREE, list);
+
+    get_comma:
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+       break;
+      cp_lexer_consume_token (parser->lexer);
+    }
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
     {
-    case PRAGMA_GCC_PCH_PREPROCESS:
-      error ("%<#pragma GCC pch_preprocess%> must be first");
-      break;
+      int ending;
 
-    default:
-      gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
-      c_invoke_pragma_handler (id);
-      break;
+      /* Try to resync to an unnested comma.  Copied from
+        cp_parser_parenthesized_expression_list.  */
+    skip_comma:
+      ending = cp_parser_skip_to_closing_parenthesis (parser,
+                                                     /*recovering=*/true,
+                                                     /*or_comma=*/true,
+                                                     /*consume_paren=*/true);
+      if (ending < 0)
+       goto get_comma;
     }
 
-  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
-  return false;
+  return list;
 }
 
-/* The interface the pragma parsers have to the lexer.  */
+/* Similarly, but expect leading and trailing parenthesis.  This is a very
+   common case for omp clauses.  */
 
-enum cpp_ttype
-pragma_lex (tree *value)
+static tree
+cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
 {
-  cp_token *tok;
-  enum cpp_ttype ret;
+  if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return cp_parser_omp_var_list_no_open (parser, kind, list);
+  return list;
+}
 
-  tok = cp_lexer_peek_token (the_parser->lexer);
+/* OpenMP 2.5:
+   default ( shared | none ) */
 
-  ret = tok->type;
-  *value = tok->value;
+static tree
+cp_parser_omp_clause_default (cp_parser *parser, tree list)
+{
+  enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
+  tree c;
 
-  if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
-    ret = CPP_EOF;
-  else if (ret == CPP_STRING)
-    *value = cp_parser_string_literal (the_parser, false, false);
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return list;
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      switch (p[0])
+       {
+       case 'n':
+         if (strcmp ("none", p) != 0)
+           goto invalid_kind;
+         kind = OMP_CLAUSE_DEFAULT_NONE;
+         break;
+
+       case 's':
+         if (strcmp ("shared", p) != 0)
+           goto invalid_kind;
+         kind = OMP_CLAUSE_DEFAULT_SHARED;
+         break;
+
+       default:
+         goto invalid_kind;
+       }
+
+      cp_lexer_consume_token (parser->lexer);
+    }
   else
     {
-      cp_lexer_consume_token (the_parser->lexer);
-      if (ret == CPP_KEYWORD)
-       ret = CPP_NAME;
+    invalid_kind:
+      cp_parser_error (parser, "expected %<none%> or %<shared%>");
     }
 
-  return ret;
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
+    return list;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+  c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+  OMP_CLAUSE_CHAIN (c) = list;
+  OMP_CLAUSE_DEFAULT_KIND (c) = kind;
+
+  return c;
 }
 
-\f
-/* External interface.  */
+/* OpenMP 2.5:
+   if ( expression ) */
 
-/* Parse one entire translation unit.  */
+static tree
+cp_parser_omp_clause_if (cp_parser *parser, tree list)
+{
+  tree t, c;
 
-void
-c_parse_file (void)
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return list;
+
+  t = cp_parser_condition (parser);
+
+  if (t == error_mark_node
+      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+
+  c = build_omp_clause (OMP_CLAUSE_IF);
+  OMP_CLAUSE_IF_EXPR (c) = t;
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
+/* OpenMP 2.5:
+   nowait */
+
+static tree
+cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
 {
-  bool error_occurred;
-  static bool already_called = false;
+  tree c;
 
-  if (already_called)
+  check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+
+  c = build_omp_clause (OMP_CLAUSE_NOWAIT);
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
+/* OpenMP 2.5:
+   num_threads ( expression ) */
+
+static tree
+cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
+{
+  tree t, c;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return list;
+
+  t = cp_parser_expression (parser, false);
+
+  if (t == error_mark_node
+      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+
+  c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
+  OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
+  OMP_CLAUSE_CHAIN (c) = list;
+
+  return c;
+}
+
+/* OpenMP 2.5:
+   ordered */
+
+static tree
+cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+{
+  tree c;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+
+  c = build_omp_clause (OMP_CLAUSE_ORDERED);
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+}
+
+/* OpenMP 2.5:
+   reduction ( reduction-operator : variable-list )
+
+   reduction-operator:
+     One of: + * - & ^ | && || */
+
+static tree
+cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
+{
+  enum tree_code code;
+  tree nlist, c;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return list;
+
+  switch (cp_lexer_peek_token (parser->lexer)->type)
     {
-      sorry ("inter-module optimizations not implemented for C++");
-      return;
+    case CPP_PLUS:
+      code = PLUS_EXPR;
+      break;
+    case CPP_MULT:
+      code = MULT_EXPR;
+      break;
+    case CPP_MINUS:
+      code = MINUS_EXPR;
+      break;
+    case CPP_AND:
+      code = BIT_AND_EXPR;
+      break;
+    case CPP_XOR:
+      code = BIT_XOR_EXPR;
+      break;
+    case CPP_OR:
+      code = BIT_IOR_EXPR;
+      break;
+    case CPP_AND_AND:
+      code = TRUTH_ANDIF_EXPR;
+      break;
+    case CPP_OR_OR:
+      code = TRUTH_ORIF_EXPR;
+      break;
+    default:
+      cp_parser_error (parser, "`+', `*', `-', `&', `^', `|', `&&', or `||'");
+    resync_fail:
+      cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                            /*or_comma=*/false,
+                                            /*consume_paren=*/true);
+      return list;
     }
-  already_called = true;
+  cp_lexer_consume_token (parser->lexer);
 
-  the_parser = cp_parser_new ();
-  push_deferring_access_checks (flag_access_control
-                               ? dk_no_deferred : dk_no_check);
-  error_occurred = cp_parser_translation_unit (the_parser);
-  the_parser = NULL;
+  if (!cp_parser_require (parser, CPP_COLON, "`:'"))
+    goto resync_fail;
+
+  nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list);
+  for (c = nlist; c != list; c = OMP_CLAUSE_CHAIN (c))
+    OMP_CLAUSE_REDUCTION_CODE (c) = code;
+
+  return nlist;
 }
 
-/* This variable must be provided by every front end.  */
+/* OpenMP 2.5:
+   schedule ( schedule-kind )
+   schedule ( schedule-kind , expression )
+
+   schedule-kind:
+     static | dynamic | guided | runtime  */
+
+static tree
+cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
+{
+  tree c, t;
+
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return list;
+
+  c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
 
-int yydebug;
+      switch (p[0])
+       {
+       case 'd':
+         if (strcmp ("dynamic", p) != 0)
+           goto invalid_kind;
+         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_DYNAMIC;
+         break;
+
+       case 'g':
+         if (strcmp ("guided", p) != 0)
+           goto invalid_kind;
+         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_GUIDED;
+         break;
+
+       case 'r':
+         if (strcmp ("runtime", p) != 0)
+           goto invalid_kind;
+         OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_RUNTIME;
+         break;
+
+       default:
+         goto invalid_kind;
+       }
+    }
+  else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
+    OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
+  else
+    goto invalid_kind;
+  cp_lexer_consume_token (parser->lexer);
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+    {
+      cp_lexer_consume_token (parser->lexer);
+
+      t = cp_parser_assignment_expression (parser, false);
+
+      if (t == error_mark_node)
+       goto resync_fail;
+      else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
+       error ("schedule %<runtime%> does not take "
+              "a %<chunk_size%> parameter");
+      else
+       OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
+
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+       goto resync_fail;
+    }
+  else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`,' or `)'"))
+    goto resync_fail;
+
+  check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+  OMP_CLAUSE_CHAIN (c) = list;
+  return c;
+
+ invalid_kind:
+  cp_parser_error (parser, "invalid schedule kind");
+ resync_fail:
+  cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                        /*or_comma=*/false,
+                                        /*consume_paren=*/true);
+  return list;
+}
+
+/* Parse all OpenMP clauses.  The set clauses allowed by the directive
+   is a bitmask in MASK.  Return the list of clauses found; the result
+   of clause default goes in *pdefault.  */
+
+static tree
+cp_parser_omp_all_clauses (cp_parser *parser, unsigned int mask,
+                          const char *where, cp_token *pragma_tok)
+{
+  tree clauses = NULL;
+
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
+    {
+      pragma_omp_clause c_kind = cp_parser_omp_clause_name (parser);
+      const char *c_name;
+      tree prev = clauses;
+
+      switch (c_kind)
+       {
+       case PRAGMA_OMP_CLAUSE_COPYIN:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYIN, clauses);
+         c_name = "copyin";
+         break;
+       case PRAGMA_OMP_CLAUSE_COPYPRIVATE:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYPRIVATE,
+                                           clauses);
+         c_name = "copyprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_DEFAULT:
+         clauses = cp_parser_omp_clause_default (parser, clauses);
+         c_name = "default";
+         break;
+       case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_FIRSTPRIVATE,
+                                           clauses);
+         c_name = "firstprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_IF:
+         clauses = cp_parser_omp_clause_if (parser, clauses);
+         c_name = "if";
+         break;
+       case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_LASTPRIVATE,
+                                           clauses);
+         c_name = "lastprivate";
+         break;
+       case PRAGMA_OMP_CLAUSE_NOWAIT:
+         clauses = cp_parser_omp_clause_nowait (parser, clauses);
+         c_name = "nowait";
+         break;
+       case PRAGMA_OMP_CLAUSE_NUM_THREADS:
+         clauses = cp_parser_omp_clause_num_threads (parser, clauses);
+         c_name = "num_threads";
+         break;
+       case PRAGMA_OMP_CLAUSE_ORDERED:
+         clauses = cp_parser_omp_clause_ordered (parser, clauses);
+         c_name = "ordered";
+         break;
+       case PRAGMA_OMP_CLAUSE_PRIVATE:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_PRIVATE,
+                                           clauses);
+         c_name = "private";
+         break;
+       case PRAGMA_OMP_CLAUSE_REDUCTION:
+         clauses = cp_parser_omp_clause_reduction (parser, clauses);
+         c_name = "reduction";
+         break;
+       case PRAGMA_OMP_CLAUSE_SCHEDULE:
+         clauses = cp_parser_omp_clause_schedule (parser, clauses);
+         c_name = "schedule";
+         break;
+       case PRAGMA_OMP_CLAUSE_SHARED:
+         clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_SHARED,
+                                           clauses);
+         c_name = "shared";
+         break;
+       default:
+         cp_parser_error (parser, "expected %<#pragma omp%> clause");
+         goto saw_error;
+       }
+
+      if (((mask >> c_kind) & 1) == 0)
+       {
+         /* Remove the invalid clause(s) from the list to avoid
+            confusing the rest of the compiler.  */
+         clauses = prev;
+         error ("%qs is not valid for %qs", c_name, where);
+       }
+    }
+ saw_error:
+  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+  return finish_omp_clauses (clauses);
+}
+
+/* OpenMP 2.5:
+   structured-block:
+     statement
+
+   In practice, we're also interested in adding the statement to an
+   outer node.  So it is convenient if we work around the fact that
+   cp_parser_statement calls add_stmt.  */
+
+static unsigned
+cp_parser_begin_omp_structured_block (cp_parser *parser)
+{
+  unsigned save = parser->in_statement;
+
+  /* Only move the values to IN_OMP_BLOCK if they weren't false.
+     This preserves the "not within loop or switch" style error messages
+     for nonsense cases like
+       void foo() {
+       #pragma omp single
+         break;
+       }
+  */
+  if (parser->in_statement)
+    parser->in_statement = IN_OMP_BLOCK;
+
+  return save;
+}
+
+static void
+cp_parser_end_omp_structured_block (cp_parser *parser, unsigned save)
+{
+  parser->in_statement = save;
+}
+
+static tree
+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, NULL);
+
+  cp_parser_end_omp_structured_block (parser, save);
+  return finish_omp_structured_block (stmt);
+}
+
+/* OpenMP 2.5:
+   # pragma omp atomic new-line
+     expression-stmt
+
+   expression-stmt:
+     x binop= expr | x++ | ++x | x-- | --x
+   binop:
+     +, *, -, /, &, ^, |, <<, >>
+
+  where x is an lvalue expression with scalar type.  */
+
+static void
+cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree lhs, rhs;
+  enum tree_code code;
+
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                   /*cast_p=*/false);
+  switch (TREE_CODE (lhs))
+    {
+    case ERROR_MARK:
+      goto saw_error;
+
+    case PREINCREMENT_EXPR:
+    case POSTINCREMENT_EXPR:
+      lhs = TREE_OPERAND (lhs, 0);
+      code = PLUS_EXPR;
+      rhs = integer_one_node;
+      break;
+
+    case PREDECREMENT_EXPR:
+    case POSTDECREMENT_EXPR:
+      lhs = TREE_OPERAND (lhs, 0);
+      code = MINUS_EXPR;
+      rhs = integer_one_node;
+      break;
+
+    default:
+      switch (cp_lexer_peek_token (parser->lexer)->type)
+       {
+       case CPP_MULT_EQ:
+         code = MULT_EXPR;
+         break;
+       case CPP_DIV_EQ:
+         code = TRUNC_DIV_EXPR;
+         break;
+       case CPP_PLUS_EQ:
+         code = PLUS_EXPR;
+         break;
+       case CPP_MINUS_EQ:
+         code = MINUS_EXPR;
+         break;
+       case CPP_LSHIFT_EQ:
+         code = LSHIFT_EXPR;
+         break;
+       case CPP_RSHIFT_EQ:
+         code = RSHIFT_EXPR;
+         break;
+       case CPP_AND_EQ:
+         code = BIT_AND_EXPR;
+         break;
+       case CPP_OR_EQ:
+         code = BIT_IOR_EXPR;
+         break;
+       case CPP_XOR_EQ:
+         code = BIT_XOR_EXPR;
+         break;
+       default:
+         cp_parser_error (parser,
+                          "invalid operator for %<#pragma omp atomic%>");
+         goto saw_error;
+       }
+      cp_lexer_consume_token (parser->lexer);
+
+      rhs = cp_parser_expression (parser, false);
+      if (rhs == error_mark_node)
+       goto saw_error;
+      break;
+    }
+  finish_omp_atomic (code, lhs, rhs);
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  return;
+
+ saw_error:
+  cp_parser_skip_to_end_of_block_or_statement (parser);
+}
+
+
+/* OpenMP 2.5:
+   # pragma omp barrier new-line  */
+
+static void
+cp_parser_omp_barrier (cp_parser *parser, cp_token *pragma_tok)
+{
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+  finish_omp_barrier ();
+}
+
+/* OpenMP 2.5:
+   # pragma omp critical [(name)] new-line
+     structured-block  */
+
+static tree
+cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree stmt, name = NULL;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      cp_lexer_consume_token (parser->lexer);
+
+      name = cp_parser_identifier (parser);
+
+      if (name == error_mark_node
+         || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+       cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                              /*or_comma=*/false,
+                                              /*consume_paren=*/true);
+      if (name == error_mark_node)
+       name = NULL;
+    }
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  stmt = cp_parser_omp_structured_block (parser);
+  return c_finish_omp_critical (stmt, name);
+}
+
+/* OpenMP 2.5:
+   # pragma omp flush flush-vars[opt] new-line
+
+   flush-vars:
+     ( variable-list ) */
+
+static void
+cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
+{
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    (void) cp_parser_omp_var_list (parser, 0, NULL);
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  finish_omp_flush ();
+}
+
+/* Parse the restricted form of the for statment allowed by OpenMP.  */
+
+static tree
+cp_parser_omp_for_loop (cp_parser *parser)
+{
+  tree init, cond, incr, body, decl, pre_body;
+  location_t loc;
+
+  if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+    {
+      cp_parser_error (parser, "for statement expected");
+      return NULL;
+    }
+  loc = cp_lexer_consume_token (parser->lexer)->location;
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return NULL;
+
+  init = decl = NULL;
+  pre_body = push_stmt_list ();
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    {
+      cp_decl_specifier_seq type_specifiers;
+
+      /* First, try to parse as an initialized declaration.  See
+        cp_parser_condition, from whence the bulk of this is copied.  */
+
+      cp_parser_parse_tentatively (parser);
+      cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+                                   &type_specifiers);
+      if (!cp_parser_error_occurred (parser))
+       {
+         tree asm_specification, attributes;
+         cp_declarator *declarator;
+
+         declarator = cp_parser_declarator (parser,
+                                            CP_PARSER_DECLARATOR_NAMED,
+                                            /*ctor_dtor_or_conv_p=*/NULL,
+                                            /*parenthesized_p=*/NULL,
+                                            /*member_p=*/false);
+         attributes = cp_parser_attributes_opt (parser);
+         asm_specification = cp_parser_asm_specification_opt (parser);
+
+         cp_parser_require (parser, CPP_EQ, "`='");
+         if (cp_parser_parse_definitely (parser))
+           {
+             tree pushed_scope;
+
+             decl = start_decl (declarator, &type_specifiers,
+                                /*initialized_p=*/false, attributes,
+                                /*prefix_attributes=*/NULL_TREE,
+                                &pushed_scope);
+
+             init = cp_parser_assignment_expression (parser, false);
+
+             cp_finish_decl (decl, NULL_TREE, /*init_const_expr_p=*/false,
+                             asm_specification, LOOKUP_ONLYCONVERTING);
+
+             if (pushed_scope)
+               pop_scope (pushed_scope);
+           }
+       }
+      else
+       cp_parser_abort_tentative_parse (parser);
+
+      /* If parsing as an initialized declaration failed, try again as
+        a simple expression.  */
+      if (decl == NULL)
+       init = cp_parser_expression (parser, false);
+    }
+  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+  pre_body = pop_stmt_list (pre_body);
+
+  cond = NULL;
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    cond = cp_parser_condition (parser);
+  cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+
+  incr = NULL;
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+    incr = cp_parser_expression (parser, false);
+
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+    cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+                                          /*or_comma=*/false,
+                                          /*consume_paren=*/true);
+
+  /* Note that we saved the original contents of this flag when we entered
+     the structured block, and so we don't need to re-save it here.  */
+  parser->in_statement = IN_OMP_FOR;
+
+  /* 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, NULL);
+  body = pop_stmt_list (body);
+
+  return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
+}
+
+/* OpenMP 2.5:
+   #pragma omp for for-clause[optseq] new-line
+     for-loop  */
+
+#define OMP_FOR_CLAUSE_MASK                            \
+       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
+       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
+       | (1u << PRAGMA_OMP_CLAUSE_ORDERED)             \
+       | (1u << PRAGMA_OMP_CLAUSE_SCHEDULE)            \
+       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree clauses, sb, ret;
+  unsigned int save;
+
+  clauses = cp_parser_omp_all_clauses (parser, OMP_FOR_CLAUSE_MASK,
+                                      "#pragma omp for", pragma_tok);
+
+  sb = begin_omp_structured_block ();
+  save = cp_parser_begin_omp_structured_block (parser);
+
+  ret = cp_parser_omp_for_loop (parser);
+  if (ret)
+    OMP_FOR_CLAUSES (ret) = clauses;
+
+  cp_parser_end_omp_structured_block (parser, save);
+  add_stmt (finish_omp_structured_block (sb));
+
+  return ret;
+}
+
+/* OpenMP 2.5:
+   # pragma omp master new-line
+     structured-block  */
+
+static tree
+cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
+{
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+  return c_finish_omp_master (cp_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 2.5:
+   # pragma omp ordered new-line
+     structured-block  */
+
+static tree
+cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok)
+{
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+  return c_finish_omp_ordered (cp_parser_omp_structured_block (parser));
+}
+
+/* OpenMP 2.5:
+
+   section-scope:
+     { section-sequence }
+
+   section-sequence:
+     section-directive[opt] structured-block
+     section-sequence section-directive structured-block  */
+
+static tree
+cp_parser_omp_sections_scope (cp_parser *parser)
+{
+  tree stmt, substmt;
+  bool error_suppress = false;
+  cp_token *tok;
+
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+    return NULL_TREE;
+
+  stmt = push_stmt_list ();
+
+  if (cp_lexer_peek_token (parser->lexer)->pragma_kind != PRAGMA_OMP_SECTION)
+    {
+      unsigned save;
+
+      substmt = begin_omp_structured_block ();
+      save = cp_parser_begin_omp_structured_block (parser);
+
+      while (1)
+       {
+         cp_parser_statement (parser, NULL_TREE, false, NULL);
+
+         tok = cp_lexer_peek_token (parser->lexer);
+         if (tok->pragma_kind == PRAGMA_OMP_SECTION)
+           break;
+         if (tok->type == CPP_CLOSE_BRACE)
+           break;
+         if (tok->type == CPP_EOF)
+           break;
+       }
+
+      cp_parser_end_omp_structured_block (parser, save);
+      substmt = finish_omp_structured_block (substmt);
+      substmt = build1 (OMP_SECTION, void_type_node, substmt);
+      add_stmt (substmt);
+    }
+
+  while (1)
+    {
+      tok = cp_lexer_peek_token (parser->lexer);
+      if (tok->type == CPP_CLOSE_BRACE)
+       break;
+      if (tok->type == CPP_EOF)
+       break;
+
+      if (tok->pragma_kind == PRAGMA_OMP_SECTION)
+       {
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_require_pragma_eol (parser, tok);
+         error_suppress = false;
+       }
+      else if (!error_suppress)
+       {
+         cp_parser_error (parser, "expected %<#pragma omp section%> or %<}%>");
+         error_suppress = true;
+       }
+
+      substmt = cp_parser_omp_structured_block (parser);
+      substmt = build1 (OMP_SECTION, void_type_node, substmt);
+      add_stmt (substmt);
+    }
+  cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+
+  substmt = pop_stmt_list (stmt);
+
+  stmt = make_node (OMP_SECTIONS);
+  TREE_TYPE (stmt) = void_type_node;
+  OMP_SECTIONS_BODY (stmt) = substmt;
+
+  add_stmt (stmt);
+  return stmt;
+}
+
+/* OpenMP 2.5:
+   # pragma omp sections sections-clause[optseq] newline
+     sections-scope  */
+
+#define OMP_SECTIONS_CLAUSE_MASK                       \
+       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_LASTPRIVATE)         \
+       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
+       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+cp_parser_omp_sections (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree clauses, ret;
+
+  clauses = cp_parser_omp_all_clauses (parser, OMP_SECTIONS_CLAUSE_MASK,
+                                      "#pragma omp sections", pragma_tok);
+
+  ret = cp_parser_omp_sections_scope (parser);
+  if (ret)
+    OMP_SECTIONS_CLAUSES (ret) = clauses;
+
+  return ret;
+}
+
+/* OpenMP 2.5:
+   # pragma parallel parallel-clause new-line
+   # pragma parallel for parallel-for-clause new-line
+   # pragma parallel sections parallel-sections-clause new-line  */
+
+#define OMP_PARALLEL_CLAUSE_MASK                       \
+       ( (1u << PRAGMA_OMP_CLAUSE_IF)                  \
+       | (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_DEFAULT)             \
+       | (1u << PRAGMA_OMP_CLAUSE_SHARED)              \
+       | (1u << PRAGMA_OMP_CLAUSE_COPYIN)              \
+       | (1u << PRAGMA_OMP_CLAUSE_REDUCTION)           \
+       | (1u << PRAGMA_OMP_CLAUSE_NUM_THREADS))
+
+static tree
+cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
+{
+  enum pragma_kind p_kind = PRAGMA_OMP_PARALLEL;
+  const char *p_name = "#pragma omp parallel";
+  tree stmt, clauses, par_clause, ws_clause, block;
+  unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
+  unsigned int save;
+
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      p_kind = PRAGMA_OMP_PARALLEL_FOR;
+      p_name = "#pragma omp parallel for";
+      mask |= OMP_FOR_CLAUSE_MASK;
+      mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+    }
+  else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->u.value;
+      const char *p = IDENTIFIER_POINTER (id);
+      if (strcmp (p, "sections") == 0)
+       {
+         cp_lexer_consume_token (parser->lexer);
+         p_kind = PRAGMA_OMP_PARALLEL_SECTIONS;
+         p_name = "#pragma omp parallel sections";
+         mask |= OMP_SECTIONS_CLAUSE_MASK;
+         mask &= ~(1u << PRAGMA_OMP_CLAUSE_NOWAIT);
+       }
+    }
+
+  clauses = cp_parser_omp_all_clauses (parser, mask, p_name, pragma_tok);
+  block = begin_omp_parallel ();
+  save = cp_parser_begin_omp_structured_block (parser);
+
+  switch (p_kind)
+    {
+    case PRAGMA_OMP_PARALLEL:
+      cp_parser_already_scoped_statement (parser);
+      par_clause = clauses;
+      break;
+
+    case PRAGMA_OMP_PARALLEL_FOR:
+      c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+      stmt = cp_parser_omp_for_loop (parser);
+      if (stmt)
+       OMP_FOR_CLAUSES (stmt) = ws_clause;
+      break;
+
+    case PRAGMA_OMP_PARALLEL_SECTIONS:
+      c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+      stmt = cp_parser_omp_sections_scope (parser);
+      if (stmt)
+       OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
+      break;
+
+    default:
+      gcc_unreachable ();
+    }
+
+  cp_parser_end_omp_structured_block (parser, save);
+  stmt = finish_omp_parallel (par_clause, block);
+  if (p_kind != PRAGMA_OMP_PARALLEL)
+    OMP_PARALLEL_COMBINED (stmt) = 1;
+  return stmt;
+}
+
+/* OpenMP 2.5:
+   # pragma omp single single-clause[optseq] new-line
+     structured-block  */
+
+#define OMP_SINGLE_CLAUSE_MASK                         \
+       ( (1u << PRAGMA_OMP_CLAUSE_PRIVATE)             \
+       | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE)        \
+       | (1u << PRAGMA_OMP_CLAUSE_COPYPRIVATE)         \
+       | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+
+static tree
+cp_parser_omp_single (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree stmt = make_node (OMP_SINGLE);
+  TREE_TYPE (stmt) = void_type_node;
+
+  OMP_SINGLE_CLAUSES (stmt)
+    = cp_parser_omp_all_clauses (parser, OMP_SINGLE_CLAUSE_MASK,
+                                "#pragma omp single", pragma_tok);
+  OMP_SINGLE_BODY (stmt) = cp_parser_omp_structured_block (parser);
+
+  return add_stmt (stmt);
+}
+
+/* OpenMP 2.5:
+   # pragma omp threadprivate (variable-list) */
+
+static void
+cp_parser_omp_threadprivate (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree vars;
+
+  vars = cp_parser_omp_var_list (parser, 0, NULL);
+  cp_parser_require_pragma_eol (parser, pragma_tok);
+
+  finish_omp_threadprivate (vars);
+}
+
+/* Main entry point to OpenMP statement pragmas.  */
+
+static void
+cp_parser_omp_construct (cp_parser *parser, cp_token *pragma_tok)
+{
+  tree stmt;
+
+  switch (pragma_tok->pragma_kind)
+    {
+    case PRAGMA_OMP_ATOMIC:
+      cp_parser_omp_atomic (parser, pragma_tok);
+      return;
+    case PRAGMA_OMP_CRITICAL:
+      stmt = cp_parser_omp_critical (parser, pragma_tok);
+      break;
+    case PRAGMA_OMP_FOR:
+      stmt = cp_parser_omp_for (parser, pragma_tok);
+      break;
+    case PRAGMA_OMP_MASTER:
+      stmt = cp_parser_omp_master (parser, pragma_tok);
+      break;
+    case PRAGMA_OMP_ORDERED:
+      stmt = cp_parser_omp_ordered (parser, pragma_tok);
+      break;
+    case PRAGMA_OMP_PARALLEL:
+      stmt = cp_parser_omp_parallel (parser, pragma_tok);
+      break;
+    case PRAGMA_OMP_SECTIONS:
+      stmt = cp_parser_omp_sections (parser, pragma_tok);
+      break;
+    case PRAGMA_OMP_SINGLE:
+      stmt = cp_parser_omp_single (parser, pragma_tok);
+      break;
+    default:
+      gcc_unreachable ();
+    }
+
+  if (stmt)
+    SET_EXPR_LOCATION (stmt, pragma_tok->location);
+}
+\f
+/* The parser.  */
+
+static GTY (()) cp_parser *the_parser;
+
+\f
+/* Special handling for the first token or line in the file.  The first
+   thing in the file might be #pragma GCC pch_preprocess, which loads a
+   PCH file, which is a GC collection point.  So we need to handle this
+   first pragma without benefit of an existing lexer structure.
+
+   Always returns one token to the caller in *FIRST_TOKEN.  This is
+   either the true first token of the file, or the first token after
+   the initial pragma.  */
+
+static void
+cp_parser_initial_pragma (cp_token *first_token)
+{
+  tree name = NULL;
+
+  cp_lexer_get_preprocessor_token (NULL, first_token);
+  if (first_token->pragma_kind != PRAGMA_GCC_PCH_PREPROCESS)
+    return;
+
+  cp_lexer_get_preprocessor_token (NULL, first_token);
+  if (first_token->type == CPP_STRING)
+    {
+      name = first_token->u.value;
+
+      cp_lexer_get_preprocessor_token (NULL, first_token);
+      if (first_token->type != CPP_PRAGMA_EOL)
+       error ("junk at end of %<#pragma GCC pch_preprocess%>");
+    }
+  else
+    error ("expected string literal");
+
+  /* Skip to the end of the pragma.  */
+  while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
+    cp_lexer_get_preprocessor_token (NULL, first_token);
+
+  /* Now actually load the PCH file.  */
+  if (name)
+    c_common_pch_pragma (parse_in, TREE_STRING_POINTER (name));
+
+  /* Read one more token to return to our caller.  We have to do this
+     after reading the PCH file in, since its pointers have to be
+     live.  */
+  cp_lexer_get_preprocessor_token (NULL, first_token);
+}
+
+/* Normal parsing of a pragma token.  Here we can (and must) use the
+   regular lexer.  */
+
+static bool
+cp_parser_pragma (cp_parser *parser, enum pragma_context context)
+{
+  cp_token *pragma_tok;
+  unsigned int id;
+
+  pragma_tok = cp_lexer_consume_token (parser->lexer);
+  gcc_assert (pragma_tok->type == CPP_PRAGMA);
+  parser->lexer->in_pragma = true;
+
+  id = pragma_tok->pragma_kind;
+  switch (id)
+    {
+    case PRAGMA_GCC_PCH_PREPROCESS:
+      error ("%<#pragma GCC pch_preprocess%> must be first");
+      break;
+
+    case PRAGMA_OMP_BARRIER:
+      switch (context)
+       {
+       case pragma_compound:
+         cp_parser_omp_barrier (parser, pragma_tok);
+         return false;
+       case pragma_stmt:
+         error ("%<#pragma omp barrier%> may only be "
+                "used in compound statements");
+         break;
+       default:
+         goto bad_stmt;
+       }
+      break;
+
+    case PRAGMA_OMP_FLUSH:
+      switch (context)
+       {
+       case pragma_compound:
+         cp_parser_omp_flush (parser, pragma_tok);
+         return false;
+       case pragma_stmt:
+         error ("%<#pragma omp flush%> may only be "
+                "used in compound statements");
+         break;
+       default:
+         goto bad_stmt;
+       }
+      break;
+
+    case PRAGMA_OMP_THREADPRIVATE:
+      cp_parser_omp_threadprivate (parser, pragma_tok);
+      return false;
+
+    case PRAGMA_OMP_ATOMIC:
+    case PRAGMA_OMP_CRITICAL:
+    case PRAGMA_OMP_FOR:
+    case PRAGMA_OMP_MASTER:
+    case PRAGMA_OMP_ORDERED:
+    case PRAGMA_OMP_PARALLEL:
+    case PRAGMA_OMP_SECTIONS:
+    case PRAGMA_OMP_SINGLE:
+      if (context == pragma_external)
+       goto bad_stmt;
+      cp_parser_omp_construct (parser, pragma_tok);
+      return true;
+
+    case PRAGMA_OMP_SECTION:
+      error ("%<#pragma omp section%> may only be used in "
+            "%<#pragma omp sections%> construct");
+      break;
+
+    default:
+      gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
+      c_invoke_pragma_handler (id);
+      break;
+
+    bad_stmt:
+      cp_parser_error (parser, "expected declaration specifiers");
+      break;
+    }
+
+  cp_parser_skip_to_pragma_eol (parser, pragma_tok);
+  return false;
+}
+
+/* The interface the pragma parsers have to the lexer.  */
+
+enum cpp_ttype
+pragma_lex (tree *value)
+{
+  cp_token *tok;
+  enum cpp_ttype ret;
+
+  tok = cp_lexer_peek_token (the_parser->lexer);
+
+  ret = tok->type;
+  *value = tok->u.value;
+
+  if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
+    ret = CPP_EOF;
+  else if (ret == CPP_STRING)
+    *value = cp_parser_string_literal (the_parser, false, false);
+  else
+    {
+      cp_lexer_consume_token (the_parser->lexer);
+      if (ret == CPP_KEYWORD)
+       ret = CPP_NAME;
+    }
+
+  return ret;
+}
+
+\f
+/* External interface.  */
+
+/* Parse one entire translation unit.  */
+
+void
+c_parse_file (void)
+{
+  bool error_occurred;
+  static bool already_called = false;
+
+  if (already_called)
+    {
+      sorry ("inter-module optimizations not implemented for C++");
+      return;
+    }
+  already_called = true;
+
+  the_parser = cp_parser_new ();
+  push_deferring_access_checks (flag_access_control
+                               ? dk_no_deferred : dk_no_check);
+  error_occurred = cp_parser_translation_unit (the_parser);
+  the_parser = NULL;
+}
 
 #include "gt-cp-parser.h"