OSDN Git Service

PR c++/48994
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 3f2c4de..4e085ab 100644 (file)
@@ -1,6 +1,6 @@
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
+   2005, 2007, 2008, 2009, 2010, 2011  Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "timevar.h"
 #include "cpplib.h"
 #include "tree.h"
 #include "cp-tree.h"
@@ -31,12 +32,14 @@ along with GCC; see the file COPYING3.  If not see
 #include "decl.h"
 #include "flags.h"
 #include "diagnostic-core.h"
-#include "toplev.h"
 #include "output.h"
 #include "target.h"
 #include "cgraph.h"
 #include "c-family/c-common.h"
+#include "c-family/c-objc.h"
 #include "plugin.h"
+#include "tree-pretty-print.h"
+#include "parser.h"
 
 \f
 /* The lexer.  */
@@ -44,110 +47,11 @@ along with GCC; see the file COPYING3.  If not see
 /* The cp_lexer_* routines mediate between the lexer proper (in libcpp
    and c-lex.c) and the C++ parser.  */
 
-/* A token's value and its associated deferred access checks and
-   qualifying scope.  */
-
-struct GTY(()) tree_check {
-  /* The value associated with the token.  */
-  tree value;
-  /* The checks that have been associated with value.  */
-  VEC (deferred_access_check, gc)* checks;
-  /* The token's qualifying scope (used when it is a
-     CPP_NESTED_NAME_SPECIFIER).  */
-  tree qualifying_scope;
-};
-
-/* A C++ token.  */
-
-typedef struct GTY (()) cp_token {
-  /* The kind of token.  */
-  ENUM_BITFIELD (cpp_ttype) type : 8;
-  /* If this token is a keyword, this value indicates which keyword.
-     Otherwise, this value is RID_MAX.  */
-  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 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 location at which this token was found.  */
-  location_t location;
-  /* The value associated with this token, if any.  */
-  union cp_token_value {
-    /* Used for CPP_NESTED_NAME_SPECIFIER and CPP_TEMPLATE_ID.  */
-    struct tree_check* GTY((tag ("1"))) tree_check_value;
-    /* Use for all other tokens.  */
-    tree GTY((tag ("0"))) value;
-  } GTY((desc ("(%1.type == CPP_TEMPLATE_ID) || (%1.type == CPP_NESTED_NAME_SPECIFIER)"))) u;
-} cp_token;
-
-/* We use a stack of token pointer for saving token sets.  */
-typedef struct cp_token *cp_token_position;
-DEF_VEC_P (cp_token_position);
-DEF_VEC_ALLOC_P (cp_token_position,heap);
-
 static cp_token eof_token =
 {
-  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, 0, { NULL }
+  CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, false, false, 0, { NULL }
 };
 
-/* The cp_lexer structure represents the C++ lexer.  It is responsible
-   for managing the token stream from the preprocessor and supplying
-   it to the parser.  Tokens are never added to the cp_lexer after
-   it is created.  */
-
-typedef struct GTY (()) cp_lexer {
-  /* The memory allocated for the buffer.  NULL if this lexer does not
-     own the token buffer.  */
-  cp_token * GTY ((length ("%h.buffer_length"))) buffer;
-  /* 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;
-
-  /* The next available token.  If NEXT_TOKEN is &eof_token, then there are
-     no more available tokens.  */
-  cp_token_position GTY ((skip)) next_token;
-
-  /* A stack indicating positions at which cp_lexer_save_tokens was
-     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,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;
-
-  /* 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
-   allocate heap memory for it, since tokens are never removed from the
-   lexer's array.  There is also no need for the GC to walk through
-   a cp_token_cache, since everything in here is referenced through
-   a lexer.  */
-
-typedef struct GTY(()) cp_token_cache {
-  /* The beginning of the token range.  */
-  cp_token * GTY((skip)) first;
-
-  /* Points immediately after the last token in the range.  */
-  cp_token * GTY ((skip)) last;
-} cp_token_cache;
-
 /* The various kinds of non integral constant we encounter. */
 typedef enum non_integral_constant {
   NIC_NONE,
@@ -280,8 +184,6 @@ static void cp_lexer_destroy
   (cp_lexer *);
 static int cp_lexer_saving_tokens
   (const cp_lexer *);
-static cp_token_position cp_lexer_token_position
-  (cp_lexer *, bool);
 static cp_token *cp_lexer_token_at
   (cp_lexer *, cp_token_position);
 static void cp_lexer_get_preprocessor_token
@@ -337,30 +239,6 @@ static void cp_parser_initial_pragma
 #define CP_LEXER_BUFFER_SIZE ((256 * 1024) / sizeof (cp_token))
 #define CP_SAVED_TOKEN_STACK 5
 
-/* A token type for keywords, as opposed to ordinary identifiers.  */
-#define CPP_KEYWORD ((enum cpp_ttype) (N_TTYPES + 1))
-
-/* A token type for template-ids.  If a template-id is processed while
-   parsing tentatively, it is replaced with a CPP_TEMPLATE_ID token;
-   the value of the CPP_TEMPLATE_ID is whatever was returned by
-   cp_parser_template_id.  */
-#define CPP_TEMPLATE_ID ((enum cpp_ttype) (CPP_KEYWORD + 1))
-
-/* A token type for nested-name-specifiers.  If a
-   nested-name-specifier is processed while parsing tentatively, it is
-   replaced with a CPP_NESTED_NAME_SPECIFIER token; the value of the
-   CPP_NESTED_NAME_SPECIFIER is whatever was returned by
-   cp_parser_nested_name_specifier_opt.  */
-#define CPP_NESTED_NAME_SPECIFIER ((enum cpp_ttype) (CPP_TEMPLATE_ID + 1))
-
-/* A token type for tokens that are not tokens at all; these are used
-   to represent slots in the array where there used to be a token
-   that has now been deleted.  */
-#define CPP_PURGED ((enum cpp_ttype) (CPP_NESTED_NAME_SPECIFIER + 1))
-
-/* The number of token types, including C++-specific ones.  */
-#define N_CP_TTYPES ((int) (CPP_PURGED + 1))
-
 /* Variables.  */
 
 #ifdef ENABLE_CHECKING
@@ -372,23 +250,65 @@ static FILE *cp_lexer_debug_stream;
    sizeof, typeof, or alignof.  */
 int cp_unevaluated_operand;
 
-/* Create a new main C++ lexer, the lexer that gets tokens from the
-   preprocessor.  */
+#ifdef ENABLE_CHECKING
+/* Dump up to NUM tokens in BUFFER to FILE.  If NUM is 0, dump all the
+   tokens.  */
+
+void
+cp_lexer_dump_tokens (FILE *file, VEC(cp_token,gc) *buffer, unsigned num)
+{
+  unsigned i;
+  cp_token *token;
+
+  fprintf (file, "%u tokens\n", VEC_length (cp_token, buffer));
+
+  if (num == 0)
+    num = VEC_length (cp_token, buffer);
+
+  for (i = 0; VEC_iterate (cp_token, buffer, i, token) && i < num; i++)
+    {
+      cp_lexer_print_token (file, token);
+      switch (token->type)
+       {
+         case CPP_SEMICOLON:
+         case CPP_OPEN_BRACE:
+         case CPP_CLOSE_BRACE:
+         case CPP_EOF:
+           fputc ('\n', file);
+           break;
+
+         default:
+           fputc (' ', file);
+       }
+    }
+
+  if (i == num && i < VEC_length (cp_token, buffer))
+    {
+      fprintf (file, " ... ");
+      cp_lexer_print_token (file, VEC_index (cp_token, buffer,
+                           VEC_length (cp_token, buffer) - 1));
+    }
+
+  fprintf (file, "\n");
+}
+
+
+/* Dump all tokens in BUFFER to stderr.  */
+
+void
+cp_lexer_debug_tokens (VEC(cp_token,gc) *buffer)
+{
+  cp_lexer_dump_tokens (stderr, buffer, 0);
+}
+#endif
+
+
+/* Allocate memory for a new lexer object and return it.  */
 
 static cp_lexer *
-cp_lexer_new_main (void)
+cp_lexer_alloc (void)
 {
-  cp_token first_token;
   cp_lexer *lexer;
-  cp_token *pos;
-  size_t alloc;
-  size_t space;
-  cp_token *buffer;
-
-  /* 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);
 
   c_common_no_more_pch ();
 
@@ -403,37 +323,50 @@ cp_lexer_new_main (void)
                                   CP_SAVED_TOKEN_STACK);
 
   /* Create the buffer.  */
-  alloc = CP_LEXER_BUFFER_SIZE;
-  buffer = ggc_alloc_vec_cp_token (alloc);
+  lexer->buffer = VEC_alloc (cp_token, gc, CP_LEXER_BUFFER_SIZE);
+
+  return lexer;
+}
+
+
+/* Create a new main C++ lexer, the lexer that gets tokens from the
+   preprocessor.  */
+
+static cp_lexer *
+cp_lexer_new_main (void)
+{
+  cp_lexer *lexer;
+  cp_token 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 (&token);
+
+  lexer = cp_lexer_alloc ();
 
   /* Put the first token in the buffer.  */
-  space = alloc;
-  pos = buffer;
-  *pos = first_token;
+  VEC_quick_push (cp_token, lexer->buffer, &token);
 
   /* Get the remaining tokens from the preprocessor.  */
-  while (pos->type != CPP_EOF)
+  while (token.type != CPP_EOF)
     {
-      pos++;
-      if (!--space)
-       {
-         space = alloc;
-         alloc *= 2;
-         buffer = GGC_RESIZEVEC (cp_token, buffer, alloc);
-         pos = buffer + space;
-       }
-      cp_lexer_get_preprocessor_token (lexer, pos);
+      cp_lexer_get_preprocessor_token (lexer, &token);
+      VEC_safe_push (cp_token, gc, lexer->buffer, &token);
     }
-  lexer->buffer = buffer;
-  lexer->buffer_length = alloc - space;
-  lexer->last_token = pos;
-  lexer->next_token = lexer->buffer_length ? buffer : &eof_token;
+
+  lexer->last_token = VEC_address (cp_token, lexer->buffer)
+                      + VEC_length (cp_token, lexer->buffer)
+                     - 1;
+  lexer->next_token = VEC_length (cp_token, lexer->buffer)
+                     ? VEC_address (cp_token, lexer->buffer)
+                     : &eof_token;
 
   /* Subsequent preprocessor diagnostics should use compiler
      diagnostic functions to get the compiler source location.  */
   done_lexing = true;
 
-  gcc_assert (lexer->next_token->type != CPP_PURGED);
+  gcc_assert (!lexer->next_token->purged_p);
   return lexer;
 }
 
@@ -449,7 +382,6 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
 
   /* We do not own the buffer.  */
   lexer->buffer = NULL;
-  lexer->buffer_length = 0;
   lexer->next_token = first == last ? &eof_token : first;
   lexer->last_token = last;
 
@@ -461,7 +393,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
   lexer->debugging_p = false;
 #endif
 
-  gcc_assert (lexer->next_token->type != CPP_PURGED);
+  gcc_assert (!lexer->next_token->purged_p);
   return lexer;
 }
 
@@ -470,8 +402,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
 static void
 cp_lexer_destroy (cp_lexer *lexer)
 {
-  if (lexer->buffer)
-    ggc_free (lexer->buffer);
+  VEC_free (cp_token, gc, lexer->buffer);
   VEC_free (cp_token_position, heap, lexer->saved_tokens);
   ggc_free (lexer);
 }
@@ -502,6 +433,29 @@ cp_lexer_token_at (cp_lexer *lexer ATTRIBUTE_UNUSED, cp_token_position pos)
   return pos;
 }
 
+static inline void
+cp_lexer_set_token_position (cp_lexer *lexer, cp_token_position pos)
+{
+  lexer->next_token = cp_lexer_token_at (lexer, pos);
+}
+
+static inline cp_token_position
+cp_lexer_previous_token_position (cp_lexer *lexer)
+{
+  if (lexer->next_token == &eof_token)
+    return lexer->last_token - 1;
+  else
+    return cp_lexer_token_position (lexer, true);
+}
+
+static inline cp_token *
+cp_lexer_previous_token (cp_lexer *lexer)
+{
+  cp_token_position tp = cp_lexer_previous_token_position (lexer);
+
+  return cp_lexer_token_at (lexer, tp);
+}
+
 /* nonzero if we are presently saving tokens.  */
 
 static inline int
@@ -526,6 +480,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
                        lexer == NULL ? 0 : C_LEX_STRING_NO_JOIN);
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
+  token->purged_p = false;
 
   /* On some systems, some header files are surrounded by an
      implicit extern "C" block.  Set a flag in the token if it
@@ -565,21 +520,28 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
          token->keyword = RID_MAX;
        }
     }
-  /* Handle Objective-C++ keywords.  */
   else if (token->type == CPP_AT_NAME)
     {
+      /* This only happens in Objective-C++; it must be a keyword.  */
       token->type = CPP_KEYWORD;
       switch (C_RID_CODE (token->u.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;
+         /* Replace 'class' with '@class', 'private' with '@private',
+            etc.  This prevents confusion with the C++ keyword
+            'class', and makes the tokens consistent with other
+            Objective-C 'AT' keywords.  For example '@class' is
+            reported as RID_AT_CLASS which is consistent with
+            '@synchronized', which is reported as
+            RID_AT_SYNCHRONIZED.
+         */
+       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->u.value);
+       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->u.value);
        }
     }
   else if (token->type == CPP_PRAGMA)
@@ -693,6 +655,7 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
     case RID_TYPEOF:
       /* C++0x extensions.  */
     case RID_DECLTYPE:
+    case RID_UNDERLYING_TYPE:
       return true;
 
     default:
@@ -730,7 +693,7 @@ cp_lexer_peek_nth_token (cp_lexer* lexer, size_t n)
          break;
        }
 
-      if (token->type != CPP_PURGED)
+      if (!token->purged_p)
        --n;
     }
 
@@ -764,7 +727,7 @@ cp_lexer_consume_token (cp_lexer* lexer)
        }
 
     }
-  while (lexer->next_token->type == CPP_PURGED);
+  while (lexer->next_token->purged_p);
 
   cp_lexer_set_source_position_from_token (token);
 
@@ -789,7 +752,7 @@ cp_lexer_purge_token (cp_lexer *lexer)
   cp_token *tok = lexer->next_token;
 
   gcc_assert (tok != &eof_token);
-  tok->type = CPP_PURGED;
+  tok->purged_p = true;
   tok->location = UNKNOWN_LOCATION;
   tok->u.value = NULL_TREE;
   tok->keyword = RID_MAX;
@@ -803,7 +766,7 @@ cp_lexer_purge_token (cp_lexer *lexer)
          break;
        }
     }
-  while (tok->type == CPP_PURGED);
+  while (tok->purged_p);
   lexer->next_token = tok;
 }
 
@@ -823,7 +786,7 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
 
   for ( tok += 1; tok != peek; tok += 1)
     {
-      tok->type = CPP_PURGED;
+      tok->purged_p = true;
       tok->location = UNKNOWN_LOCATION;
       tok->u.value = NULL_TREE;
       tok->keyword = RID_MAX;
@@ -889,14 +852,8 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
     "KEYWORD",
     "TEMPLATE_ID",
     "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));
-  fputs (token_names[token->type], stream);
-
   /* For some tokens, print the associated data.  */
   switch (token->type)
     {
@@ -918,7 +875,17 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
       fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
       break;
 
+    case CPP_NUMBER:
+      print_generic_expr (stream, token->u.value, 0);
+      break;
+
     default:
+      /* If we have a name for the token, print it out.  Otherwise, we
+        simply give the numeric code.  */
+      if (token->type < ARRAY_SIZE(token_names))
+       fputs (token_names[token->type], stream);
+      else
+       fprintf (stream, "[%d]", token->type);
       break;
     }
 }
@@ -971,7 +938,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
    VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
 
 static cp_declarator *make_call_declarator
