OSDN Git Service

PR c++/25552
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 473d205..3ba9285 100644 (file)
@@ -17,8 +17,8 @@
 
    You should have received a copy of the GNU General Public License
    along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -36,6 +36,8 @@
 #include "toplev.h"
 #include "output.h"
 #include "target.h"
+#include "cgraph.h"
+#include "c-common.h"
 
 \f
 /* The lexer.  */
@@ -54,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.  */
@@ -66,11 +74,12 @@ typedef struct cp_token GTY (())
 
 /* We use a stack of token pointer for saving token sets.  */
 typedef struct cp_token *cp_token_position;
-DEF_VEC_MALLOC_P (cp_token_position);
+DEF_VEC_P (cp_token_position);
+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
@@ -91,7 +100,7 @@ typedef struct cp_lexer GTY (())
   /* If the lexer owns the buffer, this is the number of tokens in the
      buffer.  */
   size_t buffer_length;
-  
+
   /* A pointer just past the last available token.  The tokens
      in this lexer are [buffer, last_token).  */
   cp_token_position GTY ((skip)) last_token;
@@ -104,13 +113,17 @@ typedef struct cp_lexer GTY (())
      called.  The top entry is the most recent position at which we
      began saving tokens.  If the stack is non-empty, we are saving
      tokens.  */
-  VEC (cp_token_position) *GTY ((skip)) saved_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
@@ -160,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
@@ -190,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
@@ -238,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 ();
@@ -256,21 +265,22 @@ cp_lexer_new_main (void)
   /* Allocate the memory.  */
   lexer = GGC_CNEW (cp_lexer);
 
-#ifdef ENABLE_CHECKING  
+#ifdef ENABLE_CHECKING
   /* Initially we are not debugging.  */
   lexer->debugging_p = false;
 #endif /* ENABLE_CHECKING */
-  lexer->saved_tokens = VEC_alloc (cp_token_position, CP_SAVED_TOKEN_STACK);
-        
+  lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
+                                  CP_SAVED_TOKEN_STACK);
+
   /* 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;
   pos = buffer;
   *pos = first_token;
-  
+
   /* Get the remaining tokens from the preprocessor.  */
   while (pos->type != CPP_EOF)
     {
@@ -279,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);
@@ -289,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;
@@ -313,8 +323,9 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
   lexer->buffer_length = 0;
   lexer->next_token = first == last ? (cp_token *)&eof_token : first;
   lexer->last_token = last;
-  
-  lexer->saved_tokens = VEC_alloc (cp_token_position, CP_SAVED_TOKEN_STACK);
+
+  lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
+                                  CP_SAVED_TOKEN_STACK);
 
 #ifdef ENABLE_CHECKING
   /* Initially we are not debugging.  */
@@ -332,7 +343,7 @@ cp_lexer_destroy (cp_lexer *lexer)
 {
   if (lexer->buffer)
     ggc_free (lexer->buffer);
-  VEC_free (cp_token_position, lexer->saved_tokens);
+  VEC_free (cp_token_position, heap, lexer->saved_tokens);
   ggc_free (lexer);
 }
 
@@ -352,7 +363,7 @@ static inline cp_token_position
 cp_lexer_token_position (cp_lexer *lexer, bool previous_p)
 {
   gcc_assert (!previous_p || lexer->next_token != &eof_token);
-  
+
   return lexer->next_token - previous_p;
 }
 
@@ -375,16 +386,18 @@ cp_lexer_saving_tokens (const cp_lexer* lexer)
 
 static void
 cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
-                                 cp_token *token)
+                                cp_token *token)
 {
   static int is_extern_c = 0;
 
    /* Get a new token from the preprocessor.  */
-  token->type = c_lex_with_flags (&token->value, &token->flags);
-  token->location = input_location;
+  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 
+  /* On some systems, some header files are surrounded by an
      implicit extern "C" block.  Set a flag in the token if it
      comes from such a header.  */
   is_extern_c += pending_lang_change;
@@ -392,21 +405,49 @@ 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)
+    {
+      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)
     {
-      /* 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];
+      switch (C_RID_CODE (token->value))
+       {
+       /* Map 'class' to '@class', 'private' to '@private', etc.  */
+       case RID_CLASS: token->keyword = RID_AT_CLASS; break;
+       case RID_PRIVATE: token->keyword = RID_AT_PRIVATE; break;
+       case RID_PROTECTED: token->keyword = RID_AT_PROTECTED; break;
+       case RID_PUBLIC: token->keyword = RID_AT_PUBLIC; break;
+       case RID_THROW: token->keyword = RID_AT_THROW; break;
+       case RID_TRY: token->keyword = RID_AT_TRY; break;
+       case RID_CATCH: token->keyword = RID_AT_CATCH; break;
+       default: token->keyword = C_RID_CODE (token->value);
+       }
+    }
+  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;
     }
-  else
-    token->keyword = RID_MAX;
 }
 
 /* Update the globals input_location and in_system_header from TOKEN.  */
@@ -456,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,
@@ -476,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;
@@ -492,7 +529,7 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
          token = (cp_token *)&eof_token;
          break;
        }
-      
+
       if (token->type != CPP_PURGED)
        --n;
     }
@@ -515,7 +552,8 @@ 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
     {
       lexer->next_token++;
@@ -524,12 +562,12 @@ cp_lexer_consume_token (cp_lexer* lexer)
          lexer->next_token = (cp_token *)&eof_token;
          break;
        }
-      
+
     }
   while (lexer->next_token->type == CPP_PURGED);
-  
+
   cp_lexer_set_source_position_from_token (token);
-  
+
   /* Provide debugging output.  */
   if (cp_lexer_debugging_p (lexer))
     {
@@ -537,7 +575,7 @@ cp_lexer_consume_token (cp_lexer* lexer)
       cp_lexer_print_token (cp_lexer_debug_stream, token);
       putc ('\n', cp_lexer_debug_stream);
     }
-  
+
   return token;
 }
 
@@ -549,7 +587,7 @@ static void
 cp_lexer_purge_token (cp_lexer *lexer)
 {
   cp_token *tok = lexer->next_token;
-  
+
   gcc_assert (tok != &eof_token);
   tok->type = CPP_PURGED;
   tok->location = UNKNOWN_LOCATION;
@@ -580,7 +618,7 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
 
   if (peek == &eof_token)
     peek = lexer->last_token;
-  
+
   gcc_assert (tok < peek);
 
   for ( tok += 1; tok != peek; tok += 1)
@@ -592,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.  */
 
@@ -621,7 +640,8 @@ cp_lexer_save_tokens (cp_lexer* lexer)
   if (cp_lexer_debugging_p (lexer))
     fprintf (cp_lexer_debug_stream, "cp_lexer: saving tokens\n");
 
-  VEC_safe_push (cp_token_position, lexer->saved_tokens, lexer->next_token);
+  VEC_safe_push (cp_token_position, heap,
+                lexer->saved_tokens, lexer->next_token);
 }
 
 /* Commit to the portion of the token stream most recently saved.  */
@@ -671,7 +691,7 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
     "NESTED_NAME_SPECIFIER",
     "PURGED"
   };
-  
+
   /* If we have a name for the token, print it out.  Otherwise, we
      simply give the numeric code.  */
   gcc_assert (token->type < ARRAY_SIZE(token_names));
@@ -692,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;
 
@@ -706,7 +725,7 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
 static void
 cp_lexer_start_debugging (cp_lexer* lexer)
 {
-  ++lexer->debugging_p;
+  lexer->debugging_p = true;
 }
 
 /* Stop emitting debugging information.  */
@@ -714,7 +733,7 @@ cp_lexer_start_debugging (cp_lexer* lexer)
 static void
 cp_lexer_stop_debugging (cp_lexer* lexer)
 {
-  --lexer->debugging_p;
+  lexer->debugging_p = false;
 }
 
 #endif /* ENABLE_CHECKING */
@@ -733,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
@@ -794,12 +810,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;
 
@@ -816,10 +835,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;
 }
@@ -882,7 +905,7 @@ cp_declarator *
 make_call_declarator (cp_declarator *target,
                      cp_parameter_declarator *parms,
                      cp_cv_quals cv_qualifiers,
-                      tree exception_specification)
+                     tree exception_specification)
 {
   cp_declarator *declarator;
 
@@ -1195,7 +1218,8 @@ typedef struct cp_parser GTY(())
   /* The scope in which names should be looked up.  If NULL_TREE, then
      we look up names in the scope that is currently open in the
      source program.  If non-NULL, this is either a TYPE or
-     NAMESPACE_DECL for the scope in which we should look.
+     NAMESPACE_DECL for the scope in which we should look.  It can
+     also be ERROR_MARK, when we've parsed a bogus scope.
 
      This value is not cleared automatically after a name is looked
      up, so we must be careful to clear it before starting a new look
@@ -1203,7 +1227,7 @@ typedef struct cp_parser GTY(())
      will look up `Z' in the scope of `X', rather than the current
      scope.)  Unfortunately, it is difficult to tell when name lookup
      is complete, because we sometimes peek at a token, look it up,
-     and then decide not to consume it.  */
+     and then decide not to consume it.   */
   tree scope;
 
   /* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the
@@ -1320,9 +1344,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.  */
@@ -1357,7 +1378,7 @@ 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);
 static tree cp_parser_unqualified_id
@@ -1416,9 +1437,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
@@ -1510,7 +1531,7 @@ static tree cp_parser_declarator_id
 static tree cp_parser_type_id
   (cp_parser *);
 static void cp_parser_type_specifier_seq
-  (cp_parser *, cp_decl_specifier_seq *);
+  (cp_parser *, bool, cp_decl_specifier_seq *);
 static cp_parameter_declarator *cp_parser_parameter_declaration_clause
   (cp_parser *);
 static cp_parameter_declarator *cp_parser_parameter_declaration_list
@@ -1523,7 +1544,7 @@ static tree cp_parser_initializer
   (cp_parser *, bool *, bool *);
 static tree cp_parser_initializer_clause
   (cp_parser *, bool *);
-static tree cp_parser_initializer_list
+static VEC(constructor_elt,gc) *cp_parser_initializer_list
   (cp_parser *, bool *);
 
 static bool cp_parser_ctor_initializer_opt_and_function_body
@@ -1638,10 +1659,43 @@ 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
+  (cp_parser *);
+static tree cp_parser_objc_message_args
+  (cp_parser *);
+static tree cp_parser_objc_message_expression
+  (cp_parser *);
+static tree cp_parser_objc_encode_expression
+  (cp_parser *);
+static tree cp_parser_objc_defs_expression
+  (cp_parser *);
+static tree cp_parser_objc_protocol_expression
+  (cp_parser *);
+static tree cp_parser_objc_selector_expression
+  (cp_parser *);
+static tree cp_parser_objc_expression
+  (cp_parser *);
+static bool cp_parser_objc_selector_p
+  (enum cpp_ttype);
+static tree cp_parser_objc_selector
+  (cp_parser *);
+static tree cp_parser_objc_protocol_refs_opt
+  (cp_parser *);
+static void cp_parser_objc_declaration
+  (cp_parser *);
+static tree cp_parser_objc_statement
+  (cp_parser *);
+
 /* 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
@@ -1752,6 +1806,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
@@ -1787,6 +1843,16 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword)
   return token->keyword == keyword;
 }
 
+/* A minimum or maximum operator has been seen.  As these are
+   deprecated, issue a warning.  */
+
+static inline void
+cp_parser_warn_min_max (void)
+{
+  if (warn_deprecated && !in_system_header)
+    warning (0, "minimum/maximum operators are deprecated");
+}
+
 /* If not parsing tentatively, issue a diagnostic of the form
       FILE:LINE: MESSAGE before TOKEN
    where TOKEN is the next token in the input stream.  MESSAGE
@@ -1802,12 +1868,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);
+         error ("%<#pragma%> is not allowed here");
+         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
@@ -1837,12 +1905,12 @@ cp_parser_name_lookup_error (cp_parser* parser,
               parser->scope, name);
       else if (parser->scope == global_namespace)
        error ("%<::%D%> has not been declared", name);
-      else if (parser->object_scope 
+      else if (parser->object_scope
               && !CLASS_TYPE_P (parser->object_scope))
        error ("request for member %qD in non-class type %qT",
               name, parser->object_scope);
       else if (parser->object_scope)
-       error ("%<%T::%D%> has not been declared", 
+       error ("%<%T::%D%> has not been declared",
               parser->object_scope, name);
       else
        error ("%qD has not been declared", name);
@@ -1946,7 +2014,7 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
 /* If parsing an integral constant-expression, issue an error message
    about the fact that THING appeared and return true.  Otherwise,
    return false.  In either case, set
-   PARSER->NON_INTEGRAL_CONSTANT_EXPRESSION_P.  */ 
+   PARSER->NON_INTEGRAL_CONSTANT_EXPRESSION_P.  */
 
 static bool
 cp_parser_non_integral_constant_expression (cp_parser  *parser,
@@ -1980,7 +2048,7 @@ 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);
@@ -1995,7 +2063,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
           template <typename T> struct B : public A<T> { X x; };
 
         The user should have said "typename A<T>::X".  */
-      if (processing_template_decl && current_class_type)
+      if (processing_template_decl && current_class_type
+         && TYPE_BINFO (current_class_type))
        {
          tree b;
 
@@ -2019,7 +2088,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
                        && DECL_NAME (field) == id)
                      {
                        inform ("(perhaps %<typename %T::%E%> was intended)",
-                               BINFO_TYPE (b), id);
+                               BINFO_TYPE (b), id);
                        break;
                      }
                  if (field)
@@ -2030,7 +2099,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",
@@ -2100,7 +2169,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))
@@ -2108,62 +2176,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;
+       case CPP_EOF:
+       case CPP_PRAGMA_EOL:
+         /* If we've run out of tokens, then there is no closing `)'.  */
+         return 0;
+
+       case CPP_SEMICOLON:
+         /* This matches the processing in skip_to_end_of_statement.  */
+         if (!brace_depth)
+           return 0;
          break;
-       }
 
-      token = cp_lexer_peek_token (parser->lexer);
-
-      /* 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.
@@ -2177,35 +2238,38 @@ 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:
 
-               void f g () { ... }
+               void f g () { ... }
                typedef int I;
 
             we will stop after the body of the erroneously declared
@@ -2214,13 +2278,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);
     }
@@ -2251,36 +2319,44 @@ cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
 static void
 cp_parser_skip_to_end_of_block_or_statement (cp_parser* parser)
 {
-  unsigned nesting_depth = 0;
+  int nesting_depth = 0;
 
-  while (true)
+  while (nesting_depth >= 0)
     {
-      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)
+      switch (token->type)
        {
-         /* Consume the `;'.  */
-         cp_lexer_consume_token (parser->lexer);
+       case CPP_EOF:
+       case CPP_PRAGMA_EOL:
+         /* If we've run out of tokens, stop.  */
+         return;
+
+       case CPP_SEMICOLON:
+         /* Stop if this is an unnested ';'. */
+         if (!nesting_depth)
+           nesting_depth = -1;
+         break;
+
+       case CPP_CLOSE_BRACE:
+         /* Stop if this is an unnested '}', or closes the outermost
+            nesting level.  */
+         nesting_depth--;
+         if (!nesting_depth)
+           nesting_depth = -1;
+         break;
+
+       case CPP_OPEN_BRACE:
+         /* Nest. */
+         nesting_depth++;
+         break;
+
+       default:
          break;
        }
