OSDN Git Service

* decl.c, decl2.c, parser.c: Fix comment typos. Follow
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 082727e..60a53c8 100644 (file)
@@ -36,6 +36,7 @@
 #include "toplev.h"
 #include "output.h"
 #include "target.h"
+#include "cgraph.h"
 #include "c-common.h"
 
 \f
@@ -55,10 +56,16 @@ typedef struct cp_token GTY (())
   ENUM_BITFIELD (rid) keyword : 8;
   /* Token flags.  */
   unsigned char flags;
+  /* Identifier for the pragma.  */
+  ENUM_BITFIELD (pragma_kind) pragma_kind : 6;
   /* True if this token is from a system header.  */
   BOOL_BITFIELD in_system_header : 1;
   /* True if this token is from a context where it is implicitly extern "C" */
   BOOL_BITFIELD implicit_extern_c : 1;
+  /* True for a CPP_NAME token that is not a keyword (i.e., for which
+     KEYWORD is RID_MAX) iff this name was looked up and found to be
+     ambiguous.  An error has already been reported.  */
+  BOOL_BITFIELD ambiguous_p : 1;
   /* The value associated with this token, if any.  */
   tree value;
   /* The location at which this token was found.  */
@@ -72,7 +79,7 @@ DEF_VEC_ALLOC_P (cp_token_position,heap);
 
 static const cp_token eof_token =
 {
-  CPP_EOF, RID_MAX, 0, 0, 0, NULL_TREE,
+  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, NULL_TREE,
 #if USE_MAPPED_LOCATION
   0
 #else
@@ -108,11 +115,15 @@ typedef struct cp_lexer GTY (())
      tokens.  */
   VEC(cp_token_position,heap) *GTY ((skip)) saved_tokens;
 
+  /* The next lexer in a linked list of lexers.  */
+  struct cp_lexer *next;
+
   /* True if we should output debugging information.  */
   bool debugging_p;
 
-  /* The next lexer in a linked list of lexers.  */
-  struct cp_lexer *next;
+  /* True if we're in the context of parsing a pragma, and should not
+     increment past the end-of-line marker.  */
+  bool in_pragma;
 } cp_lexer;
 
 /* cp_token_cache is a range of tokens.  There is no need to represent
@@ -162,8 +173,6 @@ static void cp_lexer_purge_token
   (cp_lexer *);
 static void cp_lexer_purge_tokens_after
   (cp_lexer *, cp_token_position);
-static void cp_lexer_handle_pragma
-  (cp_lexer *);
 static void cp_lexer_save_tokens
   (cp_lexer *);
 static void cp_lexer_commit_tokens
@@ -192,6 +201,9 @@ static void cp_lexer_stop_debugging
 static cp_token_cache *cp_token_cache_new
   (cp_token *, cp_token *);
 
+static void cp_parser_initial_pragma
+  (cp_token *);
+
 /* Manifest constants.  */
 #define CP_LEXER_BUFFER_SIZE 10000
 #define CP_SAVED_TOKEN_STACK 5
@@ -240,17 +252,12 @@ cp_lexer_new_main (void)
   size_t space;
   cp_token *buffer;
 
-  /* It's possible that lexing the first token will load a PCH file,
-     which is a GC collection point.  So we have to grab the first
-     token before allocating any memory.  Pragmas must not be deferred
-     as -fpch-preprocess can generate a pragma to load the PCH file in
-     the preprocessed output used by -save-temps.  */
-  cp_lexer_get_preprocessor_token (NULL, &first_token);
+  /* It's possible that parsing the first pragma will load a PCH file,
+     which is a GC collection point.  So we have to do that before
+     allocating any memory.  */
+  cp_parser_initial_pragma (&first_token);
 
-  /* Tell cpplib we want CPP_PRAGMA tokens.  */
-  cpp_get_options (parse_in)->defer_pragmas = true;
-
-  /* Tell c_lex not to merge string constants.  */
+  /* Tell c_lex_with_flags not to merge string constants.  */
   c_lex_return_raw_strings = true;
 
   c_common_no_more_pch ();
@@ -267,7 +274,7 @@ cp_lexer_new_main (void)
 
   /* Create the buffer.  */
   alloc = CP_LEXER_BUFFER_SIZE;
-  buffer = ggc_alloc (alloc * sizeof (cp_token));
+  buffer = GGC_NEWVEC (cp_token, alloc);
 
   /* Put the first token in the buffer.  */
   space = alloc;
@@ -282,7 +289,7 @@ cp_lexer_new_main (void)
        {
          space = alloc;
          alloc *= 2;
-         buffer = ggc_realloc (buffer, alloc * sizeof (cp_token));
+         buffer = GGC_RESIZEVEC (cp_token, buffer, alloc);
          pos = buffer + space;
        }
       cp_lexer_get_preprocessor_token (lexer, pos);
@@ -292,10 +299,10 @@ cp_lexer_new_main (void)
   lexer->last_token = pos;
   lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token;
 
-  /* Pragma processing (via cpp_handle_deferred_pragma) may result in
-     direct calls to c_lex.  Those callers all expect c_lex to do
-     string constant concatenation.  */
-  c_lex_return_raw_strings = false;
+  /* Subsequent preprocessor diagnostics should use compiler
+     diagnostic functions to get the compiler source location.  */
+  cpp_get_options (parse_in)->client_diagnostic = true;
+  cpp_get_callbacks (parse_in)->error = cp_cpp_error;
 
   gcc_assert (lexer->next_token->type != CPP_PURGED);
   return lexer;
@@ -386,6 +393,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);
+  token->keyword = RID_MAX;
+  token->pragma_kind = PRAGMA_NONE;
   token->in_system_header = in_system_header;
 
   /* On some systems, some header files are surrounded by an
@@ -396,18 +405,25 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
   token->implicit_extern_c = is_extern_c > 0;
 
   /* Check to see if this token is a keyword.  */
-  if (token->type == CPP_NAME
-      && C_IS_RESERVED_WORD (token->value))
+  if (token->type == CPP_NAME)
     {
-      /* Mark this token as a keyword.  */
-      token->type = CPP_KEYWORD;
-      /* Record which keyword.  */
-      token->keyword = C_RID_CODE (token->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];
+      if (C_IS_RESERVED_WORD (token->value))
+       {
+         /* Mark this token as a keyword.  */
+         token->type = CPP_KEYWORD;
+         /* Record which keyword.  */
+         token->keyword = C_RID_CODE (token->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];
+       }
+      else
+       {
+         token->ambiguous_p = false;
+         token->keyword = RID_MAX;
+       }
     }
   /* Handle Objective-C++ keywords.  */
   else if (token->type == CPP_AT_NAME)
@@ -426,8 +442,12 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
        default: token->keyword = C_RID_CODE (token->value);
        }
     }
-  else
-    token->keyword = RID_MAX;
+  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;
+    }
 }
 
 /* Update the globals input_location and in_system_header from TOKEN.  */
@@ -477,12 +497,7 @@ cp_lexer_next_token_is_not (cp_lexer* lexer, enum cpp_ttype type)
 static inline bool
 cp_lexer_next_token_is_keyword (cp_lexer* lexer, enum rid keyword)
 {
-  cp_token *token;
-
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (lexer);
-  /* Check to see if it is the indicated keyword.  */
-  return token->keyword == keyword;
+  return cp_lexer_peek_token (lexer)->keyword == keyword;
 }
 
 /* Return a pointer to the Nth token in the token stream.  If N is 1,
@@ -497,14 +512,15 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
   cp_token *token;
 
   /* N is 1-based, not zero-based.  */
-  gcc_assert (n > 0 && lexer->next_token != &eof_token);
-
+  gcc_assert (n > 0);
+  
   if (cp_lexer_debugging_p (lexer))
     fprintf (cp_lexer_debug_stream,
             "cp_lexer: peeking ahead %ld at token: ", (long)n);
 
   --n;
   token = lexer->next_token;
+  gcc_assert (!n || token != &eof_token);
   while (n != 0)
     {
       ++token;
@@ -536,6 +552,7 @@ cp_lexer_consume_token (cp_lexer* lexer)
   cp_token *token = lexer->next_token;
 
   gcc_assert (token != &eof_token);
+  gcc_assert (!lexer->in_pragma || token->type != CPP_PRAGMA_EOL);
 
   do
     {
@@ -613,25 +630,6 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
     }
 }
 
-/* Consume and handle a pragma token.  */
-static void
-cp_lexer_handle_pragma (cp_lexer *lexer)
-{
-  cpp_string s;
-  cp_token *token = cp_lexer_consume_token (lexer);
-  gcc_assert (token->type == CPP_PRAGMA);
-  gcc_assert (token->value);
-
-  s.len = TREE_STRING_LENGTH (token->value);
-  s.text = (const unsigned char *) TREE_STRING_POINTER (token->value);
-
-  cpp_handle_deferred_pragma (parse_in, &s);
-
-  /* Clearing token->value here means that we will get an ICE if we
-     try to process this #pragma again (which should be impossible).  */
-  token->value = NULL;
-}
-
 /* Begin saving tokens.  All tokens consumed after this point will be
    preserved.  */
 
@@ -714,7 +712,6 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
 
     case CPP_STRING:
     case CPP_WSTRING:
-    case CPP_PRAGMA:
       fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->value));
       break;
 
@@ -755,9 +752,6 @@ cp_token_cache_new (cp_token *first, cp_token *last)
 \f
 /* Decl-specifiers.  */
 
-static void clear_decl_specs
-  (cp_decl_specifier_seq *);
-
 /* Set *DECL_SPECS to represent an empty decl-specifier-seq.  */
 
 static void
@@ -786,7 +780,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.  */
@@ -816,12 +811,15 @@ make_declarator (cp_declarator_kind kind)
   return declarator;
 }
 
-/* Make a declarator for a generalized identifier.  If non-NULL, the
-   identifier is QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is
-   just UNQUALIFIED_NAME.  */
+/* Make a declarator for a generalized identifier.  If
+   QUALIFYING_SCOPE is non-NULL, the identifier is
+   QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is just
+   UNQUALIFIED_NAME.  SFK indicates the kind of special function this
+   is, if any.   */
 
 static cp_declarator *
-make_id_declarator (tree qualifying_scope, tree unqualified_name)
+make_id_declarator (tree qualifying_scope, tree unqualified_name,
+                   special_function_kind sfk)
 {
   cp_declarator *declarator;
 
@@ -838,10 +836,14 @@ make_id_declarator (tree qualifying_scope, tree unqualified_name)
   if (qualifying_scope && TYPE_P (qualifying_scope))
     qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope);
 
+  gcc_assert (TREE_CODE (unqualified_name) == IDENTIFIER_NODE
+             || TREE_CODE (unqualified_name) == BIT_NOT_EXPR
+             || TREE_CODE (unqualified_name) == TEMPLATE_ID_EXPR);
+
   declarator = make_declarator (cdk_id);
   declarator->u.id.qualifying_scope = qualifying_scope;
   declarator->u.id.unqualified_name = unqualified_name;
-  declarator->u.id.sfk = sfk_none;
+  declarator->u.id.sfk = sfk;
 
   return declarator;
 }
@@ -1292,12 +1294,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
@@ -1343,9 +1354,6 @@ typedef struct cp_parser GTY(())
   unsigned num_template_parameter_lists;
 } cp_parser;
 
-/* The type of a function that parses some kind of expression.  */
-typedef tree (*cp_parser_expression_fn) (cp_parser *);
-
 /* Prototypes.  */
 
 /* Constructors and destructors.  */
@@ -1380,11 +1388,11 @@ static bool cp_parser_translation_unit
 /* Expressions [gram.expr]  */
 
 static tree cp_parser_primary_expression