-  (cp_declarator *, tree, cp_cv_quals, tree, tree);
+  (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, tree, tree);
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
@@ -1136,6 +1103,7 @@ cp_declarator *
 make_call_declarator (cp_declarator *target,
                      tree parms,
                      cp_cv_quals cv_qualifiers,
+                     cp_virt_specifiers virt_specifiers,
                      tree exception_specification,
                      tree late_return_type)
 {
@@ -1145,6 +1113,7 @@ make_call_declarator (cp_declarator *target,
   declarator->declarator = target;
   declarator->u.function.parameters = parms;
   declarator->u.function.qualifiers = cv_qualifiers;
+  declarator->u.function.virt_specifiers = virt_specifiers;
   declarator->u.function.exception_specification = exception_specification;
   declarator->u.function.late_return_type = late_return_type;
   if (target)
@@ -1327,7 +1296,10 @@ enum
   CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2,
   /* When parsing a type-specifier, do not try to parse a class-specifier
      or enum-specifier.  */
-  CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4
+  CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4,
+  /* When parsing a decl-specifier-seq, only allow type-specifier or
+     constexpr.  */
+  CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR = 0x8
 };
 
 /* This type is used for parameters and variables which hold
@@ -1380,19 +1352,6 @@ typedef struct cp_parser_binary_operations_map_node
   enum cp_parser_prec prec;
 } cp_parser_binary_operations_map_node;
 
-/* The status of a tentative parse.  */
-
-typedef enum cp_parser_status_kind
-{
-  /* No errors have occurred.  */
-  CP_PARSER_STATUS_KIND_NO_ERROR,
-  /* An error has occurred.  */
-  CP_PARSER_STATUS_KIND_ERROR,
-  /* We are committed to this tentative parse, whether or not an error
-     has occurred.  */
-  CP_PARSER_STATUS_KIND_COMMITTED
-} cp_parser_status_kind;
-
 typedef struct cp_parser_expression_stack_entry
 {
   /* Left hand side of the binary operation we are currently
@@ -1413,21 +1372,6 @@ typedef struct cp_parser_expression_stack_entry
 typedef struct cp_parser_expression_stack_entry
   cp_parser_expression_stack[NUM_PREC_VALUES];
 
-/* Context that is saved and restored when parsing tentatively.  */
-typedef struct GTY (()) cp_parser_context {
-  /* If this is a tentative parsing context, the status of the
-     tentative parse.  */
-  enum cp_parser_status_kind status;
-  /* If non-NULL, we have just seen a `x->' or `x.' expression.  Names
-     that are looked up in this context must be looked up both in the
-     scope given by OBJECT_TYPE (the type of `x' or `*x') and also in
-     the context of the containing expression.  */
-  tree object_type;
-
-  /* The next parsing context in the stack.  */
-  struct cp_parser_context *next;
-} cp_parser_context;
-
 /* Prototypes.  */
 
 /* Constructors and destructors.  */
@@ -1518,174 +1462,6 @@ cp_parser_context_new (cp_parser_context* next)
   return context;
 }
 
-/* An entry in a queue of function arguments that require post-processing.  */
-
-typedef struct GTY(()) cp_default_arg_entry_d {
-  /* The current_class_type when we parsed this arg.  */
-  tree class_type;
-
-  /* The function decl itself.  */
-  tree decl;
-} cp_default_arg_entry;
-
-DEF_VEC_O(cp_default_arg_entry);
-DEF_VEC_ALLOC_O(cp_default_arg_entry,gc);
-
-/* An entry in a stack for member functions of local classes.  */
-
-typedef struct GTY(()) cp_unparsed_functions_entry_d {
-  /* Functions with default arguments that require post-processing.
-     Functions appear in this list in declaration order.  */
-  VEC(cp_default_arg_entry,gc) *funs_with_default_args;
-
-  /* Functions with defintions that require post-processing.  Functions
-     appear in this list in declaration order.  */
-  VEC(tree,gc) *funs_with_definitions;
-} cp_unparsed_functions_entry;
-
-DEF_VEC_O(cp_unparsed_functions_entry);
-DEF_VEC_ALLOC_O(cp_unparsed_functions_entry,gc);
-
-/* The cp_parser structure represents the C++ parser.  */
-
-typedef struct GTY(()) cp_parser {
-  /* The lexer from which we are obtaining tokens.  */
-  cp_lexer *lexer;
-
-  /* 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.  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
-     up sequence.  (If it is not cleared, then `X::Y' followed by `Z'
-     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.   */
-  tree scope;
-
-  /* OBJECT_SCOPE and QUALIFYING_SCOPE give the scopes in which the
-     last lookup took place.  OBJECT_SCOPE is used if an expression
-     like "x->y" or "x.y" was used; it gives the type of "*x" or "x",
-     respectively.  QUALIFYING_SCOPE is used for an expression of the
-     form "X::Y"; it refers to X.  */
-  tree object_scope;
-  tree qualifying_scope;
-
-  /* A stack of parsing contexts.  All but the bottom entry on the
-     stack will be tentative contexts.
-
-     We parse tentatively in order to determine which construct is in
-     use in some situations.  For example, in order to determine
-     whether a statement is an expression-statement or a
-     declaration-statement we parse it tentatively as a
-     declaration-statement.  If that fails, we then reparse the same
-     token stream as an expression-statement.  */
-  cp_parser_context *context;
-
-  /* True if we are parsing GNU C++.  If this flag is not set, then
-     GNU extensions are not recognized.  */
-  bool allow_gnu_extensions_p;
-
-  /* TRUE if the `>' token should be interpreted as the greater-than
-     operator.  FALSE if it is the end of a template-id or
-     template-parameter-list. In C++0x mode, this flag also applies to
-     `>>' tokens, which are viewed as two consecutive `>' tokens when
-     this flag is FALSE.  */
-  bool greater_than_is_operator_p;
-
-  /* TRUE if default arguments are allowed within a parameter list
-     that starts at this point. FALSE if only a gnu extension makes
-     them permissible.  */
-  bool default_arg_ok_p;
-
-  /* TRUE if we are parsing an integral constant-expression.  See
-     [expr.const] for a precise definition.  */
-  bool integral_constant_expression_p;
-
-  /* TRUE if we are parsing an integral constant-expression -- but a
-     non-constant expression should be permitted as well.  This flag
-     is used when parsing an array bound so that GNU variable-length
-     arrays are tolerated.  */
-  bool allow_non_integral_constant_expression_p;
-
-  /* TRUE if ALLOW_NON_CONSTANT_EXPRESSION_P is TRUE and something has
-     been seen that makes the expression non-constant.  */
-  bool non_integral_constant_expression_p;
-
-  /* TRUE if local variable names and `this' are forbidden in the
-     current context.  */
-  bool local_variables_forbidden_p;
-
-  /* TRUE if the declaration we are parsing is part of a
-     linkage-specification of the form `extern string-literal
-     declaration'.  */
-  bool in_unbraced_linkage_specification_p;
-
-  /* TRUE if we are presently parsing a declarator, after the
-     direct-declarator.  */
-  bool in_declarator_p;
-
-  /* TRUE if we are presently parsing a template-argument-list.  */
-  bool in_template_argument_list_p;
-
-  /* Set to IN_ITERATION_STMT if parsing an iteration-statement,
-     to IN_OMP_BLOCK if parsing OpenMP structured block and
-     IN_OMP_FOR if parsing OpenMP loop.  If parsing a switch statement,
-     this is bitwise ORed with IN_SWITCH_STMT, unless parsing an
-     iteration-statement, OpenMP block or loop within that switch.  */
-#define IN_SWITCH_STMT         1
-#define IN_ITERATION_STMT      2
-#define IN_OMP_BLOCK           4
-#define IN_OMP_FOR             8
-#define IN_IF_STMT             16
-  unsigned char in_statement;
-
-  /* TRUE if we are presently parsing the body of a switch statement.
-     Note that this doesn't quite overlap with in_statement above.
-     The difference relates to giving the right sets of error messages:
-     "case not in switch" vs "break statement used with OpenMP...".  */
-  bool in_switch_statement_p;
-
-  /* TRUE if we are parsing a type-id in an expression context.  In
-     such a situation, both "type (expr)" and "type (type)" are valid
-     alternatives.  */
-  bool in_type_id_in_expr_p;
-
-  /* TRUE if we are currently in a header file where declarations are
-     implicitly extern "C".  */
-  bool implicit_extern_c;
-
-  /* TRUE if strings in expressions should be translated to the execution
-     character set.  */
-  bool translate_strings_p;
-
-  /* TRUE if we are presently parsing the body of a function, but not
-     a local class.  */
-  bool in_function_body;
-
-  /* If non-NULL, then we are parsing a construct where new type
-     definitions are not permitted.  The string stored here will be
-     issued as an error message if a type is defined.  */
-  const char *type_definition_forbidden_message;
-
-  /* A stack used for member functions of local classes.  The lists
-     contained in an individual entry can only be processed once the
-     outermost class being defined is complete.  */
-  VEC(cp_unparsed_functions_entry,gc) *unparsed_queues;
-
-  /* The number of classes whose definitions are currently in
-     progress.  */
-  unsigned num_classes_being_defined;
-
-  /* The number of template parameter lists that apply directly to the
-     current declaration.  */
-  unsigned num_template_parameter_lists;
-} cp_parser;
-
 /* Managing the unparsed function queues.  */
 
 #define unparsed_funs_with_default_args \
@@ -1818,7 +1594,7 @@ static void cp_parser_label_for_labeled_statement
 static tree cp_parser_expression_statement
   (cp_parser *, tree);
 static tree cp_parser_compound_statement
-  (cp_parser *, tree, bool);
+  (cp_parser *, tree, bool, bool);
 static void cp_parser_statement_seq_opt
   (cp_parser *, tree);
 static tree cp_parser_selection_statement
@@ -1827,8 +1603,18 @@ static tree cp_parser_condition
   (cp_parser *);
 static tree cp_parser_iteration_statement
   (cp_parser *);
-static void cp_parser_for_init_statement
+static bool cp_parser_for_init_statement
+  (cp_parser *, tree *decl);
+static tree cp_parser_for
   (cp_parser *);
+static tree cp_parser_c_for
+  (cp_parser *, tree, tree);
+static tree cp_parser_range_for
+  (cp_parser *, tree, tree, tree);
+static tree cp_parser_perform_range_for_lookup
+  (tree, tree *, tree *);
+static tree cp_parser_range_for_member_function
+  (tree, tree);
 static tree cp_parser_jump_statement
   (cp_parser *);
 static void cp_parser_declaration_statement
@@ -1848,7 +1634,7 @@ static void cp_parser_declaration
 static void cp_parser_block_declaration
   (cp_parser *, bool);
 static void cp_parser_simple_declaration
-  (cp_parser *, bool);
+  (cp_parser *, bool, tree *);
 static void cp_parser_decl_specifier_seq
   (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *);
 static tree cp_parser_storage_class_specifier_opt
@@ -1898,7 +1684,7 @@ static tree cp_parser_decltype
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
-  (cp_parser *, cp_decl_specifier_seq *, VEC (deferred_access_check,gc)*, bool, bool, int, bool *);
+  (cp_parser *, cp_decl_specifier_seq *, VEC (deferred_access_check,gc)*, bool, bool, int, bool *, tree *);
 static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
 static cp_declarator *cp_parser_direct_declarator
@@ -1907,6 +1693,8 @@ static enum tree_code cp_parser_ptr_operator
   (cp_parser *, tree *, cp_cv_quals *);
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
+static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
+  (cp_parser *);
 static tree cp_parser_late_return_type_opt
   (cp_parser *);
 static tree cp_parser_declarator_id
@@ -2082,9 +1870,19 @@ static tree cp_parser_objc_selector
 static tree cp_parser_objc_protocol_refs_opt
   (cp_parser *);
 static void cp_parser_objc_declaration
-  (cp_parser *);
+  (cp_parser *, tree);
 static tree cp_parser_objc_statement
   (cp_parser *);
+static bool cp_parser_objc_valid_prefix_attributes
+  (cp_parser *, tree *);
+static void cp_parser_objc_at_property_declaration 
+  (cp_parser *) ;
+static void cp_parser_objc_at_synthesize_declaration 
+  (cp_parser *) ;
+static void cp_parser_objc_at_dynamic_declaration
+  (cp_parser *) ;
+static tree cp_parser_objc_struct_declaration
+  (cp_parser *) ;
 
 /* Utility Routines */
 
@@ -2647,6 +2445,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
                                      location_t location)
 {
   tree decl, old_scope;
+  cp_parser_commit_to_tentative_parse (parser);
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
@@ -2674,8 +2473,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
           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
-         && TYPE_BINFO (current_class_type))
+      if (cxx_dialect < cxx0x && id == ridpointers[(int)RID_CONSTEXPR])
+       inform (location, "C++0x %<constexpr%> only available with "
+               "-std=c++0x or -std=gnu++0x");
+      else if (processing_template_decl && current_class_type
+              && TYPE_BINFO (current_class_type))
        {
          tree b;
 
@@ -2737,7 +2539,6 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
       else
        gcc_unreachable ();
     }
-  cp_parser_commit_to_tentative_parse (parser);
 }
 
 /* Check for a common situation where a type-name should be present,
@@ -3194,6 +2995,9 @@ cp_parser_new (void)
   /* We are not parsing a function body.  */
   parser->in_function_body = false;
 
+  /* We can correct until told otherwise.  */
+  parser->colon_corrects_to_scope_p = true;
+
   /* The unparsed function queue is empty.  */
   push_unparsed_function_queues (parser);
 
@@ -3623,7 +3427,7 @@ cp_parser_primary_expression (cp_parser *parser,
                /* Start the statement-expression.  */
                expr = begin_stmt_expr ();
                /* Parse the compound-statement.  */
-               cp_parser_compound_statement (parser, expr, false);
+               cp_parser_compound_statement (parser, expr, false, false);
                /* Finish up.  */
                expr = finish_stmt_expr (expr, false);
              }
@@ -3638,6 +3442,12 @@ cp_parser_primary_expression (cp_parser *parser,
               `&A::B' might be a pointer-to-member, but `&(A::B)' is
               not.  */
            finish_parenthesized_expr (expr);
+           /* DR 705: Wrapping an unqualified name in parentheses
+              suppresses arg-dependent lookup.  We want to pass back
+              CP_ID_KIND_QUALIFIED for suppressing vtable lookup
+              (c++/37862), but none of the others.  */
+           if (*idk != CP_ID_KIND_QUALIFIED)
+             *idk = CP_ID_KIND_NONE;
          }
        /* The `>' token might be the end of a template-id or
           template-parameter-list now.  */
@@ -3654,8 +3464,14 @@ cp_parser_primary_expression (cp_parser *parser,
       if (c_dialect_objc ())
         /* We have an Objective-C++ message. */
         return cp_parser_objc_expression (parser);
-      maybe_warn_cpp0x (CPP0X_LAMBDA_EXPR);
-      return cp_parser_lambda_expression (parser);
+      {
+       tree lam = cp_parser_lambda_expression (parser);
+       /* Don't warn about a failed tentative parse.  */
+       if (cp_parser_error_occurred (parser))
+         return error_mark_node;
+       maybe_warn_cpp0x (CPP0X_LAMBDA_EXPR);
+       return lam;
+      }
 
     case CPP_OBJC_STRING:
       if (c_dialect_objc ())
@@ -3790,6 +3606,7 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_IS_STD_LAYOUT:
        case RID_IS_TRIVIAL:
        case RID_IS_UNION:
+       case RID_IS_LITERAL_TYPE:
          return cp_parser_trait_expr (parser, token->keyword);
 
        /* Objective-C++ expressions.  */
@@ -3880,6 +3697,22 @@ cp_parser_primary_expression (cp_parser *parser,
            if (ambiguous_decls)
              return error_mark_node;
 
+           /* In Objective-C++, we may have an Objective-C 2.0
+              dot-syntax for classes here.  */
+           if (c_dialect_objc ()
+               && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT
+               && TREE_CODE (decl) == TYPE_DECL
+               && objc_is_class_name (decl))
+             {
+               tree component;
+               cp_lexer_consume_token (parser->lexer);
+               component = cp_parser_identifier (parser);
+               if (component == error_mark_node)
+                 return error_mark_node;
+
+               return objc_build_class_component_ref (id_expression, component);
+             }
+
            /* In Objective-C++, an instance variable (ivar) may be preferred
               to whatever cp_parser_lookup_name() found.  */
            decl = objc_lookup_ivar (decl, id_expression);
@@ -4486,6 +4319,16 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
             template-id), nor a `::', then we are not looking at a
             nested-name-specifier.  */
          token = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+         if (token->type == CPP_COLON
+             && parser->colon_corrects_to_scope_p
+             && cp_lexer_peek_nth_token (parser->lexer, 3)->type == CPP_NAME)
+           {
+             error_at (token->location,
+                       "found %<:%> in nested-name-specifier, expected %<::%>");
+             token->type = CPP_SCOPE;
+           }
+
          if (token->type != CPP_SCOPE
              && !cp_parser_nth_token_starts_template_argument_list_p
                  (parser, 2))
@@ -5070,7 +4913,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                postfix_expression
                  = (finish_compound_literal
                     (type, build_constructor (init_list_type_node,
-                                              initializer_list)));
+                                              initializer_list),
+                     tf_warning_or_error));
                break;
              }
          }
@@ -5171,7 +5015,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                        koenig_p = true;
                        if (!any_type_dependent_arguments_p (args))
                          postfix_expression
-                           = perform_koenig_lookup (postfix_expression, args);
+                           = perform_koenig_lookup (postfix_expression, args,
+                                                    /*include_std=*/false);
                      }
                    else
                      postfix_expression
@@ -5195,7 +5040,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                        koenig_p = true;
                        if (!any_type_dependent_arguments_p (args))
                          postfix_expression
-                           = perform_koenig_lookup (postfix_expression, args);
+                           = perform_koenig_lookup (postfix_expression, args,
+                                                    /*include_std=*/false);
                      }
                  }
              }
@@ -5224,7 +5070,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                    = (build_new_method_call
                       (instance, fn, &args, NULL_TREE,
                        (idk == CP_ID_KIND_QUALIFIED
-                        ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
+                        ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
+                        : LOOKUP_NORMAL),
                        /*fn_p=*/NULL,
                        tf_warning_or_error));
                  }
@@ -5803,6 +5650,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
      unary-operator cast-expression
      sizeof unary-expression
      sizeof ( type-id )
+     alignof ( type-id )  [C++0x]
      new-expression
      delete-expression
 
@@ -5812,6 +5660,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
      __extension__ cast-expression
      __alignof__ unary-expression
      __alignof__ ( type-id )
+     alignof unary-expression  [C++0x]
      __real__ cast-expression
      __imag__ cast-expression
      && identifier
@@ -5853,7 +5702,17 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
            if (TYPE_P (operand))
              return cxx_sizeof_or_alignof_type (operand, op, true);
            else
-             return cxx_sizeof_or_alignof_expr (operand, op, true);
+             {
+               /* ISO C++ defines alignof only with types, not with
+                  expressions. So pedwarn if alignof is used with a non-
+                  type expression. However, __alignof__ is ok.  */
+               if (!strcmp (IDENTIFIER_POINTER (token->u.value), "alignof"))
+                 pedwarn (token->location, OPT_pedantic,
+                          "ISO C++ does not allow %<alignof%> "
+                          "with a non-type");
+
+               return cxx_sizeof_or_alignof_expr (operand, op, true);
+             }
          }
 
        case RID_NEW:
@@ -6447,7 +6306,8 @@ cp_parser_delete_expression (cp_parser* parser)
   if (cp_parser_non_integral_constant_expression (parser, NIC_DEL))
     return error_mark_node;
 
-  return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
+  return delete_sanity (expression, NULL_TREE, array_p, global_scope_p,
+                       tf_warning_or_error);
 }
 
 /* Returns true if TOKEN may start a cast-expression and false
@@ -6886,12 +6746,15 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
     }
   else
     {
+      bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+      parser->colon_corrects_to_scope_p = false;
       /* Parse the expression.  */
       c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
       expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
       c_inhibit_evaluation_warnings +=
        ((logical_or_expr == truthvalue_true_node)
         - (logical_or_expr == truthvalue_false_node));
+      parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
     }
 
   /* The next token should be a `:'.  */
@@ -7146,7 +7009,8 @@ cp_parser_constant_expression (cp_parser* parser,
   saved_non_integral_constant_expression_p = parser->non_integral_constant_expression_p;
   /* We are now parsing a constant-expression.  */
   parser->integral_constant_expression_p = true;
-  parser->allow_non_integral_constant_expression_p = allow_non_constant_p;
+  parser->allow_non_integral_constant_expression_p
+    = (allow_non_constant_p || cxx_dialect >= cxx0x);
   parser->non_integral_constant_expression_p = false;
   /* Although the grammar says "conditional-expression", we parse an
      "assignment-expression", which also permits "throw-expression"
@@ -7163,6 +7027,16 @@ cp_parser_constant_expression (cp_parser* parser,
     = saved_integral_constant_expression_p;
   parser->allow_non_integral_constant_expression_p
     = saved_allow_non_integral_constant_expression_p;
+  if (cxx_dialect >= cxx0x)
+    {
+      /* Require an rvalue constant expression here; that's what our
+        callers expect.  Reference constant expressions are handled
+        separately in e.g. cp_parser_template_argument.  */
+      bool is_const = potential_rvalue_constant_expression (expression);
+      parser->non_integral_constant_expression_p = !is_const;
+      if (!is_const && !allow_non_constant_p)
+       require_potential_rvalue_constant_expression (expression);
+    }
   if (allow_non_constant_p)
     *non_constant_p = parser->non_integral_constant_expression_p;
   else if (parser->non_integral_constant_expression_p)
@@ -7268,7 +7142,10 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   return expr;
 }
 
-/* Parse a trait expression.  */
+/* Parse a trait expression.
+
+   Returns a representation of the expression, the underlying type
+   of the type at issue when KEYWORD is RID_UNDERLYING_TYPE.  */
 
 static tree
 cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