+
       /* Consume the token.  */
-      token = cp_lexer_consume_token (parser->lexer);
-      /* 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 || --nesting_depth == 0))
-       break;
-      /* If it the next token is a `{', then we are entering a new
-        block.  Consume the entire block.  */
-      if (token->type == CPP_OPEN_BRACE)
-       ++nesting_depth;
+      cp_lexer_consume_token (parser->lexer);
     }
 }
 
@@ -2294,26 +2370,56 @@ 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);
+}
+
 /* 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.  */
@@ -2325,7 +2431,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;
@@ -2580,39 +2686,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))
     {
-      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;
-       }
+      /* 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_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);
@@ -2636,33 +2737,35 @@ cp_parser_translation_unit (cp_parser* parser)
    primary-expression:
      ( compound-statement )
      __builtin_va_arg ( assignment-expression , type-id )
+     __builtin_offsetof ( type-id , offsetof-expression )
 
-   literal:
-     __null
+   Objective-C++ Extension:
 
-   CAST_P is true if this primary expression is the target of a cast.
+   primary-expression:
+     objc-expression
 
-   Returns a representation of the expression.
+   literal:
+     __null
 
-   *IDK indicates what kind of id-expression (if any) was present.
+   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.
 
-   *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);
@@ -2682,7 +2785,8 @@ cp_parser_primary_expression (cp_parser *parser,
         constant expression if they are cast to an integral or
         enumeration type.  */
       if (TREE_CODE (token->value) == REAL_CST
-         && parser->integral_constant_expression_p)
+         && parser->integral_constant_expression_p
+         && pedantic)
        {
          /* CAST_P will be set even in invalid code like "int(2.7 +
             ...)".   Therefore, we have to check that the next token
@@ -2702,7 +2806,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;
            }
 
@@ -2711,7 +2818,7 @@ cp_parser_primary_expression (cp_parser *parser,
             checked at that point.  If we are not within a cast, then
             this code is invalid.  */
          if (!cast_p)
-           cp_parser_non_integral_constant_expression 
+           cp_parser_non_integral_constant_expression
              (parser, "floating-point literal");
        }
       return token->value;
@@ -2719,7 +2826,7 @@ cp_parser_primary_expression (cp_parser *parser,
     case CPP_STRING:
     case CPP_WSTRING:
       /* ??? Should wide strings be allowed when parser->translate_strings_p
-         is false (i.e. in attributes)?  If not, we can kill the third
+        is false (i.e. in attributes)?  If not, we can kill the third
         argument to cp_parser_string_literal.  */
       return cp_parser_string_literal (parser,
                                       parser->translate_strings_p,
@@ -2749,7 +2856,7 @@ cp_parser_primary_expression (cp_parser *parser,
            /* And they're not allowed outside of a function-body; you
               cannot, for example, write:
 
-                int i = ({ int j = 3; j + 1; });
+                int i = ({ int j = 3; j + 1; });
 
               at class or namespace scope.  */
            if (!at_function_scope_p ())
@@ -2862,6 +2969,12 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_OFFSETOF:
          return cp_parser_builtin_offsetof (parser);
 
+         /* Objective-C++ expressions.  */
+       case RID_AT_ENCODE:
+       case RID_AT_PROTOCOL:
+       case RID_AT_SELECTOR:
+         return cp_parser_objc_expression (parser);
+
        default:
          cp_parser_error (parser, "expected primary-expression");
          return error_mark_node;
@@ -2878,6 +2991,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.  */
@@ -2885,40 +3000,47 @@ cp_parser_primary_expression (cp_parser *parser,
          = cp_parser_id_expression (parser,
                                     /*template_keyword_p=*/false,
                                     /*check_dependency_p=*/true,
-                                    /*template_p=*/NULL,
+                                    &template_p,
                                     /*declarator_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
+              to whatever cp_parser_lookup_name() found.  */
+           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
@@ -2947,12 +3069,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;
@@ -2960,6 +3085,11 @@ cp_parser_primary_expression (cp_parser *parser,
 
       /* Anything else is an error.  */
     default:
+      /* ...unless we have an Objective-C++ message or string literal, that is.  */
+      if (c_dialect_objc ()
+         && (token->type == CPP_OPEN_SQUARE || token->type == CPP_OBJC_STRING))
+       return cp_parser_objc_expression (parser);
+
       cp_parser_error (parser, "expected primary-expression");
       return error_mark_node;
     }
@@ -3011,7 +3141,7 @@ cp_parser_id_expression (cp_parser *parser,
 
   /* 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
@@ -3132,7 +3262,7 @@ cp_parser_id_expression (cp_parser *parser,
 
 static tree
 cp_parser_unqualified_id (cp_parser* parser,
-                          bool template_keyword_p,
+                         bool template_keyword_p,
                          bool check_dependency_p,
                          bool declarator_p)
 {
@@ -3172,6 +3302,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        tree qualifying_scope;
        tree object_scope;
        tree scope;
+       bool done;
 
        /* Consume the `~' token.  */
        cp_lexer_consume_token (parser->lexer);
@@ -3181,7 +3312,7 @@ cp_parser_unqualified_id (cp_parser* parser,
             template <typename T> struct S { ~S (); };
             template <typename T> S<T>::~S() {}
 
-           is invalid, since `~' must be followed by a class-name, but
+          is invalid, since `~' must be followed by a class-name, but
           `S<T>' is dependent, and so not known to be a class.
           That's not right; we need to look in uninstantiated
           templates.  A further complication arises from:
@@ -3196,14 +3327,14 @@ cp_parser_unqualified_id (cp_parser* parser,
 
           Yet another issue is:
 
-             struct S {
-               int S;
-               ~S();
-             };
+            struct S {
+              int S;
+              ~S();
+            };
 
-             S::~S() {}
+            S::~S() {}
 
-           The standard does not seem to say that the `S' in `~S'
+          The standard does not seem to say that the `S' in `~S'
           should refer to the type `S' and not the data member
           `S::S'.  */
 
@@ -3228,6 +3359,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 
        /* If there was an explicit qualification (S::~T), first look
           in the scope given by the qualification (i.e., S).  */
+       done = false;
+       type_decl = NULL_TREE;
        if (scope)
          {
            cp_parser_parse_tentatively (parser);
@@ -3239,10 +3372,10 @@ cp_parser_unqualified_id (cp_parser* parser,
                                              /*class_head_p=*/false,
                                              declarator_p);
            if (cp_parser_parse_definitely (parser))
-             return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+             done = true;
          }
        /* In "N::S::~S", look in "N" as well.  */
-       if (scope && qualifying_scope)
+       if (!done && scope && qualifying_scope)
          {
            cp_parser_parse_tentatively (parser);
            parser->scope = qualifying_scope;
@@ -3257,10 +3390,10 @@ cp_parser_unqualified_id (cp_parser* parser,
                                      /*class_head_p=*/false,
                                      declarator_p);
            if (cp_parser_parse_definitely (parser))
-             return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+             done = true;
          }
        /* In "p->S::~T", look in the scope given by "*p" as well.  */
-       else if (object_scope)
+       else if (!done && object_scope)
          {
            cp_parser_parse_tentatively (parser);
            parser->scope = object_scope;
@@ -3275,29 +3408,41 @@ cp_parser_unqualified_id (cp_parser* parser,
                                      /*class_head_p=*/false,
                                      declarator_p);
            if (cp_parser_parse_definitely (parser))
-             return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+             done = true;
          }
        /* Look in the surrounding context.  */
-       parser->scope = NULL_TREE;
-       parser->object_scope = NULL_TREE;
-       parser->qualifying_scope = NULL_TREE;
-       type_decl
-         = cp_parser_class_name (parser,
-                                 /*typename_keyword_p=*/false,
-                                 /*template_keyword_p=*/false,
-                                 none_type,
-                                 /*check_dependency=*/false,
-                                 /*class_head_p=*/false,
-                                 declarator_p);
-       /* If an error occurred, assume that the name of the
-          destructor is the same as the name of the qualifying
-          class.  That allows us to keep parsing after running
-          into ill-formed destructor names.  */
+       if (!done)
+         {
+           parser->scope = NULL_TREE;
+           parser->object_scope = NULL_TREE;
+           parser->qualifying_scope = NULL_TREE;
+           type_decl
+             = cp_parser_class_name (parser,
+                                     /*typename_keyword_p=*/false,
+                                     /*template_keyword_p=*/false,
+                                     none_type,
+                                     /*check_dependency=*/false,
+                                     /*class_head_p=*/false,
+                                     declarator_p);
+         }
+       /* If an error occurred, assume that the name of the
+          destructor is the same as the name of the qualifying
+          class.  That allows us to keep parsing after running
+          into ill-formed destructor names.  */
        if (type_decl == error_mark_node && scope && TYPE_P (scope))
          return build_nt (BIT_NOT_EXPR, scope);
        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
@@ -3372,7 +3517,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;
 
@@ -3392,9 +3536,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)
     {
@@ -3460,11 +3605,11 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
         look up names in "X<T>::I" in order to determine that "Y" is
         a template.  So, if we have a typename at this point, we make
         an effort to look through it.  */
-      if (is_declaration 
+      if (is_declaration
          && !typename_keyword_p
-         && parser->scope 
+         && parser->scope
          && TREE_CODE (parser->scope) == TYPENAME_TYPE)
-       parser->scope = resolve_typename_type (parser->scope, 
+       parser->scope = resolve_typename_type (parser->scope,
                                               /*only_current_p=*/false);
       /* Parse the qualifying entity.  */
       new_scope
@@ -3500,16 +3645,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:
@@ -3525,29 +3686,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
@@ -3555,28 +3725,34 @@ 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;
 }
 
 /* Parse a nested-name-specifier.  See
    cp_parser_nested_name_specifier_opt for details.  This function
    behaves identically, except that it will an issue an error if no
-   nested-name-specifier is present, and it will return
-   ERROR_MARK_NODE, rather than NULL_TREE, if no nested-name-specifier
-   is present.  */
+   nested-name-specifier is present.  */
 
 static tree
 cp_parser_nested_name_specifier (cp_parser *parser,
@@ -3598,7 +3774,6 @@ cp_parser_nested_name_specifier (cp_parser *parser,
     {
       cp_parser_error (parser, "expected nested-name-specifier");
       parser->scope = NULL_TREE;
-      return error_mark_node;
     }
 
   return scope;
@@ -3708,7 +3883,7 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
 
    If ADDRESS_P is true, the postfix expression is the operand of the
    `&' operator.  CAST_P is true if this expression is the target of a
-   cast. 
+   cast.
 
    Returns a representation of the expression.  */
 
@@ -3719,10 +3894,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);
@@ -3850,45 +4021,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;
-
-       /* 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.  */
-       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);
-       /* If we look up a template-id in a non-dependent qualifying
-          scope, there's no need to create a dependent type.  */
-       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;
@@ -3919,7 +4057,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
        if (cp_parser_allow_gnu_extensions_p (parser)
            && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
          {
-           tree initializer_list = NULL_TREE;
+           VEC(constructor_elt,gc) *initializer_list = NULL;
            bool saved_in_type_id_in_expr_p;
 
            cp_parser_parse_tentatively (parser);
@@ -3964,38 +4102,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)
     {
@@ -4023,10 +4137,34 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
          /* postfix-expression ( expression-list [opt] ) */
          {
            bool koenig_p;
-           tree args = (cp_parser_parenthesized_expression_list
-                        (parser, false, 
-                         /*cast_p=*/false,
-                         /*non_constant_p=*/NULL));
+           bool is_builtin_constant_p;
+           bool saved_integral_constant_expression_p = false;
+           bool saved_non_integral_constant_expression_p = false;
+           tree args;
+
+           is_builtin_constant_p
+             = DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
+           if (is_builtin_constant_p)
+             {
+               /* The whole point of __builtin_constant_p is to allow
+                  non-constant expressions to appear as arguments.  */
+               saved_integral_constant_expression_p
+                 = parser->integral_constant_expression_p;
+               saved_non_integral_constant_expression_p
+                 = parser->non_integral_constant_expression_p;
+               parser->integral_constant_expression_p = false;
+             }
+           args = (cp_parser_parenthesized_expression_list
+                   (parser, /*is_attribute_list=*/false,
+                    /*cast_p=*/false,
+                    /*non_constant_p=*/NULL));
+           if (is_builtin_constant_p)
+             {
+               parser->integral_constant_expression_p
+                 = saved_integral_constant_expression_p;
+               parser->non_integral_constant_expression_p
+                 = saved_non_integral_constant_expression_p;
+             }
 
            if (args == error_mark_node)
              {
@@ -4036,8 +4174,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
 
            /* Function calls are not permitted in
               constant-expressions.  */
-           if (cp_parser_non_integral_constant_expression (parser,
-                                                           "a function call"))
+           if (! builtin_valid_in_constant_expr_p (postfix_expression)
+               && cp_parser_non_integral_constant_expression (parser,
+                                                              "a function call"))
              {
                postfix_expression = error_mark_node;
                break;
@@ -4258,7 +4397,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;
 
@@ -4285,7 +4423,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;
@@ -4329,18 +4473,20 @@ 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));
       /* 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;
 
-             struct X { void f(); };
-             template <typename T> void f(T* t) { t->X::f(); }
+            struct X { void f(); };
+            template <typename T> void f(T* t) { t->X::f(); }
 
         Even though "t" is dependent, "X::f" is not and has been resolved
         to a BASELINK; there is no need to include scope information.  */
@@ -4361,7 +4507,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;
@@ -4370,7 +4519,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);
        }
     }
 
@@ -4526,8 +4676,8 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 
 static void
 cp_parser_pseudo_destructor_name (cp_parser* parser,
-                                  tree* scope,
-                                  tree* type)
+                                 tree* scope,
+                                 tree* type)
 {
   bool nested_name_specifier_p;
 
@@ -4751,7 +4901,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
       token = cp_lexer_consume_token (parser->lexer);
       /* Parse the cast-expression.  */
       cast_expression
-       = cp_parser_cast_expression (parser, 
+       = cp_parser_cast_expression (parser,
                                     unary_operator == ADDR_EXPR,
                                     /*cast_p=*/false);
       /* Now, build an appropriate representation.  */
@@ -4774,7 +4924,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
          non_constant_p = (unary_operator == PREINCREMENT_EXPR
                            ? "`++'" : "`--'");
          /* Fall through.  */
-       case CONVERT_EXPR:
+       case UNARY_PLUS_EXPR:
        case NEGATE_EXPR:
        case TRUTH_NOT_EXPR:
          expression = finish_unary_op_expr (unary_operator, cast_expression);
@@ -4810,7 +4960,7 @@ cp_parser_unary_operator (cp_token* token)
       return ADDR_EXPR;
 
     case CPP_PLUS:
-      return CONVERT_EXPR;
+      return UNARY_PLUS_EXPR;
 
     case CPP_MINUS:
       return NEGATE_EXPR;
@@ -4870,7 +5020,7 @@ cp_parser_new_expression (cp_parser* parser)
       /* Look for the closing `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
       /* There should not be a direct-new-declarator in this production,
-         but GCC used to allowed this, so we check and emit a sensible error
+        but GCC used to allowed this, so we check and emit a sensible error
         message for this case.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
        {
@@ -4946,7 +5096,8 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
   parser->type_definition_forbidden_message
     = "types may not be defined in a new-type-id";
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, &type_specifier_seq);
+  cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+                               &type_specifier_seq);
   /* Restore the old message.  */
   parser->type_definition_forbidden_message = saved_message;
   /* Parse the new-declarator.  */
@@ -4978,7 +5129,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
       *nelts = declarator->u.array.bounds;
       if (*nelts == error_mark_node)
        *nelts = integer_one_node;
-      
+
       if (outer_declarator)
        outer_declarator->declarator = declarator->declarator;
       else
@@ -5077,7 +5228,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
              if (!expression)
                {
                  error ("expression in new-declarator must have integral "
-                         "or enumeration type");
+                        "or enumeration type");
                  expression = error_mark_node;
                }
            }
@@ -5250,11 +5401,11 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
       parser->type_definition_forbidden_message = saved_message;
 
       /* If ok so far, parse the dependent expression. We cannot be
-         sure it is a cast. Consider `(T ())'.  It is a parenthesized
-         ctor of T, but looks like a cast to function returning T
-         without a dependent expression.  */
+        sure it is a cast. Consider `(T ())'.  It is a parenthesized
+        ctor of T, but looks like a cast to function returning T
+        without a dependent expression.  */
       if (!cp_parser_error_occurred (parser))
-       expr = cp_parser_cast_expression (parser, 
+       expr = cp_parser_cast_expression (parser,
                                          /*address_p=*/false,
                                          /*cast_p=*/true);
 
@@ -5265,7 +5416,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 ("use of old-style cast");
+           warning (0, "use of old-style cast");
 
          /* Only type conversions to integral or enumeration types
             can be used in constant-expressions.  */
@@ -5320,7 +5471,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
      relational-expression >= shift-expression
 
   GNU Extension:
-  
+
    relational-expression:
      relational-expression <? shift-expression
      relational-expression >? shift-expression
@@ -5384,22 +5535,25 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
     {
       /* Get an operator token.  */
       token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_MIN || token->type == CPP_MAX)
+       cp_parser_warn_min_max ();
+
       new_prec = TOKEN_PRECEDENCE (token);
 
       /* Popping an entry off the stack means we completed a subexpression:
-         - either we found a token which is not an operator (`>' where it is not
-           an operator, or prec == PREC_NOT_OPERATOR), in which case popping
-           will happen repeatedly;
-         - or, we found an operator which has lower priority.  This is the case 
-           where the recursive descent *ascends*, as in `3 * 4 + 5' after
-           parsing `3 * 4'.  */
+        - either we found a token which is not an operator (`>' where it is not
+          an operator, or prec == PREC_NOT_OPERATOR), in which case popping
+          will happen repeatedly;
+        - or, we found an operator which has lower priority.  This is the case
+          where the recursive descent *ascends*, as in `3 * 4 + 5' after
+          parsing `3 * 4'.  */
       if (new_prec <= prec)
-        {
-          if (sp == stack)
+       {
+         if (sp == stack)
            break;
-          else
+         else
            goto pop;
-        }
+       }
 
      get_rhs:
       tree_type = binops_by_token[token->type].tree_type;
@@ -5408,57 +5562,57 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
       cp_lexer_consume_token (parser->lexer);
 
       /* Extract another operand.  It may be the RHS of this expression
-         or the LHS of a new, higher priority expression.  */
+        or the LHS of a new, higher priority expression.  */
       rhs = cp_parser_simple_cast_expression (parser);
 
       /* Get another operator token.  Look up its precedence to avoid
-         building a useless (immediately popped) stack entry for common
-         cases such as 3 + 4 + 5 or 3 * 4 + 5.  */
+        building a useless (immediately popped) stack entry for common
+        cases such as 3 + 4 + 5 or 3 * 4 + 5.  */
       token = cp_lexer_peek_token (parser->lexer);
       lookahead_prec = TOKEN_PRECEDENCE (token);
       if (lookahead_prec > new_prec)
-        {
-          /* ... and prepare to parse the RHS of the new, higher priority
-             expression.  Since precedence levels on the stack are
+       {
+         /* ... and prepare to parse the RHS of the new, higher priority
+            expression.  Since precedence levels on the stack are
             monotonically increasing, we do not have to care about
             stack overflows.  */
-          sp->prec = prec;
-          sp->tree_type = tree_type;
-          sp->lhs = lhs;
-          sp++;
-          lhs = rhs;
-          prec = new_prec;
-          new_prec = lookahead_prec;
-          goto get_rhs;
-
-         pop:
-          /* If the stack is not empty, we have parsed into LHS the right side
+         sp->prec = prec;
+         sp->tree_type = tree_type;
+         sp->lhs = lhs;
+         sp++;
+         lhs = rhs;
+         prec = new_prec;
+         new_prec = lookahead_prec;
+         goto get_rhs;
+
+        pop:
+         /* If the stack is not empty, we have parsed into LHS the right side
             (`4' in the example above) of an expression we had suspended.
-            We can use the information on the stack to recover the LHS (`3') 
+            We can use the information on the stack to recover the LHS (`3')
             from the stack together with the tree code (`MULT_EXPR'), and
             the precedence of the higher level subexpression
             (`PREC_ADDITIVE_EXPRESSION').  TOKEN is the CPP_PLUS token,
             which will be used to actually build the additive expression.  */
-          --sp;
+         --sp;
          prec = sp->prec;
-          tree_type = sp->tree_type;
-          rhs = lhs;
-          lhs = sp->lhs;
-        }
+         tree_type = sp->tree_type;
+         rhs = lhs;
+         lhs = sp->lhs;
+       }
 
       overloaded_p = false;
       lhs = build_x_binary_op (tree_type, lhs, rhs, &overloaded_p);
 
       /* If the binary operator required the use of an overloaded operator,
-         then this expression cannot be an integral constant-expression.
-         An overloaded operator can be used even if both operands are
-         otherwise permissible in an integral constant-expression if at
-         least one of the operands is of enumeration type.  */
+        then this expression cannot be an integral constant-expression.
+        An overloaded operator can be used even if both operands are
+        otherwise permissible in an integral constant-expression if at
+        least one of the operands is of enumeration type.  */
 
       if (overloaded_p
-          && (cp_parser_non_integral_constant_expression 
-              (parser, "calls to overloaded operators")))
-        return error_mark_node;
+         && (cp_parser_non_integral_constant_expression
+             (parser, "calls to overloaded operators")))
+       return error_mark_node;
     }
 
   return lhs;
@@ -5639,10 +5793,12 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
 
     case CPP_MIN_EQ:
       op = MIN_EXPR;
+      cp_parser_warn_min_max ();
       break;
 
     case CPP_MAX_EQ:
       op = MAX_EXPR;
+      cp_parser_warn_min_max ();
       break;
 
     default:
@@ -5758,7 +5914,7 @@ cp_parser_constant_expression (cp_parser* parser,
      constant.  */
   expression = cp_parser_assignment_expression (parser, /*cast_p=*/false);
   /* Restore the old settings.  */
-  parser->integral_constant_expression_p 
+  parser->integral_constant_expression_p
     = saved_integral_constant_expression_p;
   parser->allow_non_integral_constant_expression_p
     = saved_allow_non_integral_constant_expression_p;
@@ -5766,7 +5922,7 @@ cp_parser_constant_expression (cp_parser* parser,
     *non_constant_p = parser->non_integral_constant_expression_p;
   else if (parser->non_integral_constant_expression_p)
     expression = error_mark_node;
-  parser->non_integral_constant_expression_p 
+  parser->non_integral_constant_expression_p
     = saved_non_integral_constant_expression_p;
 
   return expression;
@@ -5870,15 +6026,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.  */
@@ -5895,8 +6056,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:
@@ -5917,6 +6078,15 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr)
          statement = cp_parser_jump_statement (parser);
          break;
 
+         /* Objective-C++ exception-handling constructs.  */
+       case RID_AT_TRY:
+       case RID_AT_CATCH:
+       case RID_AT_FINALLY:
+       case RID_AT_SYNCHRONIZED:
+       case RID_AT_THROW:
+         statement = cp_parser_objc_statement (parser);
+         break;
+
        case RID_TRY:
          statement = cp_parser_try_block (parser);
          break;
@@ -5933,7 +6103,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)
@@ -5942,7 +6113,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;
     }
 
@@ -5983,10 +6167,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;
@@ -6017,11 +6205,11 @@ cp_parser_labeled_statement (cp_parser* parser, tree in_statement_expr)
        ellipsis = cp_lexer_peek_token (parser->lexer);
        if (ellipsis->type == CPP_ELLIPSIS)
          {
-            /* Consume the `...' token.  */
+           /* Consume the `...' token.  */
            cp_lexer_consume_token (parser->lexer);
            expr_hi =
              cp_parser_constant_expression (parser,
-                                            /*allow_non_constant_p=*/false,
+                                            /*allow_non_constant_p=*/false,
                                             NULL);
            /* We don't need to emit warnings here, as the common code
               will do this for us.  */
@@ -6029,20 +6217,21 @@ 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
+
+      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:
@@ -6054,7 +6243,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;
@@ -6136,13 +6325,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);
     }
 }
 
@@ -6273,7 +6465,8 @@ cp_parser_condition (cp_parser* parser)
   parser->type_definition_forbidden_message
     = "types may not be defined in conditions";
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, &type_specifiers);
+  cp_parser_type_specifier_seq (parser, /*is_condition==*/true,
+                               &type_specifiers);
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
   /* If all is well, we might be looking at a declaration.  */
@@ -6306,7 +6499,7 @@ cp_parser_condition (cp_parser* parser)
         for sure.  */
       if (cp_parser_parse_definitely (parser))
        {
-         tree pushed_scope;    
+         tree pushed_scope;
 
          /* Create the declaration.  */
          decl = start_decl (declarator, &type_specifiers,
@@ -6632,19 +6825,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;
@@ -6660,13 +6859,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, "`}'");
     }
 }
@@ -6689,7 +6888,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)
@@ -6721,7 +6921,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;
        }
 