-  (cp_parser *, bool, cp_id_kind *, tree *);
+  (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
@@ -1439,9 +1447,9 @@ static tree cp_parser_builtin_offsetof
 /* Statements [gram.stmt.stmt]  */
 
 static void cp_parser_statement
-  (cp_parser *, tree);
+  (cp_parser *, tree, bool);
 static tree cp_parser_labeled_statement
-  (cp_parser *, tree);
+  (cp_parser *, tree, bool);
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
@@ -1519,7 +1527,7 @@ static void cp_parser_linkage_specification
 /* 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 *, tree, 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
@@ -1529,7 +1537,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
@@ -1661,6 +1669,10 @@ static bool cp_parser_extension_opt
 static void cp_parser_label_declaration
   (cp_parser *);
 
+enum pragma_context { pragma_external, pragma_stmt, pragma_compound };
+static bool cp_parser_pragma
+  (cp_parser *, enum pragma_context);
+
 /* Objective-C++ Productions */
 
 static tree cp_parser_objc_message_receiver
@@ -1693,7 +1705,7 @@ static tree cp_parser_objc_statement
 /* Utility Routines */
 
 static tree cp_parser_lookup_name
-  (cp_parser *, tree, enum tag_types, bool, bool, bool, bool *);
+  (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
 static tree cp_parser_lookup_name_simple
   (cp_parser *, tree);
 static tree cp_parser_maybe_treat_template_as_class
@@ -1714,8 +1726,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
+  (tree);
 static tree cp_parser_single_declaration
-  (cp_parser *, bool, bool *);
+  (cp_parser *, tree, bool, bool *);
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
@@ -1733,7 +1747,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
@@ -1804,6 +1818,8 @@ 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_pragma_eol
+  (cp_parser*, cp_token *);
 static bool cp_parser_error_occurred
   (cp_parser *);
 static bool cp_parser_allow_gnu_extensions_p
@@ -1846,7 +1862,7 @@ static inline void
 cp_parser_warn_min_max (void)
 {
   if (warn_deprecated && !in_system_header)
-    warning (0, "minimum/maximum operators are deprecated");
+    warning (OPT_Wdeprecated, "minimum/maximum operators are deprecated");
 }
 
 /* If not parsing tentatively, issue a diagnostic of the form
@@ -1864,12 +1880,14 @@ cp_parser_error (cp_parser* parser, const char* message)
       /* This diagnostic makes more sense if it is tagged to the line
         of the token we just peeked at.  */
       cp_lexer_set_source_position_from_token (token);
+
       if (token->type == CPP_PRAGMA)
        {
          error ("%<#pragma%> is not allowed here");
-         cp_lexer_purge_token (parser->lexer);
+         cp_parser_skip_to_pragma_eol (parser, token);
          return;
        }
+
       c_parse_error (message,
                     /* Because c_parser_error does not understand
                        CPP_KEYWORD, keywords are treated like
@@ -2042,11 +2060,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
   decl = cp_parser_lookup_name_simple (parser, id);
   parser->scope = old_scope;
   /* If the lookup found a template-name, it means that the user forgot
-  to specify an argument list. Emit an useful error message.  */
+  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);
-  else if (!parser->scope || parser->scope == error_mark_node)
+  else if (!parser->scope)
     {
       /* Issue an error message.  */
       error ("%qE does not name a type", id);
@@ -2093,7 +2111,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
     }
   /* Here we diagnose qualified-ids where the scope is actually correct,
      but the identifier does not resolve to a valid type name.  */
-  else
+  else if (parser->scope != error_mark_node)
     {
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
        error ("%qE in namespace %qE does not name a type",
@@ -2127,7 +2145,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.  */
@@ -2163,7 +2182,6 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
 {
   unsigned paren_depth = 0;
   unsigned brace_depth = 0;
-  int result;
 
   if (recovering && !or_comma
       && cp_parser_uncommitted_to_tentative_parse_p (parser))
@@ -2171,62 +2189,55 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
 
   while (true)
     {
-      cp_token *token;
+      cp_token * token = cp_lexer_peek_token (parser->lexer);
 
-      /* If we've run out of tokens, then there is no closing `)'.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+      switch (token->type)
        {
-         result = 0;
-         break;
-       }
+       case CPP_EOF:
+       case CPP_PRAGMA_EOL:
+         /* If we've run out of tokens, then there is no closing `)'.  */
+         return 0;
 
-      token = cp_lexer_peek_token (parser->lexer);
+       case CPP_SEMICOLON:
+         /* This matches the processing in skip_to_end_of_statement.  */
+         if (!brace_depth)
+           return 0;
+         break;
 
-      /* This matches the processing in skip_to_end_of_statement.  */
-      if (token->type == CPP_SEMICOLON && !brace_depth)
-       {
-         result = 0;
+       case CPP_OPEN_BRACE:
+         ++brace_depth;
          break;
-       }
-      if (token->type == CPP_OPEN_BRACE)
-       ++brace_depth;
-      if (token->type == CPP_CLOSE_BRACE)
-       {
+       case CPP_CLOSE_BRACE:
          if (!brace_depth--)
-           {
-             result = 0;
-             break;
-           }
-       }
-      if (recovering && or_comma && token->type == CPP_COMMA
-         && !brace_depth && !paren_depth)
-       {
-         result = -1;
+           return 0;
          break;
-       }
 
-      if (!brace_depth)
-       {
-         /* If it is an `(', we have entered another level of nesting.  */
-         if (token->type == CPP_OPEN_PAREN)
+       case CPP_COMMA:
+         if (recovering && or_comma && !brace_depth && !paren_depth)
+           return -1;
+         break;
+
+       case CPP_OPEN_PAREN:
+         if (!brace_depth)
            ++paren_depth;
-         /* If it is a `)', then we might be done.  */
-         else if (token->type == CPP_CLOSE_PAREN && !paren_depth--)
+         break;
+
+       case CPP_CLOSE_PAREN:
+         if (!brace_depth && !paren_depth--)
            {
              if (consume_paren)
                cp_lexer_consume_token (parser->lexer);
-             {
-               result = 1;
-               break;
-             }
+             return 1;
            }
+         break;
+
+       default:
+         break;
        }
 
       /* Consume the token.  */
       cp_lexer_consume_token (parser->lexer);
     }
-
-  return result;
 }
 
 /* Consume tokens until we reach the end of the current statement.
@@ -2240,31 +2251,34 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
 
   while (true)
     {
-      cp_token *token;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
 
-      /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If we've run out of tokens, stop.  */
-      if (token->type == CPP_EOF)
-       break;
-      /* If the next token is a `;', we have reached the end of the
-        statement.  */
-      if (token->type == CPP_SEMICOLON && !nesting_depth)
-       break;
-      /* If the next token is a non-nested `}', then we have reached
-        the end of the current block.  */
-      if (token->type == CPP_CLOSE_BRACE)
+      switch (token->type)
        {
-         /* If this is a non-nested `}', stop before consuming it.
+       case CPP_EOF:
+       case CPP_PRAGMA_EOL:
+         /* If we've run out of tokens, stop.  */
+         return;
+
+       case CPP_SEMICOLON:
+         /* If the next token is a `;', we have reached the end of the
+            statement.  */
+         if (!nesting_depth)
+           return;
+         break;
+
+       case CPP_CLOSE_BRACE:
+         /* If this is a non-nested '}', stop before consuming it.
             That way, when confronted with something like:
 
               { 3 + }
 
-            we stop before consuming the closing `}', even though we
+            we stop before consuming the closing '}', even though we
             have not yet reached a `;'.  */
          if (nesting_depth == 0)
-           break;
-         /* If it is the closing `}' for a block that we have
+           return;
+
+         /* If it is the closing '}' for a block that we have
             scanned, stop -- but only after consuming the token.
             That way given:
 
@@ -2277,13 +2291,17 @@ cp_parser_skip_to_end_of_statement (cp_parser* parser)
          if (--nesting_depth == 0)
            {
              cp_lexer_consume_token (parser->lexer);
-             break;
+             return;
            }
+
+       case CPP_OPEN_BRACE:
+         ++nesting_depth;
+         break;
+
+       default:
+         break;
        }
-      /* If it the next token is a `{', then we are entering a new
-        block.  Consume the entire block.  */
-      else if (token->type == CPP_OPEN_BRACE)
-       ++nesting_depth;
+
       /* Consume the token.  */
       cp_lexer_consume_token (parser->lexer);
     }
@@ -2320,15 +2338,12 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
     {
       cp_token *token = cp_lexer_peek_token (parser->lexer);
 
-      if (token->type == CPP_EOF)
-       break;
-
       switch (token->type)
        {
        case CPP_EOF:
+       case CPP_PRAGMA_EOL:
          /* If we've run out of tokens, stop.  */
-         nesting_depth = -1;
-         continue;
+         return;
 
        case CPP_SEMICOLON:
          /* Stop if this is an unnested ';'. */
@@ -2355,7 +2370,6 @@ cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
 
       /* Consume the token.  */
       cp_lexer_consume_token (parser->lexer);
-
     }
 }
 
@@ -2369,26 +2383,67 @@ cp_parser_skip_to_closing_brace (cp_parser *parser)
 
   while (true)
     {
-      cp_token *token;
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+      switch (token->type)
+       {
+       case CPP_EOF:
+       case CPP_PRAGMA_EOL:
+         /* If we've run out of tokens, stop.  */
+         return;
+
+       case CPP_CLOSE_BRACE:
+         /* If the next token is a non-nested `}', then we have reached
+            the end of the current block.  */
+         if (nesting_depth-- == 0)
+           return;
+         break;
+
+       case CPP_OPEN_BRACE:
+         /* If it the next token is a `{', then we are entering a new
+            block.  Consume the entire block.  */
+         ++nesting_depth;
+         break;
+
+       default:
+         break;
+       }
 
-      /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If we've run out of tokens, stop.  */
-      if (token->type == CPP_EOF)
-       break;
-      /* If the next token is a non-nested `}', then we have reached
-        the end of the current block.  */
-      if (token->type == CPP_CLOSE_BRACE && nesting_depth-- == 0)
-       break;
-      /* If it the next token is a `{', then we are entering a new
-        block.  Consume the entire block.  */
-      else if (token->type == CPP_OPEN_BRACE)
-       ++nesting_depth;
       /* Consume the token.  */
       cp_lexer_consume_token (parser->lexer);
     }
 }
 
+/* Consume tokens until we reach the end of the pragma.  The PRAGMA_TOK
+   parameter is the PRAGMA token, allowing us to purge the entire pragma
+   sequence.  */
+
+static void
+cp_parser_skip_to_pragma_eol (cp_parser* parser, cp_token *pragma_tok)
+{
+  cp_token *token;
+
+  parser->lexer->in_pragma = false;
+
+  do
+    token = cp_lexer_consume_token (parser->lexer);
+  while (token->type != CPP_PRAGMA_EOL && token->type != CPP_EOF);
+
+  /* Ensure that the pragma is not parsed again.  */
+  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.  */
@@ -2400,7 +2455,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=*/0);
+                                   /*complain=*/tf_none);
       if (result == error_mark_node)
        cp_parser_diagnose_invalid_type_name (parser, scope, id);
       return result;
@@ -2458,7 +2513,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;
@@ -2655,39 +2710,34 @@ cp_parser_translation_unit (cp_parser* parser)
       declarator_obstack_base = obstack_next_free (&declarator_obstack);
     }
 
-  while (true)
+  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.) */
+      if (parser->implicit_extern_c)
+        {
+          pop_lang_context ();
+          parser->implicit_extern_c = false;
+        }
+      
+      /* Finish up.  */
+      finish_translation_unit ();
+      
+      success = true;
+    }
+  else
     {
-      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.) */
-         if (parser->implicit_extern_c)
-           {
-             pop_lang_context ();
-             parser->implicit_extern_c = false;
-           }
-
-         /* Finish up.  */
-         finish_translation_unit ();
-
-         success = true;
-         break;
-       }
-      else
-       {
-         cp_parser_error (parser, "expected declaration");
-         success = false;
-         break;
-       }
+      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);
@@ -2711,6 +2761,7 @@ cp_parser_translation_unit (cp_parser* parser)
    primary-expression:
      ( compound-statement )
      __builtin_va_arg ( assignment-expression , type-id )