@@ -7324,6 +7201,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_ENUM:
       kind = CPTK_IS_ENUM;
       break;
+    case RID_IS_LITERAL_TYPE:
+      kind = CPTK_IS_LITERAL_TYPE;
+      break;
     case RID_IS_POD:
       kind = CPTK_IS_POD;
       break;
@@ -7339,6 +7219,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_UNION:
       kind = CPTK_IS_UNION;
       break;
+    case RID_UNDERLYING_TYPE:
+      kind = CPTK_UNDERLYING_TYPE;
+      break;
     default:
       gcc_unreachable ();
     }
@@ -7383,7 +7266,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 
   /* Complete the trait expression, which may mean either processing
      the trait expr now or saving it for template instantiation.  */
-  return finish_trait_expr (kind, type1, type2);
+  return kind != CPTK_UNDERLYING_TYPE
+    ? finish_trait_expr (kind, type1, type2)
+    : finish_underlying_type (type1);
 }
 
 /* Lambdas that appear in variable initializer or default argument scope
@@ -7784,6 +7669,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
     quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
             ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
     declarator = make_call_declarator (declarator, param_list, quals,
+                                      VIRT_SPEC_UNSPECIFIED,
                                       exception_spec,
                                        /*late_return_type=*/NULL_TREE);
     declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
@@ -8015,7 +7901,7 @@ cp_parser_statement (cp_parser* parser, tree in_statement_expr,
     }
   /* Anything that starts with a `{' must be a compound-statement.  */
   else if (token->type == CPP_OPEN_BRACE)
-    statement = cp_parser_compound_statement (parser, NULL, false);
+    statement = cp_parser_compound_statement (parser, NULL, false, false);
   /* CPP_PRAGMA is a #pragma inside a function body, which constitutes
      a statement all its own.  */
   else if (token->type == CPP_PRAGMA)
@@ -8079,6 +7965,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
 {
   cp_token *token;
   tree label = NULL_TREE;
+  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
 
   /* The next token should be an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -8089,6 +7976,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
       return;
     }
 
+  parser->colon_corrects_to_scope_p = false;
   switch (token->keyword)
     {
     case RID_CASE:
@@ -8167,6 +8055,8 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
       else
        cplus_decl_attributes (&label, attrs, 0);
     }
+
+  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
 }
 
 /* Parse an expression-statement.
@@ -8243,13 +8133,17 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
 
 static tree
 cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
-                             bool in_try)
+                             bool in_try, bool function_body)
 {
   tree compound_stmt;
 
   /* Consume the `{'.  */
   if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
     return error_mark_node;
+  if (DECL_DECLARED_CONSTEXPR_P (current_function_decl)
+      && !function_body)
+    pedwarn (input_location, OPT_pedantic,
+            "compound-statement in constexpr function");
   /* Begin the compound-statement.  */
   compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
   /* If the next keyword is `__label__' we have a label declaration.  */
@@ -8279,10 +8173,13 @@ cp_parser_statement_seq_opt (cp_parser* parser, tree in_statement_expr)
     {
       cp_token *token = cp_lexer_peek_token (parser->lexer);
 
-      /* If we're looking at a `}', then we've run out of statements.  */
+      /* If we are looking at a `}', then we have run out of
+        statements; the same is true if we have reached the end
+        of file, or have stumbled upon a stray '@end'.  */
       if (token->type == CPP_CLOSE_BRACE
          || token->type == CPP_EOF
-         || token->type == CPP_PRAGMA_EOL)
+         || token->type == CPP_PRAGMA_EOL
+         || (token->type == CPP_KEYWORD && token->keyword == RID_AT_END))
        break;
       
       /* If we are in a compound statement and find 'else' then
@@ -8483,6 +8380,7 @@ cp_parser_condition (cp_parser* parser)
 {
   cp_decl_specifier_seq type_specifiers;
   const char *saved_message;
+  int declares_class_or_enum;
 
   /* Try the declaration first.  */
   cp_parser_parse_tentatively (parser);
@@ -8492,9 +8390,10 @@ cp_parser_condition (cp_parser* parser)
   parser->type_definition_forbidden_message
     = G_("types may not be defined in conditions");
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, /*is_declaration==*/true,
-                               /*is_trailing_return=*/false,
-                               &type_specifiers);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR,
+                               &type_specifiers,
+                               &declares_class_or_enum);
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
   /* If all is well, we might be looking at a declaration.  */
@@ -8556,9 +8455,6 @@ cp_parser_condition (cp_parser* parser)
          if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
            maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
 
-         if (!non_constant_p)
-           initializer = fold_non_dependent_expr (initializer);
-
          /* Process the initializer.  */
          cp_finish_decl (decl,
                          initializer, !non_constant_p,
@@ -8580,109 +8476,409 @@ cp_parser_condition (cp_parser* parser)
   return cp_parser_expression (parser, /*cast_p=*/false, NULL);
 }
 
-/* Parse an iteration-statement.
+/* Parses a for-statement or range-for-statement until the closing ')',
+   not included. */
 
-   iteration-statement:
-     while ( condition ) statement
-     do statement while ( expression ) ;
-     for ( for-init-statement condition [opt] ; expression [opt] )
-       statement
+static tree
+cp_parser_for (cp_parser *parser)
+{
+  tree init, scope, decl;
+  bool is_range_for;
+
+  /* Begin the for-statement.  */
+  scope = begin_for_scope (&init);
 
-   Returns the new WHILE_STMT, DO_STMT, or FOR_STMT.  */
+  /* Parse the initialization.  */
+  is_range_for = cp_parser_for_init_statement (parser, &decl);
+
+  if (is_range_for)
+    return cp_parser_range_for (parser, scope, init, decl);
+  else
+    return cp_parser_c_for (parser, scope, init);
+}
 
 static tree
-cp_parser_iteration_statement (cp_parser* parser)
+cp_parser_c_for (cp_parser *parser, tree scope, tree init)
 {
-  cp_token *token;
-  enum rid keyword;
-  tree statement;
-  unsigned char in_statement;
+  /* Normal for loop */
+  tree condition = NULL_TREE;
+  tree expression = NULL_TREE;
+  tree stmt;
 
-  /* Peek at the next token.  */
-  token = cp_parser_require (parser, CPP_KEYWORD, RT_INTERATION);
-  if (!token)
-    return error_mark_node;
+  stmt = begin_for_stmt (scope, init);
+  /* The for-init-statement has already been parsed in
+     cp_parser_for_init_statement, so no work is needed here.  */
+  finish_for_init_stmt (stmt);
 
-  /* Remember whether or not we are already within an iteration
-     statement.  */
-  in_statement = parser->in_statement;
+  /* If there's a condition, process it.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+    condition = cp_parser_condition (parser);
+  finish_for_cond (condition, stmt);
+  /* Look for the `;'.  */
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
-  /* See what kind of keyword it is.  */
-  keyword = token->keyword;
-  switch (keyword)
-    {
-    case RID_WHILE:
-      {
-       tree condition;
+  /* If there's an expression, process it.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+    expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+  finish_for_expr (expression, stmt);
 
-       /* Begin the while-statement.  */
-       statement = begin_while_stmt ();
-       /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
-       /* Parse the condition.  */
-       condition = cp_parser_condition (parser);
-       finish_while_stmt_cond (condition, statement);
-       /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-       /* Parse the dependent statement.  */
-       parser->in_statement = IN_ITERATION_STMT;
-       cp_parser_already_scoped_statement (parser);
-       parser->in_statement = in_statement;
-       /* We're done with the while-statement.  */
-       finish_while_stmt (statement);
-      }
-      break;
+  return stmt;
+}
 
-    case RID_DO:
-      {
-       tree expression;
+/* Tries to parse a range-based for-statement:
 
-       /* Begin the do-statement.  */
-       statement = begin_do_stmt ();
-       /* Parse the body of the do-statement.  */
-       parser->in_statement = IN_ITERATION_STMT;
-       cp_parser_implicitly_scoped_statement (parser, NULL);
-       parser->in_statement = in_statement;
-       finish_do_body (statement);
-       /* Look for the `while' keyword.  */
-       cp_parser_require_keyword (parser, RID_WHILE, RT_WHILE);
-       /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
-       /* Parse the expression.  */
-       expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
-       /* We're done with the do-statement.  */
-       finish_do_stmt (expression, statement);
-       /* Look for the `)'.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-       /* Look for the `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
-      }
-      break;
+  range-based-for:
+    decl-specifier-seq declarator : expression
 
-    case RID_FOR:
-      {
-       tree condition = NULL_TREE;
-       tree expression = NULL_TREE;
+  The decl-specifier-seq declarator and the `:' are already parsed by
+  cp_parser_for_init_statement. If processing_template_decl it returns a
+  newly created RANGE_FOR_STMT; if not, it is converted to a
+  regular FOR_STMT.  */
 
-       /* Begin the for-statement.  */
-       statement = begin_for_stmt ();
-       /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
-       /* Parse the initialization.  */
-       cp_parser_for_init_statement (parser);
-       finish_for_init_stmt (statement);
-
-       /* If there's a condition, process it.  */
-       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-         condition = cp_parser_condition (parser);
-       finish_for_cond (condition, statement);
-       /* Look for the `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+static tree
+cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
+{
+  tree stmt, range_expr;
+
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+    {
+      bool expr_non_constant_p;
+      range_expr = cp_parser_braced_list (parser, &expr_non_constant_p);
+    }
+  else
+    range_expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+
+  /* If in template, STMT is converted to a normal for-statement
+     at instantiation. If not, it is done just ahead. */
+  if (processing_template_decl)
+    {
+      stmt = begin_range_for_stmt (scope, init);
+      finish_range_for_decl (stmt, range_decl, range_expr);
+    }
+  else
+    {
+      stmt = begin_for_stmt (scope, init);
+      stmt = cp_convert_range_for (stmt, range_decl, range_expr);
+    }
+  return stmt;
+}
+
+/* Converts a range-based for-statement into a normal
+   for-statement, as per the definition.
+
+      for (RANGE_DECL : RANGE_EXPR)
+       BLOCK
+
+   should be equivalent to:
+
+      {
+       auto &&__range = RANGE_EXPR;
+       for (auto __begin = BEGIN_EXPR, end = END_EXPR;
+             __begin != __end;
+             ++__begin)
+         {
+             RANGE_DECL = *__begin;
+             BLOCK
+         }
+      }
+
+   If RANGE_EXPR is an array:
+       BEGIN_EXPR = __range
+       END_EXPR = __range + ARRAY_SIZE(__range)
+   Else if RANGE_EXPR has a member 'begin' or 'end':
+       BEGIN_EXPR = __range.begin()
+       END_EXPR = __range.end()
+   Else:
+       BEGIN_EXPR = begin(__range)
+       END_EXPR = end(__range);
+
+   If __range has a member 'begin' but not 'end', or vice versa, we must
+   still use the second alternative (it will surely fail, however).
+   When calling begin()/end() in the third alternative we must use
+   argument dependent lookup, but always considering 'std' as an associated
+   namespace.  */
+
+tree
+cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
+{
+  tree range_type, range_temp;
+  tree begin, end;
+  tree iter_type, begin_expr, end_expr;
+  tree condition, expression;
+
+  if (range_decl == error_mark_node || range_expr == error_mark_node)
+    /* If an error happened previously do nothing or else a lot of
+       unhelpful errors would be issued.  */
+    begin_expr = end_expr = iter_type = error_mark_node;
+  else
+    {
+      /* Find out the type deduced by the declaration
+         `auto &&__range = range_expr'.  */
+      range_type = cp_build_reference_type (make_auto (), true);
+      range_type = do_auto_deduction (range_type, range_expr,
+                                     type_uses_auto (range_type));
+
+      /* Create the __range variable.  */
+      range_temp = build_decl (input_location, VAR_DECL,
+                              get_identifier ("__for_range"), range_type);
+      TREE_USED (range_temp) = 1;
+      DECL_ARTIFICIAL (range_temp) = 1;
+      pushdecl (range_temp);
+      cp_finish_decl (range_temp, range_expr,
+                     /*is_constant_init*/false, NULL_TREE,
+                     LOOKUP_ONLYCONVERTING);
+
+      range_temp = convert_from_reference (range_temp);
+      iter_type = cp_parser_perform_range_for_lookup (range_temp,
+                                                     &begin_expr, &end_expr);
+    }
+
+  /* The new for initialization statement.  */
+  begin = build_decl (input_location, VAR_DECL,
+                     get_identifier ("__for_begin"), iter_type);
+  TREE_USED (begin) = 1;
+  DECL_ARTIFICIAL (begin) = 1;
+  pushdecl (begin);
+  cp_finish_decl (begin, begin_expr,
+                 /*is_constant_init*/false, NULL_TREE,
+                 LOOKUP_ONLYCONVERTING);
+
+  end = build_decl (input_location, VAR_DECL,
+                   get_identifier ("__for_end"), iter_type);
+  TREE_USED (end) = 1;
+  DECL_ARTIFICIAL (end) = 1;
+  pushdecl (end);
+  cp_finish_decl (end, end_expr,
+                 /*is_constant_init*/false, NULL_TREE,
+                 LOOKUP_ONLYCONVERTING);
+
+  finish_for_init_stmt (statement);
+
+  /* The new for condition.  */
+  condition = build_x_binary_op (NE_EXPR,
+                                begin, ERROR_MARK,
+                                end, ERROR_MARK,
+                                NULL, tf_warning_or_error);
+  finish_for_cond (condition, statement);
+
+  /* The new increment expression.  */
+  expression = finish_unary_op_expr (PREINCREMENT_EXPR, begin);
+  finish_for_expr (expression, statement);
+
+  /* The declaration is initialized with *__begin inside the loop body.  */
+  cp_finish_decl (range_decl,
+                 build_x_indirect_ref (begin, RO_NULL, tf_warning_or_error),
+                 /*is_constant_init*/false, NULL_TREE,
+                 LOOKUP_ONLYCONVERTING);
+
+  return statement;
+}
+
+/* Solves BEGIN_EXPR and END_EXPR as described in cp_convert_range_for.
+   We need to solve both at the same time because the method used
+   depends on the existence of members begin or end.
+   Returns the type deduced for the iterator expression.  */
+
+static tree
+cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
+{
+  if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (range))))
+    {
+      error ("range-based %<for%> expression of type %qT "
+            "has incomplete type", TREE_TYPE (range));
+      *begin = *end = error_mark_node;
+      return error_mark_node;
+    }
+  if (TREE_CODE (TREE_TYPE (range)) == ARRAY_TYPE)
+    {
+      /* If RANGE is an array, we will use pointer arithmetic.  */
+      *begin = range;
+      *end = build_binary_op (input_location, PLUS_EXPR,
+                             range,
+                             array_type_nelts_top (TREE_TYPE (range)),
+                             0);
+      return build_pointer_type (TREE_TYPE (TREE_TYPE (range)));
+    }
+  else
+    {
+      /* If it is not an array, we must do a bit of magic.  */
+      tree id_begin, id_end;
+      tree member_begin, member_end;
+
+      *begin = *end = error_mark_node;
+
+      id_begin = get_identifier ("begin");
+      id_end = get_identifier ("end");
+      member_begin = lookup_member (TREE_TYPE (range), id_begin,
+                                   /*protect=*/2, /*want_type=*/false);
+      member_end = lookup_member (TREE_TYPE (range), id_end,
+                                 /*protect=*/2, /*want_type=*/false);
+
+      if (member_begin != NULL_TREE || member_end != NULL_TREE)
+       {
+         /* Use the member functions.  */
+         if (member_begin != NULL_TREE)
+           *begin = cp_parser_range_for_member_function (range, id_begin);
+         else
+           error ("range-based %<for%> expression of type %qT has an "
+                  "%<end%> member but not a %<begin%>", TREE_TYPE (range));
+
+         if (member_end != NULL_TREE)
+           *end = cp_parser_range_for_member_function (range, id_end);
+         else
+           error ("range-based %<for%> expression of type %qT has a "
+                  "%<begin%> member but not an %<end%>", TREE_TYPE (range));
+       }
+      else
+       {
+         /* Use global functions with ADL.  */
+         VEC(tree,gc) *vec;
+         vec = make_tree_vector ();
+
+         VEC_safe_push (tree, gc, vec, range);
+
+         member_begin = perform_koenig_lookup (id_begin, vec,
+                                               /*include_std=*/true);
+         *begin = finish_call_expr (member_begin, &vec, false, true,
+                                    tf_warning_or_error);
+         member_end = perform_koenig_lookup (id_end, vec,
+                                             /*include_std=*/true);
+         *end = finish_call_expr (member_end, &vec, false, true,
+                                  tf_warning_or_error);
+
+         release_tree_vector (vec);
+       }
+
+      /* Last common checks.  */
+      if (*begin == error_mark_node || *end == error_mark_node)
+       {
+         /* If one of the expressions is an error do no more checks.  */
+         *begin = *end = error_mark_node;
+         return error_mark_node;
+       }
+      else
+       {
+         tree iter_type = cv_unqualified (TREE_TYPE (*begin));
+         /* The unqualified type of the __begin and __end temporaries should
+            be the same, as required by the multiple auto declaration.  */
+         if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
+           error ("inconsistent begin/end types in range-based %<for%> "
+                  "statement: %qT and %qT",
+                  TREE_TYPE (*begin), TREE_TYPE (*end));
+         return iter_type;
+       }
+    }
+}
+
+/* Helper function for cp_parser_perform_range_for_lookup.
+   Builds a tree for RANGE.IDENTIFIER().  */
+
+static tree
+cp_parser_range_for_member_function (tree range, tree identifier)
+{
+  tree member, res;
+  VEC(tree,gc) *vec;
+
+  member = finish_class_member_access_expr (range, identifier,
+                                           false, tf_warning_or_error);
+  if (member == error_mark_node)
+    return error_mark_node;
+
+  vec = make_tree_vector ();
+  res = finish_call_expr (member, &vec,
+                         /*disallow_virtual=*/false,
+                         /*koenig_p=*/false,
+                         tf_warning_or_error);
+  release_tree_vector (vec);
+  return res;
+}
+
+/* Parse an iteration-statement.
+
+   iteration-statement:
+     while ( condition ) statement
+     do statement while ( expression ) ;
+     for ( for-init-statement condition [opt] ; expression [opt] )
+       statement
+
+   Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT.  */
+
+static tree
+cp_parser_iteration_statement (cp_parser* parser)
+{
+  cp_token *token;
+  enum rid keyword;
+  tree statement;
+  unsigned char in_statement;
+
+  /* Peek at the next token.  */
+  token = cp_parser_require (parser, CPP_KEYWORD, RT_INTERATION);
+  if (!token)
+    return error_mark_node;
+
+  /* Remember whether or not we are already within an iteration
+     statement.  */
+  in_statement = parser->in_statement;
+
+  /* See what kind of keyword it is.  */
+  keyword = token->keyword;
+  switch (keyword)
+    {
+    case RID_WHILE:
+      {
+       tree condition;
+
+       /* Begin the while-statement.  */
+       statement = begin_while_stmt ();
+       /* Look for the `('.  */
+       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+       /* Parse the condition.  */
+       condition = cp_parser_condition (parser);
+       finish_while_stmt_cond (condition, statement);
+       /* Look for the `)'.  */
+       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+       /* Parse the dependent statement.  */
+       parser->in_statement = IN_ITERATION_STMT;
+       cp_parser_already_scoped_statement (parser);
+       parser->in_statement = in_statement;
+       /* We're done with the while-statement.  */
+       finish_while_stmt (statement);
+      }
+      break;
+
+    case RID_DO:
+      {
+       tree expression;
+
+       /* Begin the do-statement.  */
+       statement = begin_do_stmt ();
+       /* Parse the body of the do-statement.  */
+       parser->in_statement = IN_ITERATION_STMT;
+       cp_parser_implicitly_scoped_statement (parser, NULL);
+       parser->in_statement = in_statement;
+       finish_do_body (statement);
+       /* Look for the `while' keyword.  */
+       cp_parser_require_keyword (parser, RID_WHILE, RT_WHILE);
+       /* Look for the `('.  */
+       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+       /* Parse the expression.  */
+       expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+       /* We're done with the do-statement.  */
+       finish_do_stmt (expression, statement);
+       /* Look for the `)'.  */
+       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+       /* Look for the `;'.  */
+       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+      }
+      break;
+
+    case RID_FOR:
+      {
+       /* Look for the `('.  */
+       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+
+       statement = cp_parser_for (parser);
 
-       /* If there's an expression, process it.  */
-       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
-         expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
-       finish_for_expr (expression, statement);
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
@@ -8705,14 +8901,15 @@ cp_parser_iteration_statement (cp_parser* parser)
   return statement;
 }
 
-/* Parse a for-init-statement.
+/* Parse a for-init-statement or the declarator of a range-based-for.
+   Returns true if a range-based-for declaration is seen.
 
    for-init-statement:
      expression-statement
      simple-declaration  */
 
-static void
-cp_parser_for_init_statement (cp_parser* parser)
+static bool
+cp_parser_for_init_statement (cp_parser* parser, tree *decl)
 {
   /* If the next token is a `;', then we have an empty
      expression-statement.  Grammatically, this is also a
@@ -8722,19 +8919,45 @@ cp_parser_for_init_statement (cp_parser* parser)
      declaration.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     {
+      bool is_range_for = false;
+      bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+
+      parser->colon_corrects_to_scope_p = false;
+
       /* We're going to speculatively look for a declaration, falling back
         to an expression, if necessary.  */
       cp_parser_parse_tentatively (parser);
       /* Parse the declaration.  */
       cp_parser_simple_declaration (parser,
-                                   /*function_definition_allowed_p=*/false);
+                                   /*function_definition_allowed_p=*/false,
+                                   decl);
+      parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+       {
+         /* It is a range-for, consume the ':' */
+         cp_lexer_consume_token (parser->lexer);
+         is_range_for = true;
+         if (cxx_dialect < cxx0x)
+           {
+             error_at (cp_lexer_peek_token (parser->lexer)->location,
+                       "range-based %<for%> loops are not allowed "
+                       "in C++98 mode");
+             *decl = error_mark_node;
+           }
+       }
+      else
+         /* The ';' is not consumed yet because we told
+            cp_parser_simple_declaration not to.  */
+         cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+
+      if (cp_parser_parse_definitely (parser))
+       return is_range_for;
       /* If the tentative parse failed, then we shall need to look for an
         expression-statement.  */
-      if (cp_parser_parse_definitely (parser))
-       return;
     }
-
+  /* If we are here, it is an expression-statement.  */
   cp_parser_expression_statement (parser, NULL_TREE);
+  return false;
 }
 
 /* Parse a jump-statement.
@@ -8915,7 +9138,7 @@ cp_parser_implicitly_scoped_statement (cp_parser* parser, bool *if_p)
     }
   /* 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);
+    statement = cp_parser_compound_statement (parser, NULL, false, false);
   /* If the token is not a `{', then we must take special action.  */
   else
     {
@@ -9039,6 +9262,7 @@ cp_parser_declaration (cp_parser* parser)
   cp_token token2;
   int saved_pedantic;
   void *p;
+  tree attributes = NULL_TREE;
 
   /* Check for the `__extension__' keyword.  */
   if (cp_parser_extension_opt (parser, &saved_pedantic))
@@ -9116,7 +9340,11 @@ cp_parser_declaration (cp_parser* parser)
     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);