@@ -6770,6 +6970,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);
@@ -6818,6 +7023,9 @@ cp_parser_declaration (cp_parser* parser)
               /* An unnamed namespace definition.  */
               || token2.type == CPP_OPEN_BRACE))
     cp_parser_namespace_definition (parser);
+  /* Objective-C++ declaration/definition.  */
+  else if (c_dialect_objc () && OBJC_IS_AT_KEYWORD (token1.keyword))
+    cp_parser_objc_declaration (parser);
   /* We must have either a block declaration or a function
      definition.  */
   else
@@ -6922,7 +7130,7 @@ cp_parser_block_declaration (cp_parser *parser,
 
 static void
 cp_parser_simple_declaration (cp_parser* parser,
-                              bool function_definition_allowed_p)
+                             bool function_definition_allowed_p)
 {
   cp_decl_specifier_seq decl_specifiers;
   int declares_class_or_enum;
@@ -6976,11 +7184,11 @@ cp_parser_simple_declaration (cp_parser* parser,
       /* Give up.  */
       goto done;
     }
-  
+
   /* If we have seen at least one decl-specifier, and the next token
      is not a parenthesis, then we must be looking at a declaration.
      (After "int (" we might be looking at a functional cast.)  */
-  if (decl_specifiers.any_specifiers_p 
+  if (decl_specifiers.any_specifiers_p
       && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
     cp_parser_commit_to_tentative_parse (parser);
 
@@ -6994,7 +7202,16 @@ 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,
                                        function_definition_allowed_p,
@@ -7029,7 +7246,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;
@@ -7051,9 +7268,9 @@ cp_parser_simple_declaration (cp_parser* parser,
       /* After the first time around, a function-definition is not
         allowed -- even if it was OK at first.  For example:
 
-           int i, f() {}
+          int i, f() {}
 
-         is not valid.  */
+        is not valid.  */
       function_definition_allowed_p = false;
     }
 
@@ -7100,9 +7317,9 @@ cp_parser_simple_declaration (cp_parser* parser,
    flags:
 
      1: one of the decl-specifiers is an elaborated-type-specifier
-        (i.e., a type declaration)
+       (i.e., a type declaration)
      2: one of the decl-specifiers is an enum-specifier or a
-        class-specifier (i.e., a type definition)
+       class-specifier (i.e., a type definition)
 
    */
 
@@ -7183,7 +7400,7 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
               extern
               mutable
 
-             GNU Extension:
+            GNU Extension:
               thread  */
        case RID_AUTO:
          /* Consume the token.  */
@@ -7489,7 +7706,7 @@ cp_parser_conversion_function_id (cp_parser* parser)
      conversion-type-id.  For example, consider:
 
        struct S {
-         typedef int I;
+        typedef int I;
         operator I();
        };
 
@@ -7532,7 +7749,8 @@ cp_parser_conversion_type_id (cp_parser* parser)
   /* Parse the attributes.  */
   attributes = cp_parser_attributes_opt (parser);
   /* Parse the type-specifiers.  */
-  cp_parser_type_specifier_seq (parser, &type_specifiers);
+  cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+                               &type_specifiers);
   /* If that didn't work, stop.  */
   if (type_specifiers.type == error_mark_node)
     return error_mark_node;
@@ -7540,7 +7758,7 @@ cp_parser_conversion_type_id (cp_parser* parser)
   declarator = cp_parser_conversion_declarator_opt (parser);
 
   type_specified =  grokdeclarator (declarator, &type_specifiers, TYPENAME,
-                                   /*initialized=*/0, &attributes);
+                                   /*initialized=*/0, &attributes);
   if (attributes)
     cplus_decl_attributes (&type_specified, attributes, /*flags=*/0);
   return type_specified;
@@ -7640,7 +7858,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;
@@ -7669,7 +7887,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)
@@ -7694,12 +7913,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.
@@ -8022,18 +8243,22 @@ cp_parser_operator (cp_parser* parser)
       /* Extensions.  */
     case CPP_MIN:
       id = ansi_opname (MIN_EXPR);
+      cp_parser_warn_min_max ();
       break;
 
     case CPP_MAX:
       id = ansi_opname (MAX_EXPR);
+      cp_parser_warn_min_max ();
       break;
 
     case CPP_MIN_EQ:
       id = ansi_assopname (MIN_EXPR);
+      cp_parser_warn_min_max ();
       break;
 
     case CPP_MAX_EQ:
       id = ansi_assopname (MAX_EXPR);
+      cp_parser_warn_min_max ();
       break;
 
     default:
@@ -8085,7 +8310,7 @@ cp_parser_template_declaration (cp_parser* parser, bool member_p)
       /* Consume the `export' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Warn that we do not support `export'.  */
-      warning ("keyword %<export%> not implemented, and will be ignored");
+      warning (0, "keyword %<export%> not implemented, and will be ignored");
     }
 
   cp_parser_template_declaration_after_export (parser, member_p);