+     __builtin_offsetof ( type-id , offsetof-expression )
 
    Objective-C++ Extension:
 
@@ -2720,29 +2771,25 @@ cp_parser_translation_unit (cp_parser* parser)
    literal:
      __null
 
-   CAST_P is true if this primary expression is the target of a cast.
-
-   Returns a representation of the expression.
+   ADDRESS_P is true iff this expression was immediately preceded by
+   "&" and therefore might denote a pointer-to-member.  CAST_P is true
+   iff this expression is the target of a cast.  TEMPLATE_ARG_P is
+   true iff this expression is a template argument.
 
-   *IDK indicates what kind of id-expression (if any) was present.
-
-   *QUALIFYING_CLASS is set to a non-NULL value if the id-expression can be
-   used as the operand of a pointer-to-member.  In that case,
-   *QUALIFYING_CLASS gives the class that is used as the qualifying
-   class in the pointer-to-member.  */
+   Returns a representation of the expression.  Upon return, *IDK
+   indicates what kind of id-expression (if any) was present.  */
 
 static tree
 cp_parser_primary_expression (cp_parser *parser,
+                             bool address_p,
                              bool cast_p,
-                             cp_id_kind *idk,
-                             tree *qualifying_class)
+                             bool template_arg_p,
+                             cp_id_kind *idk)
 {
   cp_token *token;
 
   /* Assume the primary expression is not an id-expression.  */
   *idk = CP_ID_KIND_NONE;
-  /* And that it cannot be used as pointer-to-member.  */
-  *qualifying_class = NULL_TREE;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -2783,7 +2830,10 @@ cp_parser_primary_expression (cp_parser *parser,
                  /* The end of the cast-expression.  */
                  && next_token->type != CPP_CLOSE_PAREN
                  /* The end of an array bound.  */
-                 && next_token->type != CPP_CLOSE_SQUARE)
+                 && next_token->type != CPP_CLOSE_SQUARE
+                 /* The closing ">" in a template-argument-list.  */
+                 && (next_token->type != CPP_GREATER
+                     || parser->greater_than_is_operator_p))
                cast_p = false;
            }
 
@@ -2965,6 +3015,8 @@ cp_parser_primary_expression (cp_parser *parser,
        tree id_expression;
        tree decl;
        const char *error_msg;
+       bool template_p;
+       bool done;
 
       id_expression:
        /* Parse the id-expression.  */
@@ -2972,30 +3024,38 @@ cp_parser_primary_expression (cp_parser *parser,
          = cp_parser_id_expression (parser,
                                     /*template_keyword_p=*/false,
                                     /*check_dependency_p=*/true,
-                                    /*template_p=*/NULL,
-                                    /*declarator_p=*/false);
+                                    &template_p,
+                                    /*declarator_p=*/false,
+                                    /*optional_p=*/false);
        if (id_expression == error_mark_node)
          return error_mark_node;
+       token = cp_lexer_peek_token (parser->lexer);
+       done = (token->type != CPP_OPEN_SQUARE
+               && token->type != CPP_OPEN_PAREN
+               && token->type != CPP_DOT
+               && token->type != CPP_DEREF
+               && token->type != CPP_PLUS_PLUS
+               && token->type != CPP_MINUS_MINUS);
        /* If we have a template-id, then no further lookup is
           required.  If the template-id was for a template-class, we
           will sometimes have a TYPE_DECL at this point.  */
-       else if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR
-           || TREE_CODE (id_expression) == TYPE_DECL)
+       if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR
+                || TREE_CODE (id_expression) == TYPE_DECL)
          decl = id_expression;
        /* Look up the name.  */
        else
          {
-           bool ambiguous_p;
+           tree ambiguous_decls;
 
            decl = cp_parser_lookup_name (parser, id_expression,
                                          none_type,
-                                         /*is_template=*/false,
+                                         template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
-                                         &ambiguous_p);
+                                         &ambiguous_decls);
            /* If the lookup was ambiguous, an error will already have
               been issued.  */
-           if (ambiguous_p)
+           if (ambiguous_decls)
              return error_mark_node;
 
            /* In Objective-C++, an instance variable (ivar) may be preferred
@@ -3003,14 +3063,9 @@ cp_parser_primary_expression (cp_parser *parser,
            decl = objc_lookup_ivar (decl, id_expression);
 
            /* If name lookup gives us a SCOPE_REF, then the
-              qualifying scope was dependent.  Just propagate the
-              name.  */
+              qualifying scope was dependent.  */
            if (TREE_CODE (decl) == SCOPE_REF)
-             {
-               if (TYPE_P (TREE_OPERAND (decl, 0)))
-                 *qualifying_class = TREE_OPERAND (decl, 0);
-               return decl;
-             }
+             return decl;
            /* Check to see if DECL is a local variable in a context
               where that is forbidden.  */
            if (parser->local_variables_forbidden_p
@@ -3039,12 +3094,15 @@ cp_parser_primary_expression (cp_parser *parser,
              }
          }
 
-       decl = finish_id_expression (id_expression, decl, parser->scope,
-                                    idk, qualifying_class,
-                                    parser->integral_constant_expression_p,
-                                    parser->allow_non_integral_constant_expression_p,
-                                    &parser->non_integral_constant_expression_p,
-                                    &error_msg);
+       decl = (finish_id_expression 
+               (id_expression, decl, parser->scope,
+                idk,
+                parser->integral_constant_expression_p,
+                parser->allow_non_integral_constant_expression_p,
+                &parser->non_integral_constant_expression_p,
+                template_p, done, address_p,
+                template_arg_p,
+                &error_msg));
        if (error_msg)
          cp_parser_error (parser, error_msg);
        return decl;
@@ -3101,14 +3159,15 @@ 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;
 
   /* Assume the `template' keyword was not used.  */
   if (template_p)
-    *template_p = false;
+    *template_p = template_keyword_p;
 
   /* Look for the optional `::' operator.  */
   global_scope_p
@@ -3144,7 +3203,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;
@@ -3202,7 +3262,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.
@@ -3231,7 +3292,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;
 
@@ -3401,6 +3463,15 @@ cp_parser_unqualified_id (cp_parser* parser,
        else if (type_decl == error_mark_node)
          return error_mark_node;
 
+       /* Check that destructor name and scope match.  */
+       if (declarator_p && scope && !check_dtor_name (scope, type_decl))
+         {
+           if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
+             error ("declaration of %<~%T%> as member of %qT",
+                    type_decl, scope);
+           return error_mark_node;
+         }
+
        /* [class.dtor]
 
           A typedef-name that names a class shall not be used as the
@@ -3443,6 +3514,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;
     }
@@ -3475,7 +3548,6 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                                     bool is_declaration)
 {
   bool success = false;
-  tree access_check = NULL_TREE;
   cp_token_position start = 0;
   cp_token *token;
 
@@ -3495,9 +3567,10 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
 
   /* Remember where the nested-name-specifier starts.  */
   if (cp_parser_uncommitted_to_tentative_parse_p (parser))
-    start = cp_lexer_token_position (parser->lexer, false);
-
-  push_deferring_access_checks (dk_deferred);
+    {
+      start = cp_lexer_token_position (parser->lexer, false);
+      push_deferring_access_checks (dk_deferred);
+    }
 
   while (true)
     {
@@ -3603,16 +3676,32 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
              token = cp_lexer_consume_token (parser->lexer);
              if (!error_p)
                {
-                 tree decl;
-
-                 decl = cp_parser_lookup_name_simple (parser, token->value);
-                 if (TREE_CODE (decl) == TEMPLATE_DECL)
-                   error ("%qD used without template parameters", decl);
-                 else
-                   cp_parser_name_lookup_error
-                     (parser, token->value, decl,
-                      "is not a class or namespace");
-                 parser->scope = NULL_TREE;
+                 if (!token->ambiguous_p)
+                   {
+                     tree decl;
+                     tree ambiguous_decls;
+
+                     decl = cp_parser_lookup_name (parser, token->value,
+                                                   none_type,
+                                                   /*is_template=*/false,
+                                                   /*is_namespace=*/false,
+                                                   /*check_dependency=*/true,
+                                                   &ambiguous_decls);
+                     if (TREE_CODE (decl) == TEMPLATE_DECL)
+                       error ("%qD used without template parameters", decl);
+                     else if (ambiguous_decls)
+                       {
+                         error ("reference to %qD is ambiguous", 
+                                token->value);
+                         print_candidates (ambiguous_decls);
+                         decl = error_mark_node;
+                       }
+                     else
+                       cp_parser_name_lookup_error
+                         (parser, token->value, decl,
+                          "is not a class or namespace");
+                   }
+                 parser->scope = error_mark_node;
                  error_p = true;
                  /* Treat this as a successful nested-name-specifier
                     due to:
@@ -3628,29 +3717,38 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
            }
          break;
        }
-
       /* We've found one valid nested-name-specifier.  */
       success = true;
-      /* Make sure we look in the right scope the next time through
-        the loop.  */
-      parser->scope = (TREE_CODE (new_scope) == TYPE_DECL
-                      ? TREE_TYPE (new_scope)
-                      : new_scope);
+      /* Name lookup always gives us a DECL.  */
+      if (TREE_CODE (new_scope) == TYPE_DECL)
+       new_scope = TREE_TYPE (new_scope);
+      /* Uses of "template" must be followed by actual templates.  */
+      if (template_keyword_p
+         && !(CLASS_TYPE_P (new_scope)
+              && ((CLASSTYPE_USE_TEMPLATE (new_scope)
+                   && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (new_scope)))
+                  || CLASSTYPE_IS_TEMPLATE (new_scope)))
+         && !(TREE_CODE (new_scope) == TYPENAME_TYPE
+              && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
+                  == TEMPLATE_ID_EXPR)))
+       pedwarn (TYPE_P (new_scope)
+                ? "%qT is not a template"
+                : "%qD is not a template",
+                new_scope);
       /* If it is a class scope, try to complete it; we are about to
         be looking up names inside the class.  */
-      if (TYPE_P (parser->scope)
+      if (TYPE_P (new_scope)
          /* Since checking types for dependency can be expensive,
             avoid doing it if the type is already complete.  */
-         && !COMPLETE_TYPE_P (parser->scope)
+         && !COMPLETE_TYPE_P (new_scope)
          /* Do not try to complete dependent types.  */
-         && !dependent_type_p (parser->scope))
-       complete_type (parser->scope);
+         && !dependent_type_p (new_scope))
+       new_scope = complete_type (new_scope);
+      /* Make sure we look in the right scope the next time through
+        the loop.  */
+      parser->scope = new_scope;
     }
 
-  /* 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 nested-name-specifier with a CPP_NESTED_NAME_SPECIFIER
      token.  That way, should we re-parse the token stream, we will
@@ -3658,19 +3756,27 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
      we issue duplicate error messages.  */
   if (success && start)
     {
-      cp_token *token = cp_lexer_token_at (parser->lexer, 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;
-      token->value = build_tree_list (access_check, parser->scope);
+      /* 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->keyword = RID_MAX;
 
       /* Purge all subsequent tokens.  */
       cp_lexer_purge_tokens_after (parser->lexer, start);
     }
+  
+  if (start)
+    pop_to_parent_deferring_access_checks ();
 
-  pop_deferring_access_checks ();
   return success ? parser->scope : NULL_TREE;
 }
 