+    cp_parser_objc_declaration (parser, NULL_TREE);
+  else if (c_dialect_objc ()
+          && token1.keyword == RID_ATTRIBUTE
+          && cp_parser_objc_valid_prefix_attributes (parser, &attributes))
+    cp_parser_objc_declaration (parser, attributes);
   /* We must have either a block declaration or a function
      definition.  */
   else
@@ -9216,7 +9444,8 @@ cp_parser_block_declaration (cp_parser *parser,
     cp_parser_static_assert (parser, /*member_p=*/false);
   /* Anything else must be a simple-declaration.  */
   else
-    cp_parser_simple_declaration (parser, !statement_p);
+    cp_parser_simple_declaration (parser, !statement_p,
+                                 /*maybe_range_for_decl*/NULL);
 }
 
 /* Parse a simple-declaration.
@@ -9229,16 +9458,25 @@ cp_parser_block_declaration (cp_parser *parser,
      init-declarator-list , init-declarator
 
    If FUNCTION_DEFINITION_ALLOWED_P is TRUE, then we also recognize a
-   function-definition as a simple-declaration.  */
+   function-definition as a simple-declaration.
+
+   If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the
+   parsed declaration if it is an uninitialized single declarator not followed
+   by a `;', or to error_mark_node otherwise. Either way, the trailing `;',
+   if present, will not be consumed.  */
 
 static void
 cp_parser_simple_declaration (cp_parser* parser,
-                             bool function_definition_allowed_p)
+                             bool function_definition_allowed_p,
+                             tree *maybe_range_for_decl)
 {
   cp_decl_specifier_seq decl_specifiers;
   int declares_class_or_enum;
   bool saw_declarator;
 
+  if (maybe_range_for_decl)
+    *maybe_range_for_decl = NULL_TREE;
+
   /* Defer access checks until we know what is being declared; the
      checks for names appearing in the decl-specifier-seq should be
      done as if we were in the scope of the thing being declared.  */
@@ -9313,6 +9551,8 @@ cp_parser_simple_declaration (cp_parser* parser,
          token = cp_lexer_peek_token (parser->lexer);
          gcc_assert (token->type == CPP_COMMA);
          cp_lexer_consume_token (parser->lexer);
+         if (maybe_range_for_decl)
+           *maybe_range_for_decl = error_mark_node;
        }
       else
        saw_declarator = true;
@@ -9323,7 +9563,8 @@ cp_parser_simple_declaration (cp_parser* parser,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
                                        declares_class_or_enum,
-                                       &function_definition_p);
+                                       &function_definition_p,
+                                       maybe_range_for_decl);
       /* If an error occurred while parsing tentatively, exit quickly.
         (That usually happens when in the body of a function; each
         statement is treated as a declaration-statement until proven
@@ -9353,13 +9594,15 @@ cp_parser_simple_declaration (cp_parser* parser,
              return;
            }
        }
+      if (maybe_range_for_decl && *maybe_range_for_decl == NULL_TREE)
+       *maybe_range_for_decl = decl;
       /* The next token should be either a `,' or a `;'.  */
       token = cp_lexer_peek_token (parser->lexer);
       /* If it's a `,', there are more declarators to come.  */
       if (token->type == CPP_COMMA)
        /* will be consumed next time around */;
       /* If it's a `;', we are done.  */
-      else if (token->type == CPP_SEMICOLON)
+      else if (token->type == CPP_SEMICOLON || maybe_range_for_decl)
        break;
       /* Anything else is an error.  */
       else
@@ -9397,7 +9640,8 @@ cp_parser_simple_declaration (cp_parser* parser,
     }
 
   /* Consume the `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+  if (!maybe_range_for_decl)
+      cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
  done:
   pop_deferring_access_checks ();
@@ -9576,6 +9820,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
          break;
        }
 
+      if (found_decl_spec
+         && (flags & CP_PARSER_FLAGS_ONLY_TYPE_OR_CONSTEXPR)
+         && token->keyword != RID_CONSTEXPR)
+       error ("decl-specifier invalid in condition");
+
       /* Constructors are a special case.  The `S' in `S()' is not a
         decl-specifier; it is the beginning of the declarator.  */
       constructor_p
@@ -9827,6 +10076,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
   tree message;
   cp_token *token;
   location_t saved_loc;
+  bool dummy;
 
   /* Peek at the `static_assert' token so we can keep track of exactly
      where the static assertion started.  */
@@ -9846,11 +10096,12 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
   /* Parse the `(' starting the static assertion condition.  */
   cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
-  /* Parse the constant-expression.  */
+  /* Parse the constant-expression.  Allow a non-constant expression
+     here in order to give better diagnostics in finish_static_assert.  */
   condition = 
     cp_parser_constant_expression (parser,
-                                   /*allow_non_constant_p=*/false,
-                                   /*non_constant_p=*/NULL);
+                                   /*allow_non_constant_p=*/true,
+                                   /*non_constant_p=*/&dummy);
 
   /* Parse the separating `,'.  */
   cp_parser_require (parser, CPP_COMMA, RT_COMMA);
@@ -10058,7 +10309,8 @@ cp_parser_decltype (cp_parser *parser)
       return error_mark_node;
     }
 
-  return finish_decltype_type (expr, id_expression_or_member_access_p);
+  return finish_decltype_type (expr, id_expression_or_member_access_p,
+                              tf_warning_or_error);
 }
 
 /* Special member functions [gram.special] */
@@ -10751,6 +11003,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
   tree parameter_list = NULL_TREE;
 
   begin_template_parm_list ();
+
+  /* The loop below parses the template parms.  We first need to know
+     the total number of template parms to be able to compute proper
+     canonical types of each dependent type. So after the loop, when
+     we know the total number of template parms,
+     end_template_parm_list computes the proper canonical types and
+     fixes up the dependent types accordingly.  */
   while (true)
     {
       tree parameter;
@@ -10769,11 +11028,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
                                                parm_loc,
                                                parameter,
                                                is_non_type,
-                                                is_parameter_pack);
+                                               is_parameter_pack,
+                                               0);
       else
        {
          tree err_parm = build_tree_list (parameter, parameter);
-         TREE_VALUE (err_parm) = error_mark_node;
          parameter_list = chainon (parameter_list, err_parm);
        }
 
@@ -11899,6 +12158,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
 
+  timevar_push (TV_TEMPLATE_INST);
+
   /* Look for an (optional) storage-class-specifier or
      function-specifier.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
@@ -11956,6 +12217,13 @@ cp_parser_explicit_instantiation (cp_parser* parser)
                                                       decl_specifiers.type_location);
       if (declarator != cp_error_declarator)
        {
+         if (decl_specifiers.specs[(int)ds_inline])
+           permerror (input_location, "explicit instantiation shall not use"
+                      " %<inline%> specifier");
+         if (decl_specifiers.specs[(int)ds_constexpr])
+           permerror (input_location, "explicit instantiation shall not use"
+                      " %<constexpr%> specifier");
+
          decl = grokdeclarator (declarator, &decl_specifiers,
                                 NORMAL, 0, &decl_specifiers.attributes);
          /* Turn access control back on for names used during
@@ -11975,6 +12243,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   end_explicit_instantiation ();
 
   cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+  timevar_pop (TV_TEMPLATE_INST);
 }
 
 /* Parse an explicit-specialization.
@@ -12261,6 +12531,7 @@ cp_parser_type_specifier (cp_parser* parser,
      decltype ( expression )   
      char16_t
      char32_t
+     __underlying_type ( type-id )
 
    GNU Extension:
 
@@ -12377,6 +12648,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
       return type;
 
+    case RID_UNDERLYING_TYPE:
+      type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
+
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     token->location,
+                                     /*user_defined_p=*/true);
+
+      return type;
+
     default:
       break;
     }
@@ -12478,15 +12759,15 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       return error_mark_node;
     }
 
-  /* There is no valid C++ program where a non-template type is
-     followed by a "<".  That usually indicates that the user thought
-     that the type was a template.  */
   if (type && type != error_mark_node)
     {
-      /* 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 ()
+      /* See if TYPE is an Objective-C type, and if so, parse and
+        accept any protocol references following it.  Do this before
+        the cp_parser_check_for_invalid_template_id() call, because
+        Objective-C types can be followed by '<...>' which would
+        enclose protocol names rather than template arguments, and so
+        everything is fine.  */
+      if (c_dialect_objc () && !parser->scope
          && (objc_is_id (type) || objc_is_class_name (type)))
        {
          tree protos = cp_parser_objc_protocol_refs_opt (parser);
@@ -12500,6 +12781,9 @@ cp_parser_simple_type_specifier (cp_parser* parser,
          return qual_type;
        }
 
+      /* There is no valid C++ program where a non-template type is
+        followed by a "<".  That usually indicates that the user
+        thought that the type was a template.  */
       cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type),
                                               token->location);
     }
@@ -12580,9 +12864,17 @@ cp_parser_nonclass_name (cp_parser* parser)
       if (type)
        type_decl = TYPE_NAME (type);
     }
-  
+
   /* Issue an error if we did not find a type-name.  */
-  if (TREE_CODE (type_decl) != TYPE_DECL)
+  if (TREE_CODE (type_decl) != TYPE_DECL
+      /* In Objective-C, we have the complication that class names are
+        normally type names and start declarations (eg, the
+        "NSObject" in "NSObject *object;"), but can be used in an
+        Objective-C 2.0 dot-syntax (as in "NSObject.version") which
+        is an expression.  So, a classname followed by a dot is not a
+        valid type-name.  */
+      || (objc_is_class_name (TREE_TYPE (type_decl))
+         && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT))
     {
       if (!cp_parser_simulate_error (parser))
        cp_parser_name_lookup_error (parser, identifier, type_decl,
@@ -12645,17 +12937,17 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       cp_lexer_consume_token (parser->lexer);
       /* Remember that it's an enumeration type.  */
       tag_type = enum_type;
-      /* Parse the optional `struct' or `class' key (for C++0x scoped
-         enums).  */
+      /* Issue a warning if the `struct' or `class' key (for C++0x scoped
+        enums) is used here.  */
       if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS)
-          || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
-        {
-          if (cxx_dialect == cxx98)
-            maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
-
-          /* Consume the `struct' or `class'.  */
-          cp_lexer_consume_token (parser->lexer);
-        }
+         || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
+       {
+           pedwarn (input_location, 0, "elaborated-type-specifier "
+                     "for a scoped enum must not use the %<%D%> keyword",
+                     cp_lexer_peek_token (parser->lexer)->u.value);
+         /* Consume the `struct' or `class' and parse it anyway.  */
+         cp_lexer_consume_token (parser->lexer);
+       }
       /* Parse the attributes.  */
       attributes = cp_parser_attributes_opt (parser);
     }
@@ -12945,7 +13237,11 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 /* Parse an enum-specifier.
 
    enum-specifier:
-     enum-key identifier [opt] enum-base [opt] { enumerator-list [opt] }
+     enum-head { enumerator-list [opt] }
+
+   enum-head:
+     enum-key identifier [opt] enum-base [opt]
+     enum-key nested-name-specifier identifier enum-base [opt]
 
    enum-key:
      enum
@@ -12955,6 +13251,9 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
    enum-base:   [C++0x]
      : type-specifier-seq
 
+   opaque-enum-specifier:
+     enum-key identifier enum-base [opt] ;
+
    GNU Extensions:
      enum-key attributes[opt] identifier [opt] enum-base [opt] 
        { enumerator-list [opt] }attributes[opt]
@@ -12966,11 +13265,21 @@ static tree
 cp_parser_enum_specifier (cp_parser* parser)
 {
   tree identifier;
-  tree type;
+  tree type = NULL_TREE;
+  tree prev_scope;
+  tree nested_name_specifier = NULL_TREE;
   tree attributes;
   bool scoped_enum_p = false;
   bool has_underlying_type = false;
+  bool nested_being_defined = false;
+  bool new_value_list = false;
+  bool is_new_type = false;
+  bool is_anonymous = false;
   tree underlying_type = NULL_TREE;
+  cp_token *type_start_token = NULL;
+  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
+
+  parser->colon_corrects_to_scope_p = false;
 
   /* Parse tentatively so that we can back up if we don't find a
      enum-specifier.  */