@@ -8105,6 +8330,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
 {
   tree parameter_list = NULL_TREE;
 
+  begin_template_parm_list ();
   while (true)
     {
       tree parameter;
@@ -8127,7 +8353,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.
@@ -8240,7 +8466,7 @@ cp_parser_type_parameter (cp_parser* parser)
        tree default_argument;
 
        /* If the next token is an identifier, then it names the
-           parameter.  */
+          parameter.  */
        if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
          identifier = cp_parser_identifier (parser);
        else
@@ -8275,10 +8501,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.  */
@@ -8331,7 +8554,7 @@ 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);
@@ -8442,7 +8665,7 @@ cp_parser_template_id (cp_parser *parser,
       /* Change `:' into `::'.  */
       next_token_2->type = CPP_SCOPE;
       /* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
-         CPP_LESS.  */
+        CPP_LESS.  */
       cp_lexer_consume_token (parser->lexer);
       /* Parse the arguments.  */
       arguments = cp_parser_enclosed_template_argument_list (parser);
@@ -8457,7 +8680,7 @@ cp_parser_template_id (cp_parser *parser,
          return error_mark_node;
        }
       /* Otherwise, emit an error about the invalid digraph, but continue
-         parsing because we got our argument list.  */
+        parsing because we got our argument list.  */
       pedwarn ("%<<::%> cannot begin a template-argument list");
       inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
              "between %<<%> and %<::%>");
@@ -8512,17 +8735,16 @@ cp_parser_template_id (cp_parser *parser,
      should we re-parse the token stream, we will not have to repeat
      the effort required to do the parse, nor will we issue duplicate
      error messages about problems during instantiation of the
-     template.  Do so only if parsing succeeded, otherwise we may
-     silently accept template arguments with syntax errors.  */
+     template.  */
   if (start_of_id)
     {
       cp_token *token = cp_lexer_token_at (parser->lexer, start_of_id);
-      
+
       /* Reset the contents of the START_OF_ID token.  */
       token->type = CPP_TEMPLATE_ID;
       token->value = build_tree_list (access_check, template_id);
       token->keyword = RID_MAX;
-      
+
       /* Purge all subsequent tokens.  */
       cp_lexer_purge_tokens_after (parser->lexer, start_of_id);
 
@@ -8577,8 +8799,8 @@ cp_parser_template_id (cp_parser *parser,
 
 static tree
 cp_parser_template_name (cp_parser* parser,
-                         bool template_keyword_p,
-                         bool check_dependency_p,
+                        bool template_keyword_p,
+                        bool check_dependency_p,
                         bool is_declaration,
                         bool *is_identifier)
 {
@@ -8597,10 +8819,10 @@ cp_parser_template_name (cp_parser* parser,
       identifier = cp_parser_operator_function_id (parser);
       /* If that didn't work, try a conversion-function-id.  */
       if (!cp_parser_parse_definitely (parser))
-        {
+       {
          cp_parser_error (parser, "expected template-name");
          return error_mark_node;
-        }
+       }
     }
   /* Look for the identifier.  */
   else
@@ -8642,7 +8864,7 @@ cp_parser_template_name (cp_parser* parser,
          && !constructor_name_p (identifier, parser->scope))
        {
          cp_token_position start = 0;
-         
+
          /* Explain what went wrong.  */
          error ("non-template %qD used as template", identifier);
          inform ("use %<%T::template %D%> to indicate that it is a template",
@@ -8688,7 +8910,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.  */
@@ -8696,6 +8918,8 @@ cp_parser_template_name (cp_parser* parser,
     ;
   else
     {
+      tree fn = NULL_TREE;
+
       /* The standard does not explicitly indicate whether a name that
         names a set of overloaded declarations, some of which are
         templates, is a template-name.  However, such a name should
@@ -8703,16 +8927,13 @@ cp_parser_template_name (cp_parser* parser,
         template-id for the overloaded templates.  */
       fns = BASELINK_P (decl) ? BASELINK_FUNCTIONS (decl) : decl;
       if (TREE_CODE (fns) == OVERLOAD)
-       {
-         tree fn;
+       for (fn = fns; fn; fn = OVL_NEXT (fn))
+         if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
+           break;
 
-         for (fn = fns; fn; fn = OVL_NEXT (fn))
-           if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
-             break;
-       }
-      else
+      if (!fn)
        {
-         /* Otherwise, the name does not name a template.  */
+         /* The name does not name a template.  */
          cp_parser_error (parser, "expected template-name");
          return error_mark_node;
        }
@@ -8747,9 +8968,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;
@@ -8766,11 +8997,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;
     }
@@ -8783,6 +9014,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;
 }
@@ -8812,7 +9045,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.
@@ -8879,7 +9111,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");
@@ -8890,7 +9122,7 @@ cp_parser_template_argument (cp_parser* parser)
      in [temp.arg.nontype]:
 
      -- an integral constant-expression of integral or enumeration
-        type; or
+       type; or
 
      -- the name of a non-type template-parameter; or
 
@@ -8904,9 +9136,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);
@@ -8929,9 +9162,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);
@@ -8942,12 +9176,12 @@ cp_parser_template_argument (cp_parser* parser)
              gcc_assert (REFERENCE_REF_P (argument));
              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
@@ -9076,7 +9310,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
     {
@@ -9131,6 +9366,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 `<'.  */
@@ -9139,9 +9375,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))
@@ -9158,9 +9407,12 @@ cp_parser_explicit_specialization (cp_parser* parser)
     cp_parser_single_declaration (parser,
                                  /*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;
 }
@@ -9231,7 +9483,7 @@ cp_parser_type_specifier (cp_parser* parser,
       if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE
          || (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME
              && cp_lexer_peek_nth_token (parser->lexer, 3)->type
-                == CPP_OPEN_BRACE))
+                == CPP_OPEN_BRACE))
        {
          if (parser->num_template_parameter_lists)
            {
@@ -9555,7 +9807,26 @@ cp_parser_simple_type_specifier (cp_parser* parser,
      followed by a "<".  That usually indicates that the user thought
      that the type was a template.  */
   if (type && type != error_mark_node)
-    cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+    {
+      /* As a last-ditch effort, see if TYPE is an Objective-C type.
+        If it is, then the '<'...'>' enclose protocol names rather than
+        template arguments, and so everything is fine.  */
+      if (c_dialect_objc ()
+         && (objc_is_id (type) || objc_is_class_name (type)))
+       {
+         tree protos = cp_parser_objc_protocol_refs_opt (parser);
+         tree qual_type = objc_get_protocol_qualified_type (type, protos);
+
+         /* Clobber the "unqualified" type previously entered into
+            DECL_SPECS with the new, improved protocol-qualified version.  */
+         if (decl_specs)
+           decl_specs->type = qual_type;
+
+         return qual_type;
+       }
+
+      cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+    }
 
   return type;
 }
@@ -9573,7 +9844,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
    typedef-name:
      identifier
 
-   Returns a TYPE_DECL for the the type.  */
+   Returns a TYPE_DECL for the type.  */
 
 static tree
 cp_parser_type_name (cp_parser* parser)
@@ -9601,6 +9872,17 @@ cp_parser_type_name (cp_parser* parser)
 
       /* Look up the type-name.  */
       type_decl = cp_parser_lookup_name_simple (parser, identifier);
+
+      if (TREE_CODE (type_decl) != TYPE_DECL
+         && (objc_is_id (identifier) || objc_is_class_name (identifier)))
+       {
+         /* See if this is an Objective-C type.  */
+         tree protos = cp_parser_objc_protocol_refs_opt (parser);
+         tree type = objc_get_protocol_qualified_type (identifier, protos);
+         if (type)
+           type_decl = TYPE_NAME (type);
+       }
+
       /* Issue an error if we did not find a type-name.  */
       if (TREE_CODE (type_decl) != TYPE_DECL)
        {
@@ -9638,7 +9920,7 @@ cp_parser_type_name (cp_parser* parser)
    elaborated-type-specifier:
      class-key attributes :: [opt] nested-name-specifier [opt] identifier
      class-key attributes :: [opt] nested-name-specifier [opt]
-               template [opt] template-id
+              template [opt] template-id
      enum attributes :: [opt] nested-name-specifier [opt] identifier
 
    If IS_FRIEND is TRUE, then this elaborated-type-specifier is being
@@ -9650,8 +9932,8 @@ cp_parser_type_name (cp_parser* parser)
 
 static tree
 cp_parser_elaborated_type_specifier (cp_parser* parser,
-                                     bool is_friend,
-                                     bool is_declaration)
+                                    bool is_friend,
+                                    bool is_declaration)
 {
   enum tag_types tag_type;
   tree identifier;
@@ -9696,12 +9978,11 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
   /* Look for the nested-name-specifier.  */
   if (tag_type == typename_type)
     {
-      if (cp_parser_nested_name_specifier (parser,
+      if (!cp_parser_nested_name_specifier (parser,
                                           /*typename_keyword_p=*/true,
                                           /*check_dependency_p=*/true,
                                           /*type_p=*/true,
-                                          is_declaration)
-         == error_mark_node)
+                                           is_declaration))
        return error_mark_node;
     }
   else
@@ -9722,7 +10003,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       /* Allow the `template' keyword.  */
       template_p = cp_parser_optional_template_keyword (parser);
       /* If we didn't see `template', we don't know if there's a
-         template-id or not.  */
+        template-id or not.  */
       if (!template_p)
        cp_parser_parse_tentatively (parser);
       /* Parse the template-id.  */
@@ -9730,7 +10011,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
                                    /*check_dependency_p=*/true,
                                    is_declaration);
       /* If we didn't find a template-id, look for an ordinary
-         identifier.  */
+        identifier.  */
       if (!template_p && !cp_parser_parse_definitely (parser))
        ;
       /* If DECL is a TEMPLATE_ID_EXPR, and the `typename' keyword is
@@ -9740,7 +10021,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);
     }
@@ -9757,7 +10038,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
        }
 
       /* For a `typename', we needn't call xref_tag.  */
-      if (tag_type == typename_type 
+      if (tag_type == typename_type
          && TREE_CODE (parser->scope) != NAMESPACE_DECL)
        return cp_parser_make_typename_type (parser, parser->scope,
                                             identifier);
@@ -9771,7 +10052,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
@@ -9800,7 +10081,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 
          if (TREE_CODE (decl) != TYPE_DECL)
            {
-             cp_parser_diagnose_invalid_type_name (parser, 
+             cp_parser_diagnose_invalid_type_name (parser,
                                                    parser->scope,
                                                    identifier);
              return error_mark_node;
@@ -9860,6 +10141,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;
@@ -9871,12 +10154,21 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
          else
            ts = ts_global;
 
-         /* Warn about attributes. They are ignored.  */
-         if (attributes)
-           warning ("type attributes are honored only at type definition");
-
-         type = xref_tag (tag_type, identifier, ts,
-                          parser->num_template_parameter_lists);
+         /* Warn about attributes. They are ignored.  */
+         if (attributes)
+           warning (OPT_Wattributes,
+                    "type attributes are honored only at type definition");
+
+         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)
@@ -10061,11 +10353,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;
     }
@@ -10248,7 +10542,7 @@ cp_parser_using_declaration (cp_parser* parser)
 
   /* 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)
@@ -10326,10 +10620,10 @@ cp_parser_using_directive (cp_parser* parser)
      asm volatile [opt] ( string-literal ) ;
      asm volatile [opt] ( string-literal : asm-operand-list [opt] ) ;
      asm volatile [opt] ( string-literal : asm-operand-list [opt]
-                          : asm-operand-list [opt] ) ;
+                         : asm-operand-list [opt] ) ;
      asm volatile [opt] ( string-literal : asm-operand-list [opt]
-                          : asm-operand-list [opt]
-                          : asm-operand-list [opt] ) ;  */
+                         : asm-operand-list [opt]
+                         : asm-operand-list [opt] ) ;  */
 
 static void
 cp_parser_asm_definition (cp_parser* parser)
@@ -10447,12 +10741,12 @@ cp_parser_asm_definition (cp_parser* parser)
          tree temp = asm_stmt;
          if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
            temp = TREE_OPERAND (temp, 0);
-         
+
          ASM_INPUT_P (temp) = 1;
        }
     }
   else
-    assemble_asm (string);
+    cgraph_add_asm_node (string);
 }
 
 /* Declarators [gram.dcl.decl] */
@@ -10718,7 +11012,8 @@ cp_parser_init_declarator (cp_parser* parser,
      attributes -- but ignores them.  */
   if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init)
     if (cp_parser_attributes_opt (parser))
-      warning ("attributes after parenthesized initializer ignored");
+      warning (OPT_Wattributes,
+              "attributes after parenthesized initializer ignored");
 
   /* For an in-class declaration, use `grokfield' to create the
      declaration.  */
@@ -10731,7 +11026,7 @@ cp_parser_init_declarator (cp_parser* parser,
        }
       decl = grokfield (declarator, decl_specifiers,
                        initializer, /*asmspec=*/NULL_TREE,
-                       /*attributes=*/NULL_TREE);
+                       prefix_attributes);
       if (decl && TREE_CODE (decl) == FUNCTION_DECL)
        cp_parser_save_default_args (parser, decl);
     }
@@ -10797,14 +11092,14 @@ cp_parser_init_declarator (cp_parser* parser,
    expression, not a declaration.)
 
    If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