@@ -3819,10 +3925,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
   enum rid keyword;
   cp_id_kind idk = CP_ID_KIND_NONE;
   tree postfix_expression = NULL_TREE;
-  /* Non-NULL only if the current postfix-expression can be used to
-     form a pointer-to-member.  In that case, QUALIFYING_CLASS is the
-     class used to qualify the member.  */
-  tree qualifying_class = NULL_TREE;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -3950,53 +4052,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
 
     case RID_TYPENAME:
       {
-       bool template_p = false;
-       tree id;
        tree type;
-       tree scope;
-
-       /* Consume the `typename' token.  */
-       cp_lexer_consume_token (parser->lexer);
-       /* Look for the optional `::' operator.  */
-       cp_parser_global_scope_opt (parser,
-                                   /*current_scope_valid_p=*/false);
-       /* Look for the nested-name-specifier.  In case of error here,
-          consume the trailing id to avoid subsequent error messages
-          for usual cases.  */
-       scope = cp_parser_nested_name_specifier (parser,
-                                                /*typename_keyword_p=*/true,
-                                                /*check_dependency_p=*/true,
-                                                /*type_p=*/true,
-                                                /*is_declaration=*/true);
-
-       /* Look for the optional `template' keyword.  */
-       template_p = cp_parser_optional_template_keyword (parser);
-       /* We don't know whether we're looking at a template-id or an
-          identifier.  */
-       cp_parser_parse_tentatively (parser);
-       /* Try a template-id.  */
-       id = cp_parser_template_id (parser, template_p,
-                                   /*check_dependency_p=*/true,
-                                   /*is_declaration=*/true);
-       /* If that didn't work, try an identifier.  */
-       if (!cp_parser_parse_definitely (parser))
-         id = cp_parser_identifier (parser);
-
-       /* Don't process id if nested name specifier is invalid.  */
-       if (!scope || scope == error_mark_node)
-         return error_mark_node;
-       /* If we look up a template-id in a non-dependent qualifying
-          scope, there's no need to create a dependent type.  */
-       else if (TREE_CODE (id) == TYPE_DECL
-           && !dependent_type_p (parser->scope))
-         type = TREE_TYPE (id);
-       /* Create a TYPENAME_TYPE to represent the type to which the
-          functional cast is being performed.  */
-       else
-         type = make_typename_type (parser->scope, id,
-                                    typename_type,
-                                    /*complain=*/1);
-
+       /* The syntax permitted here is the same permitted for an
+          elaborated-type-specifier.  */
+       type = cp_parser_elaborated_type_specifier (parser,
+                                                   /*is_friend=*/false,
+                                                   /*is_declaration=*/false);
        postfix_expression = cp_parser_functional_cast (parser, type);
       }
       break;
@@ -4072,38 +4133,14 @@ 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,
-                                                          cast_p,
-                                                          &idk,
-                                                          &qualifying_class);
+       postfix_expression 
+         = cp_parser_primary_expression (parser, address_p, cast_p, 
+                                         /*template_arg_p=*/false,
+                                         &idk);
       }
       break;
     }
 
-  /* If we were avoiding committing to the processing of a
-     qualified-id until we knew whether or not we had a
-     pointer-to-member, we now know.  */
-  if (qualifying_class)
-    {
-      bool done;
-
-      /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      done = (token->type != CPP_OPEN_SQUARE
-             && token->type != CPP_OPEN_PAREN
-             && token->type != CPP_DOT
-             && token->type != CPP_DEREF
-             && token->type != CPP_PLUS_PLUS
-             && token->type != CPP_MINUS_MINUS);
-
-      postfix_expression = finish_qualified_id_expr (qualifying_class,
-                                                    postfix_expression,
-                                                    done,
-                                                    address_p);
-      if (done)
-       return postfix_expression;
-    }
-
   /* Keep looping until the postfix-expression is complete.  */
   while (true)
     {
@@ -4236,7 +4273,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,
@@ -4391,7 +4429,6 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 {
   tree name;
   bool dependent_p;
-  bool template_p;
   bool pseudo_destructor_p;
   tree scope = NULL_TREE;
 
@@ -4418,7 +4455,13 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
         underlying type here.  */
       scope = non_reference (scope);
       /* The type of the POSTFIX_EXPRESSION must be complete.  */
-      scope = complete_type_or_else (scope, NULL_TREE);
+      if (scope == unknown_type_node)
+       {
+         error ("%qE does not have class type", postfix_expression);
+         scope = NULL_TREE;
+       }
+      else
+       scope = complete_type_or_else (scope, NULL_TREE);
       /* Let the name lookup machinery know that we are processing a
         class member access expression.  */
       parser->context->object_type = scope;
@@ -4462,12 +4505,15 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
       /* If the SCOPE is not a scalar type, we are looking at an
         ordinary class member access expression, rather than a
         pseudo-destructor-name.  */
-      template_p = cp_parser_optional_template_keyword (parser);
+      bool template_p;
       /* Parse the id-expression.  */
-      name = cp_parser_id_expression (parser, template_p,
-                                     /*check_dependency_p=*/true,
-                                     /*template_p=*/NULL,
-                                     /*declarator_p=*/false);
+      name = (cp_parser_id_expression 
+             (parser, 
+              cp_parser_optional_template_keyword (parser),
+              /*check_dependency_p=*/true,
+              &template_p,
+              /*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;
@@ -4494,7 +4540,10 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
        {
          if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
            {
-             name = build_nt (SCOPE_REF, parser->scope, name);
+             name = build_qualified_name (/*type=*/NULL_TREE,
+                                          parser->scope,
+                                          name,
+                                          template_p);
              parser->scope = NULL_TREE;
              parser->qualifying_scope = NULL_TREE;
              parser->object_scope = NULL_TREE;
@@ -4503,7 +4552,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
            adjust_result_of_qualified_name_lookup
              (name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
          postfix_expression
-           = finish_class_member_access_expr (postfix_expression, name);
+           = finish_class_member_access_expr (postfix_expression, name,
+                                              template_p);
        }
     }
 
@@ -5399,7 +5449,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
              && !in_system_header
              && !VOID_TYPE_P (type)
              && current_lang_name != lang_name_c)
-           warning (0, "use of old-style cast");
+           warning (OPT_Wold_style_cast, "use of old-style cast");
 
          /* Only type conversions to integral or enumeration types
             can be used in constant-expressions.  */
@@ -6009,15 +6059,20 @@ cp_parser_builtin_offsetof (cp_parser *parser)
      iteration-statement
      jump-statement
      declaration-statement
-     try-block  */
+     try-block
+
+  IN_COMPOUND is true when the statement is nested inside a 
+  cp_parser_compound_statement; this matters for certain pragmas.  */
 
 static void
-cp_parser_statement (cp_parser* parser, tree in_statement_expr)
+cp_parser_statement (cp_parser* parser, tree in_statement_expr,
+                    bool in_compound)
 {
   tree statement;
   cp_token *token;
   location_t statement_location;
 
+ restart:
   /* There is no statement yet.  */
   statement = NULL_TREE;
   /* Peek at the next token.  */
@@ -6034,8 +6089,8 @@ 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);
+         statement = cp_parser_labeled_statement (parser, in_statement_expr,
+                                                  in_compound);
          break;
 
        case RID_IF:
@@ -6081,7 +6136,8 @@ 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);
+       statement = cp_parser_labeled_statement (parser, in_statement_expr,
+                                                in_compound);
     }
   /* Anything that starts with a `{' must be a compound-statement.  */
   else if (token->type == CPP_OPEN_BRACE)
@@ -6090,7 +6146,20 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
      a statement all its own.  */
   else if (token->type == CPP_PRAGMA)
     {
-      cp_lexer_handle_pragma (parser->lexer);
+      /* 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 
+        require a real statement and must go back and read one.  */
+      if (in_compound)
+       cp_parser_pragma (parser, pragma_compound);
+      else if (!cp_parser_pragma (parser, pragma_stmt))
+       goto restart;
+      return;
+    }
+  else if (token->type == CPP_EOF)
+    {
+      cp_parser_error (parser, "expected statement");
       return;
     }
 
@@ -6131,10 +6200,14 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
      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.  */
+   For an ordinary label, returns a LABEL_EXPR.
+
+   IN_COMPOUND is as for cp_parser_statement: true when we're nested
+   inside a compound.  */
 
 static tree
-cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
+cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr,
+                            bool in_compound)
 {
   cp_token *token;
   tree statement = error_mark_node;
@@ -6177,21 +6250,22 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
        else
          expr_hi = NULL_TREE;
 
-       if (!parser->in_switch_statement_p)
-         error ("case label %qE not within a switch statement", expr);
-       else
+       if (parser->in_switch_statement_p)
          statement = finish_case_label (expr, expr_hi);
+       else
+         error ("case label %qE not within a switch statement", expr);
       }
       break;
 
     case RID_DEFAULT:
       /* Consume the `default' token.  */
       cp_lexer_consume_token (parser->lexer);
-      if (!parser->in_switch_statement_p)
-       error ("case label not within a switch statement");
-      else
-       statement = finish_case_label (NULL_TREE, NULL_TREE);
-      break;
+
+      if (parser->in_switch_statement_p)
+       statement = 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.  */
@@ -6202,7 +6276,7 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
   /* Require the `:' token.  */
   cp_parser_require (parser, CPP_COLON, "`:'");
   /* Parse the labeled statement.  */
-  cp_parser_statement (parser, in_statement_expr);
+  cp_parser_statement (parser, in_statement_expr, in_compound);
 
   /* Return the label, in the case of a `case' or `default' label.  */
   return statement;
@@ -6284,13 +6358,16 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
   /* Scan statements until there aren't any more.  */
   while (true)
     {
+      cp_token *token = cp_lexer_peek_token (parser->lexer);
+
       /* If we're looking at a `}', then we've run out of statements.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE)
-         || cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+      if (token->type == CPP_CLOSE_BRACE
+         || token->type == CPP_EOF
+         || token->type == CPP_PRAGMA_EOL)
        break;
 
       /* Parse the statement.  */
-      cp_parser_statement (parser, in_statement_expr);
+      cp_parser_statement (parser, in_statement_expr, true);
     }
 }
 
@@ -6369,15 +6446,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;
+           parser->in_statement |= IN_SWITCH_STMT;
            cp_parser_implicitly_scoped_statement (parser);
            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);
@@ -6456,6 +6537,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,
@@ -6463,12 +6545,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);
 
@@ -6503,8 +6589,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");
@@ -6513,7 +6598,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;
@@ -6533,9 +6618,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);
       }
@@ -6548,9 +6633,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;
+       parser->in_statement = IN_ITERATION_STMT;
        cp_parser_implicitly_scoped_statement (parser);
-       parser->in_iteration_statement_p = in_iteration_statement_p;
+       parser->in_statement = in_statement;
        finish_do_body (statement);
        /* Look for the `while' keyword.  */
        cp_parser_require_keyword (parser, RID_WHILE, "`while'");
@@ -6595,9 +6680,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);
@@ -6677,25 +6762,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;
 