@@ -12987,7 +13296,7 @@ cp_parser_enum_specifier (cp_parser* parser)
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS)
       || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
     {
-      if (cxx_dialect == cxx98)
+      if (cxx_dialect < cxx0x)
         maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
 
       /* Consume the `struct' or `class' token.  */
@@ -12998,10 +13307,65 @@ cp_parser_enum_specifier (cp_parser* parser)
 
   attributes = cp_parser_attributes_opt (parser);
 
-  if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
-    identifier = cp_parser_identifier (parser);
+  /* Clear the qualification.  */
+  parser->scope = NULL_TREE;
+  parser->qualifying_scope = NULL_TREE;
+  parser->object_scope = NULL_TREE;
+
+  /* Figure out in what scope the declaration is being placed.  */
+  prev_scope = current_scope ();
+
+  type_start_token = cp_lexer_peek_token (parser->lexer);
+
+  push_deferring_access_checks (dk_no_check);
+  nested_name_specifier
+      = cp_parser_nested_name_specifier_opt (parser,
+                                            /*typename_keyword_p=*/true,
+                                            /*check_dependency_p=*/false,
+                                            /*type_p=*/false,
+                                            /*is_declaration=*/false);
+
+  if (nested_name_specifier)
+    {
+      tree name;
+
+      identifier = cp_parser_identifier (parser);
+      name =  cp_parser_lookup_name (parser, identifier,
+                                    enum_type,
+                                    /*is_template=*/false,
+                                    /*is_namespace=*/false,
+                                    /*check_dependency=*/true,
+                                    /*ambiguous_decls=*/NULL,
+                                    input_location);
+      if (name)
+       {
+         type = TREE_TYPE (name);
+         if (TREE_CODE (type) == TYPENAME_TYPE)
+           {
+             /* Are template enums allowed in ISO? */
+             if (template_parm_scope_p ())
+               pedwarn (type_start_token->location, OPT_pedantic,
+                        "%qD is an enumeration template", name);
+             /* ignore a typename reference, for it will be solved by name
+                in start_enum.  */
+             type = NULL_TREE;
+           }
+       }
+      else
+       error_at (type_start_token->location,
+                 "%qD is not an enumerator-name", identifier);
+    }
   else
-    identifier = make_anon_name ();
+    {
+      if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
+       identifier = cp_parser_identifier (parser);
+      else
+       {
+         identifier = make_anon_name ();
+         is_anonymous = true;
+       }
+    }
+  pop_deferring_access_checks ();
 
   /* Check for the `:' that denotes a specified underlying type in C++0x.
      Note that a ':' could also indicate a bitfield width, however.  */
@@ -13021,7 +13385,7 @@ cp_parser_enum_specifier (cp_parser* parser)
       if (!cp_parser_parse_definitely (parser))
        return NULL_TREE;
 
-      if (cxx_dialect == cxx98)
+      if (cxx_dialect < cxx0x)
         maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
 
       has_underlying_type = true;
@@ -13039,38 +13403,137 @@ cp_parser_enum_specifier (cp_parser* parser)
   /* Look for the `{' but don't consume it yet.  */
   if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
-      cp_parser_error (parser, "expected %<{%>");
-      if (has_underlying_type)
-       return NULL_TREE;
+      if (cxx_dialect < cxx0x || (!scoped_enum_p && !underlying_type))
+       {
+         cp_parser_error (parser, "expected %<{%>");
+         if (has_underlying_type)
+           {
+             type = NULL_TREE;
+             goto out;
+           }
+       }
+      /* An opaque-enum-specifier must have a ';' here.  */
+      if ((scoped_enum_p || underlying_type)
+         && cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+       {
+         cp_parser_error (parser, "expected %<;%> or %<{%>");
+         if (has_underlying_type)
+           {
+             type = NULL_TREE;
+             goto out;
+           }
+       }
     }
 
   if (!has_underlying_type && !cp_parser_parse_definitely (parser))
     return NULL_TREE;
 
-  /* Issue an error message if type-definitions are forbidden here.  */
-  if (!cp_parser_check_type_definition (parser))
-    type = error_mark_node;
-  else
-    /* Create the new type.  We do this before consuming the opening
+  if (nested_name_specifier)
+    {
+      if (CLASS_TYPE_P (nested_name_specifier))
+       {
+         nested_being_defined = TYPE_BEING_DEFINED (nested_name_specifier);
+         TYPE_BEING_DEFINED (nested_name_specifier) = 1;
+         push_scope (nested_name_specifier);
+       }
+      else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL)
+       {
+         push_nested_namespace (nested_name_specifier);
+       }
+    }
+
+  /* Issue an error message if type-definitions are forbidden here.  */
+  if (!cp_parser_check_type_definition (parser))
+    type = error_mark_node;
+  else
+    /* Create the new type.  We do this before consuming the opening
        brace so the enum will be recorded as being on the line of its
        tag (or the 'enum' keyword, if there is no tag).  */
-    type = start_enum (identifier, underlying_type, scoped_enum_p);
-  
-  /* Consume the opening brace.  */
-  cp_lexer_consume_token (parser->lexer);
+    type = start_enum (identifier, type, underlying_type,
+                      scoped_enum_p, &is_new_type);
 
-  if (type == error_mark_node)
+  /* If the next token is not '{' it is an opaque-enum-specifier or an
+     elaborated-type-specifier.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
-      cp_parser_skip_to_end_of_block_or_statement (parser);
-      return error_mark_node;
-    }
+      timevar_push (TV_PARSE_ENUM);
+      if (nested_name_specifier)
+       {
+         /* The following catches invalid code such as:
+            enum class S<int>::E { A, B, C }; */
+         if (!processing_specialization
+             && CLASS_TYPE_P (nested_name_specifier)
+             && CLASSTYPE_USE_TEMPLATE (nested_name_specifier))
+           error_at (type_start_token->location, "cannot add an enumerator "
+                     "list to a template instantiation");
+
+         /* If that scope does not contain the scope in which the
+            class was originally declared, the program is invalid.  */
+         if (prev_scope && !is_ancestor (prev_scope, nested_name_specifier))
+           {
+             if (at_namespace_scope_p ())
+               error_at (type_start_token->location,
+                         "declaration of %qD in namespace %qD which does not "
+                         "enclose %qD",
+                         type, prev_scope, nested_name_specifier);
+             else
+               error_at (type_start_token->location,
+                         "declaration of %qD in %qD which does not enclose %qD",
+                         type, prev_scope, nested_name_specifier);
+             type = error_mark_node;
+           }
+       }
 
-  /* If the next token is not '}', then there are some enumerators.  */
-  if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
-    cp_parser_enumerator_list (parser, type);
+      if (scoped_enum_p)
+       begin_scope (sk_scoped_enum, type);
 
-  /* Consume the final '}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+      /* Consume the opening brace.  */
+      cp_lexer_consume_token (parser->lexer);
+
+      if (type == error_mark_node)
+       ; /* Nothing to add */
+      else if (OPAQUE_ENUM_P (type)
+              || (cxx_dialect > cxx98 && processing_specialization))
+       {
+         new_value_list = true;
+         SET_OPAQUE_ENUM_P (type, false);
+         DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
+       }
+      else
+       {
+         error_at (type_start_token->location, "multiple definition of %q#T", type);
+         error_at (DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)),
+                   "previous definition here");
+         type = error_mark_node;
+       }
+
+      if (type == error_mark_node)
+       cp_parser_skip_to_end_of_block_or_statement (parser);
+      /* If the next token is not '}', then there are some enumerators.  */
+      else if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
+       cp_parser_enumerator_list (parser, type);
+
+      /* Consume the final '}'.  */
+      cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+
+      if (scoped_enum_p)
+       finish_scope ();
+      timevar_pop (TV_PARSE_ENUM);
+    }
+  else
+    {
+      /* If a ';' follows, then it is an opaque-enum-specifier
+       and additional restrictions apply.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+       {
+         if (is_anonymous)
+           error_at (type_start_token->location,
+                     "opaque-enum-specifier without name");
+         else if (nested_name_specifier)
+           error_at (type_start_token->location,
+                     "opaque-enum-specifier must use a simple identifier");
+       }
+    }
 
   /* Look for trailing attributes to apply to this enumeration, and
      apply them if appropriate.  */
@@ -13084,8 +13547,28 @@ cp_parser_enum_specifier (cp_parser* parser)
     }
 
   /* Finish up the enumeration.  */
-  finish_enum (type);
+  if (type != error_mark_node)
+    {
+      if (new_value_list)
+       finish_enum_value_list (type);
+      if (is_new_type)
+       finish_enum (type);
+    }
 
+  if (nested_name_specifier)
+    {
+      if (CLASS_TYPE_P (nested_name_specifier))
+       {
+         TYPE_BEING_DEFINED (nested_name_specifier) = nested_being_defined;
+         pop_scope (nested_name_specifier);
+       }
+      else if (TREE_CODE (nested_name_specifier) == NAMESPACE_DECL)
+       {
+         pop_nested_namespace (nested_name_specifier);
+       }
+    }
+ out:
+  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
   return type;
 }
 
@@ -13164,6 +13647,10 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
   if (check_for_bare_parameter_packs (value))
     value = error_mark_node;
 
+  /* integral_constant_value will pull out this expression, so make sure
+     it's folded as appropriate.  */
+  value = fold_non_dependent_expr (value);
+
   /* Create the enumerator.  */
   build_enumerator (identifier, value, type, loc);
 }
@@ -13302,10 +13789,8 @@ cp_parser_namespace_definition (cp_parser* parser)
   /* Parse the body of the namespace.  */
   cp_parser_namespace_body (parser);
 
-#ifdef HANDLE_PRAGMA_VISIBILITY
   if (has_visibility)
     pop_visibility (1);
-#endif
 
   /* Finish the namespace.  */
   pop_namespace ();
@@ -13793,7 +14278,13 @@ cp_parser_asm_definition (cp_parser* parser)
    have been completely parsed.
 
    FUNCTION_DEFINITION_P may be NULL if FUNCTION_DEFINITION_ALLOWED_P
-   is FALSE.  */
+   is FALSE.
+
+   If MAYBE_RANGE_FOR_DECL is not NULL, the pointed tree will be set to the
+   parsed declaration if it is an uninitialized single declarator not followed
+   by a `;', or to error_mark_node otherwise. Either way, the trailing `;',
+   if present, will not be consumed.  If returned, this declarator will be
+   created with SD_INITIALIZED but will not call cp_finish_decl.  */
 
 static tree
 cp_parser_init_declarator (cp_parser* parser,
@@ -13802,7 +14293,8 @@ cp_parser_init_declarator (cp_parser* parser,
                           bool function_definition_allowed_p,
                           bool member_p,
                           int declares_class_or_enum,
-                          bool* function_definition_p)
+                          bool* function_definition_p,
+                          tree* maybe_range_for_decl)
 {
   cp_token *token = NULL, *asm_spec_start_token = NULL,
            *attributes_start_token = NULL;
@@ -13822,7 +14314,8 @@ cp_parser_init_declarator (cp_parser* parser,
   bool is_non_constant_init;
   int ctor_dtor_or_conv_p;
   bool friend_p;
-  tree pushed_scope = NULL;
+  tree pushed_scope = NULL_TREE;
+  bool range_for_decl_p = false;
 
   /* Gather the attributes that were provided with the
      decl-specifiers.  */
@@ -13966,6 +14459,8 @@ cp_parser_init_declarator (cp_parser* parser,
     {
       is_initialized = SD_INITIALIZED;
       initialization_kind = token->type;
+      if (maybe_range_for_decl)
+       *maybe_range_for_decl = error_mark_node;
 
       if (token->type == CPP_EQ
          && function_declarator_p (declarator))
@@ -13984,8 +14479,13 @@ cp_parser_init_declarator (cp_parser* parser,
       if (token->type != CPP_COMMA
          && token->type != CPP_SEMICOLON)
        {
-         cp_parser_error (parser, "expected initializer");
-         return error_mark_node;
+         if (maybe_range_for_decl && *maybe_range_for_decl != error_mark_node)
+           range_for_decl_p = true;
+         else
+           {
+             cp_parser_error (parser, "expected initializer");
+             return error_mark_node;
+           }
        }
       is_initialized = SD_UNINITIALIZED;
       initialization_kind = CPP_EOF;
@@ -14018,7 +14518,8 @@ cp_parser_init_declarator (cp_parser* parser,
       if (parser->in_unbraced_linkage_specification_p)
        decl_specifiers->storage_class = sc_extern;
       decl = start_decl (declarator, decl_specifiers,
-                        is_initialized, attributes, prefix_attributes,
+                        range_for_decl_p? SD_INITIALIZED : is_initialized,
+                        attributes, prefix_attributes,
                         &pushed_scope);
       /* Adjust location of decl if declarator->id_loc is more appropriate:
         set, and decl wasn't merged with another decl, in which case its
@@ -14120,7 +14621,7 @@ cp_parser_init_declarator (cp_parser* parser,
       if (pushed_scope)
        {
          pop_scope (pushed_scope);
-         pushed_scope = false;
+         pushed_scope = NULL_TREE;
        }
       decl = grokfield (declarator, decl_specifiers,
                        initializer, !is_non_constant_init,
@@ -14130,9 +14631,9 @@ cp_parser_init_declarator (cp_parser* parser,
        cp_parser_save_default_args (parser, decl);
     }
 
-  /* Finish processing the declaration.  But, skip friend
+  /* Finish processing the declaration.  But, skip member
      declarations.  */
-  if (!friend_p && decl && decl != error_mark_node)
+  if (!member_p && decl && decl != error_mark_node && !range_for_decl_p)
     {
       cp_finish_decl (decl,
                      initializer, !is_non_constant_init,
@@ -14398,6 +14899,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              if (member_p || cp_parser_parse_definitely (parser))
                {
                  cp_cv_quals cv_quals;
+                 cp_virt_specifiers virt_specifiers;
                  tree exception_specification;
                  tree late_return;
 
@@ -14414,6 +14916,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                  /* And the exception-specification.  */
                  exception_specification
                    = cp_parser_exception_specification_opt (parser);
+                 /* Parse the virt-specifier-seq.  */
+                 virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
 
                  late_return
                    = cp_parser_late_return_type_opt (parser);
@@ -14422,6 +14926,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                  declarator = make_call_declarator (declarator,
                                                     params,
                                                     cv_quals,
+                                                    virt_specifiers,
                                                     exception_specification,
                                                     late_return);
                  /* Any subsequent parameter lists are to do with
@@ -14499,7 +15004,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                                                 /*allow_non_constant=*/true,
                                                 &non_constant_p);
              if (!non_constant_p)
-               bounds = fold_non_dependent_expr (bounds);
+               /* OK */;
              /* Normally, the array bound must be an integral constant
                 expression.  However, as an extension, we allow VLAs
                 in function scopes as long as they aren't part of a
@@ -14929,6 +15434,53 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
   return cv_quals;
 }
 
+/* Parse an (optional) virt-specifier-seq.
+
+   virt-specifier-seq:
+     virt-specifier virt-specifier-seq [opt]
+
+   virt-specifier:
+     override
+     final
+
+   Returns a bitmask representing the virt-specifiers.  */
+
+static cp_virt_specifiers
+cp_parser_virt_specifier_seq_opt (cp_parser* parser)
+{
+  cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
+
+  while (true)
+    {
+      cp_token *token;
+      cp_virt_specifiers virt_specifier;
+
+      /* Peek at the next token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      /* See if it's a virt-specifier-qualifier.  */
+      if (token->type != CPP_NAME)
+        break;
+      if (!strcmp (IDENTIFIER_POINTER(token->u.value), "override"))
+       virt_specifier = VIRT_SPEC_OVERRIDE;
+      else if (!strcmp (IDENTIFIER_POINTER(token->u.value), "final"))
+       virt_specifier = VIRT_SPEC_FINAL;
+      else
+       break;
+
+      if (virt_specifiers & virt_specifier)
+       {
+         error_at (token->location, "duplicate virt-specifier");
+         cp_lexer_purge_token (parser->lexer);
+       }
+      else
+       {
+         cp_lexer_consume_token (parser->lexer);
+         virt_specifiers |= virt_specifier;
+       }
+    }
+  return virt_specifiers;
+}
+
 /* Parse a late-specified return type, if any.  This is not a separate
    non-terminal, but part of a function declarator, which looks like
 
@@ -15054,7 +15606,13 @@ static tree cp_parser_type_id (cp_parser *parser)
 
 static tree cp_parser_template_type_arg (cp_parser *parser)
 {
-  return cp_parser_type_id_1 (parser, true, false);
+  tree r;
+  const char *saved_message = parser->type_definition_forbidden_message;
+  parser->type_definition_forbidden_message
+    = G_("types may not be defined in template arguments");
+  r = cp_parser_type_id_1 (parser, true, false);
+  parser->type_definition_forbidden_message = saved_message;
+  return r;
 }
 
 static tree cp_parser_trailing_type_id (cp_parser *parser)
@@ -15325,6 +15883,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
        {
          retrofit_lang_decl (decl);
          DECL_PARM_INDEX (decl) = ++index;
+         DECL_PARM_LEVEL (decl) = function_parm_depth ();
        }
 
       /* Add the new parameter to the list.  */
@@ -15783,7 +16342,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
 static void
 cp_parser_function_body (cp_parser *parser)
 {
-  cp_parser_compound_statement (parser, NULL, false);
+  cp_parser_compound_statement (parser, NULL, false, true);
 }
 
 /* Parse a ctor-initializer-opt followed by a function-body.  Return
@@ -15792,15 +16351,37 @@ cp_parser_function_body (cp_parser *parser)
 static bool
 cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser)
 {
-  tree body;
+  tree body, list;
   bool ctor_initializer_p;
+  const bool check_body_p =
+     DECL_CONSTRUCTOR_P (current_function_decl)
+     && DECL_DECLARED_CONSTEXPR_P (current_function_decl);
+  tree last = NULL;
 
   /* Begin the function body.  */
   body = begin_function_body ();
   /* Parse the optional ctor-initializer.  */
   ctor_initializer_p = cp_parser_ctor_initializer_opt (parser);
+
+  /* If we're parsing a constexpr constructor definition, we need
+     to check that the constructor body is indeed empty.  However,
+     before we get to cp_parser_function_body lot of junk has been
+     generated, so we can't just check that we have an empty block.
+     Rather we take a snapshot of the outermost block, and check whether
+     cp_parser_function_body changed its state.  */
+  if (check_body_p)
+    {
+      list = body;
+      if (TREE_CODE (list) == BIND_EXPR)
+       list = BIND_EXPR_BODY (list);
+      if (TREE_CODE (list) == STATEMENT_LIST
+         && STATEMENT_LIST_TAIL (list) != NULL)
+       last = STATEMENT_LIST_TAIL (list)->stmt;
+    }
   /* Parse the function-body.  */
   cp_parser_function_body (parser);
+  if (check_body_p)
+    check_constexpr_ctor_body (last, list);
   /* Finish the function body.  */
   finish_function_body (body);
 
@@ -15903,7 +16484,15 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
                                        /*allow_non_constant_p=*/true,
                                        non_constant_p);
       if (!*non_constant_p)
-       initializer = fold_non_dependent_expr (initializer);
+       {
+         /* We only want to fold if this is really a constant
+            expression.  FIXME Actually, we don't want to fold here, but in
+            cp_finish_decl.  */
+         tree folded = fold_non_dependent_expr (initializer);
+         folded = maybe_constant_value (folded);
+         if (TREE_CONSTANT (folded))
+           initializer = folded;
+       }
     }
   else
     initializer = cp_parser_braced_list (parser, non_constant_p);
@@ -16192,7 +16781,12 @@ cp_parser_class_name (cp_parser *parser,
     }
   else if (TREE_CODE (decl) != TYPE_DECL
           || TREE_TYPE (decl) == error_mark_node
-          || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl)))
+          || !MAYBE_CLASS_TYPE_P (TREE_TYPE (decl))
+          /* In Objective-C 2.0, a classname followed by '.' starts a
+             dot-syntax expression, and it's not a type-name.  */
+          || (c_dialect_objc ()
+              && cp_lexer_peek_token (parser->lexer)->type == CPP_DOT 
+              && objc_is_class_name (decl)))
     decl = error_mark_node;
 
   if (decl == error_mark_node)
@@ -16211,7 +16805,7 @@ cp_parser_class_name (cp_parser *parser,
    Returns the TREE_TYPE representing the class.  */
 
 static tree
-cp_parser_class_specifier (cp_parser* parser)
+cp_parser_class_specifier_1 (cp_parser* parser)
 {
   tree type;
   tree attributes = NULL_TREE;
@@ -16222,6 +16816,7 @@ cp_parser_class_specifier (cp_parser* parser)
   tree old_scope = NULL_TREE;
   tree scope = NULL_TREE;
   tree bases;
+  cp_token *closing_brace;
 
   push_deferring_access_checks (dk_no_deferred);
 
@@ -16291,7 +16886,7 @@ cp_parser_class_specifier (cp_parser* parser)
     cp_parser_member_specification_opt (parser);
 
   /* Look for the trailing `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+  closing_brace = cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
   /* Look for trailing attributes to apply to this class.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
     attributes = cp_parser_attributes_opt (parser);
@@ -16299,6 +16894,100 @@ cp_parser_class_specifier (cp_parser* parser)
     type = finish_struct (type, attributes);
   if (nested_name_specifier_p)
     pop_inner_scope (old_scope, scope);
+
+  /* We've finished a type definition.  Check for the common syntax
+     error of forgetting a semicolon after the definition.  We need to
+     be careful, as we can't just check for not-a-semicolon and be done
+     with it; the user might have typed:
+
+     class X { } c = ...;
+     class X { } *p = ...;
+
+     and so forth.  Instead, enumerate all the possible tokens that
+     might follow this production; if we don't see one of them, then
+     complain and silently insert the semicolon.  */
+  {
+    cp_token *token = cp_lexer_peek_token (parser->lexer);
+    bool want_semicolon = true;
+
+    switch (token->type)
+      {
+      case CPP_NAME:
+      case CPP_SEMICOLON:
+      case CPP_MULT:
+      case CPP_AND:
+      case CPP_OPEN_PAREN:
+      case CPP_CLOSE_PAREN:
+      case CPP_COMMA:
+        want_semicolon = false;
+        break;
+
+        /* While it's legal for type qualifiers and storage class
+           specifiers to follow type definitions in the grammar, only
+           compiler testsuites contain code like that.  Assume that if
+           we see such code, then what we're really seeing is a case
+           like:
+
+           class X { }
+           const <type> var = ...;
+
+           or
+
+           class Y { }
+           static <type> func (...) ...
+
+           i.e. the qualifier or specifier applies to the next
+           declaration.  To do so, however, we need to look ahead one
+           more token to see if *that* token is a type specifier.
+
+          This code could be improved to handle:
+
+          class Z { }
+          static const <type> var = ...;  */
+      case CPP_KEYWORD:
+       if (keyword_is_decl_specifier (token->keyword))
+         {
+           cp_token *lookahead = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+           /* Handling user-defined types here would be nice, but very
+              tricky.  */
+           want_semicolon
+             = (lookahead->type == CPP_KEYWORD
+                && keyword_begins_type_specifier (lookahead->keyword));
+         }
+       break;
+      default:
+       break;
+      }
+
+    /* If we don't have a type, then something is very wrong and we
+       shouldn't try to do anything clever.  Likewise for not seeing the
+       closing brace.  */
+    if (closing_brace && TYPE_P (type) && want_semicolon)
+      {
+       cp_token_position prev
+         = cp_lexer_previous_token_position (parser->lexer);
+       cp_token *prev_token = cp_lexer_token_at (parser->lexer, prev);
+       location_t loc = prev_token->location;
+
+       if (CLASSTYPE_DECLARED_CLASS (type))
+         error_at (loc, "expected %<;%> after class definition");
+       else if (TREE_CODE (type) == RECORD_TYPE)
+         error_at (loc, "expected %<;%> after struct definition");
+       else if (TREE_CODE (type) == UNION_TYPE)
+         error_at (loc, "expected %<;%> after union definition");
+       else
+         gcc_unreachable ();
+
+       /* Unget one token and smash it to look as though we encountered
+          a semicolon in the input stream.  */
+       cp_lexer_set_token_position (parser->lexer, prev);
+       token = cp_lexer_peek_token (parser->lexer);
+       token->type = CPP_SEMICOLON;
+       token->keyword = RID_MAX;
+      }
+  }
+
   /* If this class is not itself within the scope of another class,
      then we need to parse the bodies of all of the queued function
      definitions.  Note that the queued functions defined in a class
@@ -16379,14 +17068,27 @@ cp_parser_class_specifier (cp_parser* parser)
   return type;
 }
 
+static tree
+cp_parser_class_specifier (cp_parser* parser)
+{
+  tree ret;
+  timevar_push (TV_PARSE_STRUCT);
+  ret = cp_parser_class_specifier_1 (parser);
+  timevar_pop (TV_PARSE_STRUCT);
+  return ret;
+}
+
 /* Parse a class-head.
 
    class-head:
      class-key identifier [opt] base-clause [opt]
-     class-key nested-name-specifier identifier base-clause [opt]
+     class-key nested-name-specifier identifier class-virt-specifier [opt] base-clause [opt]
      class-key nested-name-specifier [opt] template-id
        base-clause [opt]
 
+   class-virt-specifier:
+     final
+
    GNU Extensions:
      class-key attributes identifier [opt] base-clause [opt]
      class-key attributes nested-name-specifier identifier base-clause [opt]
@@ -16418,10 +17120,12 @@ cp_parser_class_head (cp_parser* parser,
   tree id = NULL_TREE;
   tree type = NULL_TREE;
   tree attributes;
+  cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
   bool template_id_p = false;
   bool qualified_p = false;
   bool invalid_nested_name_p = false;
   bool invalid_explicit_specialization_p = false;
+  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
   tree pushed_scope = NULL_TREE;
   unsigned num_templates;
   cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL;
@@ -16430,6 +17134,7 @@ cp_parser_class_head (cp_parser* parser,
   /* Assume no template parameter lists will be used in defining the
      type.  */
   num_templates = 0;
+  parser->colon_corrects_to_scope_p = false;
 
   *bases = NULL_TREE;
 
@@ -16559,8 +17264,11 @@ cp_parser_class_head (cp_parser* parser,
   pop_deferring_access_checks ();
 
   if (id)
-    cp_parser_check_for_invalid_template_id (parser, id,
-                                            type_start_token->location);
+    {
+      cp_parser_check_for_invalid_template_id (parser, id,
+                                               type_start_token->location);
+      virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
+    }
 
   /* If it's not a `:' or a `{' then we can't really be looking at a
      class-head, since a class-head only appears as part of a
@@ -16569,24 +17277,34 @@ cp_parser_class_head (cp_parser* parser,
   if (!cp_parser_next_token_starts_class_definition_p (parser))
     {
       cp_parser_error (parser, "expected %<{%> or %<:%>");
-      return error_mark_node;
+      type = error_mark_node;
+      goto out;
     }
 
   /* At this point, we're going ahead with the class-specifier, even
      if some other problem occurs.  */
   cp_parser_commit_to_tentative_parse (parser);
+  if (virt_specifiers & VIRT_SPEC_OVERRIDE)
+    {
+      cp_parser_error (parser,
+                       "cannot specify %<override%> for a class");
+      type = error_mark_node;
+      goto out;
+    }
   /* Issue the error about the overly-qualified name now.  */
   if (qualified_p)
     {
       cp_parser_error (parser,
                       "global qualification of class name is invalid");
-      return error_mark_node;
+      type = error_mark_node;
+      goto out;
     }
   else if (invalid_nested_name_p)
     {
       cp_parser_error (parser,
                       "qualified name does not name a class");
-      return error_mark_node;
+      type = error_mark_node;
+      goto out;
     }
   else if (nested_name_specifier)
     {
@@ -16789,6 +17507,10 @@ cp_parser_class_head (cp_parser* parser,
   if (type)
     DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
   *attributes_p = attributes;
+  if (type && (virt_specifiers & VIRT_SPEC_FINAL))
+    CLASSTYPE_FINAL (type) = 1;
+ out:
+  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
   return type;
 }
 
@@ -16917,6 +17639,7 @@ cp_parser_member_declaration (cp_parser* parser)
   cp_token *decl_spec_token_start = NULL;
   cp_token *initializer_token_start = NULL;
   int saved_pedantic;
+  bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
 
   /* Check for the `__extension__' keyword.  */
   if (cp_parser_extension_opt (parser, &saved_pedantic))
@@ -16975,8 +17698,10 @@ cp_parser_member_declaration (cp_parser* parser)
       return;
     }
 
+  parser->colon_corrects_to_scope_p = false;
+
   if (cp_parser_using_declaration (parser, /*access_declaration=*/true))
-    return;
+    goto out;
 
   /* Parse the decl-specifier-seq.  */
   decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
@@ -16989,7 +17714,7 @@ cp_parser_member_declaration (cp_parser* parser)
   /* Check for an invalid type-name.  */
   if (!decl_specifiers.any_type_specifiers_p
       && cp_parser_parse_and_diagnose_invalid_type_name (parser))
-    return;
+    goto out;
   /* If there is no declarator, then the decl-specifier-seq should
      specify a type.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -17073,6 +17798,8 @@ cp_parser_member_declaration (cp_parser* parser)
     }
   else
     {
+      bool assume_semicolon = false;
+
       /* See if these declarations will be friends.  */
       friend_p = cp_parser_friend_p (&decl_specifiers);
 
@@ -17157,7 +17884,7 @@ cp_parser_member_declaration (cp_parser* parser)
                  if (cp_lexer_next_token_is (parser->lexer,
                                              CPP_SEMICOLON))
                    cp_lexer_consume_token (parser->lexer);
-                 return;
+                 goto out;
                }
 
              if (declares_class_or_enum & 2)
@@ -17236,7 +17963,7 @@ cp_parser_member_declaration (cp_parser* parser)
                  /* If the next token is a semicolon, consume it.  */
                  if (token->type == CPP_SEMICOLON)
                    cp_lexer_consume_token (parser->lexer);
-                 return;
+                 goto out;
                }
              else
                if (declarator->kind == cdk_function)
@@ -17266,11 +17993,18 @@ cp_parser_member_declaration (cp_parser* parser)
          else if (cp_lexer_next_token_is_not (parser->lexer,
                                               CPP_SEMICOLON))
            {
-             cp_parser_error (parser, "expected %<;%>");
-             /* Skip tokens until we find a `;'.  */
-             cp_parser_skip_to_end_of_statement (parser);
+             /* The next token might be a ways away from where the
+                actual semicolon is missing.  Find the previous token
+                and use that for our error position.  */
+             cp_token *token = cp_lexer_previous_token (parser->lexer);
+             error_at (token->location,
+                       "expected %<;%> at end of member declaration");
 
-             break;
+             /* Assume that the user meant to provide a semicolon.  If
+                we were to cp_parser_skip_to_end_of_statement, we might
+                skip to a semicolon inside a member function definition
+                and issue nonsensical error messages.  */
+             assume_semicolon = true;
            }
 
          if (decl)
@@ -17282,10 +18016,15 @@ cp_parser_member_declaration (cp_parser* parser)
              if (TREE_CODE (decl) == FUNCTION_DECL)
                cp_parser_save_default_args (parser, decl);
            }
+
+         if (assume_semicolon)
+           goto out;
        }
     }
 
   cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+ out:
+  parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
 }
 
 /* Parse a pure-specifier.
@@ -17639,7 +18378,7 @@ cp_parser_exception_specification_opt (cp_parser* parser)
   /* Enable this once a lot of code has transitioned to noexcept?  */
   if (cxx_dialect == cxx0x && !in_system_header)
     warning (OPT_Wdeprecated, "dynamic exception specifications are "
-            "deprecated in C++0x; use %<noexcept%> instead.");
+            "deprecated in C++0x; use %<noexcept%> instead");
 #endif
 
   /* Consume the `throw'.  */