-   the declarator is a direct-declarator of the form "(...)".  
+   the declarator is a direct-declarator of the form "(...)".
 
    MEMBER_P is true iff this declarator is a member-declarator.  */
 
 static cp_declarator *
 cp_parser_declarator (cp_parser* parser,
-                      cp_parser_declarator_kind dcl_kind,
-                      int* ctor_dtor_or_conv_p,
+                     cp_parser_declarator_kind dcl_kind,
+                     int* ctor_dtor_or_conv_p,
                      bool* parenthesized_p,
                      bool member_p)
 {
@@ -10912,8 +11207,8 @@ cp_parser_declarator (cp_parser* parser,
 
 static cp_declarator *
 cp_parser_direct_declarator (cp_parser* parser,
-                             cp_parser_declarator_kind dcl_kind,
-                             int* ctor_dtor_or_conv_p,
+                            cp_parser_declarator_kind dcl_kind,
+                            int* ctor_dtor_or_conv_p,
                             bool member_p)
 {
   cp_token *token;
@@ -10931,15 +11226,15 @@ cp_parser_direct_declarator (cp_parser* parser,
       if (token->type == CPP_OPEN_PAREN)
        {
          /* This is either a parameter-declaration-clause, or a
-            parenthesized declarator. When we know we are parsing a
-            named declarator, it must be a parenthesized declarator
-            if FIRST is true. For instance, `(int)' is a
-            parameter-declaration-clause, with an omitted
-            direct-abstract-declarator. But `((*))', is a
-            parenthesized abstract declarator. Finally, when T is a
-            template parameter `(T)' is a
-            parameter-declaration-clause, and not a parenthesized
-            named declarator.
+            parenthesized declarator. When we know we are parsing a
+            named declarator, it must be a parenthesized declarator
+            if FIRST is true. For instance, `(int)' is a
+            parameter-declaration-clause, with an omitted
+            direct-abstract-declarator. But `((*))', is a
+            parenthesized abstract declarator. Finally, when T is a
+            template parameter `(T)' is a
+            parameter-declaration-clause, and not a parenthesized
+            named declarator.
 
             We first try and parse a parameter-declaration-clause,
             and then try a nested declarator (if FIRST is true).
@@ -10959,7 +11254,7 @@ cp_parser_direct_declarator (cp_parser* parser,
             these two alternatives should be selected.  Even more
             complex are examples like:
 
-               int i (int (a));
+              int i (int (a));
               int i (int (3));
 
             The former is a function-declaration; the latter is a
@@ -11005,7 +11300,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                = saved_num_template_parameter_lists;
 
              /* If all went well, parse the cv-qualifier-seq and the
-                exception-specification.  */
+                exception-specification.  */
              if (member_p || cp_parser_parse_definitely (parser))
                {
                  cp_cv_quals cv_quals;
@@ -11029,8 +11324,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                                                     cv_quals,
                                                     exception_specification);
                  /* Any subsequent parameter lists are to do with
-                    return type, so are not those of the declared
-                    function.  */
+                    return type, so are not those of the declared
+                    function.  */
                  parser->default_arg_ok_p = false;
 
                  /* Repeat the main loop.  */
@@ -11098,6 +11393,9 @@ cp_parser_direct_declarator (cp_parser* parser,
                                                 &non_constant_p);
              if (!non_constant_p)
                bounds = fold_non_dependent_expr (bounds);
+             /* Normally, the array bound must be an integral constant
+                expression.  However, as an extension, we allow VLAs
+                in function scopes.  */
              else if (!at_function_scope_p ())
                {
                  error ("array bound is not an integer constant");
@@ -11119,6 +11417,7 @@ cp_parser_direct_declarator (cp_parser* parser,
        {
          tree qualifying_scope;
          tree unqualified_name;
+         special_function_kind sfk;
 
          /* Parse a declarator-id */
          if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
@@ -11130,7 +11429,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              if (!cp_parser_parse_definitely (parser))
                unqualified_name = error_mark_node;
              else if (qualifying_scope
-                      || (TREE_CODE (unqualified_name) 
+                      || (TREE_CODE (unqualified_name)
                           != IDENTIFIER_NODE))
                {
                  cp_parser_error (parser, "expected unqualified-id");
@@ -11148,23 +11447,23 @@ cp_parser_direct_declarator (cp_parser* parser,
              && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
            {
              /* In the declaration of a member of a template class
-                outside of the class itself, the SCOPE will sometimes
-                be a TYPENAME_TYPE.  For example, given:
+                outside of the class itself, the SCOPE will sometimes
+                be a TYPENAME_TYPE.  For example, given:
 
-                        template <typename T>
-                int S<T>::R::i = 3;
+                template <typename T>
+                int S<T>::R::i = 3;
 
-                the SCOPE will be a TYPENAME_TYPE for `S<T>::R'.  In
-                this context, we must resolve S<T>::R to an ordinary
-                type, rather than a typename type.
+                the SCOPE will be a TYPENAME_TYPE for `S<T>::R'.  In
+                this context, we must resolve S<T>::R to an ordinary
+                type, rather than a typename type.
 
-                The reason we normally avoid resolving TYPENAME_TYPEs
-                is that a specialization of `S' might render
-                `S<T>::R' not a type.  However, if `S' is
-                specialized, then this `i' will not be used, so there
-                is no harm in resolving the types here.  */
+                The reason we normally avoid resolving TYPENAME_TYPEs
+                is that a specialization of `S' might render
+                `S<T>::R' not a type.  However, if `S' is
+                specialized, then this `i' will not be used, so there
+                is no harm in resolving the types here.  */
              tree type;
-             
+
              /* Resolve the TYPENAME_TYPE.  */
              type = resolve_typename_type (qualifying_scope,
                                            /*only_current_p=*/false);
@@ -11176,8 +11475,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              qualifying_scope = type;
            }
 
-         declarator = make_id_declarator (qualifying_scope, 
-                                          unqualified_name);
+         sfk = sfk_none;
          if (unqualified_name)
            {
              tree class_type;
@@ -11188,39 +11486,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);
@@ -11280,7 +11602,7 @@ cp_parser_direct_declarator (cp_parser* parser,
 
 static enum tree_code
 cp_parser_ptr_operator (cp_parser* parser,
-                        tree* type,
+                       tree* type,
                        cp_cv_quals *cv_quals)
 {
   enum tree_code code = ERROR_MARK;
@@ -11430,6 +11752,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 static tree
 cp_parser_declarator_id (cp_parser* parser)
 {
+  tree id;
   /* The expression must be an id-expression.  Assume that qualified
      names are the names of types so that:
 
@@ -11444,11 +11767,14 @@ 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);
+  if (BASELINK_P (id))
+    id = BASELINK_FUNCTIONS (id);
+  return id;
 }
 
 /* Parse a type-id.
@@ -11465,7 +11791,8 @@ cp_parser_type_id (cp_parser* parser)
   cp_declarator *abstract_declarator;
 
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, &type_specifier_seq);
+  cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+                               &type_specifier_seq);
   if (type_specifier_seq.type == error_mark_node)
     return error_mark_node;
 
@@ -11493,13 +11820,18 @@ cp_parser_type_id (cp_parser* parser)
    type-specifier-seq:
      attributes type-specifier-seq [opt]
 
+   If IS_CONDITION is true, we are at the start of a "condition",
+   e.g., we've just seen "if (".
+
    Sets *TYPE_SPECIFIER_SEQ to represent the sequence.  */
 
 static void
 cp_parser_type_specifier_seq (cp_parser* parser,
+                             bool is_condition,
                              cp_decl_specifier_seq *type_specifier_seq)
 {
   bool seen_type_specifier = false;
+  cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
 
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
@@ -11508,6 +11840,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
   while (true)
     {
       tree type_specifier;
+      bool is_cv_qualifier;
 
       /* Check for attributes first.  */
       if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
@@ -11520,28 +11853,46 @@ cp_parser_type_specifier_seq (cp_parser* parser,
 
       /* Look for the type-specifier.  */
       type_specifier = cp_parser_type_specifier (parser,
-                                                CP_PARSER_FLAGS_OPTIONAL,
+                                                flags,
                                                 type_specifier_seq,
                                                 /*is_declaration=*/false,
                                                 NULL,
-                                                NULL);
-      /* If the first type-specifier could not be found, this is not a
-        type-specifier-seq at all.  */
-      if (!seen_type_specifier && !type_specifier)
+                                                &is_cv_qualifier);
+      if (!type_specifier)
        {
-         cp_parser_error (parser, "expected type-specifier");
-         type_specifier_seq->type = error_mark_node;
-         return;
+         /* If the first type-specifier could not be found, this is not a
+            type-specifier-seq at all.  */
+         if (!seen_type_specifier)
+           {
+             cp_parser_error (parser, "expected type-specifier");
+             type_specifier_seq->type = error_mark_node;
+             return;
+           }
+         /* If subsequent type-specifiers could not be found, the
+            type-specifier-seq is complete.  */
+         break;
        }
-      /* If subsequent type-specifiers could not be found, the
-        type-specifier-seq is complete.  */
-      else if (seen_type_specifier && !type_specifier)
-       break;
 
       seen_type_specifier = true;
-    }
+      /* The standard says that a condition can be:
+
+           type-specifier-seq declarator = assignment-expression
+
+        However, given:
+
+          struct S {};
+          if (int S = ...)
 
-  return;
+        we should treat the "S" as a declarator, not as a
+        type-specifier.  The standard doesn't say that explicitly for
+        type-specifier-seq, but it does say that for
+        decl-specifier-seq in an ordinary declaration.  Perhaps it
+        would be clearer just to allow a decl-specifier-seq here, and
+        then add a semantic restriction that if any decl-specifiers
+        that are not type-specifiers appear, the program is invalid.  */
+      if (is_condition && !is_cv_qualifier)
+       flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
+    }
 }
 
 /* Parse a parameter-declaration-clause.
@@ -11676,7 +12027,10 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 
       /* Peek at the next token.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
-         || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+         || cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS)
+         /* These are for Objective-C++ */
+         || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+         || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
        /* The parameter-declaration-list is complete.  */
        break;
       else if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
@@ -11693,9 +12047,9 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
          cp_lexer_consume_token (parser->lexer);
          /* When parsing something like:
 
-               int i(float f, double d)
+               int i(float f, double d)
 
-             we can tell after seeing the declaration for "f" that we
+            we can tell after seeing the declaration for "f" that we
             are not looking at an initialization of a variable "i",
             but rather at the declaration of a function "i".
 
@@ -11903,6 +12257,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;
@@ -11931,13 +12286,14 @@ cp_parser_parameter_declaration (cp_parser *parser,
            }
 
          /* Create a DEFAULT_ARG to represented the unparsed default
-             argument.  */
+            argument.  */
          default_argument = make_node (DEFAULT_ARG);
          DEFARG_TOKENS (default_argument)
-           = cp_token_cache_new (first_token, token);  
+           = cp_token_cache_new (first_token, token);
+         DEFARG_INSTANTIATIONS (default_argument) = NULL;
        }
       /* Outside of a class definition, we can just parse the
-         assignment-expression.  */
+        assignment-expression.  */
       else
        {
          bool saved_local_variables_forbidden_p;
@@ -11953,7 +12309,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
            = parser->local_variables_forbidden_p;
          parser->local_variables_forbidden_p = true;
          /* Parse the assignment-expression.  */
-         default_argument 
+         default_argument
            = cp_parser_assignment_expression (parser, /*cast_p=*/false);
          /* Restore saved state.  */
          parser->greater_than_is_operator_p
@@ -11964,7 +12320,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
       if (!parser->default_arg_ok_p)
        {
          if (!flag_pedantic_errors)
-           warning ("deprecated use of default argument for parameter of non-function");
+           warning (0, "deprecated use of default argument for parameter of non-function");
          else
            {
              error ("default arguments are only permitted for function parameters");
@@ -12018,7 +12374,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 )'
@@ -12077,7 +12433,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
    returned is simply a representation for the expression.
 
    Otherwise, a CONSTRUCTOR is returned.  The CONSTRUCTOR_ELTS will be
-   the elements of the initializer-list (or NULL_TREE, if the last
+   the elements of the initializer-list (or NULL, if the last
    production is used).  The TREE_TYPE for the CONSTRUCTOR will be
    NULL_TREE.  There is no way to detect whether or not the optional
    trailing `,' was provided.  NON_CONSTANT_P is as for
@@ -12137,15 +12493,15 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
      identifier : initializer-clause
      initializer-list, identifier : initializer-clause
 
-   Returns a TREE_LIST.  The TREE_VALUE of each node is an expression
-   for the initializer.  If the TREE_PURPOSE is non-NULL, it is the
+   Returns a VEC of constructor_elt.  The VALUE of each elt is an expression
+   for the initializer.  If the INDEX of the elt is non-NULL, it is the
    IDENTIFIER_NODE naming the field to initialize.  NON_CONSTANT_P is
    as for cp_parser_initializer.  */
 
-static tree
+static VEC(constructor_elt,gc) *
 cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
 {
-  tree initializers = NULL_TREE;
+  VEC(constructor_elt,gc) *v = NULL;
 
   /* Assume all of the expressions are constant.  */
   *non_constant_p = false;
@@ -12179,8 +12535,9 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
       /* If any clause is non-constant, so is the entire initializer.  */
       if (clause_non_constant_p)
        *non_constant_p = true;
-      /* Add it to the list.  */
-      initializers = tree_cons (identifier, initializer, initializers);
+
+      /* Add it to the vector.  */
+      CONSTRUCTOR_APPEND_ELT(v, identifier, initializer);
 
       /* If the next token is not a comma, we have reached the end of
         the list.  */
@@ -12199,9 +12556,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
       cp_lexer_consume_token (parser->lexer);
     }
 
-  /* The initializers were built up in reverse order, so we need to
-     reverse them now.  */
-  return nreverse (initializers);
+  return v;
 }
 
 /* Classes [gram.class] */
@@ -12260,9 +12615,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.  */
@@ -12274,6 +12633,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.
 
@@ -12290,7 +12658,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
@@ -12308,7 +12687,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);
     }
@@ -12429,7 +12809,7 @@ cp_parser_class_specifier (cp_parser* parser)
      class-specifier for that class.  Consider:
 
        struct A {
-         struct B { void f() { sizeof (A); } };
+        struct B { void f() { sizeof (A); } };
        };
 
      If `f' were processed before the processing of `A' were
@@ -12448,17 +12828,17 @@ 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:
 
            struct S {
-              void f() { g(); }
-              void g(int i = 3);
-            };
+             void f() { g(); }
+             void g(int i = 3);
+           };
 
-         */
+        */
       for (TREE_PURPOSE (parser->unparsed_functions_queues)
             = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));
           (queue_entry = TREE_PURPOSE (parser->unparsed_functions_queues));
@@ -12493,13 +12873,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--;
        }
     }
 
@@ -12532,7 +12907,7 @@ cp_parser_class_specifier (cp_parser* parser)
    involving a nested-name-specifier was used, and FALSE otherwise.
 
    Returns error_mark_node if this is not a class-head.
-   
+
    Returns NULL_TREE if the class-head is syntactically valid, but
    semantically invalid in a way that means we should skip the entire
    body of the class.  */
@@ -12605,10 +12980,10 @@ cp_parser_class_head (cp_parser* parser,
 
         It is OK to define an inaccessible class; for example:
 
-           class A { class B; };
-           class A::B {};
+          class A { class B; };
+          class A::B {};
 
-         We do not know if we will see a class-name, or a
+        We do not know if we will see a class-name, or a
         template-name.  We look for a class-name first, in case the
         class-name is a template-id; if we looked for the
         template-name first we would stop after the template-name.  */
@@ -12721,13 +13096,13 @@ cp_parser_class_head (cp_parser* parser,
       if (scope && !is_ancestor (scope, nested_name_specifier))
        {
          error ("declaration of %qD in %qD which does not enclose %qD",
-                 type, scope, nested_name_specifier);
+                type, scope, nested_name_specifier);
          type = NULL_TREE;
          goto done;
        }
       /* [dcl.meaning]
 
-         A declarator-id shall not be qualified exception of the
+        A declarator-id shall not be qualified exception of the
         definition of a ... nested class outside of its class
         ... [or] a the definition or explicit instantiation of a
         class member of a namespace outside of its namespace.  */
@@ -12813,7 +13188,7 @@ cp_parser_class_head (cp_parser* parser,
              goto done;
            }
        }
-      
+
       type = TREE_TYPE (type);
       *nested_name_specifier_p = true;
     }
@@ -12832,9 +13207,18 @@ cp_parser_class_head (cp_parser* parser,
     CLASSTYPE_DECLARED_CLASS (type) = (class_key == class_type);
   cp_parser_check_class_key (class_key, type);
 
+  /* If this type was already complete, and we see another definition,
+     that's an error.  */
+  if (type != error_mark_node && COMPLETE_TYPE_P (type))
+    {
+      error ("redefinition of %q#T", type);
+      error ("previous definition of %q+#T", type);
+      type = NULL_TREE;
+      goto done;
+    }
+
   /* We will have entered the scope containing the class; the names of
-     base classes should be looked up in that context.  For example,
-     given:
+     base classes should be looked up in that context.  For example:
 
        struct A { struct B {}; struct C; };
        struct A::C : B {};
@@ -12909,7 +13293,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.  */
@@ -12931,7 +13317,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;
            }
 
@@ -12995,8 +13381,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;
     }
@@ -13010,6 +13401,22 @@ cp_parser_member_declaration (cp_parser* parser)
       return;
     }
 
+  /* Check for @defs.  */
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_DEFS))
+    {
+      tree ivar, member;
+      tree ivar_chains = cp_parser_objc_defs_expression (parser);
+      ivar = ivar_chains;
+      while (ivar)
+       {
+         member = ivar;
+         ivar = TREE_CHAIN (member);
+         TREE_CHAIN (member) = NULL_TREE;
+         finish_member_declaration (member);
+       }
+      return;
+    }
+
   /* Parse the decl-specifier-seq.  */
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
@@ -13060,8 +13467,8 @@ cp_parser_member_declaration (cp_parser* parser)
               /* In this case:
 
                    template <typename T> struct A {
-                      friend struct A<T>::B;
-                    };
+                     friend struct A<T>::B;
+                   };
 
                  A<T>::B will be represented by a TYPENAME_TYPE, and
                  therefore not recognized by check_tag_decl.  */