@@ -6781,19 +6883,25 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser)
 {
   tree statement;
 
+  /* Mark if () ; with a special NOP_EXPR.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      statement = add_stmt (build_empty_stmt ());
+    }
+  /* if a compound is opened, we simply parse the statement directly.  */
+  else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    statement = cp_parser_compound_statement (parser, NULL, false);
   /* If the token is not a `{', then we must take special action.  */
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+  else
     {
       /* Create a compound-statement.  */
       statement = begin_compound_stmt (0);
       /* Parse the dependent-statement.  */
-      cp_parser_statement (parser, false);
+      cp_parser_statement (parser, NULL_TREE, false);
       /* Finish the dummy compound-statement.  */
       finish_compound_stmt (statement);
     }
-  /* Otherwise, we simply parse the statement directly.  */
-  else
-    statement = cp_parser_compound_statement (parser, NULL, false);
 
   /* Return the statement.  */
   return statement;
@@ -6809,13 +6917,13 @@ 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, false);
+    cp_parser_statement (parser, NULL_TREE, false);
   else
     {
       /* Avoid calling cp_parser_compound_statement, so that we
         don't create a new scope.  Do everything else by hand.  */
       cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
-      cp_parser_statement_seq_opt (parser, false);
+      cp_parser_statement_seq_opt (parser, NULL_TREE);
       cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
     }
 }
@@ -6838,7 +6946,8 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
       token = cp_lexer_peek_token (parser->lexer);
 
       if (token->type == CPP_CLOSE_BRACE
-         || token->type == CPP_EOF)
+         || token->type == CPP_EOF
+         || token->type == CPP_PRAGMA_EOL)
        break;
 
       if (token->type == CPP_SEMICOLON)
@@ -6870,7 +6979,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
             A nested declaration cannot, so this is done here and not
             in cp_parser_declaration.  (A #pragma at block scope is
             handled in cp_parser_statement.)  */
-         cp_lexer_handle_pragma (parser->lexer);
+         cp_parser_pragma (parser, pragma_external);
          continue;
        }
 
@@ -6919,6 +7028,11 @@ cp_parser_declaration (cp_parser* parser)
 
   if (token1.type != CPP_EOF)
     token2 = *cp_lexer_peek_nth_token (parser->lexer, 2);
+  else
+    {
+      token2.type = CPP_EOF;
+      token2.keyword = RID_MAX;
+    }
 
   /* Get the high-water mark for the DECLARATOR_OBSTACK.  */
   p = obstack_alloc (&declarator_obstack, 0);
@@ -6963,9 +7077,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))
@@ -7146,9 +7261,19 @@ cp_parser_simple_declaration (cp_parser* parser,
       bool function_definition_p;
       tree decl;
 
-      saw_declarator = true;
+      if (saw_declarator)
+       {
+         /* If we are processing next declarator, coma is expected */
+         token = cp_lexer_peek_token (parser->lexer);
+         gcc_assert (token->type == CPP_COMMA);
+         cp_lexer_consume_token (parser->lexer);
+       }
+      else
+       saw_declarator = true;
+
       /* Parse the init-declarator.  */
       decl = cp_parser_init_declarator (parser, &decl_specifiers,
+                                       /*checks=*/NULL_TREE,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
                                        declares_class_or_enum,
@@ -7181,7 +7306,7 @@ cp_parser_simple_declaration (cp_parser* parser,
       token = cp_lexer_peek_token (parser->lexer);
       /* If it's a `,', there are more declarators to come.  */
       if (token->type == CPP_COMMA)
-       cp_lexer_consume_token (parser->lexer);
+       /* will be consumed next time around */;
       /* If it's a `;', we are done.  */
       else if (token->type == CPP_SEMICOLON)
        break;
@@ -7265,6 +7390,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
                              int* declares_class_or_enum)
 {
   bool constructor_possible_p = !parser->in_declarator_p;
+  cp_decl_spec ds;
 
   /* Clear DECL_SPECS.  */
   clear_decl_specs (decl_specs);
@@ -7299,8 +7425,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
          /* decl-specifier:
               friend  */
        case RID_FRIEND:
-         if (decl_specs->specs[(int) ds_friend]++)
-           error ("duplicate %<friend%>");
+         ++decl_specs->specs[(int) ds_friend];
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
          break;
@@ -7338,39 +7463,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.  */
@@ -7466,6 +7565,42 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
+  /* Check for repeated decl-specifiers.  */
+  for (ds = ds_first; ds != ds_last; ++ds)
+    {
+      unsigned count = decl_specs->specs[(int)ds];
+      if (count < 2)
+       continue;
+      /* The "long" specifier is a special case because of "long long".  */
+      if (ds == ds_long)
+       {
+         if (count > 2)
+           error ("%<long long long%> is too long for GCC");
+         else if (pedantic && !in_system_header && warn_long_long)
+           pedwarn ("ISO C++ does not support %<long long%>");
+       }
+      else if (count > 1)
+       {
+         static const char *const decl_spec_names[] = {
+           "signed",
+           "unsigned",
+           "short",
+           "long",
+           "const",
+           "volatile",
+           "restrict",
+           "inline",
+           "virtual",
+           "explicit",
+           "friend",
+           "typedef",
+           "__complex",
+           "__thread"
+         };
+         error ("duplicate %qs", decl_spec_names[(int)ds]);
+       }
+    }
+
   /* Don't allow a friend specifier with a class definition.  */
   if (decl_specs->specs[(int) ds_friend] != 0
       && (*declares_class_or_enum & 2))
@@ -7529,7 +7664,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;
 
@@ -7793,7 +7933,7 @@ cp_parser_mem_initializer_list (cp_parser* parser)
       /* Parse the mem-initializer.  */
       mem_initializer = cp_parser_mem_initializer (parser);
       /* Add it to the list, unless it was erroneous.  */
-      if (mem_initializer)
+      if (mem_initializer != error_mark_node)
        {
          TREE_CHAIN (mem_initializer) = mem_initializer_list;
          mem_initializer_list = mem_initializer;
@@ -7822,7 +7962,8 @@ cp_parser_mem_initializer_list (cp_parser* parser)
 
    Returns a TREE_LIST.  The TREE_PURPOSE is the TYPE (for a base
    class) or FIELD_DECL (for a non-static data member) to initialize;
-   the TREE_VALUE is the expression-list.  */
+   the TREE_VALUE is the expression-list.  An empty initialization
+   list is represented by void_list_node.  */
 
 static tree
 cp_parser_mem_initializer (cp_parser* parser)
@@ -7847,12 +7988,14 @@ cp_parser_mem_initializer (cp_parser* parser)
     = cp_parser_parenthesized_expression_list (parser, false,
                                               /*cast_p=*/false,
                                               /*non_constant_p=*/NULL);
+  if (expression_list == error_mark_node)
+    return error_mark_node;
   if (!expression_list)
     expression_list = void_type_node;
 
   in_base_initializer = 0;
 
-  return member ? build_tree_list (member, expression_list) : NULL_TREE;
+  return member ? build_tree_list (member, expression_list) : error_mark_node;
 }
 
 /* Parse a mem-initializer-id.
@@ -8262,6 +8405,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
 {
   tree parameter_list = NULL_TREE;
 
+  begin_template_parm_list ();
   while (true)
     {
       tree parameter;
@@ -8284,7 +8428,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
     }
 
-  return parameter_list;
+  return end_template_parm_list (parameter_list);
 }
 
 /* Parse a template-parameter.
@@ -8412,7 +8556,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;
@@ -8432,10 +8578,7 @@ cp_parser_type_parameter (cp_parser* parser)
        /* Look for the `<'.  */
        cp_parser_require (parser, CPP_LESS, "`<'");
        /* Parse the template-parameter-list.  */
-       begin_template_parm_list ();
-       parameter_list
-         = cp_parser_template_parameter_list (parser);
-       parameter_list = end_template_parm_list (parameter_list);
+       parameter_list = cp_parser_template_parameter_list (parser);
        /* Look for the `>'.  */
        cp_parser_require (parser, CPP_GREATER, "`>'");
        /* Look for the `class' keyword.  */
@@ -8469,12 +8612,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,
@@ -8488,10 +8633,11 @@ cp_parser_type_parameter (cp_parser* parser)
                                         /*is_template=*/is_template,
                                         /*is_namespace=*/false,
                                         /*check_dependency=*/true,
-                                        /*ambiguous_p=*/NULL);
+                                        /*ambiguous_decls=*/NULL);
            /* 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;
@@ -8844,7 +8990,7 @@ cp_parser_template_name (cp_parser* parser,
                                /*is_template=*/false,
                                /*is_namespace=*/false,
                                check_dependency_p,
-                               /*ambiguous_p=*/NULL);
+                               /*ambiguous_decls=*/NULL);
   decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
@@ -8902,9 +9048,19 @@ cp_parser_template_argument_list (cp_parser* parser)
   tree *arg_ary = fixed_args;
   tree vec;
   bool saved_in_template_argument_list_p;
+  bool saved_ice_p;
+  bool saved_non_ice_p;
 
   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.  */ 
+  saved_ice_p = parser->integral_constant_expression_p;
+  parser->integral_constant_expression_p = false;
+  saved_non_ice_p = parser->non_integral_constant_expression_p;
+  parser->non_integral_constant_expression_p = false;
+  /* Parse the arguments.  */
   do
     {
       tree argument;
@@ -8921,11 +9077,11 @@ cp_parser_template_argument_list (cp_parser* parser)
 
          if (arg_ary == fixed_args)
            {
-             arg_ary = xmalloc (sizeof (tree) * alloced);
+             arg_ary = XNEWVEC (tree, alloced);
              memcpy (arg_ary, fixed_args, sizeof (tree) * n_args);
            }
          else
-           arg_ary = xrealloc (arg_ary, sizeof (tree) * alloced);
+           arg_ary = XRESIZEVEC (tree, arg_ary, alloced);
        }
       arg_ary[n_args++] = argument;
     }
@@ -8938,6 +9094,8 @@ cp_parser_template_argument_list (cp_parser* parser)
 
   if (arg_ary != fixed_args)
     free (arg_ary);
+  parser->non_integral_constant_expression_p = saved_non_ice_p;
+  parser->integral_constant_expression_p = saved_ice_p;
   parser->in_template_argument_list_p = saved_in_template_argument_list_p;
   return vec;
 }
@@ -8967,7 +9125,6 @@ cp_parser_template_argument (cp_parser* parser)
   bool maybe_type_id = false;
   cp_token *token;
   cp_id_kind idk;
-  tree qualifying_class;
 
   /* There's really no way to know what we're looking at, so we just
      try each alternative in order.
@@ -9017,7 +9174,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))
@@ -9034,7 +9192,7 @@ cp_parser_template_argument (cp_parser* parser)
                                          /*is_template=*/template_p,
                                          /*is_namespace=*/false,
                                          /*check_dependency=*/true,
-                                         /*ambiguous_p=*/NULL);
+                                         /*ambiguous_decls=*/NULL);
       if (TREE_CODE (argument) != TEMPLATE_DECL
          && TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
        cp_parser_error (parser, "expected template-name");
@@ -9059,9 +9217,10 @@ cp_parser_template_argument (cp_parser* parser)
     {
       cp_parser_parse_tentatively (parser);
       argument = cp_parser_primary_expression (parser,
+                                              /*adress_p=*/false,
                                               /*cast_p=*/false,
-                                              &idk,
-                                              &qualifying_class);
+                                              /*template_arg_p=*/true,
+                                              &idk);
       if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX
          || !cp_parser_next_token_ends_template_argument_p (parser))
        cp_parser_simulate_error (parser);
@@ -9084,9 +9243,10 @@ cp_parser_template_argument (cp_parser* parser)
     {
       cp_parser_parse_tentatively (parser);
       argument = cp_parser_primary_expression (parser,
+                                              address_p,
                                               /*cast_p=*/false,
-                                              &idk,
-                                              &qualifying_class);
+                                              /*template_arg_p=*/true,
+                                              &idk);
       if (cp_parser_error_occurred (parser)
          || !cp_parser_next_token_ends_template_argument_p (parser))
        cp_parser_abort_tentative_parse (parser);
@@ -9098,11 +9258,11 @@ cp_parser_template_argument (cp_parser* parser)
              argument = TREE_OPERAND (argument, 0);
            }
 