@@ -17727,7 +18466,7 @@ cp_parser_try_block (cp_parser* parser)
 
   cp_parser_require_keyword (parser, RID_TRY, RT_TRY);
   try_block = begin_try_block ();
-  cp_parser_compound_statement (parser, NULL, true);
+  cp_parser_compound_statement (parser, NULL, true, false);
   finish_try_block (try_block);
   cp_parser_handler_seq (parser);
   finish_handler_sequence (try_block);
@@ -17804,7 +18543,7 @@ cp_parser_handler (cp_parser* parser)
   declaration = cp_parser_exception_declaration (parser);
   finish_handler_parms (declaration, handler);
   cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
-  cp_parser_compound_statement (parser, NULL, false);
+  cp_parser_compound_statement (parser, NULL, false, false);
   finish_handler (handler);
 }
 
@@ -19000,8 +19739,17 @@ cp_parser_function_definition_from_specifiers_and_declarator
        pop_nested_class ();
     }
   else
-    fn = cp_parser_function_definition_after_declarator (parser,
+    {
+      timevar_id_t tv;
+      if (DECL_DECLARED_INLINE_P (current_function_decl))
+        tv = TV_PARSE_INLINE;
+      else
+        tv = TV_PARSE_FUNC;
+      timevar_push (tv);
+      fn = cp_parser_function_definition_after_declarator (parser,
                                                         /*inline_p=*/false);
+      timevar_pop (tv);
+    }
 
   return fn;
 }
@@ -19151,8 +19899,11 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
       parameter_list = NULL_TREE;
     }
   else
-    /* Parse the template parameters.  */
-    parameter_list = cp_parser_template_parameter_list (parser);
+    {
+      /* Parse the template parameters.  */
+      parameter_list = cp_parser_template_parameter_list (parser);
+      fixup_template_parms ();
+    }
 
   /* Get the deferred access checks from the parameter list.  These
      will be checked once we know what is being declared, as for a
@@ -19313,8 +20064,15 @@ cp_parser_single_declaration (cp_parser* parser,
     }
 
   /* Complain about missing 'typename' or other invalid type names.  */
-  if (!decl_specifiers.any_type_specifiers_p)
-    cp_parser_parse_and_diagnose_invalid_type_name (parser);
+  if (!decl_specifiers.any_type_specifiers_p
+      && cp_parser_parse_and_diagnose_invalid_type_name (parser))
+    {
+      /* cp_parser_parse_and_diagnose_invalid_type_name calls
+        cp_parser_skip_to_end_of_block_or_statement, so don't try to parse
+        the rest of this declaration.  */
+      decl = error_mark_node;
+      goto out;
+    }
 
   /* If it's not a template class, try for a template function.  If
      the next token is a `;', then this declaration does not declare
@@ -19331,7 +20089,8 @@ cp_parser_single_declaration (cp_parser* parser,
                                        /*function_definition_allowed_p=*/true,
                                        member_p,
                                        declares_class_or_enum,
-                                       &function_definition_p);
+                                       &function_definition_p,
+                                       NULL);
 
     /* 7.1.1-1 [dcl.stc]
 
@@ -19347,6 +20106,13 @@ cp_parser_single_declaration (cp_parser* parser,
       }
     }
 
+  /* Look for a trailing `;' after the declaration.  */
+  if (!function_definition_p
+      && (decl == error_mark_node
+         || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)))
+    cp_parser_skip_to_end_of_block_or_statement (parser);
+
+ out:
   pop_deferring_access_checks ();
 
   /* Clear any current qualification; whatever comes next is the start
@@ -19354,11 +20120,6 @@ cp_parser_single_declaration (cp_parser* parser,
   parser->scope = NULL_TREE;
   parser->qualifying_scope = NULL_TREE;
   parser->object_scope = NULL_TREE;
-  /* Look for a trailing `;' after the declaration.  */
-  if (!function_definition_p
-      && (decl == error_mark_node
-         || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)))
-    cp_parser_skip_to_end_of_block_or_statement (parser);
 
   return decl;
 }
@@ -19390,7 +20151,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
       CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
       if (TREE_CODE (type) == TYPE_DECL)
        type = TREE_TYPE (type);
-      return finish_compound_literal (type, expression_list);
+      return finish_compound_literal (type, expression_list,
+                                     tf_warning_or_error);
     }
 
 
@@ -19604,6 +20366,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
 static void
 cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
 {
+  timevar_push (TV_PARSE_INMETH);
   /* If this member is a template, get the underlying
      FUNCTION_DECL.  */
   if (DECL_FUNCTION_TEMPLATE_P (member_function))
@@ -19670,6 +20433,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
 
   /* Restore the queue.  */
   pop_unparsed_function_queues (parser);
+  timevar_pop (TV_PARSE_INMETH);
 }
 
 /* If DECL contains any default args, remember it on the unparsed
@@ -19716,6 +20480,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
   saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
   parser->local_variables_forbidden_p = true;
 
+  push_defarg_context (fn);
+
   for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn)),
         parmdecl = DECL_ARGUMENTS (fn);
        parm && parm != void_list_node;
@@ -19774,6 +20540,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       cp_parser_pop_lexer (parser);
     }
 
+  pop_defarg_context ();
+
   /* Make sure no default arg is missing.  */
   check_default_args (fn);
 
@@ -20589,6 +21357,8 @@ cp_parser_commit_to_tentative_parse (cp_parser* parser)
 static void
 cp_parser_abort_tentative_parse (cp_parser* parser)
 {
+  gcc_assert (parser->context->status != CP_PARSER_STATUS_KIND_COMMITTED
+             || errorcount > 0);
   cp_parser_simulate_error (parser);
   /* Now, pretend that we want to see if the construct was
      successfully parsed.  */
@@ -20735,7 +21505,7 @@ cp_parser_objc_message_expression (cp_parser* parser)
   messageargs = cp_parser_objc_message_args (parser);
   cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
 
-  return objc_build_message_expr (build_tree_list (receiver, messageargs));
+  return objc_build_message_expr (receiver, messageargs);
 }
 
 /* Parse an objc-message-receiver.
@@ -20830,6 +21600,12 @@ cp_parser_objc_message_args (cp_parser* parser)
       token = cp_lexer_peek_token (parser->lexer);
     }
 
+  if (sel_args == NULL_TREE && addl_args == NULL_TREE)
+    {
+      cp_parser_error (parser, "objective-c++ message argument(s) are expected");
+      return build_tree_list (error_mark_node, error_mark_node);
+    }
+
   return build_tree_list (sel_args, addl_args);
 }
 
@@ -20859,6 +21635,19 @@ cp_parser_objc_encode_expression (cp_parser* parser)
       return error_mark_node;
     }
 
+  /* This happens if we find @encode(T) (where T is a template
+     typename or something dependent on a template typename) when
+     parsing a template.  In that case, we can't compile it
+     immediately, but we rather create an AT_ENCODE_EXPR which will
+     need to be instantiated when the template is used.
+  */
+  if (dependent_type_p (type))
+    {
+      tree value = build_min (AT_ENCODE_EXPR, size_type_node, type);
+      TREE_READONLY (value) = 1;
+      return value;
+    }
+
   return objc_build_encode_expr (type);
 }
 
@@ -20984,18 +21773,29 @@ cp_parser_objc_selector_expression (cp_parser* parser)
 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);
+  tree identifier;
+  tree list;
+  cp_token *sep;
+
+  identifier = cp_parser_identifier (parser);
+  if (identifier == error_mark_node)
+    return error_mark_node;      
+
+  list = build_tree_list (NULL_TREE, identifier);
+  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)));
+      identifier = cp_parser_identifier (parser);
+      if (identifier == error_mark_node)
+       return list;
+
+      list = chainon (list, build_tree_list (NULL_TREE,
+                                            identifier));
       sep = cp_lexer_peek_token (parser->lexer);
     }
-
+  
   return list;
 }
 
@@ -21031,7 +21831,21 @@ 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));
+  while (true)
+    {
+      tree id;
+      
+      id = cp_parser_identifier (parser);
+      if (id == error_mark_node)
+       break;
+      
+      objc_declare_class (id);
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+      else
+       break;
+    }
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 }
 