@@ -13148,7 +13555,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);
@@ -13331,14 +13739,14 @@ cp_parser_pure_specifier (cp_parser* parser)
   if (!cp_parser_require (parser, CPP_EQ, "`='"))
     return error_mark_node;
   /* Look for the `0' token.  */
-  token = cp_parser_require (parser, CPP_NUMBER, "`0'");
-  /* 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.  */
-  if (!token || !integer_zerop (token->value))
-    return error_mark_node;
+  token = cp_lexer_consume_token (parser->lexer);
+  /* c_lex_with_flags marks a single digit '0' with PURE_ZERO.  */
+  if (token->type == CPP_NUMBER && (token->flags & PURE_ZERO))
+    return integer_zero_node;
 
-  return integer_zero_node;
+  cp_parser_error (parser, "invalid pure specifier (only `= 0' is allowed)");
+  cp_parser_skip_to_end_of_statement (parser);
+  return error_mark_node;
 }
 
 /* Parse a constant-initializer.
@@ -13778,7 +14186,8 @@ cp_parser_exception_declaration (cp_parser* parser)
     = "types may not be defined in exception-declarations";
 
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, &type_specifiers);
+  cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+                               &type_specifiers);
   /* If it's a `)', then there is no declarator.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
     declarator = NULL;
@@ -14036,10 +14445,10 @@ cp_parser_attributes_opt (cp_parser* parser)
      identifier ( identifier , expression-list )
      identifier ( expression-list )
 
-   Returns a TREE_LIST.  Each node corresponds to an attribute.  THe
-   TREE_PURPOSE of each node is the identifier indicating which
-   attribute is in use.  The TREE_VALUE represents the arguments, if
-   any.  */
+   Returns a TREE_LIST, or NULL_TREE on error.  Each node corresponds
+   to an attribute.  The TREE_PURPOSE of each node is the identifier
+   indicating which attribute is in use.  The TREE_VALUE represents
+   the arguments, if any.  */
 
 static tree
 cp_parser_attribute_list (cp_parser* parser)
@@ -14057,37 +14466,39 @@ cp_parser_attribute_list (cp_parser* parser)
       /* Look for the identifier.  We also allow keywords here; for
         example `__attribute__ ((const))' is legal.  */
       token = cp_lexer_peek_token (parser->lexer);
-      if (token->type != CPP_NAME
-         && token->type != CPP_KEYWORD)
-       return error_mark_node;
-      /* Consume the token.  */
-      token = cp_lexer_consume_token (parser->lexer);
+      if (token->type == CPP_NAME
+         || token->type == CPP_KEYWORD)
+       {
+         /* Consume the token.  */
+         token = cp_lexer_consume_token (parser->lexer);
 
-      /* Save away the identifier that indicates which attribute this is.  */
-      identifier = token->value;
-      attribute = build_tree_list (identifier, NULL_TREE);
+         /* Save away the identifier that indicates which attribute
+            this is.  */
+         identifier = token->value;
+         attribute = build_tree_list (identifier, NULL_TREE);
 
-      /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If it's an `(', then parse the attribute arguments.  */
-      if (token->type == CPP_OPEN_PAREN)
-       {
-         tree arguments;
+         /* Peek at the next token.  */
+         token = cp_lexer_peek_token (parser->lexer);
+         /* If it's an `(', then parse the attribute arguments.  */
+         if (token->type == CPP_OPEN_PAREN)
+           {
+             tree arguments;
 
-         arguments = (cp_parser_parenthesized_expression_list
-                      (parser, true, /*cast_p=*/false, 
-                       /*non_constant_p=*/NULL));
-         /* Save the identifier and arguments away.  */
-         TREE_VALUE (attribute) = arguments;
-       }
+             arguments = (cp_parser_parenthesized_expression_list
+                          (parser, true, /*cast_p=*/false,
+                           /*non_constant_p=*/NULL));
+             /* Save the identifier and arguments away.  */
+             TREE_VALUE (attribute) = arguments;
+           }
 
-      /* Add this attribute to the list.  */
-      TREE_CHAIN (attribute) = attribute_list;
-      attribute_list = attribute;
+         /* Add this attribute to the list.  */
+         TREE_CHAIN (attribute) = attribute_list;
+         attribute_list = attribute;
 
-      /* Now, look for more attributes.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If the next token isn't a `,', we're done.  */
+         token = cp_lexer_peek_token (parser->lexer);
+       }
+      /* Now, look for more attributes.  If the next token isn't a
+        `,', we're done.  */
       if (token->type != CPP_COMMA)
        break;
 
@@ -14147,7 +14558,10 @@ cp_parser_label_declaration (cp_parser* parser)
 
       /* Look for an identifier.  */
       identifier = cp_parser_identifier (parser);
-      /* Declare it as a lobel.  */
+      /* If we failed, stop.  */
+      if (identifier == error_mark_node)
+       break;
+      /* Declare it as a label.  */
       finish_label_decl (identifier);
       /* If the next token is a `;', stop.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -14191,24 +14605,30 @@ cp_parser_label_declaration (cp_parser* parser)
    are ignored.
 
    If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
-   types.  
+   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
@@ -14246,6 +14666,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
       /* If that's not a class type, there is no destructor.  */
       if (!type || !CLASS_TYPE_P (type))
        return error_mark_node;
+      if (CLASSTYPE_LAZY_DESTRUCTOR (type))
+       lazily_declare_fn (sfk_destructor, type);
       if (!CLASSTYPE_DESTRUCTORS (type))
          return error_mark_node;
       /* If it was a class type, return the destructor.  */
@@ -14285,15 +14707,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
        {
@@ -14306,12 +14733,12 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
             lookup_member, we must enter the scope here.  */
          if (dependent_p)
            pushed_scope = push_scope (parser->scope);
-         /* If the PARSER->SCOPE is a template specialization, it
+         /* If the PARSER->SCOPE is a template specialization, it
             may be instantiated during name lookup.  In that case,
             errors may be issued.  Even if we rollback the current
             tentative parse, those errors are valid.  */
-         decl = lookup_qualified_name (parser->scope, name, 
-                                       tag_type != none_type, 
+         decl = lookup_qualified_name (parser->scope, name,
+                                       tag_type != none_type,
                                        /*complain=*/true);
          if (pushed_scope)
            pop_scope (pushed_scope);
@@ -14331,13 +14758,12 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
           parse, those errors are valid.  */
        object_decl = lookup_member (object_type,
                                     name,
-                                    /*protect=*/0, 
+                                    /*protect=*/0,
                                     tag_type != none_type);
       /* Look it up in the enclosing context, too.  */
-      decl = lookup_name_real (name, tag_type != none_type, 
+      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)
@@ -14345,26 +14771,22 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
     }
   else
     {
-      decl = lookup_name_real (name, tag_type != none_type, 
+      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;
     }
 
   /* If the lookup failed, let our caller know.  */
-  if (!decl
-      || decl == error_mark_node
-      || (TREE_CODE (decl) == FUNCTION_DECL
-         && DECL_ANTICIPATED (decl)))
+  if (!decl || decl == error_mark_node)
     return error_mark_node;
 
   /* 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))
@@ -14406,7 +14828,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
@@ -14423,17 +14845,17 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
      the translation from TEMPLATE_DECL to TYPE_DECL occurs:
 
        struct A {
-         template <typename T> struct B;
+        template <typename T> struct B;
        };
 
        template <typename T> struct A::B {};
 
-     Similarly, in a elaborated-type-specifier:
+     Similarly, in an elaborated-type-specifier:
 
        namespace N { struct X{}; }
 
        struct A {
-         template <typename T> friend struct N::X;
+        template <typename T> friend struct N::X;
        };
 
      However, if the DECL refers to a class type, and we are in
@@ -14442,7 +14864,7 @@ cp_parser_maybe_treat_template_as_class (tree decl, bool tag_name_p)
      than a TEMPLATE_DECL.  For example, in:
 
        template <class T> struct S {
-         S s;
+        S s;
        };
 
      there is no need to handle such case.  */
@@ -14498,7 +14920,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
              scope = TYPE_CONTEXT (scope);
            }
        }
-      else if (TREE_CODE (declarator->u.id.unqualified_name) 
+      else if (TREE_CODE (declarator->u.id.unqualified_name)
               == TEMPLATE_ID_EXPR)
        /* If the DECLARATOR has the form `X<y>' then it uses one
           additional level of template parameters.  */
@@ -14530,7 +14952,7 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
 
 static bool
 cp_parser_check_template_parameters (cp_parser* parser,
-                                     unsigned num_templates)
+                                    unsigned num_templates)
 {
   /* If there are more template classes than parameter lists, we have
      something like:
@@ -14816,9 +15238,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'.  */
@@ -14864,6 +15292,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   tree decl = NULL_TREE;
   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'"))
@@ -14872,7 +15301,19 @@ 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;
   /* If the next token is `>', then we have an invalid
      specialization.  Rather than complain about an invalid template
      parameter, issue an error message here.  */
@@ -14883,12 +15324,8 @@ 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);
 
   /* Look for the `>'.  */
   cp_parser_skip_until_found (parser, CPP_GREATER, "`>'");
@@ -14902,7 +15339,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   else
     {
       /* There are no access checks when parsing a template, as we do not
-         know if a specialization will be a friend.  */
+        know if a specialization will be a friend.  */
       push_deferring_access_checks (dk_no_check);
 
       decl = cp_parser_single_declaration (parser,
@@ -14933,7 +15370,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   /* 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.)  */
@@ -15074,8 +15514,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"))
@@ -15156,6 +15598,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]
 
@@ -15170,6 +15613,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;
@@ -15207,11 +15654,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;
@@ -15219,6 +15663,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;
 }
@@ -15260,12 +15705,14 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
       tokens = DECL_PENDING_INLINE_INFO (member_function);
       DECL_PENDING_INLINE_INFO (member_function) = NULL;
       DECL_PENDING_INLINE_P (member_function) = 0;
-      /* If this was an inline function in a local class, enter the scope
-        of the containing function.  */
-      function_scope = decl_function_context (member_function);
+
+      /* If this is a local class, enter the scope of the containing
+        function.  */
+      function_scope = current_function_decl;
       if (function_scope)
        push_function_context_to (function_scope);
 
+
       /* Push the body of the function onto the lexer stack.  */
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
@@ -15274,10 +15721,17 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
       start_preparsed_function (member_function, NULL_TREE,
                                SF_PRE_PARSED | SF_INCLASS_INLINE);
 
+      /* Don't do access checking if it is a templated function.  */
+      if (processing_template_decl)
+       push_deferring_access_checks (dk_no_check);
+
       /* Now, parse the body of the function.  */
       cp_parser_function_definition_after_declarator (parser,
                                                      /*inline_p=*/true);
 
+      if (processing_template_decl)
+       pop_deferring_access_checks ();
+
       /* Leave the scope of the containing function.  */
       if (function_scope)
        pop_function_context_from (function_scope);
@@ -15310,7 +15764,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
@@ -15341,19 +15794,37 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
        parm = TREE_CHAIN (parm))
     {
       cp_token_cache *tokens;
+      tree default_arg = TREE_PURPOSE (parm);
+      tree parsed_arg;
+      VEC(tree,gc) *insts;
+      tree copy;
+      unsigned ix;
+
+      if (!default_arg)
+       continue;
 
-      if (!TREE_PURPOSE (parm)
-         || TREE_CODE (TREE_PURPOSE (parm)) != DEFAULT_ARG)
+      if (TREE_CODE (default_arg) != DEFAULT_ARG)
+       /* This can happen for a friend declaration for a function
+          already declared with default arguments.  */
        continue;
 
        /* Push the saved tokens for the default argument onto the parser's
          lexer stack.  */
-      tokens = DEFARG_TOKENS (TREE_PURPOSE (parm));
+      tokens = DEFARG_TOKENS (default_arg);
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
       /* Parse the assignment-expression.  */
-      TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser,
-                                                            /*cast_p=*/false);
+      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.  */
+      for (insts = DEFARG_INSTANTIATIONS (default_arg), ix = 0;
+          VEC_iterate (tree, insts, ix, copy); ix++)
+       TREE_PURPOSE (copy) = parsed_arg;
 
       /* If the token stream has not been completely used up, then
         there was extra junk after the end of the default
@@ -15365,6 +15836,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;
 
@@ -15396,7 +15870,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,
@@ -15404,7 +15878,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 
   /* The restrictions on constant-expressions do not apply inside
      sizeof expressions.  */
-  saved_integral_constant_expression_p 
+  saved_integral_constant_expression_p
     = parser->integral_constant_expression_p;
   saved_non_integral_constant_expression_p
     = parser->non_integral_constant_expression_p;
@@ -15461,7 +15935,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   free ((char *) parser->type_definition_forbidden_message);
   /* And restore the old one.  */
   parser->type_definition_forbidden_message = saved_message;
-  parser->integral_constant_expression_p 
+  parser->integral_constant_expression_p
     = saved_integral_constant_expression_p;
   parser->non_integral_constant_expression_p
     = saved_non_integral_constant_expression_p;
@@ -15551,8 +16025,8 @@ cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers)
 
 static cp_token *
 cp_parser_require (cp_parser* parser,
-                   enum cpp_ttype type,
-                   const char* token_desc)
+                  enum cpp_ttype type,
+                  const char* token_desc)
 {
   if (cp_lexer_next_token_is (parser->lexer, type))
     return cp_lexer_consume_token (parser->lexer);
@@ -15575,8 +16049,8 @@ cp_parser_require (cp_parser* parser,
 
 static void
 cp_parser_skip_until_found (cp_parser* parser,
-                            enum cpp_ttype type,
-                            const char* token_desc)
+                           enum cpp_ttype type,
+                           const char* token_desc)
 {
   cp_token *token;
   unsigned nesting_depth = 0;
@@ -15589,27 +16063,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);
     }