-         if (qualifying_class)
-           argument = finish_qualified_id_expr (qualifying_class,
-                                                argument,
-                                                /*done=*/true,
-                                                address_p);
+         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
@@ -9231,7 +9391,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
         template instantiation.  */
       pop_deferring_access_checks ();
       if (type)
-       do_type_instantiation (type, extension_specifier, /*complain=*/1);
+       do_type_instantiation (type, extension_specifier,
+                               /*complain=*/tf_error);
     }
   else
     {
@@ -9286,6 +9447,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
 static void
 cp_parser_explicit_specialization (cp_parser* parser)
 {
+  bool need_lang_pop;
   /* Look for the `template' keyword.  */
   cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
   /* Look for the `<'.  */
@@ -9294,9 +9456,22 @@ cp_parser_explicit_specialization (cp_parser* parser)
   cp_parser_require (parser, CPP_GREATER, "`>'");
   /* We have processed another parameter list.  */
   ++parser->num_template_parameter_lists;
+  /* [temp]
+   
+     A template ... explicit specialization ... shall not have C
+     linkage.  */ 
+  if (current_lang_name == lang_name_c)
+    {
+      error ("template specialization with C linkage");
+      /* Give it C++ linkage to avoid confusing other parts of the
+        front end.  */
+      push_lang_context (lang_name_cplusplus);
+      need_lang_pop = true;
+    }
+  else
+    need_lang_pop = false;
   /* Let the front end know that we are beginning a specialization.  */
   begin_specialization ();
-
   /* 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))
@@ -9311,11 +9486,15 @@ cp_parser_explicit_specialization (cp_parser* parser)
   else
     /* Parse the dependent declaration.  */
     cp_parser_single_declaration (parser,
+                                 /*checks=*/NULL_TREE,
                                  /*member_p=*/false,
                                  /*friend_p=*/NULL);
-
   /* We're done with the specialization.  */
   end_specialization ();
+  /* For the erroneous case of a template with C linkage, we pushed an
+     implicit C++ linkage scope; exit that scope now.  */
+  if (need_lang_pop)
+    pop_lang_context ();
   /* We're done with this parameter list.  */
   --parser->num_template_parameter_lists;
 }
@@ -9924,7 +10103,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
               && tag_type == typename_type)
        type = make_typename_type (parser->scope, decl,
                                   typename_type,
-                                  /*complain=*/1);
+                                  /*complain=*/tf_error);
       else
        type = TREE_TYPE (decl);
     }
@@ -9955,7 +10134,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
                                        /*check_dependency=*/true,
-                                       /*ambiguous_p=*/NULL);
+                                       /*ambiguous_decls=*/NULL);
 
          /* If we are parsing friend declaration, DECL may be a
             TEMPLATE_DECL tree node here.  However, we need to check
@@ -10044,6 +10223,8 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
             declaration context.  */
 
          tag_scope ts;
+         bool template_p;
+
          if (is_friend)
            /* Friends have special name lookup rules.  */
            ts = ts_within_enclosing_non_class;
@@ -10060,8 +10241,16 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
            warning (OPT_Wattributes,
                     "type attributes are honored only at type definition");
 
-         type = xref_tag (tag_type, identifier, ts,
-                          parser->num_template_parameter_lists);
+         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, 
+                                                   /*num_templates=*/0))
+           return error_mark_node;
+         type = xref_tag (tag_type, identifier, ts, template_p);
        }
     }
   if (tag_type != enum_type)
@@ -10246,11 +10435,13 @@ cp_parser_namespace_name (cp_parser* parser)
                                          /*is_template=*/false,
                                          /*is_namespace=*/true,
                                          /*check_dependency=*/true,
-                                         /*ambiguous_p=*/NULL);
+                                         /*ambiguous_decls=*/NULL);
   /* If it's not a namespace, issue an error.  */
   if (namespace_decl == error_mark_node
       || TREE_CODE (namespace_decl) != NAMESPACE_DECL)
     {
+      if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
+       error ("%qD is not a namespace-name", identifier);
       cp_parser_error (parser, "expected namespace-name");
       namespace_decl = error_mark_node;
     }
@@ -10280,7 +10471,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'");
@@ -10294,10 +10485,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.  */
@@ -10429,11 +10623,12 @@ cp_parser_using_declaration (cp_parser* parser)
   identifier = cp_parser_unqualified_id (parser,
                                         /*template_keyword_p=*/false,
                                         /*check_dependency_p=*/true,
-                                        /*declarator_p=*/true);
+                                        /*declarator_p=*/true,
+                                        /*optional_p=*/false);
 
   /* The function we call to handle a using-declaration is different
      depending on what scope we are in.  */
-  if (identifier == error_mark_node)
+  if (qscope == error_mark_node || identifier == error_mark_node)
     ;
   else if (TREE_CODE (identifier) != IDENTIFIER_NODE
           && TREE_CODE (identifier) != BIT_NOT_EXPR)
@@ -10637,7 +10832,7 @@ cp_parser_asm_definition (cp_parser* parser)
        }
     }
   else
-    assemble_asm (string);
+    cgraph_add_asm_node (string);
 }
 
 /* Declarators [gram.dcl.decl] */
@@ -10662,10 +10857,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
@@ -10679,6 +10878,7 @@ cp_parser_asm_definition (cp_parser* parser)
 static tree
 cp_parser_init_declarator (cp_parser* parser,
                           cp_decl_specifier_seq *decl_specifiers,
+                          tree checks,
                           bool function_definition_allowed_p,
                           bool member_p,
                           int declares_class_or_enum,
@@ -10693,7 +10893,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;
@@ -10807,16 +11011,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
@@ -10876,6 +11088,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 ();
@@ -10886,15 +11101,19 @@ 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 (declarator->kind == cdk_function
+         && declarator->declarator->kind == cdk_id
+         && initialization_kind == CPP_EQ)
+       initializer = cp_parser_pure_specifier (parser);
+      else
+       initializer = cp_parser_initializer (parser,
+                                            &is_parenthesized_init,
+                                            &is_non_constant_init);
     }
 
   /* The old parser allows attributes to appear after a parenthesized
@@ -10916,8 +11135,9 @@ cp_parser_init_declarator (cp_parser* parser,
          pushed_scope = false;
        }
       decl = grokfield (declarator, decl_specifiers,
-                       initializer, /*asmspec=*/NULL_TREE,
-                       /*attributes=*/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);
     }
@@ -10927,7 +11147,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
@@ -10939,12 +11159,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;
 }
 
@@ -11308,25 +11522,32 @@ 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;
@@ -11365,9 +11586,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              qualifying_scope = type;
            }
 
-         declarator = make_id_declarator (qualifying_scope,
-                                          unqualified_name);
-         declarator->id_loc = token->location;
+         sfk = sfk_none;
          if (unqualified_name)
            {
              tree class_type;
@@ -11378,39 +11597,63 @@ cp_parser_direct_declarator (cp_parser* parser,
              else
                class_type = current_class_type;
 
+             if (TREE_CODE (unqualified_name) == TYPE_DECL)
+               {
+                 tree name_type = TREE_TYPE (unqualified_name);
+                 if (class_type && same_type_p (name_type, class_type))
+                   {
+                     if (qualifying_scope
+                         && CLASSTYPE_USE_TEMPLATE (name_type))
+                       {
+                         error ("invalid use of constructor as a template");
+                         inform ("use %<%T::%D%> instead of %<%T::%D%> to "
+                                 "name the constructor in a qualified name",
+                                 class_type,
+                                 DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
+                                 class_type, name_type);
+                         declarator = cp_error_declarator;
+                         break;
+                       }
+                     else
+                       unqualified_name = constructor_name (class_type);
+                   }
+                 else
+                   {
+                     /* We do not attempt to print the declarator
+                        here because we do not have enough
+                        information about its original syntactic
+                        form.  */
+                     cp_parser_error (parser, "invalid declarator");
+                     declarator = cp_error_declarator;
+                     break;
+                   }
+               }
+
              if (class_type)
                {
                  if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
-                   declarator->u.id.sfk = sfk_destructor;
+                   sfk = sfk_destructor;
                  else if (IDENTIFIER_TYPENAME_P (unqualified_name))
-                   declarator->u.id.sfk = sfk_conversion;
+                   sfk = sfk_conversion;
                  else if (/* There's no way to declare a constructor
                              for an anonymous type, even if the type
                              got a name for linkage purposes.  */
                           !TYPE_WAS_ANONYMOUS (class_type)
-                          && (constructor_name_p (unqualified_name,
-                                                  class_type)
-                              || (TREE_CODE (unqualified_name) == TYPE_DECL
-                                  && (same_type_p
-                                      (TREE_TYPE (unqualified_name),
-                                       class_type)))))
-                   declarator->u.id.sfk = sfk_constructor;
-
-                 if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none)
-                   *ctor_dtor_or_conv_p = -1;
-                 if (qualifying_scope
-                     && TREE_CODE (unqualified_name) == TYPE_DECL
-                     && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
+                          && constructor_name_p (unqualified_name,
+                                                 class_type))
                    {
-                     error ("invalid use of constructor as a template");
-                     inform ("use %<%T::%D%> instead of %<%T::%T%> to name "
-                             "the constructor in a qualified name",
-                             class_type,
-                             DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
-                             class_type, class_type);
+                     unqualified_name = constructor_name (class_type);
+                     sfk = sfk_constructor;
                    }
+
+                 if (ctor_dtor_or_conv_p && sfk != sfk_none)
+                   *ctor_dtor_or_conv_p = -1;
                }
            }
+         declarator = make_id_declarator (qualifying_scope, 
+                                          unqualified_name,
+                                          sfk);
+         declarator->id_loc = token->location;
 
        handle_declarator:;
          scope = get_scope_of_declarator (declarator);
@@ -11518,17 +11761,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))
@@ -11618,8 +11867,9 @@ 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
      names are the names of types so that:
 
@@ -11634,11 +11884,15 @@ cp_parser_declarator_id (cp_parser* parser)
        int S<T>::R<T>::i = 3;
 
      will work, too.  */
-  return cp_parser_id_expression (parser,
-                                 /*template_keyword_p=*/false,
-                                 /*check_dependency_p=*/false,
-                                 /*template_p=*/NULL,
-                                 /*declarator_p=*/true);
+  id = cp_parser_id_expression (parser,
+                               /*template_keyword_p=*/false,
+                               /*check_dependency_p=*/false,
+                               /*template_p=*/NULL,
+                               /*declarator_p=*/true,
+                               optional_p);
+  if (id && BASELINK_P (id))
+    id = BASELINK_FUNCTIONS (id);
+  return id;
 }
 
 /* Parse a type-id.
@@ -11757,8 +12011,6 @@ cp_parser_type_specifier_seq (cp_parser* parser,
       if (is_condition && !is_cv_qualifier)
        flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
-
-  return;
 }
 
 /* Parse a parameter-declaration-clause.
@@ -12123,6 +12375,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 
                  /* If we run out of tokens, issue an error message.  */
                case CPP_EOF:
+               case CPP_PRAGMA_EOL:
                  error ("file ends in default argument");
                  done = true;
                  break;
@@ -12173,10 +12426,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
@@ -12239,7 +12503,7 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser)
      = initializer-clause
      ( expression-list )
 
-   Returns a expression representing the initializer.  If no
+   Returns an expression representing the initializer.  If no
    initializer is present, NULL_TREE is returned.
 
    *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )'