@@ -21070,13 +21884,16 @@ cp_parser_objc_visibility_spec (cp_parser* parser)
   switch (vis->keyword)
     {
     case RID_AT_PRIVATE:
-      objc_set_visibility (2);
+      objc_set_visibility (OBJC_IVAR_VIS_PRIVATE);
       break;
     case RID_AT_PROTECTED:
-      objc_set_visibility (0);
+      objc_set_visibility (OBJC_IVAR_VIS_PROTECTED);
       break;
     case RID_AT_PUBLIC:
-      objc_set_visibility (1);
+      objc_set_visibility (OBJC_IVAR_VIS_PUBLIC);
+      break;
+    case RID_AT_PACKAGE:
+      objc_set_visibility (OBJC_IVAR_VIS_PACKAGE);
       break;
     default:
       return;
@@ -21086,15 +21903,16 @@ cp_parser_objc_visibility_spec (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);
 }
 
-/* Parse an Objective-C method type.  */
+/* Parse an Objective-C method type.  Return 'true' if it is a class
+   (+) method, and 'false' if it is an instance (-) method.  */
 
-static void
+static inline bool
 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);
+  if (cp_lexer_consume_token (parser->lexer)->type == CPP_PLUS)
+    return true;
+  else
+    return false;
 }
 
 /* Parse an Objective-C protocol qualifier.  */
@@ -21141,7 +21959,25 @@ cp_parser_objc_typename (cp_parser* 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_type = cp_parser_type_id (parser);
+         
+         /* If the type could not be parsed, an error has already
+            been produced.  For error recovery, behave as if it had
+            not been specified, which will use the default type
+            'id'.  */
+         if (cp_type == error_mark_node)
+           {
+             cp_type = NULL_TREE;
+             /* We need to skip to the closing parenthesis as
+                cp_parser_type_id() does not seem to do it for
+                us.  */
+             cp_parser_skip_to_closing_parenthesis (parser,
+                                                    /*recovering=*/true,
+                                                    /*or_comma=*/false,
+                                                    /*consume_paren=*/false);
+           }
+       }
 
       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
       type_name = build_tree_list (proto_quals, cp_type);
@@ -21196,7 +22032,7 @@ cp_parser_objc_selector (cp_parser* parser)
 /* Parse an Objective-C params list.  */
 
 static tree
-cp_parser_objc_method_keyword_params (cp_parser* parser)
+cp_parser_objc_method_keyword_params (cp_parser* parser, tree* attributes)
 {
   tree params = NULL_TREE;
   bool maybe_unary_selector_p = true;
@@ -21205,6 +22041,10 @@ cp_parser_objc_method_keyword_params (cp_parser* parser)
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
     {
       tree selector = NULL_TREE, type_name, identifier;
+      tree parm_attr = NULL_TREE;
+
+      if (token->keyword == RID_ATTRIBUTE)
+       break;
 
       if (token->type != CPP_COLON)
        selector = cp_parser_objc_selector (parser);
@@ -21212,29 +22052,65 @@ cp_parser_objc_method_keyword_params (cp_parser* 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;
+       {
+         params = selector; /* Might be followed by attributes.  */
+         break;
+       }
 
       maybe_unary_selector_p = false;
-      cp_parser_require (parser, CPP_COLON, RT_COLON);
+      if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
+       {
+         /* Something went quite wrong.  There should be a colon
+            here, but there is not.  Stop parsing parameters.  */
+         break;
+       }
       type_name = cp_parser_objc_typename (parser);
+      /* New ObjC allows attributes on parameters too.  */
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+       parm_attr = cp_parser_attributes_opt (parser);
       identifier = cp_parser_identifier (parser);
 
       params
        = chainon (params,
                   objc_build_keyword_decl (selector,
                                            type_name,
-                                           identifier));
+                                           identifier,
+                                           parm_attr));
 
       token = cp_lexer_peek_token (parser->lexer);
     }
 
+  if (params == NULL_TREE)
+    {
+      cp_parser_error (parser, "objective-c++ method declaration is expected");
+      return error_mark_node;
+    }
+
+  /* We allow tail attributes for the method.  */
+  if (token->keyword == RID_ATTRIBUTE)
+    {
+      *attributes = cp_parser_attributes_opt (parser);
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+         || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+       return params;
+      cp_parser_error (parser, 
+                      "method attributes must be specified at the end");
+      return error_mark_node;
+    }
+
+  if (params == NULL_TREE)
+    {
+      cp_parser_error (parser, "objective-c++ method declaration is expected");
+      return error_mark_node;
+    }
   return params;
 }
 
 /* Parse the non-keyword Objective-C params.  */
 
 static tree
-cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp)
+cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp, 
+                                      tree* attributes)
 {
   tree params = make_node (TREE_LIST);
   cp_token *token = cp_lexer_peek_token (parser->lexer);
@@ -21252,9 +22128,11 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp)
        {
          cp_lexer_consume_token (parser->lexer);  /* Eat '...'.  */
          *ellipsisp = true;
+         token = cp_lexer_peek_token (parser->lexer);
          break;
        }
 
+      /* TODO: parse attributes for tail parameters.  */
       parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
       parm = grokdeclarator (parmdecl->declarator,
                             &parmdecl->decl_specifiers,
@@ -21265,6 +22143,26 @@ cp_parser_objc_method_tail_params_opt (cp_parser* parser, bool *ellipsisp)
       token = cp_lexer_peek_token (parser->lexer);
     }
 
+  /* We allow tail attributes for the method.  */
+  if (token->keyword == RID_ATTRIBUTE)
+    {
+      if (*attributes == NULL_TREE)
+       {
+         *attributes = cp_parser_attributes_opt (parser);
+         if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
+             || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+           return params;
+       }
+      else        
+       /* We have an error, but parse the attributes, so that we can 
+          carry on.  */
+       *attributes = cp_parser_attributes_opt (parser);
+
+      cp_parser_error (parser, 
+                      "method attributes must be specified at the end");
+      return error_mark_node;
+    }
+
   return params;
 }
 
@@ -21286,42 +22184,107 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
   /* 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);
-}
+  /* Mark methods as optional or required, when building protocols.  */
+  else if (token->keyword == RID_AT_OPTIONAL)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      objc_set_method_opt (true);
+    }
+  else if (token->keyword == RID_AT_REQUIRED)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      objc_set_method_opt (false);
+    }
+  else if (token->keyword == RID_NAMESPACE)
+    cp_parser_namespace_definition (parser);
+  /* Other stray characters must generate errors.  */
+  else if (token->type == CPP_OPEN_BRACE || token->type == CPP_CLOSE_BRACE)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      error ("stray %qs between Objective-C++ methods",
+            token->type == CPP_OPEN_BRACE ? "{" : "}");
+    }
+  /* 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)
+cp_parser_objc_method_signature (cp_parser* parser, tree* attributes)
 {
   tree rettype, kwdparms, optparms;
   bool ellipsis = false;
+  bool is_class_method;
 
-  cp_parser_objc_method_type (parser);
+  is_class_method = 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);
+  *attributes = NULL_TREE;
+  kwdparms = cp_parser_objc_method_keyword_params (parser, attributes);
+  if (kwdparms == error_mark_node)
+    return error_mark_node;
+  optparms = cp_parser_objc_method_tail_params_opt (parser, &ellipsis, attributes);
+  if (optparms == error_mark_node)
+    return error_mark_node;
 
-  return objc_build_method_signature (rettype, kwdparms, optparms, ellipsis);
+  return objc_build_method_signature (is_class_method, rettype, kwdparms, optparms, ellipsis);
 }
 
-/* Pars an Objective-C method prototype list.  */
+static bool
+cp_parser_objc_method_maybe_bad_prefix_attributes (cp_parser* parser)
+{
+  tree tattr;  
+  cp_lexer_save_tokens (parser->lexer);
+  tattr = cp_parser_attributes_opt (parser);
+  gcc_assert (tattr) ;
+  
+  /* If the attributes are followed by a method introducer, this is not allowed.
+     Dump the attributes and flag the situation.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_PLUS)
+      || cp_lexer_next_token_is (parser->lexer, CPP_MINUS))
+    return true;
+
+  /* Otherwise, the attributes introduce some interstitial code, possibly so
+     rewind to allow that check.  */
+  cp_lexer_rollback_tokens (parser->lexer);
+  return false;  
+}
+
+/* Parse 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)
+  while (token->keyword != RID_AT_END && token->type != CPP_EOF)
     {
       if (token->type == CPP_PLUS || token->type == CPP_MINUS)
        {
-         objc_add_method_declaration
-          (cp_parser_objc_method_signature (parser));
+         tree attributes, sig;
+         bool is_class_method;
+         if (token->type == CPP_PLUS)
+           is_class_method = true;
+         else
+           is_class_method = false;
+         sig = cp_parser_objc_method_signature (parser, &attributes);
+         if (sig == error_mark_node)
+           {
+             cp_parser_skip_to_end_of_block_or_statement (parser);
+             token = cp_lexer_peek_token (parser->lexer);
+             continue;
+           }
+         objc_add_method_declaration (is_class_method, sig, attributes);
          cp_parser_consume_semicolon_at_end_of_statement (parser);
        }
+      else if (token->keyword == RID_AT_PROPERTY)
+       cp_parser_objc_at_property_declaration (parser);
+      else if (token->keyword == RID_ATTRIBUTE 
+              && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
+       warning_at (cp_lexer_peek_token (parser->lexer)->location, 
+                   OPT_Wattributes, 
+                   "prefix attributes are ignored for methods");
       else
        /* Allow for interspersed non-ObjC++ code.  */
        cp_parser_objc_interstitial_code (parser);
@@ -21329,7 +22292,11 @@ cp_parser_objc_method_prototype_list (cp_parser* parser)
       token = cp_lexer_peek_token (parser->lexer);
     }
 
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  if (token->type != CPP_EOF)
+    cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  else
+    cp_parser_error (parser, "expected %<@end%>");
+
   objc_finish_interface ();
 }
 
@@ -21340,27 +22307,58 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
 {
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
-  while (token->keyword != RID_AT_END)
+  while (token->keyword != RID_AT_END && token->type != CPP_EOF)
     {
       tree meth;
 
       if (token->type == CPP_PLUS || token->type == CPP_MINUS)
        {
+         cp_token *ptk;
+         tree sig, attribute;
+         bool is_class_method;
+         if (token->type == CPP_PLUS)
+           is_class_method = true;
+         else
+           is_class_method = false;
          push_deferring_access_checks (dk_deferred);
-         objc_start_method_definition
-          (cp_parser_objc_method_signature (parser));
+         sig = cp_parser_objc_method_signature (parser, &attribute);
+         if (sig == error_mark_node)
+           {
+             cp_parser_skip_to_end_of_block_or_statement (parser);
+             token = cp_lexer_peek_token (parser->lexer);
+             continue;
+           }
+         objc_start_method_definition (is_class_method, sig, attribute,
+                                       NULL_TREE);
 
          /* 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);
+         ptk = cp_lexer_peek_token (parser->lexer);
+         if (!(ptk->type == CPP_PLUS || ptk->type == CPP_MINUS 
+               || ptk->type == CPP_EOF || ptk->keyword == RID_AT_END))
+           {
+             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);
+           }
        }
+      /* The following case will be removed once @synthesize is
+        completely implemented.  */
+      else if (token->keyword == RID_AT_PROPERTY)
+       cp_parser_objc_at_property_declaration (parser);
+      else if (token->keyword == RID_AT_SYNTHESIZE)
+       cp_parser_objc_at_synthesize_declaration (parser);
+      else if (token->keyword == RID_AT_DYNAMIC)
+       cp_parser_objc_at_dynamic_declaration (parser);
+      else if (token->keyword == RID_ATTRIBUTE 
+              && cp_parser_objc_method_maybe_bad_prefix_attributes(parser))
+       warning_at (token->location, OPT_Wattributes,
+                   "prefix attributes are ignored for methods");
       else
        /* Allow for interspersed non-ObjC++ code.  */
        cp_parser_objc_interstitial_code (parser);
@@ -21368,7 +22366,11 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
       token = cp_lexer_peek_token (parser->lexer);
     }
 
-  cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  if (token->type != CPP_EOF)
+    cp_lexer_consume_token (parser->lexer);  /* Eat '@end'.  */
+  else
+    cp_parser_error (parser, "expected %<@end%>");
+
   objc_finish_implementation ();
 }
 
@@ -21385,7 +22387,8 @@ cp_parser_objc_class_ivars (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '{'.  */
   token = cp_lexer_peek_token (parser->lexer);
 
-  while (token->type != CPP_CLOSE_BRACE)
+  while (token->type != CPP_CLOSE_BRACE 
+       && token->keyword != RID_AT_END && token->type != CPP_EOF)
     {
       cp_decl_specifier_seq declspecs;
       int decl_class_or_enum_p;
@@ -21400,6 +22403,28 @@ cp_parser_objc_class_ivars (cp_parser* parser)
                                    CP_PARSER_FLAGS_OPTIONAL,
                                    &declspecs,
                                    &decl_class_or_enum_p);
+
+      /* auto, register, static, extern, mutable.  */
+      if (declspecs.storage_class != sc_none)
+       {
+         cp_parser_error (parser, "invalid type for instance variable");         
+         declspecs.storage_class = sc_none;
+       }
+
+      /* __thread.  */
+      if (declspecs.specs[(int) ds_thread])
+       {
+         cp_parser_error (parser, "invalid type for instance variable");
+         declspecs.specs[(int) ds_thread] = 0;
+       }
+      
+      /* typedef.  */
+      if (declspecs.specs[(int) ds_typedef])
+       {
+         cp_parser_error (parser, "invalid type for instance variable");
+         declspecs.specs[(int) ds_typedef] = 0;
+       }
+
       prefix_attributes = declspecs.attributes;
       declspecs.attributes = NULL_TREE;
 
@@ -21484,7 +22509,14 @@ cp_parser_objc_class_ivars (cp_parser* parser)
       token = cp_lexer_peek_token (parser->lexer);
     }
 
-  cp_lexer_consume_token (parser->lexer);  /* Eat '}'.  */
+  if (token->keyword == RID_AT_END)
+    cp_parser_error (parser, "expected %<}%>");
+
+  /* Do not consume the RID_AT_END, so it will be read again as terminating
+     the @interface of @implementation.  */ 
+  if (token->keyword != RID_AT_END && token->type != CPP_EOF)
+    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);
@@ -21493,7 +22525,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
 /* Parse an Objective-C protocol declaration.  */
 
 static void
-cp_parser_objc_protocol_declaration (cp_parser* parser)
+cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
 {
   tree proto, protorefs;
   cp_token *tok;
@@ -21503,7 +22535,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
     {
       tok = cp_lexer_peek_token (parser->lexer);
       error_at (tok->location, "identifier expected after %<@protocol%>");
-      goto finish;
+      cp_parser_consume_semicolon_at_end_of_statement (parser);
+      return;
     }
 
   /* See if we have a forward declaration or a definition.  */
@@ -21512,8 +22545,21 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
   /* Try a forward declaration first.  */
   if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
     {
-      objc_declare_protocols (cp_parser_objc_identifier_list (parser));
-     finish:
+      while (true)
+       {
+         tree id;
+         
+         id = cp_parser_identifier (parser);
+         if (id == error_mark_node)
+           break;
+         
+         objc_declare_protocol (id, attributes);
+         
+         if(cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+           cp_lexer_consume_token (parser->lexer);
+         else
+           break;
+       }
       cp_parser_consume_semicolon_at_end_of_statement (parser);
     }
 
@@ -21522,7 +22568,7 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
     {
       proto = cp_parser_identifier (parser);
       protorefs = cp_parser_objc_protocol_refs_opt (parser);
-      objc_start_protocol (proto, protorefs);
+      objc_start_protocol (proto, protorefs, attributes);
       cp_parser_objc_method_prototype_list (parser);
     }
 }
@@ -21530,12 +22576,15 @@ cp_parser_objc_protocol_declaration (cp_parser* parser)
 /* Parse an Objective-C superclass or category.  */
 
 static void
-cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
-                                                         tree *categ)
+cp_parser_objc_superclass_or_category (cp_parser *parser, 
+                                      bool iface_p,
+                                      tree *super,
+                                      tree *categ, bool *is_class_extension)
 {
   cp_token *next = cp_lexer_peek_token (parser->lexer);
 
   *super = *categ = NULL_TREE;
+  *is_class_extension = false;
   if (next->type == CPP_COLON)
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat ':'.  */
@@ -21544,7 +22593,17 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
   else if (next->type == CPP_OPEN_PAREN)
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
-      *categ = cp_parser_identifier (parser);
+
+      /* If there is no category name, and this is an @interface, we
+        have a class extension.  */
+      if (iface_p && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+       {
+         *categ = NULL_TREE;
+         *is_class_extension = true;
+       }
+      else
+       *categ = cp_parser_identifier (parser);
+
       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
     }
 }
@@ -21552,21 +22611,32 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
 /* Parse an Objective-C class interface.  */
 
 static void
-cp_parser_objc_class_interface (cp_parser* parser)
+cp_parser_objc_class_interface (cp_parser* parser, tree attributes)
 {
   tree name, super, categ, protos;
+  bool is_class_extension;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@interface'.  */
   name = cp_parser_identifier (parser);
-  cp_parser_objc_superclass_or_category (parser, &super, &categ);
+  if (name == error_mark_node)
+    {
+      /* It's hard to recover because even if valid @interface stuff
+        is to follow, we can't compile it (or validate it) if we
+        don't even know which class it refers to.  Let's assume this
+        was a stray '@interface' token in the stream and skip it.
+      */
+      return;
+    }
+  cp_parser_objc_superclass_or_category (parser, true, &super, &categ,
+                                        &is_class_extension);
   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);