@@ -15623,8 +16108,8 @@ cp_parser_skip_until_found (cp_parser* parser,
 
 static cp_token *
 cp_parser_require_keyword (cp_parser* parser,
-                           enum rid keyword,
-                           const char* token_desc)
+                          enum rid keyword,
+                          const char* token_desc)
 {
   cp_token *token = cp_parser_require (parser, CPP_KEYWORD, token_desc);
 
@@ -15684,7 +16169,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
@@ -15828,7 +16313,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);
@@ -15841,6 +16328,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;
     }
@@ -15963,12 +16452,1217 @@ cp_parser_allow_gnu_extensions_p (cp_parser* parser)
 {
   return parser->allow_gnu_extensions_p;
 }
-
 \f
-/* The parser.  */
+/* Objective-C++ Productions */
 
-static GTY (()) cp_parser *the_parser;
 
+/* Parse an Objective-C expression, which feeds into a primary-expression
+   above.
+
+   objc-expression:
+     objc-message-expression
+     objc-string-literal
+     objc-encode-expression
+     objc-protocol-expression
+     objc-selector-expression
+
+  Returns a tree representation of the expression.  */
+
+static tree
+cp_parser_objc_expression (cp_parser* parser)
+{
+  /* Try to figure out what kind of declaration is present.  */
+  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+  switch (kwd->type)
+    {
+    case CPP_OPEN_SQUARE:
+      return cp_parser_objc_message_expression (parser);
+
+    case CPP_OBJC_STRING:
+      kwd = cp_lexer_consume_token (parser->lexer);
+      return objc_build_string_object (kwd->value);
+
+    case CPP_KEYWORD:
+      switch (kwd->keyword)
+       {
+       case RID_AT_ENCODE:
+         return cp_parser_objc_encode_expression (parser);
+
+       case RID_AT_PROTOCOL:
+         return cp_parser_objc_protocol_expression (parser);
+
+       case RID_AT_SELECTOR:
+         return cp_parser_objc_selector_expression (parser);
+
+       default:
+         break;
+       }
+    default:
+      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+    }
+
+  return error_mark_node;
+}
+
+/* Parse an Objective-C message expression.
+
+   objc-message-expression:
+     [ objc-message-receiver objc-message-args ]
+
+   Returns a representation of an Objective-C message.  */
+
+static tree
+cp_parser_objc_message_expression (cp_parser* parser)
+{
+  tree receiver, messageargs;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '['.  */
+  receiver = cp_parser_objc_message_receiver (parser);
+  messageargs = cp_parser_objc_message_args (parser);
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+
+  return objc_build_message_expr (build_tree_list (receiver, messageargs));
+}
+
+/* Parse an objc-message-receiver.
+
+   objc-message-receiver:
+     expression
+     simple-type-specifier
+
+  Returns a representation of the type or expression.  */
+
+static tree
+cp_parser_objc_message_receiver (cp_parser* parser)
+{
+  tree rcv;
+
+  /* An Objective-C message receiver may be either (1) a type
+     or (2) an expression.  */
+  cp_parser_parse_tentatively (parser);
+  rcv = cp_parser_expression (parser, false);
+
+  if (cp_parser_parse_definitely (parser))
+    return rcv;
+
+  rcv = cp_parser_simple_type_specifier (parser,
+                                        /*decl_specs=*/NULL,
+                                        CP_PARSER_FLAGS_NONE);
+
+  return objc_get_class_reference (rcv);
+}
+
+/* Parse the arguments and selectors comprising an Objective-C message.
+
+   objc-message-args:
+     objc-selector
+     objc-selector-args
+     objc-selector-args , objc-comma-args
+
+   objc-selector-args:
+     objc-selector [opt] : assignment-expression
+     objc-selector-args objc-selector [opt] : assignment-expression
+
+   objc-comma-args:
+     assignment-expression
+     objc-comma-args , assignment-expression
+
+   Returns a TREE_LIST, with TREE_PURPOSE containing a list of
+   selector arguments and TREE_VALUE containing a list of comma
+   arguments.  */
+
+static tree
+cp_parser_objc_message_args (cp_parser* parser)
+{
+  tree sel_args = NULL_TREE, addl_args = NULL_TREE;
+  bool maybe_unary_selector_p = true;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+    {
+      tree selector = NULL_TREE, arg;
+
+      if (token->type != CPP_COLON)
+       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))
+       return build_tree_list (selector, NULL_TREE);
+
+      maybe_unary_selector_p = false;
+      cp_parser_require (parser, CPP_COLON, "`:'");
+      arg = cp_parser_assignment_expression (parser, false);
+
+      sel_args
+       = chainon (sel_args,
+                  build_tree_list (selector, arg));
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  /* Handle non-selector arguments, if any. */
+  while (token->type == CPP_COMMA)
+    {
+      tree arg;
+
+      cp_lexer_consume_token (parser->lexer);
+      arg = cp_parser_assignment_expression (parser, false);
+
+      addl_args
+       = chainon (addl_args,
+                  build_tree_list (NULL_TREE, arg));
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  return build_tree_list (sel_args, addl_args);
+}
+
+/* Parse an Objective-C encode expression.
+
+   objc-encode-expression:
+     @encode objc-typename
+
+   Returns an encoded representation of the type argument.  */
+
+static tree
+cp_parser_objc_encode_expression (cp_parser* parser)
+{
+  tree type;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  type = complete_type (cp_parser_type_id (parser));
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+  if (!type)
+    {
+      error ("%<@encode%> must specify a type as an argument");
+      return error_mark_node;
+    }
+
+  return objc_build_encode_expr (type);
+}
+
+/* Parse an Objective-C @defs expression.  */
+
+static tree
+cp_parser_objc_defs_expression (cp_parser *parser)
+{
+  tree name;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@defs'.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  name = cp_parser_identifier (parser);
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+  return objc_get_class_ivars (name);
+}
+
+/* Parse an Objective-C protocol expression.
+
+  objc-protocol-expression:
+    @protocol ( identifier )
+
+  Returns a representation of the protocol expression.  */
+
+static tree
+cp_parser_objc_protocol_expression (cp_parser* parser)
+{
+  tree proto;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  proto = cp_parser_identifier (parser);
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+  return objc_build_protocol_expr (proto);
+}
+
+/* Parse an Objective-C selector expression.
+
+   objc-selector-expression:
+     @selector ( objc-method-signature )
+
+   objc-method-signature:
+     objc-selector
+     objc-selector-seq
+
+   objc-selector-seq:
+     objc-selector :
+     objc-selector-seq objc-selector :
+
+  Returns a representation of the method selector.  */
+
+static tree
+cp_parser_objc_selector_expression (cp_parser* parser)
+{
+  tree sel_seq = NULL_TREE;
+  bool maybe_unary_selector_p = true;
+  cp_token *token;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@selector'.  */
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  token = cp_lexer_peek_token (parser->lexer);
+
+  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
+         || token->type == CPP_SCOPE)
+    {
+      tree selector = NULL_TREE;
+
+      if (token->type != CPP_COLON
+         || token->type == CPP_SCOPE)
+       selector = cp_parser_objc_selector (parser);
+
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
+          && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
+       {
+         /* 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;
+      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);
+    }
+
+ finish_selector:
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+  return objc_build_selector_expr (sel_seq);
+}
+
+/* Parse a list of identifiers.
+
+   objc-identifier-list:
+     identifier
+     objc-identifier-list , identifier
+
+   Returns a TREE_LIST of identifier nodes.  */
+
+static tree
+cp_parser_objc_identifier_list (cp_parser* parser)
+{
+  tree list = build_tree_list (NULL_TREE, cp_parser_identifier (parser));
+  cp_token *sep = cp_lexer_peek_token (parser->lexer);
+
+  while (sep->type == CPP_COMMA)
+    {
+      cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
+      list = chainon (list,
+                     build_tree_list (NULL_TREE,
+                                      cp_parser_identifier (parser)));
+      sep = cp_lexer_peek_token (parser->lexer);
+    }
+
+  return list;
+}
+
+/* Parse an Objective-C alias declaration.
+
+   objc-alias-declaration:
+     @compatibility_alias identifier identifier ;
+
+   This function registers the alias mapping with the Objective-C front-end.
+   It returns nothing.  */
+
+static void
+cp_parser_objc_alias_declaration (cp_parser* parser)
+{
+  tree alias, orig;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@compatibility_alias'.  */
+  alias = cp_parser_identifier (parser);
+  orig = cp_parser_identifier (parser);
+  objc_declare_alias (alias, orig);
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse an Objective-C class forward-declaration.
+
+   objc-class-declaration:
+     @class objc-identifier-list ;
+
+   The function registers the forward declarations with the Objective-C
+   front-end.  It returns nothing.  */
+
+static void
+cp_parser_objc_class_declaration (cp_parser* parser)
+{
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@class'.  */
+  objc_declare_class (cp_parser_objc_identifier_list (parser));
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse a list of Objective-C protocol references.
+
+   objc-protocol-refs-opt:
+     objc-protocol-refs [opt]
+
+   objc-protocol-refs:
+     < objc-identifier-list >
+
+   Returns a TREE_LIST of identifiers, if any.  */
+
+static tree
+cp_parser_objc_protocol_refs_opt (cp_parser* parser)
+{
+  tree protorefs = NULL_TREE;
+
+  if(cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+    {
+      cp_lexer_consume_token (parser->lexer);  /* Eat '<'.  */
+      protorefs = cp_parser_objc_identifier_list (parser);
+      cp_parser_require (parser, CPP_GREATER, "`>'");
+    }
+
+  return protorefs;
+}
+
+/* Parse a Objective-C visibility specification.  */
+
+static void
+cp_parser_objc_visibility_spec (cp_parser* parser)
+{
+  cp_token *vis = cp_lexer_peek_token (parser->lexer);
+
+  switch (vis->keyword)
+    {
+    case RID_AT_PRIVATE:
+      objc_set_visibility (2);
+      break;
+    case RID_AT_PROTECTED:
+      objc_set_visibility (0);
+      break;
+    case RID_AT_PUBLIC:
+      objc_set_visibility (1);
+      break;
+    default:
+      return;
+    }
+
+  /* Eat '@private'/'@protected'/'@public'.  */
+  cp_lexer_consume_token (parser->lexer);
+}
+
+/* Parse an Objective-C method type.  */
+
+static void
+cp_parser_objc_method_type (cp_parser* parser)
+{
+  objc_set_method_type
+   (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS
+    ? PLUS_EXPR
+    : MINUS_EXPR);
+}
+
+/* Parse an Objective-C protocol qualifier.  */
+
+static tree
+cp_parser_objc_protocol_qualifiers (cp_parser* parser)
+{
+  tree quals = NULL_TREE, node;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  node = token->value;
+
+  while (node && TREE_CODE (node) == IDENTIFIER_NODE
+        && (node == ridpointers [(int) RID_IN]
+            || node == ridpointers [(int) RID_OUT]
+            || node == ridpointers [(int) RID_INOUT]
+            || node == ridpointers [(int) RID_BYCOPY]
+            || node == ridpointers [(int) RID_BYREF]
+            || node == ridpointers [(int) RID_ONEWAY]))
+    {
+      quals = tree_cons (NULL_TREE, node, quals);
+      cp_lexer_consume_token (parser->lexer);
+      token = cp_lexer_peek_token (parser->lexer);
+      node = token->value;
+    }
+
+  return quals;
+}
+
+/* Parse an Objective-C typename.  */
+
+static tree
+cp_parser_objc_typename (cp_parser* parser)
+{
+  tree typename = NULL_TREE;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      tree proto_quals, cp_type = NULL_TREE;
+
+      cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
+      proto_quals = cp_parser_objc_protocol_qualifiers (parser);
+
+      /* An ObjC type name may consist of just protocol qualifiers, in which
+        case the type shall default to 'id'.  */
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+       cp_type = cp_parser_type_id (parser);
+
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      typename = build_tree_list (proto_quals, cp_type);
+    }
+
+  return typename;
+}
+
+/* Check to see if TYPE refers to an Objective-C selector name.  */
+
+static bool
+cp_parser_objc_selector_p (enum cpp_ttype type)
+{
+  return (type == CPP_NAME || type == CPP_KEYWORD
+         || type == CPP_AND_AND || type == CPP_AND_EQ || type == CPP_AND
+         || type == CPP_OR || type == CPP_COMPL || type == CPP_NOT
+         || type == CPP_NOT_EQ || type == CPP_OR_OR || type == CPP_OR_EQ
+         || type == CPP_XOR || type == CPP_XOR_EQ);
+}
+
+/* Parse an Objective-C selector.  */
+
+static tree
+cp_parser_objc_selector (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_consume_token (parser->lexer);
+
+  if (!cp_parser_objc_selector_p (token->type))
+    {
+      error ("invalid Objective-C++ selector name");
+      return error_mark_node;
+    }
+
+  /* C++ operator names are allowed to appear in ObjC selectors.  */
+  switch (token->type)
+    {
+    case CPP_AND_AND: return get_identifier ("and");
+    case CPP_AND_EQ: return get_identifier ("and_eq");
+    case CPP_AND: return get_identifier ("bitand");
+    case CPP_OR: return get_identifier ("bitor");
+    case CPP_COMPL: return get_identifier ("compl");
+    case CPP_NOT: return get_identifier ("not");
+    case CPP_NOT_EQ: return get_identifier ("not_eq");
+    case CPP_OR_OR: return get_identifier ("or");
+    case CPP_OR_EQ: return get_identifier ("or_eq");
+    case CPP_XOR: return get_identifier ("xor");
+    case CPP_XOR_EQ: return get_identifier ("xor_eq");
+    default: return token->value;
+    }
+}
+
+/* Parse an Objective-C params list.  */
+
+static tree
+cp_parser_objc_method_keyword_params (cp_parser* parser)
+{
+  tree params = NULL_TREE;
+  bool maybe_unary_selector_p = true;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+    {
+      tree selector = NULL_TREE, typename, identifier;
+
+      if (token->type != CPP_COLON)
+       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))
+       return selector;
+
+      maybe_unary_selector_p = false;
+      cp_parser_require (parser, CPP_COLON, "`:'");
+      typename = cp_parser_objc_typename (parser);
+      identifier = cp_parser_identifier (parser);
+
+      params
+       = chainon (params,
+                  objc_build_keyword_decl (selector,
+                                           typename,
+                                           identifier));
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  return params;
+}
+
+/* Parse the non-keyword Objective-C params.  */
+
+static tree
+cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp)
+{
+  tree params = make_node (TREE_LIST);
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+  *ellipsisp = false;  /* Initially, assume no ellipsis.  */
+
+  while (token->type == CPP_COMMA)
+    {
+      cp_parameter_declarator *parmdecl;
+      tree parm;
+
+      cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
+      token = cp_lexer_peek_token (parser->lexer);
+
+      if (token->type == CPP_ELLIPSIS)
+       {
+         cp_lexer_consume_token (parser->lexer);  /* Eat '...'.  */
+         *ellipsisp = true;
+         break;
+       }
+
+      parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+      parm = grokdeclarator (parmdecl->declarator,
+                            &parmdecl->decl_specifiers,
+                            PARM, /*initialized=*/0,
+                            /*attrlist=*/NULL);
+
+      chainon (params, build_tree_list (NULL_TREE, parm));
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  return params;
+}
+
+/* Parse a linkage specification, a pragma, an extra semicolon or a block.  */
+
+static void
+cp_parser_objc_interstitial_code (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  /* If the next token is `extern' and the following token is a string
+     literal, then we have a linkage specification.  */
+  if (token->keyword == RID_EXTERN
+      && cp_parser_is_string_literal (cp_lexer_peek_nth_token (parser->lexer, 2)))
+    cp_parser_linkage_specification (parser);
+  /* Handle #pragma, if any.  */
+  else if (token->type == CPP_PRAGMA)
+    cp_parser_pragma (parser, pragma_external);
+  /* Allow stray semicolons.  */
+  else if (token->type == CPP_SEMICOLON)
+    cp_lexer_consume_token (parser->lexer);
+  /* Finally, try to parse a block-declaration, or a function-definition.  */
+  else
+    cp_parser_block_declaration (parser, /*statement_p=*/false);
+}
+
+/* Parse a method signature.  */
+
+static tree
+cp_parser_objc_method_signature (cp_parser* parser)
+{
+  tree rettype, kwdparms, optparms;
+  bool ellipsis = false;
+
+  cp_parser_objc_method_type (parser);
+  rettype = cp_parser_objc_typename (parser);
+  kwdparms = cp_parser_objc_method_keyword_params (parser);
+  optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis);
+
+  return objc_build_method_signature (rettype, kwdparms, optparms, ellipsis);
+}
+
+/* Pars an Objective-C method prototype list.  */
+
+static void
+cp_parser_objc_method_prototype_list (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  while (token->keyword != RID_AT_END)
+    {
+      if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+       {
+         objc_add_method_declaration
+          (cp_parser_objc_method_signature (parser));
+         cp_parser_consume_semicolon_at_end_of_statement (parser);
+       }
+      else
+       /* Allow for interspersed non-ObjC++ code.  */
+       cp_parser_objc_interstitial_code (parser);
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  objc_finish_interface ();
+}
+
+/* Parse an Objective-C method definition list.  */
+
+static void
+cp_parser_objc_method_definition_list (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  while (token->keyword != RID_AT_END)
+    {
+      tree meth;
+
+      if (token->type == CPP_PLUS || token->type == CPP_MINUS)
+       {
+         push_deferring_access_checks (dk_deferred);
+         objc_start_method_definition
+          (cp_parser_objc_method_signature (parser));
+
+         /* For historical reasons, we accept an optional semicolon.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+           cp_lexer_consume_token (parser->lexer);
+
+         perform_deferred_access_checks ();
+         stop_deferring_access_checks ();
+         meth = cp_parser_function_definition_after_declarator (parser,
+                                                                false);
+         pop_deferring_access_checks ();
+         objc_finish_method_definition (meth);
+       }
+      else
+       /* Allow for interspersed non-ObjC++ code.  */
+       cp_parser_objc_interstitial_code (parser);
+
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  objc_finish_implementation ();
+}
+
+/* Parse Objective-C ivars.  */
+
+static void
+cp_parser_objc_class_ivars (cp_parser* parser)
+{
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+  if (token->type != CPP_OPEN_BRACE)
+    return;    /* No ivars specified.  */
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '{'.  */
+  token = cp_lexer_peek_token (parser->lexer);
+
+  while (token->type != CPP_CLOSE_BRACE)
+    {
+      cp_decl_specifier_seq declspecs;
+      int decl_class_or_enum_p;
+      tree prefix_attributes;
+
+      cp_parser_objc_visibility_spec (parser);
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+       break;
+
+      cp_parser_decl_specifier_seq (parser,
+                                   CP_PARSER_FLAGS_OPTIONAL,
+                                   &declspecs,
+                                   &decl_class_or_enum_p);
+      prefix_attributes = declspecs.attributes;
+      declspecs.attributes = NULL_TREE;
+
+      /* Keep going until we hit the `;' at the end of the
+        declaration.  */
+      while (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       {
+         tree width = NULL_TREE, attributes, first_attribute, decl;
+         cp_declarator *declarator = NULL;
+         int ctor_dtor_or_conv_p;
+
+         /* Check for a (possibly unnamed) bitfield declaration.  */
+         token = cp_lexer_peek_token (parser->lexer);
+         if (token->type == CPP_COLON)
+           goto eat_colon;
+
+         if (token->type == CPP_NAME
+             && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
+                 == CPP_COLON))
+           {
+             /* Get the name of the bitfield.  */
+             declarator = make_id_declarator (NULL_TREE,
+                                              cp_parser_identifier (parser),
+                                              sfk_none);
+
+            eat_colon:
+             cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
+             /* Get the width of the bitfield.  */
+             width
+               = cp_parser_constant_expression (parser,
+                                                /*allow_non_constant=*/false,
+                                                NULL);
+           }
+         else
+           {
+             /* Parse the declarator.  */
+             declarator
+               = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+                                       &ctor_dtor_or_conv_p,
+                                       /*parenthesized_p=*/NULL,
+                                       /*member_p=*/false);
+           }
+
+         /* Look for attributes that apply to the ivar.  */
+         attributes = cp_parser_attributes_opt (parser);
+         /* Remember which attributes are prefix attributes and
+            which are not.  */
+         first_attribute = attributes;
+         /* Combine the attributes.  */
+         attributes = chainon (prefix_attributes, attributes);
+
+         if (width)
+           {
+             /* Create the bitfield declaration.  */
+             decl = grokbitfield (declarator, &declspecs, width);
+             cplus_decl_attributes (&decl, attributes, /*flags=*/0);
+           }
+         else
+           decl = grokfield (declarator, &declspecs, NULL_TREE,
+                             NULL_TREE, attributes);
+
+         /* Add the instance variable.  */
+         objc_add_instance_variable (decl);
+
+         /* Reset PREFIX_ATTRIBUTES.  */
+         while (attributes && TREE_CHAIN (attributes) != first_attribute)
+           attributes = TREE_CHAIN (attributes);
+         if (attributes)
+           TREE_CHAIN (attributes) = NULL_TREE;
+
+         token = cp_lexer_peek_token (parser->lexer);
+
+         if (token->type == CPP_COMMA)
+           {
+             cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
+             continue;
+           }
+         break;
+       }
+
+      cp_parser_consume_semicolon_at_end_of_statement (parser);
+      token = cp_lexer_peek_token (parser->lexer);
+    }
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '}'.  */
+  /* For historical reasons, we accept an optional semicolon.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+    cp_lexer_consume_token (parser->lexer);
+}
+
+/* Parse an Objective-C protocol declaration.  */
+
+static void
+cp_parser_objc_protocol_declaration (cp_parser* parser)
+{
+  tree proto, protorefs;
+  cp_token *tok;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+    {
+      error ("identifier expected after %<@protocol%>");
+      goto finish;
+    }
+
+  /* See if we have a forward declaration or a definition.  */
+  tok = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+  /* Try a forward declaration first.  */
+  if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
+    {
+      objc_declare_protocols (cp_parser_objc_identifier_list (parser));
+     finish:
+      cp_parser_consume_semicolon_at_end_of_statement (parser);
+    }
+
+  /* Ok, we got a full-fledged definition (or at least should).  */
+  else
+    {
+      proto = cp_parser_identifier (parser);
+      protorefs = cp_parser_objc_protocol_refs_opt (parser);
+      objc_start_protocol (proto, protorefs);
+      cp_parser_objc_method_prototype_list (parser);
+    }
+}
+
+/* Parse an Objective-C superclass or category.  */
+
+static void
+cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
+                                                         tree *categ)
+{
+  cp_token *next = cp_lexer_peek_token (parser->lexer);
+
+  *super = *categ = NULL_TREE;
+  if (next->type == CPP_COLON)
+    {
+      cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
+      *super = cp_parser_identifier (parser);
+    }
+  else if (next->type == CPP_OPEN_PAREN)
+    {
+      cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
+      *categ = cp_parser_identifier (parser);
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+    }
+}
+
+/* Parse an Objective-C class interface.  */
+
+static void
+cp_parser_objc_class_interface (cp_parser* parser)
+{
+  tree name, super, categ, protos;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@interface'.  */
+  name = cp_parser_identifier (parser);
+  cp_parser_objc_superclass_or_category (parser, &super, &categ);
+  protos = cp_parser_objc_protocol_refs_opt (parser);
+
+  /* We have either a class or a category on our hands.  */
+  if (categ)
+    objc_start_category_interface (name, categ, protos);
+  else
+    {
+      objc_start_class_interface (name, super, protos);
+      /* Handle instance variable declarations, if any.  */
+      cp_parser_objc_class_ivars (parser);
+      objc_continue_interface ();
+    }
+
+  cp_parser_objc_method_prototype_list (parser);
+}
+
+/* Parse an Objective-C class implementation.  */
+
+static void
+cp_parser_objc_class_implementation (cp_parser* parser)
+{
+  tree name, super, categ;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@implementation'.  */
+  name = cp_parser_identifier (parser);
+  cp_parser_objc_superclass_or_category (parser, &super, &categ);
+
+  /* We have either a class or a category on our hands.  */
+  if (categ)
+    objc_start_category_implementation (name, categ);
+  else
+    {
+      objc_start_class_implementation (name, super);
+      /* Handle instance variable declarations, if any.  */
+      cp_parser_objc_class_ivars (parser);
+      objc_continue_implementation ();
+    }
+
+  cp_parser_objc_method_definition_list (parser);
+}
+
+/* Consume the @end token and finish off the implementation.  */
+
+static void
+cp_parser_objc_end_implementation (cp_parser* parser)
+{
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  objc_finish_implementation ();
+}
+
+/* Parse an Objective-C declaration.  */
+
+static void
+cp_parser_objc_declaration (cp_parser* parser)
+{
+  /* Try to figure out what kind of declaration is present.  */
+  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+  switch (kwd->keyword)
+    {
+    case RID_AT_ALIAS:
+      cp_parser_objc_alias_declaration (parser);
+      break;
+    case RID_AT_CLASS:
+      cp_parser_objc_class_declaration (parser);
+      break;
+    case RID_AT_PROTOCOL:
+      cp_parser_objc_protocol_declaration (parser);
+      break;
+    case RID_AT_INTERFACE:
+      cp_parser_objc_class_interface (parser);
+      break;
+    case RID_AT_IMPLEMENTATION:
+      cp_parser_objc_class_implementation (parser);
+      break;
+    case RID_AT_END:
+      cp_parser_objc_end_implementation (parser);
+      break;
+    default:
+      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+    }
+}
+
+/* Parse an Objective-C try-catch-finally statement.
+
+   objc-try-catch-finally-stmt:
+     @try compound-statement objc-catch-clause-seq [opt]
+       objc-finally-clause [opt]
+
+   objc-catch-clause-seq:
+     objc-catch-clause objc-catch-clause-seq [opt]
+
+   objc-catch-clause:
+     @catch ( exception-declaration ) compound-statement
+
+   objc-finally-clause
+     @finally compound-statement
+
+   Returns NULL_TREE.  */
+
+static tree
+cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
+  location_t location;
+  tree stmt;
+
+  cp_parser_require_keyword (parser, RID_AT_TRY, "`@try'");
+  location = cp_lexer_peek_token (parser->lexer)->location;
+  /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
+     node, lest it get absorbed into the surrounding block.  */
+  stmt = push_stmt_list ();
+  cp_parser_compound_statement (parser, NULL, false);
+  objc_begin_try_stmt (location, pop_stmt_list (stmt));
+
+  while (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_CATCH))
+    {
+      cp_parameter_declarator *parmdecl;
+      tree parm;
+
+      cp_lexer_consume_token (parser->lexer);
+      cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+      parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
+      parm = grokdeclarator (parmdecl->declarator,
+                            &parmdecl->decl_specifiers,
+                            PARM, /*initialized=*/0,
+                            /*attrlist=*/NULL);
+      cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+      objc_begin_catch_clause (parm);
+      cp_parser_compound_statement (parser, NULL, false);
+      objc_finish_catch_clause ();
+    }
+
+  if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
+    {
+      cp_lexer_consume_token (parser->lexer);
+      location = cp_lexer_peek_token (parser->lexer)->location;
+      /* NB: The @finally block needs to be wrapped in its own STATEMENT_LIST
+        node, lest it get absorbed into the surrounding block.  */
+      stmt = push_stmt_list ();
+      cp_parser_compound_statement (parser, NULL, false);
+      objc_build_finally_clause (location, pop_stmt_list (stmt));
+    }
+
+  return objc_finish_try_stmt ();
+}
+
+/* Parse an Objective-C synchronized statement.
+
+   objc-synchronized-stmt:
+     @synchronized ( expression ) compound-statement
+
+   Returns NULL_TREE.  */
+
+static tree
+cp_parser_objc_synchronized_statement (cp_parser *parser) {
+  location_t location;
+  tree lock, stmt;
+
+  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "`@synchronized'");
+
+  location = cp_lexer_peek_token (parser->lexer)->location;
+  cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+  lock = cp_parser_expression (parser, false);
+  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+
+  /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
+     node, lest it get absorbed into the surrounding block.  */
+  stmt = push_stmt_list ();
+  cp_parser_compound_statement (parser, NULL, false);
+
+  return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
+}
+
+/* Parse an Objective-C throw statement.
+
+   objc-throw-stmt:
+     @throw assignment-expression [opt] ;
+
+   Returns a constructed '@throw' statement.  */
+
+static tree
+cp_parser_objc_throw_statement (cp_parser *parser) {
+  tree expr = NULL_TREE;
+
+  cp_parser_require_keyword (parser, RID_AT_THROW, "`@throw'");
+
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    expr = cp_parser_assignment_expression (parser, false);
+
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+  return objc_build_throw_stmt (expr);
+}
+
+/* Parse an Objective-C statement.  */
+
+static tree
+cp_parser_objc_statement (cp_parser * parser) {
+  /* Try to figure out what kind of declaration is present.  */
+  cp_token *kwd = cp_lexer_peek_token (parser->lexer);
+
+  switch (kwd->keyword)
+    {
+    case RID_AT_TRY:
+      return cp_parser_objc_try_catch_finally_statement (parser);
+    case RID_AT_SYNCHRONIZED:
+      return cp_parser_objc_synchronized_statement (parser);
+    case RID_AT_THROW:
+      return cp_parser_objc_throw_statement (parser);
+    default:
+      error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
+      cp_parser_skip_to_end_of_block_or_statement (parser);
+    }
+
+  return error_mark_node;
+}
+/* The parser.  */
+
+static GTY (()) cp_parser *the_parser;
+
+\f
+/* Special handling for the first token or line in the file.  The first
+   thing in the file might be #pragma GCC pch_preprocess, which loads a
+   PCH file, which is a GC collection point.  So we need to handle this
+   first pragma without benefit of an existing lexer structure.
+
+   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 ATTRIBUTE_UNUSED)
+{
+  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;
+
+    default:
+      gcc_assert (id >= PRAGMA_FIRST_EXTERNAL);
+      c_invoke_pragma_handler (id);
+      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.  */