@@ -12480,9 +12744,13 @@ cp_parser_class_name (cp_parser *parser,
   if (token->type == CPP_NAME
       && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
     {
+      cp_token *identifier_token;
       tree identifier;
+      bool ambiguous_p;
 
       /* Look for the identifier.  */
+      identifier_token = cp_lexer_peek_token (parser->lexer);
+      ambiguous_p = identifier_token->ambiguous_p;
       identifier = cp_parser_identifier (parser);
       /* If the next token isn't an identifier, we are certainly not
         looking at a class-name.  */
@@ -12494,6 +12762,15 @@ cp_parser_class_name (cp_parser *parser,
        decl = identifier;
       else
        {
+         tree ambiguous_decls;
+         /* If we already know that this lookup is ambiguous, then
+            we've already issued an error message; there's no reason
+            to check again.  */
+         if (ambiguous_p)
+           {
+             cp_parser_simulate_error (parser);
+             return error_mark_node;
+           }
          /* If the next token is a `::', then the name must be a type
             name.
 
@@ -12510,7 +12787,18 @@ cp_parser_class_name (cp_parser *parser,
                                        /*is_template=*/false,
                                        /*is_namespace=*/false,
                                        check_dependency_p,
-                                       /*ambiguous_p=*/NULL);
+                                       &ambiguous_decls);
+         if (ambiguous_decls)
+           {
+             error ("reference to %qD is ambiguous", identifier);
+             print_candidates (ambiguous_decls);
+             if (cp_parser_parsing_tentatively (parser))
+               {
+                 identifier_token->ambiguous_p = true;
+                 cp_parser_simulate_error (parser);
+               }
+             return error_mark_node;
+           }
        }
     }
   else
@@ -12528,7 +12816,8 @@ cp_parser_class_name (cp_parser *parser,
   /* If this is a typename, create a TYPENAME_TYPE.  */
   if (typename_p && decl != error_mark_node)
     {
-      decl = make_typename_type (scope, decl, typename_type, /*complain=*/1);
+      decl = make_typename_type (scope, decl, typename_type,
+                                 /*complain=*/tf_error);
       if (decl != error_mark_node)
        decl = TYPE_NAME (decl);
     }
@@ -12547,15 +12836,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;
 }
@@ -12668,7 +12960,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:
@@ -12713,13 +13005,8 @@ cp_parser_class_specifier (cp_parser* parser)
        {
          /* Figure out which function we need to process.  */
          fn = TREE_VALUE (queue_entry);
-
-         /* A hack to prevent garbage collection.  */
-         function_depth++;
-
          /* Parse the function.  */
          cp_parser_late_parsing_for_member (parser, fn);
-         function_depth--;
        }
     }
 
@@ -12820,7 +13107,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:
@@ -13138,7 +13425,9 @@ cp_parser_member_specification_opt (cp_parser* parser)
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
       /* If it's a `}', or EOF then we've seen all the members.  */
-      if (token->type == CPP_CLOSE_BRACE || token->type == CPP_EOF)
+      if (token->type == CPP_CLOSE_BRACE
+         || token->type == CPP_EOF
+         || token->type == CPP_PRAGMA_EOL)
        break;
 
       /* See if this token is a keyword.  */
@@ -13160,7 +13449,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
          /* Accept #pragmas at class scope.  */
          if (token->type == CPP_PRAGMA)
            {
-             cp_lexer_handle_pragma (parser->lexer);
+             cp_parser_pragma (parser, pragma_external);
              break;
            }
 
@@ -13224,8 +13513,13 @@ cp_parser_member_declaration (cp_parser* parser)
   /* Check for a template-declaration.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
     {
-      /* Parse the template-declaration.  */
-      cp_parser_template_declaration (parser, /*member_p=*/true);
+      /* An explicit specialization here is an error condition, and we
+        expect the specialization handler to detect and report this.  */
+      if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_LESS
+         && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_GREATER)
+       cp_parser_explicit_specialization (parser);
+      else
+       cp_parser_template_declaration (parser, /*member_p=*/true);
 
       return;
     }
@@ -13393,7 +13687,8 @@ cp_parser_member_declaration (cp_parser* parser)
              /* Create the bitfield declaration.  */
              decl = grokbitfield (identifier
                                   ? make_id_declarator (NULL_TREE,
-                                                        identifier)
+                                                        identifier,
+                                                        sfk_none)
                                   : NULL,
                                   &decl_specifiers,
                                   width);
@@ -13467,7 +13762,8 @@ cp_parser_member_declaration (cp_parser* parser)
                     for a pure-specifier; otherwise, we look for a
                     constant-initializer.  When we call `grokfield', it will
                     perform more stringent semantics checks.  */
-                 if (declarator->kind == cdk_function)
+                 if (declarator->kind == cdk_function
+                     && declarator->declarator->kind == cdk_id)
                    initializer = cp_parser_pure_specifier (parser);
                  else
                    /* Parse the initializer.  */
@@ -13507,16 +13803,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.  */
@@ -13577,17 +13868,20 @@ cp_parser_pure_specifier (cp_parser* parser)
     return error_mark_node;
   /* Look for the `0' token.  */
   token = cp_lexer_consume_token (parser->lexer);
-  if (token->type != CPP_NUMBER || !integer_zerop (token->value))
+  /* c_lex_with_flags marks a single digit '0' with PURE_ZERO.  */
+  if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO))
     {
-      cp_parser_error (parser,
+      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;
+    }
 
-  /* FIXME: Unfortunately, this will accept `0L' and `0x00' as well.
-     We need to get information from the lexer about how the number
-     was spelled in order to fix this problem.  */
   return integer_zero_node;
 }
 
@@ -13931,6 +14225,7 @@ 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;
 
@@ -13938,7 +14233,7 @@ cp_parser_function_try_block (cp_parser* parser)
   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 ();
+  try_block = begin_function_try_block (&compound_stmt);
   /* Parse the function-body.  */
   ctor_initializer_p
     = cp_parser_ctor_initializer_opt_and_function_body (parser);
@@ -13947,7 +14242,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;
 }
@@ -14449,22 +14744,28 @@ cp_parser_label_declaration (cp_parser* parser)
    If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
    types.
 
-   If AMBIGUOUS_P is non-NULL, it is set to true if name-lookup
-   results in an ambiguity, and false otherwise.  */
+   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.  */ 
 
 static tree
 cp_parser_lookup_name (cp_parser *parser, tree name,
                       enum tag_types tag_type,
-                      bool is_template, bool is_namespace,
+                      bool is_template, 
+                      bool is_namespace,
                       bool check_dependency,
-                      bool *ambiguous_p)
+                      tree *ambiguous_decls)
 {
+  int flags = 0;
   tree decl;
   tree object_type = parser->context->object_type;
 
+  if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
+    flags |= LOOKUP_COMPLAIN;
+
   /* Assume that the lookup will be unambiguous.  */
-  if (ambiguous_p)
-    *ambiguous_p = false;
+  if (ambiguous_decls)
+    *ambiguous_decls = NULL_TREE;
 
   /* Now that we have looked up the name, the OBJECT_TYPE (if any) is
      no longer valid.  Note that if we are parsing tentatively, and
@@ -14543,15 +14844,20 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                 A::B' should be considered a type-name, even if `A'
                 is dependent.  */
              type = make_typename_type (parser->scope, name, tag_type,
-                                        /*complain=*/1);
+                                        /*complain=*/tf_error);
              decl = TYPE_NAME (type);
            }
-         else if (is_template)
+         else if (is_template
+                  && (cp_parser_next_token_ends_template_argument_p (parser)
+                      || cp_lexer_next_token_is (parser->lexer,
+                                                 CPP_CLOSE_PAREN)))
            decl = make_unbound_class_template (parser->scope,
                                                name, NULL_TREE,
-                                               /*complain=*/1);
+                                               /*complain=*/tf_error);
          else
-           decl = build_nt (SCOPE_REF, parser->scope, name);
+           decl = build_qualified_name (/*type=*/NULL_TREE,
+                                        parser->scope, name,
+                                        is_template);
        }
       else
        {
@@ -14594,8 +14900,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
       /* Look it up in the enclosing context, too.  */
       decl = lookup_name_real (name, tag_type != none_type,
                               /*nonclass=*/0,
-                              /*block_p=*/true, is_namespace,
-                              /*flags=*/0);
+                              /*block_p=*/true, is_namespace, flags);
       parser->object_scope = object_type;
       parser->qualifying_scope = NULL_TREE;
       if (object_decl)
@@ -14605,8 +14910,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
     {
       decl = lookup_name_real (name, tag_type != none_type,
                               /*nonclass=*/0,
-                              /*block_p=*/true, is_namespace,
-                              /*flags=*/0);
+                              /*block_p=*/true, is_namespace, flags);
       parser->qualifying_scope = NULL_TREE;
       parser->object_scope = NULL_TREE;
     }
@@ -14618,8 +14922,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   /* If it's a TREE_LIST, the result of the lookup was ambiguous.  */
   if (TREE_CODE (decl) == TREE_LIST)
     {
-      if (ambiguous_p)
-       *ambiguous_p = true;
+      if (ambiguous_decls)
+       *ambiguous_decls = decl;
       /* The error message we have to print is too complicated for
         cp_parser_error, so we incorporate its actions directly.  */
       if (!cp_parser_simulate_error (parser))
@@ -14661,7 +14965,7 @@ cp_parser_lookup_name_simple (cp_parser* parser, tree name)
                                /*is_template=*/false,
                                /*is_namespace=*/false,
                                /*check_dependency=*/true,
-                               /*ambiguous_p=*/NULL);
+                               /*ambiguous_decls=*/NULL);
 }
 
 /* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
@@ -14683,7 +14987,7 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
 
        template <typename T> struct A::B {};
 
-     Similarly, in a elaborated-type-specifier:
+     Similarly, in an elaborated-type-specifier:
 
        namespace N { struct X{}; }
 
@@ -15032,7 +15336,6 @@ 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;
     }
@@ -15071,9 +15374,15 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
       /* Issue an error message.  */
       error ("named return values are no longer supported");
       /* Skip tokens until we reach the start of the function body.  */
-      while (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
-            && cp_lexer_next_token_is_not (parser->lexer, CPP_EOF))
-       cp_lexer_consume_token (parser->lexer);
+      while (true)
+       {
+         cp_token *token = cp_lexer_peek_token (parser->lexer);
+         if (token->type == CPP_OPEN_BRACE
+             || token->type == CPP_EOF
+             || token->type == CPP_PRAGMA_EOL)
+           break;
+         cp_lexer_consume_token (parser->lexer);
+       }
     }
   /* The `extern' in `extern "C" void f () { ... }' does not apply to
      anything declared inside `f'.  */
@@ -15117,8 +15426,10 @@ static void
 cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 {
   tree decl = NULL_TREE;
+  tree checks;
   tree parameter_list;
   bool friend_p = false;
+  bool need_lang_pop;
 
   /* Look for the `template' keyword.  */
   if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"))
@@ -15127,6 +15438,24 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   /* And the `<'.  */
   if (!cp_parser_require (parser, CPP_LESS, "`<'"))
     return;
+  /* [temp]
+   
+     A template ... shall not have C linkage.  */
+  if (current_lang_name == lang_name_c)
+    {
+      error ("template with C linkage");
+      /* Give it C++ linkage to avoid confusing other parts of the
+        front end.  */
+      push_lang_context (lang_name_cplusplus);
+      need_lang_pop = true;
+    }
+  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
@@ -15138,12 +15467,14 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       parameter_list = NULL_TREE;
     }
   else
-    {
-      /* Parse the template parameters.  */
-      begin_template_parm_list ();
-      parameter_list = cp_parser_template_parameter_list (parser);
-      parameter_list = end_template_parm_list (parameter_list);
-    }
+    /* 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, "`>'");
@@ -15159,11 +15490,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
@@ -15182,13 +15512,18 @@ 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);
 
   /* Register member declarations.  */
   if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl))
     finish_member_declaration (decl);