+  if (categ || is_class_extension)
+    objc_start_category_interface (name, categ, protos, attributes);
   else
     {
-      objc_start_class_interface (name, super, protos);
+      objc_start_class_interface (name, super, protos, attributes);
       /* Handle instance variable declarations, if any.  */
       cp_parser_objc_class_ivars (parser);
       objc_continue_interface ();
@@ -21581,10 +22651,22 @@ static void
 cp_parser_objc_class_implementation (cp_parser* parser)
 {
   tree name, super, categ;
+  bool is_class_extension;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@implementation'.  */
   name = cp_parser_identifier (parser);
-  cp_parser_objc_superclass_or_category (parser, &super, &categ);
+  if (name == error_mark_node)
+    {
+      /* It's hard to recover because even if valid @implementation
+        stuff is to follow, we can't compile it (or validate it) if
+        we don't even know which class it refers to.  Let's assume
+        this was a stray '@implementation' token in the stream and
+        skip it.
+      */
+      return;
+    }
+  cp_parser_objc_superclass_or_category (parser, false, &super, &categ,
+                                        &is_class_extension);
 
   /* We have either a class or a category on our hands.  */
   if (categ)
@@ -21612,11 +22694,31 @@ cp_parser_objc_end_implementation (cp_parser* parser)
 /* Parse an Objective-C declaration.  */
 
 static void
-cp_parser_objc_declaration (cp_parser* parser)
+cp_parser_objc_declaration (cp_parser* parser, tree attributes)
 {
   /* Try to figure out what kind of declaration is present.  */
   cp_token *kwd = cp_lexer_peek_token (parser->lexer);
 
+  if (attributes)
+    switch (kwd->keyword)
+      {
+       case RID_AT_ALIAS:
+       case RID_AT_CLASS:
+       case RID_AT_END:
+         error_at (kwd->location, "attributes may not be specified before"
+                   " the %<@%D%> Objective-C++ keyword",
+                   kwd->u.value);
+         attributes = NULL;
+         break;
+       case RID_AT_IMPLEMENTATION:
+         warning_at (kwd->location, OPT_Wattributes,
+                     "prefix attributes are ignored before %<@%D%>",
+                     kwd->u.value);
+         attributes = NULL;
+       default:
+         break;
+      }
+
   switch (kwd->keyword)
     {
     case RID_AT_ALIAS:
@@ -21626,10 +22728,10 @@ cp_parser_objc_declaration (cp_parser* parser)
       cp_parser_objc_class_declaration (parser);
       break;
     case RID_AT_PROTOCOL:
-      cp_parser_objc_protocol_declaration (parser);
+      cp_parser_objc_protocol_declaration (parser, attributes);
       break;
     case RID_AT_INTERFACE:
-      cp_parser_objc_class_interface (parser);
+      cp_parser_objc_class_interface (parser, attributes);
       break;
     case RID_AT_IMPLEMENTATION:
       cp_parser_objc_class_implementation (parser);
@@ -21654,44 +22756,93 @@ cp_parser_objc_declaration (cp_parser* parser)
      objc-catch-clause objc-catch-clause-seq [opt]
 
    objc-catch-clause:
-     @catch ( exception-declaration ) compound-statement
+     @catch ( objc-exception-declaration ) compound-statement
 
-   objc-finally-clause
+   objc-finally-clause:
      @finally compound-statement
 
-   Returns NULL_TREE.  */
+   objc-exception-declaration:
+     parameter-declaration
+     '...'
+
+   where '...' is to be interpreted literally, that is, it means CPP_ELLIPSIS.
+
+   Returns NULL_TREE.
+
+   PS: This function is identical to c_parser_objc_try_catch_finally_statement
+   for C.  Keep them in sync.  */   
 
 static tree
-cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
+cp_parser_objc_try_catch_finally_statement (cp_parser *parser)
+{
   location_t location;
   tree stmt;
 
   cp_parser_require_keyword (parser, RID_AT_TRY, RT_AT_TRY);
   location = cp_lexer_peek_token (parser->lexer)->location;
+  objc_maybe_warn_exceptions (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);
+  cp_parser_compound_statement (parser, NULL, false, 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_parameter_declarator *parm;
+      tree parameter_declaration = error_mark_node;
+      bool seen_open_paren = false;
 
       cp_lexer_consume_token (parser->lexer);
-      cp_parser_require (parser, CPP_OPEN_PAREN, RT_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, RT_CLOSE_PAREN);
-      objc_begin_catch_clause (parm);
-      cp_parser_compound_statement (parser, NULL, false);
+      if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+       seen_open_paren = true;
+      if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+       {
+         /* We have "@catch (...)" (where the '...' are literally
+            what is in the code).  Skip the '...'.
+            parameter_declaration is set to NULL_TREE, and
+            objc_being_catch_clauses() knows that that means
+            '...'.  */
+         cp_lexer_consume_token (parser->lexer);
+         parameter_declaration = NULL_TREE;
+       }
+      else
+       {
+         /* We have "@catch (NSException *exception)" or something
+            like that.  Parse the parameter declaration.  */
+         parm = cp_parser_parameter_declaration (parser, false, NULL);
+         if (parm == NULL)
+           parameter_declaration = error_mark_node;
+         else
+           parameter_declaration = grokdeclarator (parm->declarator,
+                                                   &parm->decl_specifiers,
+                                                   PARM, /*initialized=*/0,
+                                                   /*attrlist=*/NULL);
+       }
+      if (seen_open_paren)
+       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+      else
+       {
+         /* If there was no open parenthesis, we are recovering from
+            an error, and we are trying to figure out what mistake
+            the user has made.  */
+
+         /* If there is an immediate closing parenthesis, the user
+            probably forgot the opening one (ie, they typed "@catch
+            NSException *e)".  Parse the closing parenthesis and keep
+            going.  */
+         if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
+           cp_lexer_consume_token (parser->lexer);
+         
+         /* If these is no immediate closing parenthesis, the user
+            probably doesn't know that parenthesis are required at
+            all (ie, they typed "@catch NSException *e").  So, just
+            forget about the closing parenthesis and keep going.  */
+       }
+      objc_begin_catch_clause (parameter_declaration);
+      cp_parser_compound_statement (parser, NULL, false, false);
       objc_finish_catch_clause ();
     }
-
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AT_FINALLY))
     {
       cp_lexer_consume_token (parser->lexer);
@@ -21699,7 +22850,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
       /* 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);
+      cp_parser_compound_statement (parser, NULL, false, false);
       objc_build_finally_clause (location, pop_stmt_list (stmt));
     }
 
@@ -21714,13 +22865,15 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
    Returns NULL_TREE.  */
 
 static tree
-cp_parser_objc_synchronized_statement (cp_parser *parser) {
+cp_parser_objc_synchronized_statement (cp_parser *parser)
+{
   location_t location;
   tree lock, stmt;
 
   cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, RT_AT_SYNCHRONIZED);
 
   location = cp_lexer_peek_token (parser->lexer)->location;
+  objc_maybe_warn_exceptions (location);
   cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
   lock = cp_parser_expression (parser, false, NULL);
   cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
@@ -21728,7 +22881,7 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
   /* 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);
+  cp_parser_compound_statement (parser, NULL, false, false);
 
   return objc_build_synchronized (location, lock, pop_stmt_list (stmt));
 }
@@ -21741,14 +22894,15 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
    Returns a constructed '@throw' statement.  */
 
 static tree
-cp_parser_objc_throw_statement (cp_parser *parser) {
+cp_parser_objc_throw_statement (cp_parser *parser)
+{
   tree expr = NULL_TREE;
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   cp_parser_require_keyword (parser, RID_AT_THROW, RT_AT_THROW);
 
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    expr = cp_parser_assignment_expression (parser, false, NULL);
+    expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
@@ -21758,7 +22912,8 @@ cp_parser_objc_throw_statement (cp_parser *parser) {
 /* Parse an Objective-C statement.  */
 
 static tree
-cp_parser_objc_statement (cp_parser * parser) {
+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);
 
@@ -21778,6 +22933,412 @@ cp_parser_objc_statement (cp_parser * parser) {
 
   return error_mark_node;
 }
+
+/* If we are compiling ObjC++ and we see an __attribute__ we neeed to 
+   look ahead to see if an objc keyword follows the attributes.  This
+   is to detect the use of prefix attributes on ObjC @interface and 
+   @protocol.  */
+
+static bool
+cp_parser_objc_valid_prefix_attributes (cp_parser* parser, tree *attrib)
+{
+  cp_lexer_save_tokens (parser->lexer);
+  *attrib = cp_parser_attributes_opt (parser);
+  gcc_assert (*attrib);
+  if (OBJC_IS_AT_KEYWORD (cp_lexer_peek_token (parser->lexer)->keyword))
+    {
+      cp_lexer_commit_tokens (parser->lexer);
+      return true;
+    }
+  cp_lexer_rollback_tokens (parser->lexer);
+  return false;  
+}
+
+/* This routine is a minimal replacement for
+   c_parser_struct_declaration () used when parsing the list of
+   types/names or ObjC++ properties.  For example, when parsing the
+   code
+
+   @property (readonly) int a, b, c;
+
+   this function is responsible for parsing "int a, int b, int c" and
+   returning the declarations as CHAIN of DECLs.
+
+   TODO: Share this code with cp_parser_objc_class_ivars.  It's very
+   similar parsing.  */
+static tree
+cp_parser_objc_struct_declaration (cp_parser *parser)
+{
+  tree decls = NULL_TREE;
+  cp_decl_specifier_seq declspecs;
+  int decl_class_or_enum_p;
+  tree prefix_attributes;
+
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_NONE,
+                               &declspecs,
+                               &decl_class_or_enum_p);
+
+  if (declspecs.type == error_mark_node)
+    return error_mark_node;
+
+  /* auto, register, static, extern, mutable.  */
+  if (declspecs.storage_class != sc_none)
+    {
+      cp_parser_error (parser, "invalid type for property");
+      declspecs.storage_class = sc_none;
+    }
+  
+  /* __thread.  */
+  if (declspecs.specs[(int) ds_thread])
+    {
+      cp_parser_error (parser, "invalid type for property");
+      declspecs.specs[(int) ds_thread] = 0;
+    }
+  
+  /* typedef.  */
+  if (declspecs.specs[(int) ds_typedef])
+    {
+      cp_parser_error (parser, "invalid type for property");
+      declspecs.specs[(int) ds_typedef] = 0;
+    }
+
+  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 attributes, first_attribute, decl;
+      cp_declarator *declarator;
+      cp_token *token;
+
+      /* Parse the declarator.  */
+      declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+                                        NULL, NULL, 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);
+      
+      decl = grokfield (declarator, &declspecs,
+                       NULL_TREE, /*init_const_expr_p=*/false,
+                       NULL_TREE, attributes);
+
+      if (decl == error_mark_node || decl == NULL_TREE)
+       return error_mark_node;
+      
+      /* Reset PREFIX_ATTRIBUTES.  */
+      while (attributes && TREE_CHAIN (attributes) != first_attribute)
+       attributes = TREE_CHAIN (attributes);
+      if (attributes)
+       TREE_CHAIN (attributes) = NULL_TREE;
+
+      DECL_CHAIN (decl) = decls;
+      decls = decl;
+
+      token = cp_lexer_peek_token (parser->lexer);
+      if (token->type == CPP_COMMA)
+       {
+         cp_lexer_consume_token (parser->lexer);  /* Eat ','.  */
+         continue;
+       }
+      else
+       break;
+    }
+  return decls;
+}
+
+/* Parse an Objective-C @property declaration.  The syntax is:
+
+   objc-property-declaration:
+     '@property' objc-property-attributes[opt] struct-declaration ;
+
+   objc-property-attributes:
+    '(' objc-property-attribute-list ')'
+
+   objc-property-attribute-list:
+     objc-property-attribute
+     objc-property-attribute-list, objc-property-attribute
+
+   objc-property-attribute
+     'getter' = identifier
+     'setter' = identifier
+     'readonly'
+     'readwrite'
+     'assign'
+     'retain'
+     'copy'
+     'nonatomic'
+
+  For example:
+    @property NSString *name;
+    @property (readonly) id object;
+    @property (retain, nonatomic, getter=getTheName) id name;
+    @property int a, b, c;
+
+   PS: This function is identical to
+   c_parser_objc_at_property_declaration for C.  Keep them in sync.  */
+static void 
+cp_parser_objc_at_property_declaration (cp_parser *parser)
+{
+  /* The following variables hold the attributes of the properties as
+     parsed.  They are 'false' or 'NULL_TREE' if the attribute was not
+     seen.  When we see an attribute, we set them to 'true' (if they
+     are boolean properties) or to the identifier (if they have an
+     argument, ie, for getter and setter).  Note that here we only
+     parse the list of attributes, check the syntax and accumulate the
+     attributes that we find.  objc_add_property_declaration() will
+     then process the information.  */
+  bool property_assign = false;
+  bool property_copy = false;
+  tree property_getter_ident = NULL_TREE;
+  bool property_nonatomic = false;
+  bool property_readonly = false;
+  bool property_readwrite = false;
+  bool property_retain = false;
+  tree property_setter_ident = NULL_TREE;
+
+  /* 'properties' is the list of properties that we read.  Usually a
+     single one, but maybe more (eg, in "@property int a, b, c;" there
+     are three).  */
+  tree properties;
+  location_t loc;
+
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@property'.  */
+
+  /* Parse the optional attribute list...  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      /* Eat the '('.  */
+      cp_lexer_consume_token (parser->lexer);
+
+      while (true)
+       {
+         bool syntax_error = false;
+         cp_token *token = cp_lexer_peek_token (parser->lexer);
+         enum rid keyword;
+
+         if (token->type != CPP_NAME)
+           {
+             cp_parser_error (parser, "expected identifier");
+             break;
+           }
+         keyword = C_RID_CODE (token->u.value);
+         cp_lexer_consume_token (parser->lexer);
+         switch (keyword)
+           {
+           case RID_ASSIGN:    property_assign = true;    break;
+           case RID_COPY:      property_copy = true;      break;
+           case RID_NONATOMIC: property_nonatomic = true; break;
+           case RID_READONLY:  property_readonly = true;  break;
+           case RID_READWRITE: property_readwrite = true; break;
+           case RID_RETAIN:    property_retain = true;    break;
+
+           case RID_GETTER:
+           case RID_SETTER:
+             if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+               {
+                 if (keyword == RID_GETTER)
+                   cp_parser_error (parser,
+                                    "missing %<=%> (after %<getter%> attribute)");
+                 else
+                   cp_parser_error (parser,
+                                    "missing %<=%> (after %<setter%> attribute)");
+                 syntax_error = true;
+                 break;
+               }
+             cp_lexer_consume_token (parser->lexer); /* eat the = */
+             if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+               {
+                 cp_parser_error (parser, "expected identifier");
+                 syntax_error = true;
+                 break;
+               }
+             if (keyword == RID_SETTER)
+               {
+                 if (property_setter_ident != NULL_TREE)
+                   cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
+                 else
+                   property_setter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
+                 cp_lexer_consume_token (parser->lexer);
+                 if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+                   cp_parser_error (parser, "setter name must terminate with %<:%>");
+                 else
+                   cp_lexer_consume_token (parser->lexer);
+               }
+             else
+               {
+                 if (property_getter_ident != NULL_TREE)
+                   cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
+                 else
+                   property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
+                 cp_lexer_consume_token (parser->lexer);
+               }
+             break;
+           default:
+             cp_parser_error (parser, "unknown property attribute");
+             syntax_error = true;
+             break;
+           }
+
+         if (syntax_error)
+           break;
+
+         if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+           cp_lexer_consume_token (parser->lexer);
+         else
+           break;
+       }
+
+      /* FIXME: "@property (setter, assign);" will generate a spurious
+        "error: expected ‘)’ before ‘,’ token".  This is because
+        cp_parser_require, unlike the C counterpart, will produce an
+        error even if we are in error recovery.  */
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
+       {
+         cp_parser_skip_to_closing_parenthesis (parser,
+                                                /*recovering=*/true,
+                                                /*or_comma=*/false,
+                                                /*consume_paren=*/true);
+       }
+    }
+
+  /* ... and the property declaration(s).  */
+  properties = cp_parser_objc_struct_declaration (parser);
+
+  if (properties == error_mark_node)
+    {
+      cp_parser_skip_to_end_of_statement (parser);
+      /* If the next token is now a `;', consume it.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+       cp_lexer_consume_token (parser->lexer);
+      return;
+    }
+
+  if (properties == NULL_TREE)
+    cp_parser_error (parser, "expected identifier");
+  else
+    {
+      /* Comma-separated properties are chained together in
+        reverse order; add them one by one.  */
+      properties = nreverse (properties);
+      
+      for (; properties; properties = TREE_CHAIN (properties))
+       objc_add_property_declaration (loc, copy_node (properties),
+                                      property_readonly, property_readwrite,
+                                      property_assign, property_retain,
+                                      property_copy, property_nonatomic,
+                                      property_getter_ident, property_setter_ident);
+    }
+  
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+}
+
+/* Parse an Objective-C++ @synthesize declaration.  The syntax is:
+
+   objc-synthesize-declaration:
+     @synthesize objc-synthesize-identifier-list ;
+
+   objc-synthesize-identifier-list:
+     objc-synthesize-identifier
+     objc-synthesize-identifier-list, objc-synthesize-identifier
+
+   objc-synthesize-identifier
+     identifier
+     identifier = identifier
+
+  For example:
+    @synthesize MyProperty;
+    @synthesize OneProperty, AnotherProperty=MyIvar, YetAnotherProperty;
+
+  PS: This function is identical to c_parser_objc_at_synthesize_declaration
+  for C.  Keep them in sync.
+*/
+static void 
+cp_parser_objc_at_synthesize_declaration (cp_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@synthesize'.  */
+  while (true)
+    {
+      tree property, ivar;
+      property = cp_parser_identifier (parser);
+      if (property == error_mark_node)
+       {
+         cp_parser_consume_semicolon_at_end_of_statement (parser);
+         return;
+       }
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         ivar = cp_parser_identifier (parser);
+         if (ivar == error_mark_node)
+           {
+             cp_parser_consume_semicolon_at_end_of_statement (parser);
+             return;
+           }
+       }
+      else
+       ivar = NULL_TREE;
+      list = chainon (list, build_tree_list (ivar, property));
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+      else
+       break;
+    }
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  objc_add_synthesize_declaration (loc, list);
+}
+
+/* Parse an Objective-C++ @dynamic declaration.  The syntax is:
+
+   objc-dynamic-declaration:
+     @dynamic identifier-list ;
+
+   For example:
+     @dynamic MyProperty;
+     @dynamic MyProperty, AnotherProperty;
+
+  PS: This function is identical to c_parser_objc_at_dynamic_declaration
+  for C.  Keep them in sync.
+*/
+static void 
+cp_parser_objc_at_dynamic_declaration (cp_parser *parser)
+{
+  tree list = NULL_TREE;
+  location_t loc;
+  loc = cp_lexer_peek_token (parser->lexer)->location;
+
+  cp_lexer_consume_token (parser->lexer);  /* Eat '@dynamic'.  */
+  while (true)
+    {
+      tree property;
+      property = cp_parser_identifier (parser);
+      if (property == error_mark_node)
+       {
+         cp_parser_consume_semicolon_at_end_of_statement (parser);
+         return;
+       }
+      list = chainon (list, build_tree_list (NULL, property));
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+      else
+       break;
+    }
+  cp_parser_consume_semicolon_at_end_of_statement (parser);
+  objc_add_dynamic_declaration (loc, list);
+}
+
 \f
 /* OpenMP 2.5 parsing routines.  */
 
@@ -23063,7 +24624,8 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
          /* If decl is an iterator, preserve the operator on decl
             until finish_omp_for.  */
          if (decl
-             && (type_dependent_expression_p (decl)
+             && ((type_dependent_expression_p (decl)
+                  && !POINTER_TYPE_P (TREE_TYPE (decl)))
                  || CLASS_TYPE_P (TREE_TYPE (decl))))
            incr = cp_parser_omp_for_incr (parser, decl);
          else