-
+  /* For the erroneous case of a template with C linkage, we pushed an
+     implicit C++ linkage scope; exit that scope now.  */
+  if (need_lang_pop)
+    pop_lang_context ();
   /* If DECL is a function template, we must return to parse it later.
      (Even though there is no definition, there might be default
      arguments that need handling.)  */
@@ -15200,6 +15535,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 (tree 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.
@@ -15209,6 +15556,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 
 static tree
 cp_parser_single_declaration (cp_parser* parser,
+                             tree checks,
                              bool member_p,
                              bool* friend_p)
 {
@@ -15270,6 +15618,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
@@ -15282,6 +15633,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,
@@ -15329,8 +15681,10 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
   cast = build_functional_cast (type, expression_list);
   /* [expr.const]/1: In an integral constant expression "only type
      conversions to integral or enumeration type can be used".  */
-  if (cast != error_mark_node && !type_dependent_expression_p (type)
-      && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (type)))
+  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"))
@@ -15411,6 +15765,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   tree saved_qualifying_scope;
   tree saved_object_scope;
   bool saved_greater_than_is_operator_p;
+  bool saved_skip_evaluation;
 
   /* [temp.names]
 
@@ -15425,6 +15780,10 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   saved_scope = parser->scope;
   saved_qualifying_scope = parser->qualifying_scope;
   saved_object_scope = parser->object_scope;
+  /* We need to evaluate the template arguments, even though this
+     template-id may be nested within a "sizeof".  */
+  saved_skip_evaluation = skip_evaluation;
+  skip_evaluation = false;
   /* Parse the template-argument-list itself.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
     arguments = NULL_TREE;
@@ -15462,11 +15821,8 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
                 "a template argument list");
        }
     }
-  else if (!cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
-    error ("missing %<>%> to terminate the template argument list");
   else
-    /* It's what we want, a '>'; consume it.  */
-    cp_lexer_consume_token (parser->lexer);
+    cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
   /* The `>' token might be a greater-than operator again now.  */
   parser->greater_than_is_operator_p
     = saved_greater_than_is_operator_p;
@@ -15474,6 +15830,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
   parser->scope = saved_scope;
   parser->qualifying_scope = saved_qualifying_scope;
   parser->object_scope = saved_object_scope;
+  skip_evaluation = saved_skip_evaluation;
 
   return arguments;
 }
@@ -15574,7 +15931,6 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
                       TREE_PURPOSE (parser->unparsed_functions_queues));
        break;
       }
-  return;
 }
 
 /* FN is a FUNCTION_DECL which may contains a parameter with an
@@ -15627,6 +15983,9 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       /* Parse the assignment-expression.  */
       parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false);
 
+      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.  */
@@ -15644,6 +16003,9 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       cp_parser_pop_lexer (parser);
     }
 
+  /* Make sure no default arg is missing.  */
+  check_default_args (fn);
+
   /* Restore the state of local_variables_forbidden_p.  */
   parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
 
@@ -15675,7 +16037,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   saved_message = parser->type_definition_forbidden_message;
   /* And create the new one.  */
   parser->type_definition_forbidden_message
-    = xmalloc (strlen (format)
+    = XNEWVEC (const char, strlen (format)
               + strlen (IDENTIFIER_POINTER (ridpointers[keyword]))
               + 1 /* `\0' */);
   sprintf ((char *) parser->type_definition_forbidden_message,
@@ -15759,16 +16121,56 @@ 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->multiple_storage_classes_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;
 }
 
 /* Update the DECL_SPECS to reflect the TYPE_SPEC.  If USER_DEFINED_P
@@ -15868,27 +16270,38 @@ cp_parser_skip_until_found (cp_parser* parser,
     {
       /* 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 we've reached the token we want, consume it and stop.  */
       if (token->type == type && !nesting_depth)
        {
          cp_lexer_consume_token (parser->lexer);
          return;
        }
-      /* If we've run out of tokens, stop.  */
-      if (token->type == CPP_EOF)
-       return;
-      if (token->type == CPP_OPEN_BRACE
-         || token->type == CPP_OPEN_PAREN
-         || token->type == CPP_OPEN_SQUARE)
-       ++nesting_depth;
-      else if (token->type == CPP_CLOSE_BRACE
-              || token->type == CPP_CLOSE_PAREN
-              || token->type == CPP_CLOSE_SQUARE)
+
+      switch (token->type)
        {
+       case CPP_EOF:
+       case CPP_PRAGMA_EOL:
+         /* If we've run out of tokens, stop.  */
+         return;
+
+       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;
+
+       default:
+         break;
        }
+
       /* Consume this token.  */
       cp_lexer_consume_token (parser->lexer);
     }
@@ -15963,7 +16376,7 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
   return (token->type == CPP_COMMA || token->type == CPP_GREATER);
 }
 
-/* Returns TRUE iff the n-th token is a ">", or the n-th is a "[" and the
+/* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the
    (n+1)-th is a ":" (which is a possible digraph typo for "< ::").  */
 
 static bool
@@ -16107,7 +16520,9 @@ cp_parser_cache_group (cp_parser *parser,
          && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
        return;
       /* If we've reached the end of the file, stop.  */
-      if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)
+         || (end != CPP_PRAGMA_EOL
+             && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL)))
        return;
       /* Consume the next token.  */
       token = cp_lexer_consume_token (parser->lexer);
@@ -16120,6 +16535,8 @@ cp_parser_cache_group (cp_parser *parser,
        }
       else if (token->type == CPP_OPEN_PAREN)
        cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1);
+      else if (token->type == CPP_PRAGMA)
+       cp_parser_cache_group (parser, CPP_PRAGMA_EOL, depth + 1);
       else if (token->type == end)
        return;
     }
@@ -16498,27 +16915,45 @@ cp_parser_objc_selector_expression (cp_parser* parser)
   cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
   token = cp_lexer_peek_token (parser->lexer);
 
-  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
+         || token->type == CPP_SCOPE)
     {
       tree selector = NULL_TREE;
 
-      if (token->type != CPP_COLON)
+      if (token->type != CPP_COLON
+         || token->type == CPP_SCOPE)
        selector = cp_parser_objc_selector (parser);
 
-      /* Detect if we have a unary selector.  */
-      if (maybe_unary_selector_p
-         && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
+          && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
        {
-         sel_seq = selector;
-         goto finish_selector;
+         /* Detect if we have a unary selector.  */
+         if (maybe_unary_selector_p)
+           {
+             sel_seq = selector;
+             goto finish_selector;
+           }
+         else
+           {
+             cp_parser_error (parser, "expected %<:%>");
+           }
        }
-
       maybe_unary_selector_p = false;
-      cp_parser_require (parser, CPP_COLON, "`:'");
-
-      sel_seq
-       = chainon (sel_seq,
-                  build_tree_list (selector, NULL_TREE));
+      token = cp_lexer_consume_token (parser->lexer);
+      
+      if (token->type == CPP_SCOPE)
+        {
+         sel_seq
+           = chainon (sel_seq,
+                      build_tree_list (selector, NULL_TREE));
+         sel_seq
+           = chainon (sel_seq,
+                      build_tree_list (NULL_TREE, NULL_TREE));
+       }
+      else
+       sel_seq
+         = chainon (sel_seq,
+                    build_tree_list (selector, NULL_TREE));
 
       token = cp_lexer_peek_token (parser->lexer);
     }
@@ -16838,7 +17273,7 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
     cp_parser_linkage_specification (parser);
   /* Handle #pragma, if any.  */
   else if (token->type == CPP_PRAGMA)
-    cp_lexer_handle_pragma (parser->lexer);
+    cp_parser_pragma (parser, pragma_external);
   /* Allow stray semicolons.  */
   else if (token->type == CPP_SEMICOLON)
     cp_lexer_consume_token (parser->lexer);
@@ -16978,7 +17413,8 @@ cp_parser_objc_class_ivars (cp_parser* parser)
            {
              /* Get the name of the bitfield.  */
              declarator = make_id_declarator (NULL_TREE,
-                                              cp_parser_identifier (parser));
+                                              cp_parser_identifier (parser),
+                                              sfk_none);
 
             eat_colon:
              cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
@@ -17013,7 +17449,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.  */
@@ -17330,10 +17767,1359 @@ cp_parser_objc_statement (cp_parser * parser) {
   return error_mark_node;
 }
 \f
-/* The parser.  */
-
-static GTY (()) cp_parser *the_parser;
-
+/* OpenMP 2.5 parsing routines.  */
+
+/* All OpenMP clauses.  OpenMP 2.5.  */
+typedef enum pragma_omp_clause {
+  PRAGMA_OMP_CLAUSE_NONE = 0,
+
+  PRAGMA_OMP_CLAUSE_COPYIN,
+  PRAGMA_OMP_CLAUSE_COPYPRIVATE,
+  PRAGMA_OMP_CLAUSE_DEFAULT,
+  PRAGMA_OMP_CLAUSE_FIRSTPRIVATE,
+  PRAGMA_OMP_CLAUSE_IF,
+  PRAGMA_OMP_CLAUSE_LASTPRIVATE,
+  PRAGMA_OMP_CLAUSE_NOWAIT,
+  PRAGMA_OMP_CLAUSE_NUM_THREADS,
+  PRAGMA_OMP_CLAUSE_ORDERED,
+  PRAGMA_OMP_CLAUSE_PRIVATE,
+  PRAGMA_OMP_CLAUSE_REDUCTION,
+  PRAGMA_OMP_CLAUSE_SCHEDULE,
+  PRAGMA_OMP_CLAUSE_SHARED
+} pragma_omp_clause;
+
+/* Returns name of the next clause.
+   If the clause is not recognized PRAGMA_OMP_CLAUSE_NONE is returned and
+   the token is not consumed.  Otherwise appropriate pragma_omp_clause is
+   returned and the token is consumed.  */
+
+static pragma_omp_clause
+cp_parser_omp_clause_name (cp_parser *parser)
+{
+  pragma_omp_clause result = PRAGMA_OMP_CLAUSE_NONE;
+
+  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))
+    {
+      tree id = cp_lexer_peek_token (parser->lexer)->value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      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;
+       }
+    }
+
+  if (result != PRAGMA_OMP_CLAUSE_NONE)
+    cp_lexer_consume_token (parser->lexer);
+
+  return result;
+}
+
+/* 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;
+      }
+}
+
+/* OpenMP 2.5:
+   variable-list:
+     identifier
+     variable-list , identifier
+
+   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)
+{
+  while (1)
+    {
+      tree name, decl;
+
+      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;
+
+      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, "`)'"))
+    {
+      int ending;
+
+      /* 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;
+    }
+
+  return list;
+}
+
+/* Similarly, but expect leading and trailing parenthesis.  This is a very
+   common case for omp clauses.  */
+
+static tree
+cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
+{
+  if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+    return cp_parser_omp_var_list_no_open (parser, kind, list);
+  return list;
+}
+
+/* OpenMP 2.5:
+   default ( shared | none ) */
+
+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 (!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)->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
+    {
+    invalid_kind:
+      cp_parser_error (parser, "expected %<none%> or %<shared%>");
+    }
+
+  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;
+}
+
+/* OpenMP 2.5:
+   if ( expression ) */
+
+static tree
+cp_parser_omp_clause_if (cp_parser *parser, tree list)
+{
+  tree t, c;
+
+  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)
+{
+  tree c;
+
+  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)
+    {
+    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;
+    }
+  cp_lexer_consume_token (parser->lexer);
+
+  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;
+}
+
+/* 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)->value;
+      const char *p = IDENTIFIER_POINTER (id);
+
+      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);
+
+  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);
+  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);
+
+         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)->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);
+
+  if (!targetm.have_tls)
+    sorry ("threadprivate variables not supported in this target");
+
+  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->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);
+
+  /* Read one more token to return to our caller.  */
+  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));
+}
+
+/* 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->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.  */