OSDN Git Service

Restore canonical type comparison for dependent type(def)s
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index a3e9f0e..864ec9b 100644 (file)
@@ -1,6 +1,6 @@
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005, 2007, 2008, 2009  Free Software Foundation, Inc.
+   2005, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -23,20 +23,19 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "dyn-string.h"
-#include "varray.h"
 #include "cpplib.h"
 #include "tree.h"
 #include "cp-tree.h"
-#include "c-pragma.h"
+#include "intl.h"
+#include "c-family/c-pragma.h"
 #include "decl.h"
 #include "flags.h"
-#include "diagnostic.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "output.h"
 #include "target.h"
 #include "cgraph.h"
-#include "c-common.h"
+#include "c-family/c-common.h"
 #include "plugin.h"
 
 \f
@@ -149,6 +148,128 @@ typedef struct GTY(()) cp_token_cache {
   cp_token * GTY ((skip)) last;
 } cp_token_cache;
 
+/* The various kinds of non integral constant we encounter. */
+typedef enum non_integral_constant {
+  NIC_NONE,
+  /* floating-point literal */
+  NIC_FLOAT,
+  /* %<this%> */
+  NIC_THIS,
+  /* %<__FUNCTION__%> */
+  NIC_FUNC_NAME,
+  /* %<__PRETTY_FUNCTION__%> */
+  NIC_PRETTY_FUNC,
+  /* %<__func__%> */
+  NIC_C99_FUNC,
+  /* "%<va_arg%> */
+  NIC_VA_ARG,
+  /* a cast */
+  NIC_CAST,
+  /* %<typeid%> operator */
+  NIC_TYPEID,
+  /* non-constant compound literals */
+  NIC_NCC,
+  /* a function call */
+  NIC_FUNC_CALL,
+  /* an increment */
+  NIC_INC,
+  /* an decrement */
+  NIC_DEC,
+  /* an array reference */
+  NIC_ARRAY_REF,
+  /* %<->%> */
+  NIC_ARROW,
+  /* %<.%> */
+  NIC_POINT,
+  /* the address of a label */
+  NIC_ADDR_LABEL,
+  /* %<*%> */
+  NIC_STAR,
+  /* %<&%> */
+  NIC_ADDR,
+  /* %<++%> */
+  NIC_PREINCREMENT,
+  /* %<--%> */
+  NIC_PREDECREMENT,
+  /* %<new%> */
+  NIC_NEW,
+  /* %<delete%> */
+  NIC_DEL,
+  /* calls to overloaded operators */
+  NIC_OVERLOADED,
+  /* an assignment */
+  NIC_ASSIGNMENT,
+  /* a comma operator */
+  NIC_COMMA,
+  /* a call to a constructor */
+  NIC_CONSTRUCTOR
+} non_integral_constant;
+
+/* The various kinds of errors about name-lookup failing. */
+typedef enum name_lookup_error {
+  /* NULL */
+  NLE_NULL,
+  /* is not a type */
+  NLE_TYPE,
+  /* is not a class or namespace */
+  NLE_CXX98,
+  /* is not a class, namespace, or enumeration */
+  NLE_NOT_CXX98
+} name_lookup_error;
+
+/* The various kinds of required token */
+typedef enum required_token {
+  RT_NONE,
+  RT_SEMICOLON,  /* ';' */
+  RT_OPEN_PAREN, /* '(' */
+  RT_CLOSE_BRACE, /* '}' */
+  RT_OPEN_BRACE,  /* '{' */
+  RT_CLOSE_SQUARE, /* ']' */
+  RT_OPEN_SQUARE,  /* '[' */
+  RT_COMMA, /* ',' */
+  RT_SCOPE, /* '::' */
+  RT_LESS, /* '<' */
+  RT_GREATER, /* '>' */
+  RT_EQ, /* '=' */
+  RT_ELLIPSIS, /* '...' */
+  RT_MULT, /* '*' */
+  RT_COMPL, /* '~' */
+  RT_COLON, /* ':' */
+  RT_COLON_SCOPE, /* ':' or '::' */
+  RT_CLOSE_PAREN, /* ')' */
+  RT_COMMA_CLOSE_PAREN, /* ',' or ')' */
+  RT_PRAGMA_EOL, /* end of line */
+  RT_NAME, /* identifier */
+
+  /* The type is CPP_KEYWORD */
+  RT_NEW, /* new */
+  RT_DELETE, /* delete */
+  RT_RETURN, /* return */
+  RT_WHILE, /* while */
+  RT_EXTERN, /* extern */
+  RT_STATIC_ASSERT, /* static_assert */
+  RT_DECLTYPE, /* decltype */
+  RT_OPERATOR, /* operator */
+  RT_CLASS, /* class */
+  RT_TEMPLATE, /* template */
+  RT_NAMESPACE, /* namespace */
+  RT_USING, /* using */
+  RT_ASM, /* asm */
+  RT_TRY, /* try */
+  RT_CATCH, /* catch */
+  RT_THROW, /* throw */
+  RT_LABEL, /* __label__ */
+  RT_AT_TRY, /* @try */
+  RT_AT_SYNCHRONIZED, /* @synchronized */
+  RT_AT_THROW, /* @throw */
+
+  RT_SELECT,  /* selection-statement */
+  RT_INTERATION, /* iteration-statement */
+  RT_JUMP, /* jump-statement */
+  RT_CLASS_KEY, /* class-key */
+  RT_CLASS_TYPENAME_TEMPLATE /* class, typename, or template */
+} required_token;
+
 /* Prototypes.  */
 
 static cp_lexer *cp_lexer_new_main
@@ -272,7 +393,7 @@ cp_lexer_new_main (void)
   c_common_no_more_pch ();
 
   /* Allocate the memory.  */
-  lexer = GGC_CNEW (cp_lexer);
+  lexer = ggc_alloc_cleared_cp_lexer ();
 
 #ifdef ENABLE_CHECKING
   /* Initially we are not debugging.  */
@@ -283,7 +404,7 @@ cp_lexer_new_main (void)
 
   /* Create the buffer.  */
   alloc = CP_LEXER_BUFFER_SIZE;
-  buffer = GGC_NEWVEC (cp_token, alloc);
+  buffer = ggc_alloc_vec_cp_token (alloc);
 
   /* Put the first token in the buffer.  */
   space = alloc;
@@ -324,7 +445,7 @@ cp_lexer_new_from_tokens (cp_token_cache *cache)
 {
   cp_token *first = cache->first;
   cp_token *last = cache->last;
-  cp_lexer *lexer = GGC_CNEW (cp_lexer);
+  cp_lexer *lexer = ggc_alloc_cleared_cp_lexer ();
 
   /* We do not own the buffer.  */
   lexer->buffer = NULL;
@@ -402,7 +523,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
    /* Get a new token from the preprocessor.  */
   token->type
     = c_lex_with_flags (&token->u.value, &token->location, &token->flags,
-                       lexer == NULL ? 0 : C_LEX_RAW_STRINGS);
+                       lexer == NULL ? 0 : C_LEX_STRING_NO_JOIN);
   token->keyword = RID_MAX;
   token->pragma_kind = PRAGMA_NONE;
 
@@ -444,21 +565,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)
@@ -561,6 +689,7 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
     case RID_SHORT:
     case RID_INT:
     case RID_LONG:
+    case RID_INT128:
     case RID_SIGNED:
     case RID_UNSIGNED:
     case RID_FLOAT:
@@ -792,6 +921,7 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
     case CPP_STRING16:
     case CPP_STRING32:
     case CPP_WSTRING:
+    case CPP_UTF8STRING:
       fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
       break;
 
@@ -823,7 +953,7 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
 static cp_token_cache *
 cp_token_cache_new (cp_token *first, cp_token *last)
 {
-  cp_token_cache *cache = GGC_NEW (cp_token_cache);
+  cp_token_cache *cache = ggc_alloc_cp_token_cache ();
   cache->first = first;
   cache->last = last;
   return cache;
@@ -888,6 +1018,7 @@ make_declarator (cp_declarator_kind kind)
   declarator->attributes = NULL_TREE;
   declarator->declarator = NULL;
   declarator->parameter_pack_p = false;
+  declarator->id_loc = UNKNOWN_LOCATION;
 
   return declarator;
 }
@@ -944,6 +1075,7 @@ make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
   declarator->u.pointer.class_type = NULL_TREE;
   if (target)
     {
+      declarator->id_loc = target->id_loc;
       declarator->parameter_pack_p = target->parameter_pack_p;
       target->parameter_pack_p = false;
     }
@@ -967,6 +1099,7 @@ make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target,
   declarator->u.reference.rvalue_ref = rvalue_ref;
   if (target)
     {
+      declarator->id_loc = target->id_loc;
       declarator->parameter_pack_p = target->parameter_pack_p;
       target->parameter_pack_p = false;
     }
@@ -1023,6 +1156,7 @@ make_call_declarator (cp_declarator *target,
   declarator->u.function.late_return_type = late_return_type;
   if (target)
     {
+      declarator->id_loc = target->id_loc;
       declarator->parameter_pack_p = target->parameter_pack_p;
       target->parameter_pack_p = false;
     }
@@ -1045,6 +1179,7 @@ make_array_declarator (cp_declarator *element, tree bounds)
   declarator->u.array.bounds = bounds;
   if (element)
     {
+      declarator->id_loc = element->id_loc;
       declarator->parameter_pack_p = element->parameter_pack_p;
       element->parameter_pack_p = false;
     }
@@ -1194,8 +1329,15 @@ enum
   /* The construct is optional.  If it is not present, then no error
      should be issued.  */
   CP_PARSER_FLAGS_OPTIONAL = 0x1,
-  /* When parsing a type-specifier, do not allow user-defined types.  */
-  CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2
+  /* When parsing a type-specifier, treat user-defined type-names
+     as non-type identifiers.  */
+  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,
+  /* 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
@@ -1368,7 +1510,7 @@ cp_parser_context_new (cp_parser_context* next)
       memset (context, 0, sizeof (*context));
     }
   else
-    context = GGC_CNEW (cp_parser_context);
+    context = ggc_alloc_cleared_cp_parser_context ();
 
   /* No errors have occurred yet in this context.  */
   context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
@@ -1386,6 +1528,34 @@ 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 {
@@ -1512,21 +1682,10 @@ typedef struct GTY(()) cp_parser {
      issued as an error message if a type is defined.  */
   const char *type_definition_forbidden_message;
 
-  /* A list of lists. The outer list is a stack, used for member
-     functions of local classes. At each level there are two sub-list,
-     one on TREE_VALUE and one on TREE_PURPOSE. Each of those
-     sub-lists has a FUNCTION_DECL or TEMPLATE_DECL on their
-     TREE_VALUE's. The functions are chained in reverse declaration
-     order.
-
-     The TREE_PURPOSE sublist contains those functions with default
-     arguments that need post processing, and the TREE_VALUE sublist
-     contains those functions with definitions that need post
-     processing.
-
-     These lists can only be processed once the outermost class being
-     defined is complete.  */
-  tree unparsed_functions_queues;
+  /* 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.  */
@@ -1537,6 +1696,29 @@ typedef struct GTY(()) cp_parser {
   unsigned num_template_parameter_lists;
 } cp_parser;
 
+/* Managing the unparsed function queues.  */
+
+#define unparsed_funs_with_default_args \
+  VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_default_args
+#define unparsed_funs_with_definitions \
+  VEC_last (cp_unparsed_functions_entry, parser->unparsed_queues)->funs_with_definitions
+
+static void
+push_unparsed_function_queues (cp_parser *parser)
+{
+  VEC_safe_push (cp_unparsed_functions_entry, gc,
+                parser->unparsed_queues, NULL);
+  unparsed_funs_with_default_args = NULL;
+  unparsed_funs_with_definitions = make_tree_vector ();
+}
+
+static void
+pop_unparsed_function_queues (cp_parser *parser)
+{
+  release_tree_vector (unparsed_funs_with_definitions);
+  VEC_pop (cp_unparsed_functions_entry, parser->unparsed_queues);
+}
+
 /* Prototypes.  */
 
 /* Constructors and destructors.  */
@@ -1589,7 +1771,9 @@ static tree cp_parser_postfix_open_square_expression
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
 static VEC(tree,gc) *cp_parser_parenthesized_expression_list
-  (cp_parser *, bool, bool, bool, bool *);
+  (cp_parser *, int, bool, bool, bool *);
+/* Values for the second parameter of cp_parser_parenthesized_expression_list.  */
+enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
 static void cp_parser_pseudo_destructor_name
   (cp_parser *, tree *, tree *);
 static tree cp_parser_unary_expression
@@ -1626,6 +1810,14 @@ static tree cp_parser_constant_expression
   (cp_parser *, bool, bool *);
 static tree cp_parser_builtin_offsetof
   (cp_parser *);
+static tree cp_parser_lambda_expression
+  (cp_parser *);
+static void cp_parser_lambda_introducer
+  (cp_parser *, tree);
+static void cp_parser_lambda_declarator_opt
+  (cp_parser *, tree);
+static void cp_parser_lambda_body
+  (cp_parser *, tree);
 
 /* Statements [gram.stmt.stmt]  */
 
@@ -1647,6 +1839,10 @@ static tree cp_parser_iteration_statement
   (cp_parser *);
 static void cp_parser_for_init_statement
   (cp_parser *);
+static tree  cp_parser_c_for
+  (cp_parser *);
+static tree  cp_parser_range_for
+  (cp_parser *);
 static tree cp_parser_jump_statement
   (cp_parser *);
 static void cp_parser_declaration_statement
@@ -1733,10 +1929,11 @@ static tree cp_parser_type_id
   (cp_parser *);
 static tree cp_parser_template_type_arg
   (cp_parser *);
+static tree cp_parser_trailing_type_id (cp_parser *);
 static tree cp_parser_type_id_1
-  (cp_parser *, bool);
+  (cp_parser *, bool, bool);
 static void cp_parser_type_specifier_seq
-  (cp_parser *, bool, cp_decl_specifier_seq *);
+  (cp_parser *, bool, bool, cp_decl_specifier_seq *);
 static tree cp_parser_parameter_declaration_clause
   (cp_parser *);
 static tree cp_parser_parameter_declaration_list
@@ -1859,6 +2056,8 @@ static tree cp_parser_asm_operand_list
   (cp_parser *);
 static tree cp_parser_asm_clobber_list
   (cp_parser *);
+static tree cp_parser_asm_label_list
+  (cp_parser *);
 static tree cp_parser_attributes_opt
   (cp_parser *);
 static tree cp_parser_attribute_list
@@ -1897,9 +2096,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 */
 
@@ -1953,10 +2162,12 @@ static void cp_parser_set_decl_spec_type
   (cp_decl_specifier_seq *, tree, location_t, bool);
 static bool cp_parser_friend_p
   (const cp_decl_specifier_seq *);
+static void cp_parser_required_error
+  (cp_parser *, required_token, bool);
 static cp_token *cp_parser_require
-  (cp_parser *, enum cpp_ttype, const char *);
+  (cp_parser *, enum cpp_ttype, required_token);
 static cp_token *cp_parser_require_keyword
-  (cp_parser *, enum rid, const char *);
+  (cp_parser *, enum rid, required_token);
 static bool cp_parser_token_starts_function_definition_p
   (cp_token *);
 static bool cp_parser_next_token_starts_class_definition_p
@@ -1992,7 +2203,7 @@ static bool cp_parser_uncommitted_to_tentative_parse_p
 static void cp_parser_error
   (cp_parser *, const char *);
 static void cp_parser_name_lookup_error
-  (cp_parser *, tree, tree, const char *, location_t);
+  (cp_parser *, tree, tree, name_lookup_error, location_t);
 static bool cp_parser_simulate_error
   (cp_parser *);
 static bool cp_parser_check_type_definition
@@ -2002,7 +2213,7 @@ static void cp_parser_check_for_definition_in_return_type
 static void cp_parser_check_for_invalid_template_id
   (cp_parser *, tree, location_t location);
 static bool cp_parser_non_integral_constant_expression
-  (cp_parser *, const char *);
+  (cp_parser *, non_integral_constant);
 static void cp_parser_diagnose_invalid_type_name
   (cp_parser *, tree, tree, location_t);
 static bool cp_parser_parse_and_diagnose_invalid_type_name
@@ -2050,7 +2261,8 @@ cp_parser_is_string_literal (cp_token* token)
   return (token->type == CPP_STRING ||
          token->type == CPP_STRING16 ||
          token->type == CPP_STRING32 ||
-         token->type == CPP_WSTRING);
+         token->type == CPP_WSTRING ||
+         token->type == CPP_UTF8STRING);
 }
 
 /* Returns nonzero if TOKEN is the indicated KEYWORD.  */
@@ -2068,7 +2280,7 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword)
    OTHER-TOKEN".  */
 
 static void
-cp_parser_error (cp_parser* parser, const char* message)
+cp_parser_error (cp_parser* parser, const char* gmsgid)
 {
   if (!cp_parser_simulate_error (parser))
     {
@@ -2085,7 +2297,7 @@ cp_parser_error (cp_parser* parser, const char* message)
          return;
        }
 
-      c_parse_error (message,
+      c_parse_error (gmsgid,
                     /* Because c_parser_error does not understand
                        CPP_KEYWORD, keywords are treated like
                        identifiers.  */
@@ -2103,7 +2315,7 @@ static void
 cp_parser_name_lookup_error (cp_parser* parser,
                             tree name,
                             tree decl,
-                            const char* desired,
+                            name_lookup_error desired,
                             location_t location)
 {
   /* If name lookup completely failed, tell the user that NAME was not
@@ -2126,11 +2338,64 @@ cp_parser_name_lookup_error (cp_parser* parser,
        error_at (location, "%qE has not been declared", name);
     }
   else if (parser->scope && parser->scope != global_namespace)
-    error_at (location, "%<%E::%E%> %s", parser->scope, name, desired);
+    {
+      switch (desired)
+       {
+         case NLE_TYPE:
+           error_at (location, "%<%E::%E%> is not a type",
+                               parser->scope, name);
+           break;
+         case NLE_CXX98:
+           error_at (location, "%<%E::%E%> is not a class or namespace",
+                               parser->scope, name);
+           break;
+         case NLE_NOT_CXX98:
+           error_at (location,
+                     "%<%E::%E%> is not a class, namespace, or enumeration",
+                     parser->scope, name);
+           break;
+         default:
+           gcc_unreachable ();
+           
+       }
+    }
   else if (parser->scope == global_namespace)
-    error_at (location, "%<::%E%> %s", name, desired);
+    {
+      switch (desired)
+       {
+         case NLE_TYPE:
+           error_at (location, "%<::%E%> is not a type", name);
+           break;
+         case NLE_CXX98:
+           error_at (location, "%<::%E%> is not a class or namespace", name);
+           break;
+         case NLE_NOT_CXX98:
+           error_at (location,
+                     "%<::%E%> is not a class, namespace, or enumeration",
+                     name);
+           break;
+         default:
+           gcc_unreachable ();
+       }
+    }
   else
-    error_at (location, "%qE %s", name, desired);
+    {
+      switch (desired)
+       {
+         case NLE_TYPE:
+           error_at (location, "%qE is not a type", name);
+           break;
+         case NLE_CXX98:
+           error_at (location, "%qE is not a class or namespace", name);
+           break;
+         case NLE_NOT_CXX98:
+           error_at (location,
+                     "%qE is not a class, namespace, or enumeration", name);
+           break;
+         default:
+           gcc_unreachable ();
+       }
+    }
 }
 
 /* If we are parsing tentatively, remember that an error has occurred
@@ -2185,6 +2450,7 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
            "explicit",
            "friend",
            "typedef",
+            "constexpr",
            "__complex",
            "__thread"
          };
@@ -2281,20 +2547,112 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
 
 static bool
 cp_parser_non_integral_constant_expression (cp_parser  *parser,
-                                           const char *thing)
+                                           non_integral_constant thing)
 {
   parser->non_integral_constant_expression_p = true;
   if (parser->integral_constant_expression_p)
     {
       if (!parser->allow_non_integral_constant_expression_p)
        {
-         /* Don't use `%s' to print THING, because quotations (`%<', `%>')
-            in the message need to be interpreted.  */
-         char *message = concat (thing,
-                                 " cannot appear in a constant-expression",
-                                 NULL);
-         error (message);
-         free (message);
+         const char *msg = NULL;
+         switch (thing)
+           {
+             case NIC_FLOAT:
+               error ("floating-point literal "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_CAST:
+               error ("a cast to a type other than an integral or "
+                      "enumeration type cannot appear in a "
+                      "constant-expression");
+               return true;
+             case NIC_TYPEID:
+               error ("%<typeid%> operator "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_NCC:
+               error ("non-constant compound literals "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_FUNC_CALL:
+               error ("a function call "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_INC:
+               error ("an increment "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_DEC:
+               error ("an decrement "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_ARRAY_REF:
+               error ("an array reference "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_ADDR_LABEL:
+               error ("the address of a label "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_OVERLOADED:
+               error ("calls to overloaded operators "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_ASSIGNMENT:
+               error ("an assignment cannot appear in a constant-expression");
+               return true;
+             case NIC_COMMA:
+               error ("a comma operator "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_CONSTRUCTOR:
+               error ("a call to a constructor "
+                      "cannot appear in a constant-expression");
+               return true;
+             case NIC_THIS:
+               msg = "this";
+               break;
+             case NIC_FUNC_NAME:
+               msg = "__FUNCTION__";
+               break;
+             case NIC_PRETTY_FUNC:
+               msg = "__PRETTY_FUNCTION__";
+               break;
+             case NIC_C99_FUNC:
+               msg = "__func__";
+               break;
+             case NIC_VA_ARG:
+               msg = "va_arg";
+               break;
+             case NIC_ARROW:
+               msg = "->";
+               break;
+             case NIC_POINT:
+               msg = ".";
+               break;
+             case NIC_STAR:
+               msg = "*";
+               break;
+             case NIC_ADDR:
+               msg = "&";
+               break;
+             case NIC_PREINCREMENT:
+               msg = "++";
+               break;
+             case NIC_PREDECREMENT:
+               msg = "--";
+               break;
+             case NIC_NEW:
+               msg = "new";
+               break;
+             case NIC_DEL:
+               msg = "delete";
+               break;
+             default:
+               gcc_unreachable ();
+           }
+         if (msg)
+           error ("%qs cannot appear in a constant-expression", msg);
          return true;
        }
     }
@@ -2340,8 +2698,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;
 
@@ -2360,7 +2721,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
                  base_type = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (base_type);
                  for (field = TYPE_FIELDS (base_type);
                       field;
-                      field = TREE_CHAIN (field))
+                      field = DECL_CHAIN (field))
                    if (TREE_CODE (field) == TYPE_DECL
                        && DECL_NAME (field) == id)
                      {
@@ -2382,6 +2743,21 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
       if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
        error_at (location, "%qE in namespace %qE does not name a type",
                  id, parser->scope);
+      else if (CLASS_TYPE_P (parser->scope)
+              && constructor_name_p (id, parser->scope))
+       {
+         /* A<T>::A<T>() */
+         error_at (location, "%<%T::%E%> names the constructor, not"
+                   " the type", parser->scope, id);
+         if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+           error_at (location, "and %qT has no template constructors",
+                     parser->scope);
+       }
+      else if (TYPE_P (parser->scope)
+              && dependent_scope_p (parser->scope))
+       error_at (location, "need %<typename%> before %<%T::%E%> because "
+                 "%qT is a dependent scope",
+                 parser->scope, id, parser->scope);
       else if (TYPE_P (parser->scope))
        error_at (location, "%qE in class %qT does not name a type",
                  id, parser->scope);
@@ -2407,6 +2783,14 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
   tree id;
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
+  /* Avoid duplicate error about ambiguous lookup.  */
+  if (token->type == CPP_NESTED_NAME_SPECIFIER)
+    {
+      cp_token *next = cp_lexer_peek_nth_token (parser->lexer, 2);
+      if (next->type == CPP_NAME && next->ambiguous_p)
+       goto out;
+    }
+
   cp_parser_parse_tentatively (parser);
   id = cp_parser_id_expression (parser,
                                /*template_keyword_p=*/false,
@@ -2414,12 +2798,9 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
                                /*template_p=*/NULL,
                                /*declarator_p=*/true,
                                /*optional_p=*/false);
-  /* After the id-expression, there should be a plain identifier,
-     otherwise this is not a simple variable declaration. Also, if
-     the scope is dependent, we cannot do much.  */
-  if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
-      || (parser->scope && TYPE_P (parser->scope)
-         && dependent_type_p (parser->scope))
+  /* If the next token is a (, this is a function with no explicit return
+     type, i.e. constructor, destructor or conversion op.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
       || TREE_CODE (id) == TYPE_DECL)
     {
       cp_parser_abort_tentative_parse (parser);
@@ -2431,9 +2812,12 @@ cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
   /* Emit a diagnostic for the invalid type.  */
   cp_parser_diagnose_invalid_type_name (parser, parser->scope,
                                        id, token->location);
-  /* Skip to the end of the declaration; there's no point in
-     trying to process it.  */
-  cp_parser_skip_to_end_of_block_or_statement (parser);
+ out:
+  /* If we aren't in the middle of a declarator (i.e. in a
+     parameter-declaration-clause), skip to the end of the declaration;
+     there's no point in trying to process it.  */
+  if (!parser->in_declarator_p)
+    cp_parser_skip_to_end_of_block_or_statement (parser);
   return true;
 }
 
@@ -2450,6 +2834,7 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
 {
   unsigned paren_depth = 0;
   unsigned brace_depth = 0;
+  unsigned square_depth = 0;
 
   if (recovering && !or_comma
       && cp_parser_uncommitted_to_tentative_parse_p (parser))
@@ -2466,6 +2851,15 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
          /* If we've run out of tokens, then there is no closing `)'.  */
          return 0;
 
+        /* This is good for lambda expression capture-lists.  */
+        case CPP_OPEN_SQUARE:
+          ++square_depth;
+          break;
+        case CPP_CLOSE_SQUARE:
+          if (!square_depth--)
+            return 0;
+          break;
+
        case CPP_SEMICOLON:
          /* This matches the processing in skip_to_end_of_statement.  */
          if (!brace_depth)
@@ -2481,7 +2875,8 @@ cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
          break;
 
        case CPP_COMMA:
-         if (recovering && or_comma && !brace_depth && !paren_depth)
+         if (recovering && or_comma && !brace_depth && !paren_depth
+             && !square_depth)
            return -1;
          break;
 
@@ -2583,7 +2978,7 @@ static void
 cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
 {
   /* Look for the trailing `;'.  */
-  if (!cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"))
+  if (!cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON))
     {
       /* If there is additional (erroneous) input, skip to the end of
         the statement.  */
@@ -2711,7 +3106,7 @@ static void
 cp_parser_require_pragma_eol (cp_parser *parser, cp_token *pragma_tok)
 {
   parser->lexer->in_pragma = false;
-  if (!cp_parser_require (parser, CPP_PRAGMA_EOL, "end of line"))
+  if (!cp_parser_require (parser, CPP_PRAGMA_EOL, RT_PRAGMA_EOL))
     cp_parser_skip_to_pragma_eol (parser, pragma_tok);
 }
 
@@ -2769,7 +3164,7 @@ cp_parser_new (void)
   cp_lexer *lexer;
   unsigned i;
 
-  /* cp_lexer_new_main is called before calling ggc_alloc because
+  /* cp_lexer_new_main is called before doing GC allocation because
      cp_lexer_new_main might load a PCH file.  */
   lexer = cp_lexer_new_main ();
 
@@ -2778,7 +3173,7 @@ cp_parser_new (void)
   for (i = 0; i < sizeof (binops) / sizeof (binops[0]); i++)
     binops_by_token[binops[i].token_type] = binops[i];
 
-  parser = GGC_CNEW (cp_parser);
+  parser = ggc_alloc_cleared_cp_parser ();
   parser->lexer = lexer;
   parser->context = cp_parser_context_new (NULL);
 
@@ -2827,7 +3222,7 @@ cp_parser_new (void)
   parser->in_function_body = false;
 
   /* The unparsed function queue is empty.  */
-  parser->unparsed_functions_queues = build_tree_list (NULL_TREE, NULL_TREE);
+  push_unparsed_function_queues (parser);
 
   /* There are no classes being defined.  */
   parser->num_classes_being_defined = 0;
@@ -2879,7 +3274,7 @@ cp_parser_identifier (cp_parser* parser)
   cp_token *token;
 
   /* Look for the identifier.  */
-  token = cp_parser_require (parser, CPP_NAME, "identifier");
+  token = cp_parser_require (parser, CPP_NAME, RT_NAME);
   /* Return the value.  */
   return token ? token->u.value : error_mark_node;
 }
@@ -2977,6 +3372,7 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
        {
        default:
        case CPP_STRING:
+       case CPP_UTF8STRING:
          TREE_TYPE (value) = char_array_type_node;
          break;
        case CPP_STRING16:
@@ -3197,8 +3593,7 @@ cp_parser_primary_expression (cp_parser *parser,
             checked at that point.  If we are not within a cast, then
             this code is invalid.  */
          if (!cast_p)
-           cp_parser_non_integral_constant_expression
-             (parser, "floating-point literal");
+           cp_parser_non_integral_constant_expression (parser, NIC_FLOAT);
        }
       return token->u.value;
 
@@ -3206,6 +3601,7 @@ cp_parser_primary_expression (cp_parser *parser,
     case CPP_STRING16:
     case CPP_STRING32:
     case CPP_WSTRING:
+    case CPP_UTF8STRING:
       /* ??? Should wide strings be allowed when parser->translate_strings_p
         is false (i.e. in attributes)?  If not, we can kill the third
         argument to cp_parser_string_literal.  */
@@ -3275,12 +3671,26 @@ cp_parser_primary_expression (cp_parser *parser,
        parser->greater_than_is_operator_p
          = saved_greater_than_is_operator_p;
        /* Consume the `)'.  */
-       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
          cp_parser_skip_to_end_of_statement (parser);
 
        return expr;
       }
 
+    case CPP_OPEN_SQUARE:
+      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);
+
+    case CPP_OBJC_STRING:
+      if (c_dialect_objc ())
+       /* We have an Objective-C++ string literal. */
+        return cp_parser_objc_expression (parser);
+      cp_parser_error (parser, "expected primary-expression");
+      return error_mark_node;
+
     case CPP_KEYWORD:
       switch (token->keyword)
        {
@@ -3297,6 +3707,11 @@ cp_parser_primary_expression (cp_parser *parser,
          cp_lexer_consume_token (parser->lexer);
          return null_node;
 
+         /* The `nullptr' literal.  */
+       case RID_NULLPTR:
+         cp_lexer_consume_token (parser->lexer);
+         return nullptr_node;
+
          /* Recognize the `this' keyword.  */
        case RID_THIS:
          cp_lexer_consume_token (parser->lexer);
@@ -3307,7 +3722,7 @@ cp_parser_primary_expression (cp_parser *parser,
              return error_mark_node;
            }
          /* Pointers cannot appear in constant-expressions.  */
-         if (cp_parser_non_integral_constant_expression (parser, "%<this%>"))
+         if (cp_parser_non_integral_constant_expression (parser, NIC_THIS))
            return error_mark_node;
          return finish_this_expr ();
 
@@ -3320,7 +3735,7 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_PRETTY_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
          {
-           const char *name;
+           non_integral_constant name;
 
            /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
               __func__ are the names of variables -- but they are
@@ -3334,13 +3749,13 @@ cp_parser_primary_expression (cp_parser *parser,
            switch (token->keyword)
              {
              case RID_FUNCTION_NAME:
-               name = "%<__FUNCTION__%>";
+               name = NIC_FUNC_NAME;
                break;
              case RID_PRETTY_FUNCTION_NAME:
-               name = "%<__PRETTY_FUNCTION__%>";
+               name = NIC_PRETTY_FUNC;
                break;
              case RID_C99_FUNCTION_NAME:
-               name = "%<__func__%>";
+               name = NIC_C99_FUNC;
                break;
              default:
                gcc_unreachable ();
@@ -3362,20 +3777,20 @@ cp_parser_primary_expression (cp_parser *parser,
               `va_arg'.  Consume the `__builtin_va_arg' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Look for the opening `('.  */
-           cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+           cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
            /* Now, parse the assignment-expression.  */
            expression = cp_parser_assignment_expression (parser,
                                                          /*cast_p=*/false, NULL);
            /* Look for the `,'.  */
-           cp_parser_require (parser, CPP_COMMA, "%<,%>");
+           cp_parser_require (parser, CPP_COMMA, RT_COMMA);
            /* Parse the type-id.  */
            type = cp_parser_type_id (parser);
            /* Look for the closing `)'.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
            /* Using `va_arg' in a constant-expression is not
               allowed.  */
            if (cp_parser_non_integral_constant_expression (parser,
-                                                           "%<va_arg%>"))
+                                                           NIC_VA_ARG))
              return error_mark_node;
            return build_x_va_arg (expression, type);
          }
@@ -3402,6 +3817,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.  */
@@ -3410,6 +3826,16 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_AT_SELECTOR:
          return cp_parser_objc_expression (parser);
 
+       case RID_TEMPLATE:
+         if (parser->in_function_body
+             && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
+                 == CPP_LESS))
+           {
+             error_at (token->location,
+                       "a template declaration cannot appear at block scope");
+             cp_parser_skip_to_end_of_block_or_statement (parser);
+             return error_mark_node;
+           }
        default:
          cp_parser_error (parser, "expected primary-expression");
          return error_mark_node;
@@ -3460,6 +3886,16 @@ cp_parser_primary_expression (cp_parser *parser,
          {
            tree ambiguous_decls;
 
+           /* If we already know that this lookup is ambiguous, then
+              we've already issued an error message; there's no reason
+              to check again.  */
+           if (id_expr_token->type == CPP_NAME
+               && id_expr_token->ambiguous_p)
+             {
+               cp_parser_simulate_error (parser);
+               return error_mark_node;
+             }
+
            decl = cp_parser_lookup_name (parser, id_expression,
                                          none_type,
                                          template_p,
@@ -3538,13 +3974,6 @@ cp_parser_primary_expression (cp_parser *parser,
 
       /* Anything else is an error.  */
     default:
-      /* ...unless we have an Objective-C++ message or string literal,
-         that is.  */
-      if (c_dialect_objc ()
-         && (token->type == CPP_OPEN_SQUARE
-              || token->type == CPP_OBJC_STRING))
-       return cp_parser_objc_expression (parser);
-
       cp_parser_error (parser, "expected primary-expression");
       return error_mark_node;
     }
@@ -3824,20 +4253,26 @@ cp_parser_unqualified_id (cp_parser* parser,
          }
        gcc_assert (!scope || TYPE_P (scope));
 
-       /* If the name is of the form "X::~X" it's OK.  */
+       /* If the name is of the form "X::~X" it's OK even if X is a
+          typedef.  */
        token = cp_lexer_peek_token (parser->lexer);
        if (scope
            && token->type == CPP_NAME
            && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
-               == CPP_OPEN_PAREN)
-           && constructor_name_p (token->u.value, scope))
+               != CPP_LESS)
+           && (token->u.value == TYPE_IDENTIFIER (scope)
+               || constructor_name_p (token->u.value, scope)))
          {
            cp_lexer_consume_token (parser->lexer);
            return build_nt (BIT_NOT_EXPR, scope);
          }
 
        /* If there was an explicit qualification (S::~T), first look
-          in the scope given by the qualification (i.e., S).  */
+          in the scope given by the qualification (i.e., S).
+
+          Note: in the calls to cp_parser_class_name below we pass
+          typename_type so that lookup finds the injected-class-name
+          rather than the constructor.  */
        done = false;
        type_decl = NULL_TREE;
        if (scope)
@@ -3846,7 +4281,7 @@ cp_parser_unqualified_id (cp_parser* parser,
            type_decl = cp_parser_class_name (parser,
                                              /*typename_keyword_p=*/false,
                                              /*template_keyword_p=*/false,
-                                             none_type,
+                                             typename_type,
                                              /*check_dependency=*/false,
                                              /*class_head_p=*/false,
                                              declarator_p);
@@ -3864,7 +4299,7 @@ cp_parser_unqualified_id (cp_parser* parser,
              = cp_parser_class_name (parser,
                                      /*typename_keyword_p=*/false,
                                      /*template_keyword_p=*/false,
-                                     none_type,
+                                     typename_type,
                                      /*check_dependency=*/false,
                                      /*class_head_p=*/false,
                                      declarator_p);
@@ -3882,7 +4317,7 @@ cp_parser_unqualified_id (cp_parser* parser,
              = cp_parser_class_name (parser,
                                      /*typename_keyword_p=*/false,
                                      /*template_keyword_p=*/false,
-                                     none_type,
+                                     typename_type,
                                      /*check_dependency=*/false,
                                      /*class_head_p=*/false,
                                      declarator_p);
@@ -3901,7 +4336,7 @@ cp_parser_unqualified_id (cp_parser* parser,
              = cp_parser_class_name (parser,
                                      /*typename_keyword_p=*/false,
                                      /*template_keyword_p=*/false,
-                                     none_type,
+                                     typename_type,
                                      /*check_dependency=*/false,
                                      /*class_head_p=*/false,
                                      declarator_p);
@@ -4119,7 +4554,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                                        type_p,
                                        is_declaration);
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
+      cp_parser_require (parser, CPP_SCOPE, RT_SCOPE);
 
       /* If we found what we wanted, we keep going; otherwise, we're
         done.  */
@@ -4172,12 +4607,14 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                        }
                      else
                         {
-                          const char* msg = "is not a class or namespace";
                           if (cxx_dialect != cxx98)
-                            msg = "is not a class, namespace, or enumeration";
-                          cp_parser_name_lookup_error
-                            (parser, token->u.value, decl, msg,
+                            cp_parser_name_lookup_error
+                            (parser, token->u.value, decl, NLE_NOT_CXX98,
                             token->location);
+                         else
+                           cp_parser_name_lookup_error
+                           (parser, token->u.value, decl, NLE_CXX98,
+                            token->location);
                         }
                    }
                  parser->scope = error_mark_node;
@@ -4250,7 +4687,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
       token->type = CPP_NESTED_NAME_SPECIFIER;
       /* Retrieve any deferred checks.  Do not pop this access checks yet
         so the memory will not be reclaimed during token replacing below.  */
-      token->u.tree_check_value = GGC_CNEW (struct tree_check);
+      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
       token->u.tree_check_value->value = parser->scope;
       token->u.tree_check_value->checks = get_deferred_access_checks ();
       token->u.tree_check_value->qualifying_scope =
@@ -4364,6 +4801,16 @@ cp_parser_qualifying_entity (cp_parser *parser,
      
       /* Parse a typedef-name or enum-name.  */
       scope = cp_parser_nonclass_name (parser);
+
+      /* "If the name found does not designate a namespace or a class,
+        enumeration, or dependent type, the program is ill-formed."
+
+         We cover classes and dependent types above and namespaces below,
+         so this code is only looking for enums.  */
+      if (!scope || TREE_CODE (scope) != TYPE_DECL
+         || TREE_CODE (TREE_TYPE (scope)) != ENUMERAL_TYPE)
+       cp_parser_simulate_error (parser);
+
       successful_parse_p = cp_parser_parse_definitely (parser);
     }
   /* If that didn't work, try for a namespace-name.  */
@@ -4462,29 +4909,26 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
        /* New types cannot be defined in the cast.  */
        saved_message = parser->type_definition_forbidden_message;
        parser->type_definition_forbidden_message
-         = "types may not be defined in casts";
+         = G_("types may not be defined in casts");
 
        /* Look for the opening `<'.  */
-       cp_parser_require (parser, CPP_LESS, "%<<%>");
+       cp_parser_require (parser, CPP_LESS, RT_LESS);
        /* Parse the type to which we are casting.  */
        type = cp_parser_type_id (parser);
        /* Look for the closing `>'.  */
-       cp_parser_require (parser, CPP_GREATER, "%<>%>");
+       cp_parser_require (parser, CPP_GREATER, RT_GREATER);
        /* Restore the old message.  */
        parser->type_definition_forbidden_message = saved_message;
 
        /* And the expression which is being cast.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
        expression = cp_parser_expression (parser, /*cast_p=*/true, & idk);
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
        /* Only type conversions to integral or enumeration types
           can be used in constant-expressions.  */
        if (!cast_valid_in_integral_constant_expression_p (type)
-           && (cp_parser_non_integral_constant_expression
-               (parser,
-                "a cast to a type other than an integral or "
-                "enumeration type")))
+           && cp_parser_non_integral_constant_expression (parser, NIC_CAST))
          return error_mark_node;
 
        switch (keyword)
@@ -4521,11 +4965,11 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
        /* Consume the `typeid' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Look for the `(' token.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
        /* Types cannot be defined in a `typeid' expression.  */
        saved_message = parser->type_definition_forbidden_message;
        parser->type_definition_forbidden_message
-         = "types may not be defined in a %<typeid%> expression";
+         = G_("types may not be defined in a %<typeid%> expression");
        /* We can't be sure yet whether we're looking at a type-id or an
           expression.  */
        cp_parser_parse_tentatively (parser);
@@ -4537,7 +4981,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
        /* Look for the `)' token.  Otherwise, we can't be sure that
           we're not looking at an expression: consider `typeid (int
           (3))', for example.  */
-       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
        /* If all went well, simply lookup the type-id.  */
        if (cp_parser_parse_definitely (parser))
          postfix_expression = get_typeid (type);
@@ -4551,13 +4995,12 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            /* Compute its typeid.  */
            postfix_expression = build_typeid (expression);
            /* Look for the `)' token.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
          }
        /* Restore the saved message.  */
        parser->type_definition_forbidden_message = saved_message;
        /* `typeid' may not appear in an integral constant expression.  */
-       if (cp_parser_non_integral_constant_expression(parser,
-                                                      "%<typeid%> operator"))
+       if (cp_parser_non_integral_constant_expression(parser, NIC_TYPEID))
          return error_mark_node;
       }
       break;
@@ -4612,9 +5055,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            type = cp_parser_type_id (parser);
            parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
            /* Look for the `)'.  */
-           cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+           cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
            /* Look for the `{'.  */
-           cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
+           cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
            /* If things aren't going well, there's no need to
               keep going.  */
            if (!cp_parser_error_occurred (parser))
@@ -4627,7 +5070,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
                  cp_lexer_consume_token (parser->lexer);
                /* Look for the final `}'.  */
-               cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+               cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
              }
            /* If that worked, we're definitely looking at a
               compound-literal expression.  */
@@ -4645,8 +5088,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                   currently accepted programs.  (Of course, as
                   compound literals are not part of ISO C++, the
                   standard has nothing to say.)  */
-               if (cp_parser_non_integral_constant_expression 
-                   (parser, "non-constant compound literals"))
+               if (cp_parser_non_integral_constant_expression (parser,
+                                                               NIC_NCC))
                  {
                    postfix_expression = error_mark_node;
                    break;
@@ -4717,7 +5160,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                parser->integral_constant_expression_p = false;
              }
            args = (cp_parser_parenthesized_expression_list
-                   (parser, /*is_attribute_list=*/false,
+                   (parser, non_attr,
                     /*cast_p=*/false, /*allow_expansion_p=*/true,
                     /*non_constant_p=*/NULL));
            if (is_builtin_constant_p)
@@ -4738,7 +5181,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
               constant-expressions.  */
            if (! builtin_valid_in_constant_expr_p (postfix_expression)
                && cp_parser_non_integral_constant_expression (parser,
-                                                              "a function call"))
+                                                              NIC_FUNC_CALL))
              {
                postfix_expression = error_mark_node;
                release_tree_vector (args);
@@ -4756,7 +5199,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
@@ -4769,19 +5213,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                         && is_overloaded_fn (postfix_expression))
                  {
                    tree fn = get_first_fn (postfix_expression);
+                   fn = STRIP_TEMPLATE (fn);
 
-                   if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
-                     fn = OVL_CURRENT (TREE_OPERAND (fn, 0));
-
-                   /* Only do argument dependent lookup if regular
-                      lookup does not find a set of member functions.
-                      [basic.lookup.koenig]/2a  */
-                   if (!DECL_FUNCTION_MEMBER_P (fn))
+                   /* Do not do argument dependent lookup if regular
+                      lookup finds a member function or a block-scope
+                      function declaration.  [basic.lookup.argdep]/3  */
+                   if (!DECL_FUNCTION_MEMBER_P (fn)
+                       && !DECL_LOCAL_FUNCTION_P (fn))
                      {
                        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);
                      }
                  }
              }
@@ -4877,8 +5321,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            = finish_increment_expr (postfix_expression,
                                     POSTINCREMENT_EXPR);
          /* Increments may not appear in constant-expressions.  */
-         if (cp_parser_non_integral_constant_expression (parser,
-                                                         "an increment"))
+         if (cp_parser_non_integral_constant_expression (parser, NIC_INC))
            postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
           is_member_access = false;
@@ -4893,8 +5336,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            = finish_increment_expr (postfix_expression,
                                     POSTDECREMENT_EXPR);
          /* Decrements may not appear in constant-expressions.  */
-         if (cp_parser_non_integral_constant_expression (parser,
-                                                         "a decrement"))
+         if (cp_parser_non_integral_constant_expression (parser, NIC_DEC))
            postfix_expression = error_mark_node;
          idk = CP_ID_KIND_NONE;
           is_member_access = false;
@@ -4947,7 +5389,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
     index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
   /* Look for the closing `]'.  */
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
 
   /* Build the ARRAY_REF.  */
   postfix_expression = grok_array_decl (postfix_expression, index);
@@ -4955,8 +5397,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
   /* When not doing offsetof, array references are not permitted in
      constant-expressions.  */
   if (!for_offsetof
-      && (cp_parser_non_integral_constant_expression
-         (parser, "an array reference")))
+      && (cp_parser_non_integral_constant_expression (parser, NIC_ARRAY_REF)))
     postfix_expression = error_mark_node;
 
   return postfix_expression;
@@ -5131,7 +5572,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
      constant-expressions.  */
   if (!for_offsetof
       && (cp_parser_non_integral_constant_expression
-         (parser, token_type == CPP_DEREF ? "%<->%>" : "%<.%>")))
+         (parser, token_type == CPP_DEREF ? NIC_ARROW : NIC_POINT)))
     postfix_expression = error_mark_node;
 
   return postfix_expression;
@@ -5156,20 +5597,22 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
    Returns a vector of trees.  Each element is a representation of an
    assignment-expression.  NULL is returned if the ( and or ) are
    missing.  An empty, but allocated, vector is returned on no
-   expressions.  The parentheses are eaten.  IS_ATTRIBUTE_LIST is true
-   if this is really an attribute list being parsed.  If
+   expressions.  The parentheses are eaten.  IS_ATTRIBUTE_LIST is id_attr
+   if we are parsing an attribute list for an attribute that wants a
+   plain identifier argument, normal_attr for an attribute that wants
+   an expression, or non_attr if we aren't parsing an attribute list.  If
    NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or
    not all of the expressions in the list were constant.  */
 
 static VEC(tree,gc) *
 cp_parser_parenthesized_expression_list (cp_parser* parser,
-                                        bool is_attribute_list,
+                                        int is_attribute_list,
                                         bool cast_p,
                                          bool allow_expansion_p,
                                         bool *non_constant_p)
 {
   VEC(tree,gc) *expression_list;
-  bool fold_expr_p = is_attribute_list;
+  bool fold_expr_p = is_attribute_list != non_attr;
   tree identifier = NULL_TREE;
   bool saved_greater_than_is_operator_p;
 
@@ -5177,7 +5620,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
   if (non_constant_p)
     *non_constant_p = false;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return NULL;
 
   expression_list = make_tree_vector ();
@@ -5196,7 +5639,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 
        /* At the beginning of attribute lists, check to see if the
           next token is an identifier.  */
-       if (is_attribute_list
+       if (is_attribute_list == id_attr
            && cp_lexer_peek_token (parser->lexer)->type == CPP_NAME)
          {
            cp_token *token;
@@ -5214,7 +5657,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
            if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
              {
                /* A braced-init-list.  */
-               maybe_warn_cpp0x ("extended initializer lists");
+               maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
                expr = cp_parser_braced_list (parser, &expr_non_constant_p);
                if (non_constant_p && expr_non_constant_p)
                  *non_constant_p = true;
@@ -5257,7 +5700,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
 
        /* After the first item, attribute lists look the same as
           expression lists.  */
-       is_attribute_list = false;
+       is_attribute_list = non_attr;
 
       get_comma:;
        /* If the next token isn't a `,', then we are done.  */
@@ -5268,7 +5711,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
        cp_lexer_consume_token (parser->lexer);
       }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
     {
       int ending;
 
@@ -5343,7 +5786,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
                             /*check_dependency_p=*/false,
                             /*is_declaration=*/true);
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
+      cp_parser_require (parser, CPP_SCOPE, RT_SCOPE);
     }
   /* If the next token is not a `~', then there might be some
      additional qualification.  */
@@ -5369,13 +5812,13 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
        return;
 
       /* Look for the `::' token.  */
-      cp_parser_require (parser, CPP_SCOPE, "%<::%>");
+      cp_parser_require (parser, CPP_SCOPE, RT_SCOPE);
     }
   else
     *scope = NULL_TREE;
 
   /* Look for the `~'.  */
-  cp_parser_require (parser, CPP_COMPL, "%<~%>");
+  cp_parser_require (parser, CPP_COMPL, RT_COMPL);
   /* Look for the type-name again.  We are not responsible for
      checking that it matches the first type-name.  */
   *type = cp_parser_nonclass_name (parser);
@@ -5482,6 +5925,51 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
          }
          break;
 
+       case RID_NOEXCEPT:
+         {
+           tree expr;
+           const char *saved_message;
+           bool saved_integral_constant_expression_p;
+           bool saved_non_integral_constant_expression_p;
+           bool saved_greater_than_is_operator_p;
+
+           cp_lexer_consume_token (parser->lexer);
+           cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+
+           saved_message = parser->type_definition_forbidden_message;
+           parser->type_definition_forbidden_message
+             = G_("types may not be defined in %<noexcept%> expressions");
+
+           saved_integral_constant_expression_p
+             = parser->integral_constant_expression_p;
+           saved_non_integral_constant_expression_p
+             = parser->non_integral_constant_expression_p;
+           parser->integral_constant_expression_p = false;
+
+           saved_greater_than_is_operator_p
+             = parser->greater_than_is_operator_p;
+           parser->greater_than_is_operator_p = true;
+
+           ++cp_unevaluated_operand;
+           ++c_inhibit_evaluation_warnings;
+           expr = cp_parser_expression (parser, false, NULL);
+           --c_inhibit_evaluation_warnings;
+           --cp_unevaluated_operand;
+
+           parser->greater_than_is_operator_p
+             = saved_greater_than_is_operator_p;
+
+           parser->integral_constant_expression_p
+             = saved_integral_constant_expression_p;
+           parser->non_integral_constant_expression_p
+             = saved_non_integral_constant_expression_p;
+
+           parser->type_definition_forbidden_message = saved_message;
+
+           cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+           return finish_noexcept_expr (expr, tf_warning_or_error);
+         }
+
        default:
          break;
        }
@@ -5531,7 +6019,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
          /* Create an expression representing the address.  */
          expression = finish_label_address_expr (identifier, loc);
          if (cp_parser_non_integral_constant_expression (parser,
-                                               "the address of a label"))
+                                                         NIC_ADDR_LABEL))
            expression = error_mark_node;
          return expression;
        }
@@ -5540,7 +6028,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
     {
       tree cast_expression;
       tree expression = error_mark_node;
-      const char *non_constant_p = NULL;
+      non_integral_constant non_constant_p = NIC_NONE;
 
       /* Consume the operator token.  */
       token = cp_lexer_consume_token (parser->lexer);
@@ -5553,13 +6041,13 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
       switch (unary_operator)
        {
        case INDIRECT_REF:
-         non_constant_p = "%<*%>";
-         expression = build_x_indirect_ref (cast_expression, "unary *",
+         non_constant_p = NIC_STAR;
+         expression = build_x_indirect_ref (cast_expression, RO_UNARY_STAR,
                                              tf_warning_or_error);
          break;
 
        case ADDR_EXPR:
-         non_constant_p = "%<&%>";
+          non_constant_p = NIC_ADDR;
          /* Fall through.  */
        case BIT_NOT_EXPR:
          expression = build_x_unary_op (unary_operator, cast_expression,
@@ -5568,8 +6056,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
 
        case PREINCREMENT_EXPR:
        case PREDECREMENT_EXPR:
-         non_constant_p = (unary_operator == PREINCREMENT_EXPR
-                           ? "%<++%>" : "%<--%>");
+         non_constant_p = unary_operator == PREINCREMENT_EXPR
+                          ? NIC_PREINCREMENT : NIC_PREDECREMENT;
          /* Fall through.  */
        case UNARY_PLUS_EXPR:
        case NEGATE_EXPR:
@@ -5581,7 +6069,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
          gcc_unreachable ();
        }
 
-      if (non_constant_p
+      if (non_constant_p != NIC_NONE
          && cp_parser_non_integral_constant_expression (parser,
                                                         non_constant_p))
        expression = error_mark_node;
@@ -5649,7 +6137,7 @@ cp_parser_new_expression (cp_parser* parser)
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `new' operator.  */
-  cp_parser_require_keyword (parser, RID_NEW, "%<new%>");
+  cp_parser_require_keyword (parser, RID_NEW, RT_NEW);
   /* There's no easy way to tell a new-placement from the
      `( type-id )' construct.  */
   cp_parser_parse_tentatively (parser);
@@ -5673,7 +6161,7 @@ cp_parser_new_expression (cp_parser* parser)
       /* Parse the type-id.  */
       type = cp_parser_type_id (parser);
       /* Look for the closing `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
       token = cp_lexer_peek_token (parser->lexer);
       /* There should not be a direct-new-declarator in this production,
         but GCC used to allowed this, so we check and emit a sensible error
@@ -5701,7 +6189,7 @@ cp_parser_new_expression (cp_parser* parser)
 
   /* A new-expression may not appear in an integral constant
      expression.  */
-  if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
+  if (cp_parser_non_integral_constant_expression (parser, NIC_NEW))
     ret = error_mark_node;
   else
     {
@@ -5732,7 +6220,8 @@ cp_parser_new_placement (cp_parser* parser)
 
   /* Parse the expression-list.  */
   expression_list = (cp_parser_parenthesized_expression_list
-                    (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+                    (parser, non_attr, /*cast_p=*/false,
+                     /*allow_expansion_p=*/true,
                      /*non_constant_p=*/NULL));
 
   return expression_list;
@@ -5763,9 +6252,10 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
      complete.)  */
   saved_message = parser->type_definition_forbidden_message;
   parser->type_definition_forbidden_message
-    = "types may not be defined in a new-type-id";
+    = G_("types may not be defined in a new-type-id");
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+  cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+                               /*is_trailing_return=*/false,
                                &type_specifier_seq);
   /* Restore the old message.  */
   parser->type_definition_forbidden_message = saved_message;
@@ -5865,7 +6355,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       tree expression;
 
       /* Look for the opening `['.  */
-      cp_parser_require (parser, CPP_OPEN_SQUARE, "%<[%>");
+      cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE);
       /* The first expression is not required to be constant.  */
       if (!declarator)
        {
@@ -5899,7 +6389,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
                                           /*allow_non_constant=*/false,
                                           NULL);
       /* Look for the closing `]'.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
 
       /* Add this bound to the declarator.  */
       declarator = make_array_declarator (declarator, expression);
@@ -5930,14 +6420,15 @@ cp_parser_new_initializer (cp_parser* parser)
     {
       tree t;
       bool expr_non_constant_p;
-      maybe_warn_cpp0x ("extended initializer lists");
+      maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       t = cp_parser_braced_list (parser, &expr_non_constant_p);
       CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
       expression_list = make_tree_vector_single (t);
     }
   else
     expression_list = (cp_parser_parenthesized_expression_list
-                      (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+                      (parser, non_attr, /*cast_p=*/false,
+                       /*allow_expansion_p=*/true,
                        /*non_constant_p=*/NULL));
 
   return expression_list;
@@ -5964,14 +6455,14 @@ cp_parser_delete_expression (cp_parser* parser)
                                   /*current_scope_valid_p=*/false)
        != NULL_TREE);
   /* Look for the `delete' keyword.  */
-  cp_parser_require_keyword (parser, RID_DELETE, "%<delete%>");
+  cp_parser_require_keyword (parser, RID_DELETE, RT_DELETE);
   /* See if the array syntax is in use.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
     {
       /* Consume the `[' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the `]' token.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
       /* Remember that this is the `[]' construct.  */
       array_p = true;
     }
@@ -5983,7 +6474,7 @@ cp_parser_delete_expression (cp_parser* parser)
 
   /* A delete-expression may not appear in an integral constant
      expression.  */
-  if (cp_parser_non_integral_constant_expression (parser, "%<delete%>"))
+  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);
@@ -6075,7 +6566,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
       /* Types may not be defined in a cast.  */
       saved_message = parser->type_definition_forbidden_message;
       parser->type_definition_forbidden_message
-       = "types may not be defined in casts";
+       = G_("types may not be defined in casts");
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* A very tricky bit is that `(struct S) { 3 }' is a
@@ -6116,7 +6607,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
          /* Look for the type-id.  */
          type = cp_parser_type_id (parser);
          /* Look for the closing `)'.  */
-         cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+         cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
          parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
        }
 
@@ -6145,10 +6636,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
          /* Only type conversions to integral or enumeration types
             can be used in constant-expressions.  */
          if (!cast_valid_in_integral_constant_expression_p (type)
-             && (cp_parser_non_integral_constant_expression
-                 (parser,
-                  "a cast to a type other than an integral or "
-                  "enumeration type")))
+             && cp_parser_non_integral_constant_expression (parser,
+                                                            NIC_CAST))
            return error_mark_node;
 
          /* Perform the cast.  */
@@ -6383,8 +6872,8 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
         least one of the operands is of enumeration type.  */
 
       if (overloaded_p
-         && (cp_parser_non_integral_constant_expression
-             (parser, "calls to overloaded operators")))
+         && cp_parser_non_integral_constant_expression (parser,
+                                                        NIC_OVERLOADED))
        return error_mark_node;
     }
 
@@ -6410,15 +6899,20 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
 {
   tree expr;
   tree assignment_expr;
+  struct cp_token *token;
 
   /* Consume the `?' token.  */
   cp_lexer_consume_token (parser->lexer);
+  token = cp_lexer_peek_token (parser->lexer);
   if (cp_parser_allow_gnu_extensions_p (parser)
-      && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+      && token->type == CPP_COLON)
     {
+      pedwarn (token->location, OPT_pedantic, 
+               "ISO C++ does not allow ?: with omitted middle operand");
       /* Implicit true clause.  */
       expr = NULL_TREE;
       c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
+      warn_for_omitted_condop (token->location, logical_or_expr);
     }
   else
     {
@@ -6431,7 +6925,7 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
     }
 
   /* The next token should be a `:'.  */
-  cp_parser_require (parser, CPP_COLON, "%<:%>");
+  cp_parser_require (parser, CPP_COLON, RT_COLON);
   /* Parse the assignment-expression.  */
   assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
   c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
@@ -6491,12 +6985,12 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
              tree rhs = cp_parser_initializer_clause (parser, &non_constant_p);
 
              if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
-               maybe_warn_cpp0x ("extended initializer lists");
+               maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
 
              /* An assignment may not appear in a
                 constant-expression.  */
              if (cp_parser_non_integral_constant_expression (parser,
-                                                             "an assignment"))
+                                                             NIC_ASSIGNMENT))
                return error_mark_node;
              /* Build the assignment expression.  */
              expr = build_x_modify_expr (expr,
@@ -6631,8 +7125,7 @@ cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
       /* Consume the `,'.  */
       cp_lexer_consume_token (parser->lexer);
       /* A comma operator cannot appear in a constant-expression.  */
-      if (cp_parser_non_integral_constant_expression (parser,
-                                                     "a comma operator"))
+      if (cp_parser_non_integral_constant_expression (parser, NIC_COMMA))
        expression = error_mark_node;
     }
 
@@ -6683,7 +7176,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"
@@ -6702,7 +7196,8 @@ cp_parser_constant_expression (cp_parser* parser,
     = saved_allow_non_integral_constant_expression_p;
   if (allow_non_constant_p)
     *non_constant_p = parser->non_integral_constant_expression_p;
-  else if (parser->non_integral_constant_expression_p)
+  else if (parser->non_integral_constant_expression_p
+          && cxx_dialect < cxx0x)
     expression = error_mark_node;
   parser->non_integral_constant_expression_p
     = saved_non_integral_constant_expression_p;
@@ -6738,11 +7233,11 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   /* Consume the "__builtin_offsetof" token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Consume the opening `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
   /* Parse the type-id.  */
   type = cp_parser_type_id (parser);
   /* Look for the `,'.  */
-  cp_parser_require (parser, CPP_COMMA, "%<,%>");
+  cp_parser_require (parser, CPP_COMMA, RT_COMMA);
   token = cp_lexer_peek_token (parser->lexer);
 
   /* Build the (type *)null that begins the traditional offsetof macro.  */
@@ -6783,7 +7278,7 @@ cp_parser_builtin_offsetof (cp_parser *parser)
        default:
          /* Error.  We know the following require will fail, but
             that gives the proper error message.  */
-         cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+         cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
          cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
          expr = error_mark_node;
          goto failure;
@@ -6876,6 +7371,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_UNION:
       kind = CPTK_IS_UNION;
       break;
+    case RID_IS_LITERAL_TYPE:
+      kind = CPTK_IS_LITERAL_TYPE;
+      break;
     default:
       gcc_unreachable ();
     }
@@ -6883,7 +7381,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
   /* Consume the token.  */
   cp_lexer_consume_token (parser->lexer);
 
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
   type1 = cp_parser_type_id (parser);
 
@@ -6900,7 +7398,7 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 
   if (binary)
     {
-      cp_parser_require (parser, CPP_COMMA, "%<,%>");
+      cp_parser_require (parser, CPP_COMMA, RT_COMMA);
  
       type2 = cp_parser_type_id (parser);
 
@@ -6916,112 +7414,629 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
                              /*initialized=*/0, /*attrlist=*/NULL);
     }
 
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
   /* 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);
 }
 
-/* Statements [gram.stmt.stmt]  */
+/* Lambdas that appear in variable initializer or default argument scope
+   get that in their mangling, so we need to record it.  We might as well
+   use the count for function and namespace scopes as well.  */
+static GTY(()) tree lambda_scope;
+static GTY(()) int lambda_count;
+typedef struct GTY(()) tree_int
+{
+  tree t;
+  int i;
+} tree_int;
+DEF_VEC_O(tree_int);
+DEF_VEC_ALLOC_O(tree_int,gc);
+static GTY(()) VEC(tree_int,gc) *lambda_scope_stack;
 
-/* Parse a statement.
+static void
+start_lambda_scope (tree decl)
+{
+  tree_int ti;
+  gcc_assert (decl);
+  /* Once we're inside a function, we ignore other scopes and just push
+     the function again so that popping works properly.  */
+  if (current_function_decl && TREE_CODE (decl) != FUNCTION_DECL)
+    decl = current_function_decl;
+  ti.t = lambda_scope;
+  ti.i = lambda_count;
+  VEC_safe_push (tree_int, gc, lambda_scope_stack, &ti);
+  if (lambda_scope != decl)
+    {
+      /* Don't reset the count if we're still in the same function.  */
+      lambda_scope = decl;
+      lambda_count = 0;
+    }
+}
 
-   statement:
-     labeled-statement
-     expression-statement
-     compound-statement
-     selection-statement
-     iteration-statement
-     jump-statement
-     declaration-statement
-     try-block
+static void
+record_lambda_scope (tree lambda)
+{
+  LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope;
+  LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++;
+}
 
-  IN_COMPOUND is true when the statement is nested inside a
-  cp_parser_compound_statement; this matters for certain pragmas.
+static void
+finish_lambda_scope (void)
+{
+  tree_int *p = VEC_last (tree_int, lambda_scope_stack);
+  if (lambda_scope != p->t)
+    {
+      lambda_scope = p->t;
+      lambda_count = p->i;
+    }
+  VEC_pop (tree_int, lambda_scope_stack);
+}
 
-  If IF_P is not NULL, *IF_P is set to indicate whether the statement
-  is a (possibly labeled) if statement which is not enclosed in braces
-  and has an else clause.  This is used to implement -Wparentheses.  */
+/* Parse a lambda expression.
 
-static void
-cp_parser_statement (cp_parser* parser, tree in_statement_expr,
-                    bool in_compound, bool *if_p)
+   lambda-expression:
+     lambda-introducer lambda-declarator [opt] compound-statement
+
+   Returns a representation of the expression.  */
+
+static tree
+cp_parser_lambda_expression (cp_parser* parser)
 {
-  tree statement;
-  cp_token *token;
-  location_t statement_location;
+  tree lambda_expr = build_lambda_expr ();
+  tree type;
 
- restart:
-  if (if_p != NULL)
-    *if_p = false;
-  /* There is no statement yet.  */
-  statement = NULL_TREE;
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-  /* Remember the location of the first token in the statement.  */
-  statement_location = token->location;
-  /* If this is a keyword, then that will often determine what kind of
-     statement we have.  */
-  if (token->type == CPP_KEYWORD)
-    {
-      enum rid keyword = token->keyword;
+  LAMBDA_EXPR_LOCATION (lambda_expr)
+    = cp_lexer_peek_token (parser->lexer)->location;
 
-      switch (keyword)
-       {
-       case RID_CASE:
-       case RID_DEFAULT:
-         /* Looks like a labeled-statement with a case label.
-            Parse the label, and then use tail recursion to parse
-            the statement.  */
-         cp_parser_label_for_labeled_statement (parser);
-         goto restart;
+  if (cp_unevaluated_operand)
+    error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
+             "lambda-expression in unevaluated context");
 
-       case RID_IF:
-       case RID_SWITCH:
-         statement = cp_parser_selection_statement (parser, if_p);
-         break;
+  /* We may be in the middle of deferred access check.  Disable
+     it now.  */
+  push_deferring_access_checks (dk_no_deferred);
 
-       case RID_WHILE:
-       case RID_DO:
-       case RID_FOR:
-         statement = cp_parser_iteration_statement (parser);
-         break;
+  cp_parser_lambda_introducer (parser, lambda_expr);
 
-       case RID_BREAK:
-       case RID_CONTINUE:
-       case RID_RETURN:
-       case RID_GOTO:
-         statement = cp_parser_jump_statement (parser);
-         break;
+  type = begin_lambda_type (lambda_expr);
 
-         /* Objective-C++ exception-handling constructs.  */
-       case RID_AT_TRY:
-       case RID_AT_CATCH:
-       case RID_AT_FINALLY:
-       case RID_AT_SYNCHRONIZED:
-       case RID_AT_THROW:
-         statement = cp_parser_objc_statement (parser);
-         break;
+  record_lambda_scope (lambda_expr);
 
-       case RID_TRY:
-         statement = cp_parser_try_block (parser);
-         break;
+  /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set.  */
+  determine_visibility (TYPE_NAME (type));
 
-       case RID_NAMESPACE:
-         /* This must be a namespace alias definition.  */
-         cp_parser_declaration_statement (parser);
-         return;
-         
-       default:
-         /* It might be a keyword like `int' that can start a
-            declaration-statement.  */
-         break;
+  /* Now that we've started the type, add the capture fields for any
+     explicit captures.  */
+  register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr));
+
+  {
+    /* Inside the class, surrounding template-parameter-lists do not apply.  */
+    unsigned int saved_num_template_parameter_lists
+        = parser->num_template_parameter_lists;
+
+    parser->num_template_parameter_lists = 0;
+
+    /* By virtue of defining a local class, a lambda expression has access to
+       the private variables of enclosing classes.  */
+
+    cp_parser_lambda_declarator_opt (parser, lambda_expr);
+
+    cp_parser_lambda_body (parser, lambda_expr);
+
+    /* The capture list was built up in reverse order; fix that now.  */
+    {
+      tree newlist = NULL_TREE;
+      tree elt, next;
+
+      for (elt = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr);
+          elt; elt = next)
+       {
+         tree field = TREE_PURPOSE (elt);
+         char *buf;
+
+         next = TREE_CHAIN (elt);
+         TREE_CHAIN (elt) = newlist;
+         newlist = elt;
+
+         /* Also add __ to the beginning of the field name so that code
+            outside the lambda body can't see the captured name.  We could
+            just remove the name entirely, but this is more useful for
+            debugging.  */
+         if (field == LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
+           /* The 'this' capture already starts with __.  */
+           continue;
+
+         buf = (char *) alloca (IDENTIFIER_LENGTH (DECL_NAME (field)) + 3);
+         buf[1] = buf[0] = '_';
+         memcpy (buf + 2, IDENTIFIER_POINTER (DECL_NAME (field)),
+                 IDENTIFIER_LENGTH (DECL_NAME (field)) + 1);
+         DECL_NAME (field) = get_identifier (buf);
        }
+      LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = newlist;
     }
-  else if (token->type == CPP_NAME)
-    {
-      /* If the next token is a `:', then we are looking at a
+
+    maybe_add_lambda_conv_op (type);
+
+    type = finish_struct (type, /*attributes=*/NULL_TREE);
+
+    parser->num_template_parameter_lists = saved_num_template_parameter_lists;
+  }
+
+  pop_deferring_access_checks ();
+
+  return build_lambda_object (lambda_expr);
+}
+
+/* Parse the beginning of a lambda expression.
+
+   lambda-introducer:
+     [ lambda-capture [opt] ]
+
+   LAMBDA_EXPR is the current representation of the lambda expression.  */
+
+static void
+cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
+{
+  /* Need commas after the first capture.  */
+  bool first = true;
+
+  /* Eat the leading `['.  */
+  cp_parser_require (parser, CPP_OPEN_SQUARE, RT_OPEN_SQUARE);
+
+  /* Record default capture mode.  "[&" "[=" "[&," "[=,"  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_AND)
+      && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_NAME)
+    LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE;
+  else if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+    LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_COPY;
+
+  if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE)
+    {
+      cp_lexer_consume_token (parser->lexer);
+      first = false;
+    }
+
+  while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
+    {
+      cp_token* capture_token;
+      tree capture_id;
+      tree capture_init_expr;
+      cp_id_kind idk = CP_ID_KIND_NONE;
+      bool explicit_init_p = false;
+
+      enum capture_kind_type
+      {
+       BY_COPY,
+       BY_REFERENCE
+      };
+      enum capture_kind_type capture_kind = BY_COPY;
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+       {
+         error ("expected end of capture-list");
+         return;
+       }
+
+      if (first)
+       first = false;
+      else
+       cp_parser_require (parser, CPP_COMMA, RT_COMMA);
+
+      /* Possibly capture `this'.  */
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_THIS))
+       {
+         cp_lexer_consume_token (parser->lexer);
+         add_capture (lambda_expr,
+                      /*id=*/get_identifier ("__this"),
+                      /*initializer=*/finish_this_expr(),
+                      /*by_reference_p=*/false,
+                      explicit_init_p);
+         continue;
+       }
+
+      /* Remember whether we want to capture as a reference or not.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_AND))
+       {
+         capture_kind = BY_REFERENCE;
+         cp_lexer_consume_token (parser->lexer);
+       }
+
+      /* Get the identifier.  */
+      capture_token = cp_lexer_peek_token (parser->lexer);
+      capture_id = cp_parser_identifier (parser);
+
+      if (capture_id == error_mark_node)
+       /* Would be nice to have a cp_parser_skip_to_closing_x for general
+           delimiters, but I modified this to stop on unnested ']' as well.  It
+           was already changed to stop on unnested '}', so the
+           "closing_parenthesis" name is no more misleading with my change.  */
+       {
+         cp_parser_skip_to_closing_parenthesis (parser,
+                                                /*recovering=*/true,
+                                                /*or_comma=*/true,
+                                                /*consume_paren=*/true);
+         break;
+       }
+
+      /* Find the initializer for this capture.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+       {
+         /* An explicit expression exists.  */
+         cp_lexer_consume_token (parser->lexer);
+          pedwarn (input_location, OPT_pedantic,
+                   "ISO C++ does not allow initializers "
+                   "in lambda expression capture lists");
+         capture_init_expr = cp_parser_assignment_expression (parser,
+                                                              /*cast_p=*/true,
+                                                              &idk);
+         explicit_init_p = true;
+       }
+      else
+       {
+         const char* error_msg;
+
+         /* Turn the identifier into an id-expression.  */
+         capture_init_expr
+            = cp_parser_lookup_name
+                (parser,
+                capture_id,
+                 none_type,
+                 /*is_template=*/false,
+                 /*is_namespace=*/false,
+                 /*check_dependency=*/true,
+                 /*ambiguous_decls=*/NULL,
+                 capture_token->location);
+
+         capture_init_expr
+            = finish_id_expression
+                (capture_id,
+                capture_init_expr,
+                 parser->scope,
+                 &idk,
+                 /*integral_constant_expression_p=*/false,
+                 /*allow_non_integral_constant_expression_p=*/false,
+                 /*non_integral_constant_expression_p=*/NULL,
+                 /*template_p=*/false,
+                 /*done=*/true,
+                 /*address_p=*/false,
+                 /*template_arg_p=*/false,
+                 &error_msg,
+                 capture_token->location);
+       }
+
+      if (TREE_CODE (capture_init_expr) == IDENTIFIER_NODE)
+       capture_init_expr
+         = unqualified_name_lookup_error (capture_init_expr);
+
+      add_capture (lambda_expr,
+                  capture_id,
+                  capture_init_expr,
+                  /*by_reference_p=*/capture_kind == BY_REFERENCE,
+                  explicit_init_p);
+    }
+
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
+}
+
+/* Parse the (optional) middle of a lambda expression.
+
+   lambda-declarator:
+     ( parameter-declaration-clause [opt] )
+       attribute-specifier [opt]
+       mutable [opt]
+       exception-specification [opt]
+       lambda-return-type-clause [opt]
+
+   LAMBDA_EXPR is the current representation of the lambda expression.  */
+
+static void
+cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
+{
+  /* 5.1.1.4 of the standard says:
+       If a lambda-expression does not include a lambda-declarator, it is as if
+       the lambda-declarator were ().
+     This means an empty parameter list, no attributes, and no exception
+     specification.  */
+  tree param_list = void_list_node;
+  tree attributes = NULL_TREE;
+  tree exception_spec = NULL_TREE;
+  tree t;
+
+  /* The lambda-declarator is optional, but must begin with an opening
+     parenthesis if present.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+    {
+      cp_lexer_consume_token (parser->lexer);
+
+      begin_scope (sk_function_parms, /*entity=*/NULL_TREE);
+
+      /* Parse parameters.  */
+      param_list = cp_parser_parameter_declaration_clause (parser);
+
+      /* Default arguments shall not be specified in the
+        parameter-declaration-clause of a lambda-declarator.  */
+      for (t = param_list; t; t = TREE_CHAIN (t))
+       if (TREE_PURPOSE (t))
+         pedwarn (DECL_SOURCE_LOCATION (TREE_VALUE (t)), OPT_pedantic,
+                  "default argument specified for lambda parameter");
+
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
+      attributes = cp_parser_attributes_opt (parser);
+
+      /* Parse optional `mutable' keyword.  */
+      if (cp_lexer_next_token_is_keyword (parser->lexer, RID_MUTABLE))
+        {
+          cp_lexer_consume_token (parser->lexer);
+          LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
+        }
+
+      /* Parse optional exception specification.  */
+      exception_spec = cp_parser_exception_specification_opt (parser);
+
+      /* Parse optional trailing return type.  */
+      if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
+        {
+          cp_lexer_consume_token (parser->lexer);
+          LAMBDA_EXPR_RETURN_TYPE (lambda_expr) = cp_parser_type_id (parser);
+        }
+
+      /* The function parameters must be in scope all the way until after the
+         trailing-return-type in case of decltype.  */
+      for (t = current_binding_level->names; t; t = DECL_CHAIN (t))
+       pop_binding (DECL_NAME (t), t);
+
+      leave_scope ();
+    }
+
+  /* Create the function call operator.
+
+     Messing with declarators like this is no uglier than building up the
+     FUNCTION_DECL by hand, and this is less likely to get out of sync with
+     other code.  */
+  {
+    cp_decl_specifier_seq return_type_specs;
+    cp_declarator* declarator;
+    tree fco;
+    int quals;
+    void *p;
+
+    clear_decl_specs (&return_type_specs);
+    if (LAMBDA_EXPR_RETURN_TYPE (lambda_expr))
+      return_type_specs.type = LAMBDA_EXPR_RETURN_TYPE (lambda_expr);
+    else
+      /* Maybe we will deduce the return type later, but we can use void
+        as a placeholder return type anyways.  */
+      return_type_specs.type = void_type_node;
+
+    p = obstack_alloc (&declarator_obstack, 0);
+
+    declarator = make_id_declarator (NULL_TREE, ansi_opname (CALL_EXPR),
+                                    sfk_none);
+
+    quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
+            ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
+    declarator = make_call_declarator (declarator, param_list, quals,
+                                      exception_spec,
+                                       /*late_return_type=*/NULL_TREE);
+    declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
+
+    fco = grokmethod (&return_type_specs,
+                     declarator,
+                     attributes);
+    DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
+    DECL_ARTIFICIAL (fco) = 1;
+
+    finish_member_declaration (fco);
+
+    obstack_free (&declarator_obstack, p);
+  }
+}
+
+/* Parse the body of a lambda expression, which is simply
+
+   compound-statement
+
+   but which requires special handling.
+   LAMBDA_EXPR is the current representation of the lambda expression.  */
+
+static void
+cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
+{
+  bool nested = (current_function_decl != NULL_TREE);
+  if (nested)
+    push_function_context ();
+
+  /* Finish the function call operator
+     - class_specifier
+     + late_parsing_for_member
+     + function_definition_after_declarator
+     + ctor_initializer_opt_and_function_body  */
+  {
+    tree fco = lambda_function (lambda_expr);
+    tree body;
+    bool done = false;
+
+    /* Let the front end know that we are going to be defining this
+       function.  */
+    start_preparsed_function (fco,
+                             NULL_TREE,
+                             SF_PRE_PARSED | SF_INCLASS_INLINE);
+
+    start_lambda_scope (fco);
+    body = begin_function_body ();
+
+    /* 5.1.1.4 of the standard says:
+         If a lambda-expression does not include a trailing-return-type, it
+         is as if the trailing-return-type denotes the following type:
+         * if the compound-statement is of the form
+               { return attribute-specifier [opt] expression ; }
+             the type of the returned expression after lvalue-to-rvalue
+             conversion (_conv.lval_ 4.1), array-to-pointer conversion
+             (_conv.array_ 4.2), and function-to-pointer conversion
+             (_conv.func_ 4.3);
+          * otherwise, void.  */
+
+    /* In a lambda that has neither a lambda-return-type-clause
+       nor a deducible form, errors should be reported for return statements
+       in the body.  Since we used void as the placeholder return type, parsing
+       the body as usual will give such desired behavior.  */
+    if (!LAMBDA_EXPR_RETURN_TYPE (lambda_expr)
+        && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)
+        && cp_lexer_peek_nth_token (parser->lexer, 2)->keyword == RID_RETURN
+        && cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_SEMICOLON)
+      {
+       tree compound_stmt;
+       tree expr = NULL_TREE;
+       cp_id_kind idk = CP_ID_KIND_NONE;
+
+       /* Parse tentatively in case there's more after the initial return
+          statement.  */
+       cp_parser_parse_tentatively (parser);
+
+       cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
+       cp_parser_require_keyword (parser, RID_RETURN, RT_RETURN);
+
+       expr = cp_parser_expression (parser, /*cast_p=*/false, &idk);
+
+       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
+       cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
+
+       if (cp_parser_parse_definitely (parser))
+         {
+           apply_lambda_return_type (lambda_expr, lambda_return_type (expr));
+
+           compound_stmt = begin_compound_stmt (0);
+           /* Will get error here if type not deduced yet.  */
+           finish_return_stmt (expr);
+           finish_compound_stmt (compound_stmt);
+
+           done = true;
+         }
+      }
+
+    if (!done)
+      {
+       if (!LAMBDA_EXPR_RETURN_TYPE (lambda_expr))
+         LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = true;
+       /* TODO: does begin_compound_stmt want BCS_FN_BODY?
+          cp_parser_compound_stmt does not pass it.  */
+       cp_parser_function_body (parser);
+       LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = false;
+      }
+
+    finish_function_body (body);
+    finish_lambda_scope ();
+
+    /* Finish the function and generate code for it if necessary.  */
+    expand_or_defer_fn (finish_function (/*inline*/2));
+  }
+
+  if (nested)
+    pop_function_context();
+}
+
+/* Statements [gram.stmt.stmt]  */
+
+/* Parse a statement.
+
+   statement:
+     labeled-statement
+     expression-statement
+     compound-statement
+     selection-statement
+     iteration-statement
+     jump-statement
+     declaration-statement
+     try-block
+
+  IN_COMPOUND is true when the statement is nested inside a
+  cp_parser_compound_statement; this matters for certain pragmas.
+
+  If IF_P is not NULL, *IF_P is set to indicate whether the statement
+  is a (possibly labeled) if statement which is not enclosed in braces
+  and has an else clause.  This is used to implement -Wparentheses.  */
+
+static void
+cp_parser_statement (cp_parser* parser, tree in_statement_expr,
+                    bool in_compound, bool *if_p)
+{
+  tree statement;
+  cp_token *token;
+  location_t statement_location;
+
+ restart:
+  if (if_p != NULL)
+    *if_p = false;
+  /* There is no statement yet.  */
+  statement = NULL_TREE;
+  /* Peek at the next token.  */
+  token = cp_lexer_peek_token (parser->lexer);
+  /* Remember the location of the first token in the statement.  */
+  statement_location = token->location;
+  /* If this is a keyword, then that will often determine what kind of
+     statement we have.  */
+  if (token->type == CPP_KEYWORD)
+    {
+      enum rid keyword = token->keyword;
+
+      switch (keyword)
+       {
+       case RID_CASE:
+       case RID_DEFAULT:
+         /* Looks like a labeled-statement with a case label.
+            Parse the label, and then use tail recursion to parse
+            the statement.  */
+         cp_parser_label_for_labeled_statement (parser);
+         goto restart;
+
+       case RID_IF:
+       case RID_SWITCH:
+         statement = cp_parser_selection_statement (parser, if_p);
+         break;
+
+       case RID_WHILE:
+       case RID_DO:
+       case RID_FOR:
+         statement = cp_parser_iteration_statement (parser);
+         break;
+
+       case RID_BREAK:
+       case RID_CONTINUE:
+       case RID_RETURN:
+       case RID_GOTO:
+         statement = cp_parser_jump_statement (parser);
+         break;
+
+         /* Objective-C++ exception-handling constructs.  */
+       case RID_AT_TRY:
+       case RID_AT_CATCH:
+       case RID_AT_FINALLY:
+       case RID_AT_SYNCHRONIZED:
+       case RID_AT_THROW:
+         statement = cp_parser_objc_statement (parser);
+         break;
+
+       case RID_TRY:
+         statement = cp_parser_try_block (parser);
+         break;
+
+       case RID_NAMESPACE:
+         /* This must be a namespace alias definition.  */
+         cp_parser_declaration_statement (parser);
+         return;
+         
+       default:
+         /* It might be a keyword like `int' that can start a
+            declaration-statement.  */
+         break;
+       }
+    }
+  else if (token->type == CPP_NAME)
+    {
+      /* If the next token is a `:', then we are looking at a
         labeled-statement.  */
       token = cp_lexer_peek_nth_token (parser->lexer, 2);
       if (token->type == CPP_COLON)
@@ -7164,7 +8179,7 @@ cp_parser_label_for_labeled_statement (cp_parser* parser)
     }
 
   /* Require the `:' token.  */
-  cp_parser_require (parser, CPP_COLON, "%<:%>");
+  cp_parser_require (parser, CPP_COLON, RT_COLON);
 
   /* An ordinary label may optionally be followed by attributes.
      However, this is only permitted if the attributes are then
@@ -7203,12 +8218,32 @@ static tree
 cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
 {
   tree statement = NULL_TREE;
+  cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* If the next token is a ';', then there is no expression
      statement.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
+  /* Give a helpful message for "A<T>::type t;" and the like.  */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
+      && !cp_parser_uncommitted_to_tentative_parse_p (parser))
+    {
+      if (TREE_CODE (statement) == SCOPE_REF)
+       error_at (token->location, "need %<typename%> before %qE because "
+                 "%qT is a dependent scope",
+                 statement, TREE_OPERAND (statement, 0));
+      else if (is_overloaded_fn (statement)
+              && DECL_CONSTRUCTOR_P (get_first_fn (statement)))
+       {
+         /* A::A a; */
+         tree fn = get_first_fn (statement);
+         error_at (token->location,
+                   "%<%T::%D%> names the constructor, not the type",
+                   DECL_CONTEXT (fn), DECL_NAME (fn));
+       }
+    }
+
   /* Consume the final `;'.  */
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
@@ -7248,7 +8283,7 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   tree compound_stmt;
 
   /* Consume the `{'.  */
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
     return error_mark_node;
   /* Begin the compound-statement.  */
   compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
@@ -7260,7 +8295,7 @@ cp_parser_compound_statement (cp_parser *parser, tree in_statement_expr,
   /* Finish the compound-statement.  */
   finish_compound_stmt (compound_stmt);
   /* Consume the `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
 
   return compound_stmt;
 }
@@ -7279,10 +8314,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
@@ -7327,7 +8365,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
     *if_p = false;
 
   /* Peek at the next token.  */
-  token = cp_parser_require (parser, CPP_KEYWORD, "selection-statement");
+  token = cp_parser_require (parser, CPP_KEYWORD, RT_SELECT);
 
   /* See what kind of keyword it is.  */
   keyword = token->keyword;
@@ -7340,7 +8378,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
        tree condition;
 
        /* Look for the `('.  */
-       if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+       if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
          {
            cp_parser_skip_to_end_of_statement (parser);
            return error_mark_node;
@@ -7355,7 +8393,7 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        /* Look for the `)'.  */
-       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
          cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                                 /*consume_paren=*/true);
 
@@ -7483,6 +8521,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);
@@ -7490,10 +8529,12 @@ cp_parser_condition (cp_parser* parser)
      condition.  */
   saved_message = parser->type_definition_forbidden_message;
   parser->type_definition_forbidden_message
-    = "types may not be defined in conditions";
+    = G_("types may not be defined in conditions");
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, /*is_condition==*/true,
-                               &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.  */
@@ -7549,11 +8590,11 @@ cp_parser_condition (cp_parser* parser)
          else
            {
              /* Consume the `='.  */
-             cp_parser_require (parser, CPP_EQ, "%<=%>");
+             cp_parser_require (parser, CPP_EQ, RT_EQ);
              initializer = cp_parser_initializer_clause (parser, &non_constant_p);
            }
          if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
-           maybe_warn_cpp0x ("extended initializer lists");
+           maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
 
          if (!non_constant_p)
            initializer = fold_non_dependent_expr (initializer);
@@ -7579,6 +8620,262 @@ cp_parser_condition (cp_parser* parser)
   return cp_parser_expression (parser, /*cast_p=*/false, NULL);
 }
 
+/* Parses a traditional for-statement until the closing ')', not included. */
+
+static tree
+cp_parser_c_for (cp_parser *parser)
+{
+  /* Normal for loop */
+  tree stmt;
+  tree condition = NULL_TREE;
+  tree expression = NULL_TREE;
+
+  /* Begin the for-statement.  */
+  stmt = begin_for_stmt ();
+
+  /* Parse the initialization.  */
+  cp_parser_for_init_statement (parser);
+  finish_for_init_stmt (stmt);
+
+  /* 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);
+
+  /* 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);
+
+  return stmt;
+}
+
+/* Tries to parse a range-based for-statement:
+
+  range-based-for:
+    type-specifier-seq declarator : expression
+
+  If succesful, assigns to *DECL the DECLARATOR and to *EXPR the
+  expression. Note that the *DECL is returned unfinished, so
+  later you should call cp_finish_decl().
+
+  Returns TRUE iff a range-based for is parsed. */
+
+static tree
+cp_parser_range_for (cp_parser *parser)
+{
+  tree stmt, range_decl, range_expr;
+  cp_decl_specifier_seq type_specifiers;
+  cp_declarator *declarator;
+  const char *saved_message;
+  tree attributes, pushed_scope;
+
+  cp_parser_parse_tentatively (parser);
+  /* New types are not allowed in the type-specifier-seq for a
+     range-based for loop.  */
+  saved_message = parser->type_definition_forbidden_message;
+  parser->type_definition_forbidden_message
+    = G_("types may not be defined in range-based for loops");
+  /* Parse the type-specifier-seq.  */
+  cp_parser_type_specifier_seq (parser, /*is_declaration==*/true,
+                               /*is_trailing_return=*/false,
+                               &type_specifiers);
+  /* Restore the saved message.  */
+  parser->type_definition_forbidden_message = saved_message;
+  /* If all is well, we might be looking at a declaration.  */
+  if (cp_parser_error_occurred (parser))
+    {
+      cp_parser_abort_tentative_parse (parser);
+      return NULL_TREE;
+    }
+  /* Parse the declarator.  */
+  declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
+                                    /*ctor_dtor_or_conv_p=*/NULL,
+                                    /*parenthesized_p=*/NULL,
+                                    /*member_p=*/false);
+  /* Parse the attributes.  */
+  attributes = cp_parser_attributes_opt (parser);
+  /* The next token should be `:'. */
+  if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+    cp_parser_simulate_error (parser);
+
+  /* Check if it is a range-based for */
+  if (!cp_parser_parse_definitely (parser))
+    return NULL_TREE;
+
+  cp_parser_require (parser, CPP_COLON, RT_COLON);
+  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-statements
+     at instantiation. If not, it is done just ahead. */
+  if (processing_template_decl)
+    stmt = begin_range_for_stmt ();
+  else
+    stmt = begin_for_stmt ();
+
+  /* Create the declaration. It must be after begin{,_range}_for_stmt(). */
+  range_decl = start_decl (declarator, &type_specifiers,
+                          /*initialized_p=*/SD_INITIALIZED,
+                          attributes, /*prefix_attributes=*/NULL_TREE,
+                          &pushed_scope);
+  /* No scope allowed here */
+  pop_scope (pushed_scope);
+
+  if (TREE_CODE (stmt) == RANGE_FOR_STMT)
+    finish_range_for_decl (stmt, range_decl, range_expr);
+  else
+    /* Convert the range-based for loop into a normal for-statement. */
+    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:
+       BEGIN_EXPR = begin(__range)
+       END_EXPR = end(__range);
+
+   When calling begin()/end() 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;
+
+  /* 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);
+
+  if (TREE_CODE (TREE_TYPE (range_temp)) == ARRAY_TYPE)
+    {
+      /* If RANGE_TEMP is an array we will use pointer arithmetic */
+      iter_type = build_pointer_type (TREE_TYPE (TREE_TYPE (range_temp)));
+      begin_expr = range_temp;
+      end_expr
+       = build_binary_op (input_location, PLUS_EXPR,
+                          range_temp,
+                          array_type_nelts_top (TREE_TYPE (range_temp)), 0);
+    }
+  else
+    {
+      /* If it is not an array, we must call begin(__range)/end__range() */
+      VEC(tree,gc) *vec;
+
+      begin_expr = get_identifier ("begin");
+      vec = make_tree_vector ();
+      VEC_safe_push (tree, gc, vec, range_temp);
+      begin_expr = perform_koenig_lookup (begin_expr, vec,
+                                         /*include_std=*/true);
+      begin_expr = finish_call_expr (begin_expr, &vec, false, true,
+                                    tf_warning_or_error);
+      release_tree_vector (vec);
+
+      end_expr = get_identifier ("end");
+      vec = make_tree_vector ();
+      VEC_safe_push (tree, gc, vec, range_temp);
+      end_expr = perform_koenig_lookup (end_expr, vec,
+                                       /*include_std=*/true);
+      end_expr = finish_call_expr (end_expr, &vec, false, true,
+                                  tf_warning_or_error);
+      release_tree_vector (vec);
+
+      /* The unqualified type of the __begin and __end temporaries should
+      * be the same as required by the multiple auto declaration */
+      iter_type = cv_unqualified (TREE_TYPE (begin_expr));
+      if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (end_expr))))
+       error ("inconsistent begin/end types in range-based for: %qT and %qT",
+              TREE_TYPE (begin_expr), TREE_TYPE (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;
+}
+
+
 /* Parse an iteration-statement.
 
    iteration-statement:
@@ -7587,7 +8884,7 @@ cp_parser_condition (cp_parser* parser)
      for ( for-init-statement condition [opt] ; expression [opt] )
        statement
 
-   Returns the new WHILE_STMT, DO_STMT, or FOR_STMT.  */
+   Returns the new WHILE_STMT, DO_STMT, FOR_STMT or RANGE_FOR_STMT.  */
 
 static tree
 cp_parser_iteration_statement (cp_parser* parser)
@@ -7598,7 +8895,7 @@ cp_parser_iteration_statement (cp_parser* parser)
   unsigned char in_statement;
 
   /* Peek at the next token.  */
-  token = cp_parser_require (parser, CPP_KEYWORD, "iteration-statement");
+  token = cp_parser_require (parser, CPP_KEYWORD, RT_INTERATION);
   if (!token)
     return error_mark_node;
 
@@ -7617,12 +8914,12 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Begin the while-statement.  */
        statement = begin_while_stmt ();
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+       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, "%<)%>");
+       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);
@@ -7644,46 +8941,34 @@ cp_parser_iteration_statement (cp_parser* parser)
        parser->in_statement = in_statement;
        finish_do_body (statement);
        /* Look for the `while' keyword.  */
-       cp_parser_require_keyword (parser, RID_WHILE, "%<while%>");
+       cp_parser_require_keyword (parser, RID_WHILE, RT_WHILE);
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+       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, "%<)%>");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
        /* Look for the `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       }
       break;
 
     case RID_FOR:
       {
-       tree condition = NULL_TREE;
-       tree expression = NULL_TREE;
-
-       /* Begin the for-statement.  */
-       statement = begin_for_stmt ();
        /* Look for the `('.  */
-       cp_parser_require (parser, CPP_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, "%<;%>");
+       cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+
+       if (cxx_dialect == cxx0x)
+         statement = cp_parser_range_for (parser);
+       else
+         statement = NULL_TREE;
+       if (statement == NULL_TREE)
+         statement = cp_parser_c_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, "%<)%>");
+       cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
        /* Parse the body of the for-statement.  */
        parser->in_statement = IN_ITERATION_STMT;
@@ -7733,7 +9018,7 @@ cp_parser_for_init_statement (cp_parser* parser)
        return;
     }
 
-  cp_parser_expression_statement (parser, false);
+  cp_parser_expression_statement (parser, NULL_TREE);
 }
 
 /* Parse a jump-statement.
@@ -7761,7 +9046,7 @@ cp_parser_jump_statement (cp_parser* parser)
   unsigned char in_statement;
 
   /* Peek at the next token.  */
-  token = cp_parser_require (parser, CPP_KEYWORD, "jump-statement");
+  token = cp_parser_require (parser, CPP_KEYWORD, RT_JUMP);
   if (!token)
     return error_mark_node;
 
@@ -7788,7 +9073,7 @@ cp_parser_jump_statement (cp_parser* parser)
          error_at (token->location, "break statement used with OpenMP for loop");
          break;
        }
-      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+      cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       break;
 
     case RID_CONTINUE:
@@ -7807,7 +9092,7 @@ cp_parser_jump_statement (cp_parser* parser)
        default:
          gcc_unreachable ();
        }
-      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+      cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       break;
 
     case RID_RETURN:
@@ -7817,7 +9102,7 @@ cp_parser_jump_statement (cp_parser* parser)
 
        if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
          {
-           maybe_warn_cpp0x ("extended initializer lists");
+           maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
            expr = cp_parser_braced_list (parser, &expr_non_constant_p);
          }
        else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
@@ -7829,7 +9114,7 @@ cp_parser_jump_statement (cp_parser* parser)
        /* Build the return-statement.  */
        statement = finish_return_stmt (expr);
        /* Look for the final `;'.  */
-       cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+       cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       }
       break;
 
@@ -7847,7 +9132,7 @@ cp_parser_jump_statement (cp_parser* parser)
       else
        finish_goto_stmt (cp_parser_identifier (parser));
       /* Look for the final `;'.  */
-      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+      cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       break;
 
     default:
@@ -7945,13 +9230,13 @@ cp_parser_already_scoped_statement (cp_parser* parser)
     {
       /* Avoid calling cp_parser_compound_statement, so that we
         don't create a new scope.  Do everything else by hand.  */
-      cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
+      cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
       /* If the next keyword is `__label__' we have a label declaration.  */
       while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
        cp_parser_label_declaration (parser);
       /* Parse an (optional) statement-seq.  */
       cp_parser_statement_seq_opt (parser, NULL_TREE);
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
     }
 }
 
@@ -8038,6 +9323,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))
@@ -8115,7 +9401,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
@@ -8277,7 +9567,7 @@ cp_parser_simple_declaration (cp_parser* parser,
        T t;
 
      where "T" should name a type -- but does not.  */
-  if (!decl_specifiers.type
+  if (!decl_specifiers.any_type_specifiers_p
       && cp_parser_parse_and_diagnose_invalid_type_name (parser))
     {
       /* If parsing tentatively, we should commit; we really are
@@ -8396,7 +9686,7 @@ cp_parser_simple_declaration (cp_parser* parser,
     }
 
   /* Consume the `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
  done:
   pop_deferring_access_checks ();
@@ -8478,7 +9768,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       switch (token->keyword)
        {
          /* decl-specifier:
-              friend  */
+              friend
+               constexpr */
        case RID_FRIEND:
          if (!at_class_scope_p ())
            {
@@ -8493,6 +9784,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
            }
          break;
 
+        case RID_CONSTEXPR:
+          ++decl_specs->specs[(int) ds_constexpr];
+          cp_lexer_consume_token (parser->lexer);
+          break;
+
          /* function-specifier:
               inline
               virtual
@@ -8569,6 +9865,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
@@ -8636,6 +9937,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
            {
              constructor_possible_p = false;
              found_decl_spec = true;
+             if (!is_cv_qualifier)
+               decl_specs->any_type_specifiers_p = true;
            }
        }
 
@@ -8755,7 +10058,7 @@ cp_parser_linkage_specification (cp_parser* parser)
   tree linkage;
 
   /* Look for the `extern' keyword.  */
-  cp_parser_require_keyword (parser, RID_EXTERN, "%<extern%>");
+  cp_parser_require_keyword (parser, RID_EXTERN, RT_EXTERN);
 
   /* Look for the string-literal.  */
   linkage = cp_parser_string_literal (parser, false, false);
@@ -8785,7 +10088,7 @@ cp_parser_linkage_specification (cp_parser* parser)
       /* Parse the declarations.  */
       cp_parser_declaration_seq_opt (parser);
       /* Look for the closing `}'.  */
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
     }
   /* Otherwise, there's just one declaration.  */
   else
@@ -8826,7 +10129,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
 
   /* Look for the `static_assert' keyword.  */
   if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT, 
-                                  "%<static_assert%>"))
+                                  RT_STATIC_ASSERT))
     return;
 
   /*  We know we are in a static assertion; commit to any tentative
@@ -8835,7 +10138,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
     cp_parser_commit_to_tentative_parse (parser);
 
   /* Parse the `(' starting the static assertion condition.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
   /* Parse the constant-expression.  */
   condition = 
@@ -8844,7 +10147,7 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
                                    /*non_constant_p=*/NULL);
 
   /* Parse the separating `,'.  */
-  cp_parser_require (parser, CPP_COMMA, "%<,%>");
+  cp_parser_require (parser, CPP_COMMA, RT_COMMA);
 
   /* Parse the string-literal message.  */
   message = cp_parser_string_literal (parser, 
@@ -8852,14 +10155,14 @@ cp_parser_static_assert(cp_parser *parser, bool member_p)
                                       /*wide_ok=*/true);
 
   /* A `)' completes the static assertion.  */
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+  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);
 
   /* A semicolon terminates the declaration.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
   /* Complete the static assertion, which may mean either processing 
      the static assert now or saving it for template instantiation.  */
@@ -8882,7 +10185,7 @@ cp_parser_decltype (cp_parser *parser)
   cp_token *id_expr_start_token;
 
   /* Look for the `decltype' token.  */
-  if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
+  if (!cp_parser_require_keyword (parser, RID_DECLTYPE, RT_DECLTYPE))
     return error_mark_node;
 
   /* Types cannot be defined in a `decltype' expression.  Save away the
@@ -8891,7 +10194,7 @@ cp_parser_decltype (cp_parser *parser)
 
   /* And create the new one.  */
   parser->type_definition_forbidden_message
-    = "types may not be defined in %<decltype%> expressions";
+    = G_("types may not be defined in %<decltype%> expressions");
 
   /* The restrictions on constant-expressions do not apply inside
      decltype expressions.  */
@@ -8908,7 +10211,7 @@ cp_parser_decltype (cp_parser *parser)
   ++c_inhibit_evaluation_warnings;
 
   /* Parse the opening `('.  */
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return error_mark_node;
   
   /* First, try parsing an id-expression.  */
@@ -9000,12 +10303,25 @@ cp_parser_decltype (cp_parser *parser)
     cp_parser_parse_definitely (parser);
   else
     {
+      bool saved_greater_than_is_operator_p;
+
       /* Abort our attempt to parse an id-expression or member access
          expression.  */
       cp_parser_abort_tentative_parse (parser);
 
+      /* Within a parenthesized expression, a `>' token is always
+        the greater-than operator.  */
+      saved_greater_than_is_operator_p
+       = parser->greater_than_is_operator_p;
+      parser->greater_than_is_operator_p = true;
+
       /* Parse a full expression.  */
       expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+
+      /* The `>' token might be the end of a template-id or
+        template-parameter-list now.  */
+      parser->greater_than_is_operator_p
+       = saved_greater_than_is_operator_p;
     }
 
   /* Go back to evaluating expressions.  */
@@ -9029,7 +10345,7 @@ cp_parser_decltype (cp_parser *parser)
     }
   
   /* Parse to the closing `)'.  */
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
     {
       cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                             /*consume_paren=*/true);
@@ -9058,7 +10374,7 @@ cp_parser_conversion_function_id (cp_parser* parser)
   tree pushed_scope = NULL_TREE;
 
   /* Look for the `operator' token.  */
-  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%<operator%>"))
+  if (!cp_parser_require_keyword (parser, RID_OPERATOR, RT_OPERATOR))
     return error_mark_node;
   /* When we parse the conversion-type-id, the current scope will be
      reset.  However, we need that information in able to look up the
@@ -9114,7 +10430,8 @@ cp_parser_conversion_type_id (cp_parser* parser)
   /* Parse the attributes.  */
   attributes = cp_parser_attributes_opt (parser);
   /* Parse the type-specifiers.  */
-  cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+  cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+                               /*is_trailing_return=*/false,
                                &type_specifiers);
   /* If that didn't work, stop.  */
   if (type_specifiers.type == error_mark_node)
@@ -9217,7 +10534,7 @@ cp_parser_mem_initializer_list (cp_parser* parser)
      mem-initializer-list.  */
   if (!DECL_CONSTRUCTOR_P (current_function_decl))
     error_at (token->location,
-             "only constructors take base initializers");
+             "only constructors take member initializers");
 
   /* Loop through the list.  */
   while (true)
@@ -9310,7 +10627,7 @@ cp_parser_mem_initializer (cp_parser* parser)
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
       bool expr_non_constant_p;
-      maybe_warn_cpp0x ("extended initializer lists");
+      maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
       CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
       expression_list = build_tree_list (NULL_TREE, expression_list);
@@ -9318,7 +10635,7 @@ cp_parser_mem_initializer (cp_parser* parser)
   else
     {
       VEC(tree,gc)* vec;
-      vec = cp_parser_parenthesized_expression_list (parser, false,
+      vec = cp_parser_parenthesized_expression_list (parser, non_attr,
                                                     /*cast_p=*/false,
                                                     /*allow_expansion_p=*/true,
                                                     /*non_constant_p=*/NULL);
@@ -9398,7 +10715,7 @@ cp_parser_mem_initializer_id (cp_parser* parser)
     return cp_parser_class_name (parser,
                                 /*typename_keyword_p=*/true,
                                 /*template_keyword_p=*/template_p,
-                                none_type,
+                                typename_type,
                                 /*check_dependency_p=*/true,
                                 /*class_head_p=*/false,
                                 /*is_declaration=*/true);
@@ -9433,7 +10750,7 @@ static tree
 cp_parser_operator_function_id (cp_parser* parser)
 {
   /* Look for the `operator' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%<operator%>"))
+  if (!cp_parser_require_keyword (parser, RID_OPERATOR, RT_OPERATOR))
     return error_mark_node;
   /* And then the name of the operator itself.  */
   return cp_parser_operator (parser);
@@ -9489,7 +10806,7 @@ cp_parser_operator (cp_parser* parser)
            /* Consume the `[' token.  */
            cp_lexer_consume_token (parser->lexer);
            /* Look for the `]' token.  */
-           cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+           cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
            id = ansi_opname (op == NEW_EXPR
                              ? VEC_NEW_EXPR : VEC_DELETE_EXPR);
          }
@@ -9648,14 +10965,14 @@ cp_parser_operator (cp_parser* parser)
       /* Consume the `('.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
       return ansi_opname (CALL_EXPR);
 
     case CPP_OPEN_SQUARE:
       /* Consume the `['.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the matching `]'.  */
-      cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+      cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
       return ansi_opname (ARRAY_REF);
 
     default:
@@ -9728,6 +11045,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;
@@ -9746,11 +11070,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);
        }
 
@@ -9905,7 +11229,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type,
 
   parm = grokdeclarator (parameter_declarator->declarator,
                         &parameter_declarator->decl_specifiers,
-                        PARM, /*initialized=*/0,
+                        TPARM, /*initialized=*/0,
                         /*attrlist=*/NULL);
   if (parm == error_mark_node)
     return error_mark_node;
@@ -9943,8 +11267,7 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
   tree parameter;
 
   /* Look for a keyword to tell us what kind of parameter this is.  */
-  token = cp_parser_require (parser, CPP_KEYWORD,
-                            "%<class%>, %<typename%>, or %<template%>");
+  token = cp_parser_require (parser, CPP_KEYWORD, RT_CLASS_TYPENAME_TEMPLATE);
   if (!token)
     return error_mark_node;
 
@@ -10013,18 +11336,17 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
 
     case RID_TEMPLATE:
       {
-       tree parameter_list;
        tree identifier;
        tree default_argument;
 
        /* Look for the `<'.  */
-       cp_parser_require (parser, CPP_LESS, "%<<%>");
+       cp_parser_require (parser, CPP_LESS, RT_LESS);
        /* Parse the template-parameter-list.  */
-       parameter_list = cp_parser_template_parameter_list (parser);
+       cp_parser_template_parameter_list (parser);
        /* Look for the `>'.  */
-       cp_parser_require (parser, CPP_GREATER, "%<>%>");
+       cp_parser_require (parser, CPP_GREATER, RT_GREATER);
        /* Look for the `class' keyword.  */
-       cp_parser_require_keyword (parser, RID_CLASS, "%<class%>");
+       cp_parser_require_keyword (parser, RID_CLASS, RT_CLASS);
         /* If the next token is an ellipsis, we have a template
            argument pack. */
         if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
@@ -10154,7 +11476,7 @@ cp_parser_template_id (cp_parser *parser,
   cp_token_position start_of_id = 0;
   deferred_access_check *chk;
   VEC (deferred_access_check,gc) *access_check;
-  cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
+  cp_token *next_token = NULL, *next_token_2 = NULL;
   bool is_identifier;
 
   /* If the next token corresponds to a template-id, there is no need
@@ -10170,14 +11492,10 @@ cp_parser_template_id (cp_parser *parser,
       access_check = check_value->checks;
       if (access_check)
        {
-         for (i = 0 ;
-              VEC_iterate (deferred_access_check, access_check, i, chk) ;
-              ++i)
-           {
-             perform_or_defer_access_check (chk->binfo,
-                                            chk->decl,
-                                            chk->diag_decl);
-           }
+         FOR_EACH_VEC_ELT (deferred_access_check, access_check, i, chk)
+           perform_or_defer_access_check (chk->binfo,
+                                          chk->decl,
+                                          chk->diag_decl);
        }
       /* Return the stored value.  */
       return check_value->value;
@@ -10202,7 +11520,6 @@ cp_parser_template_id (cp_parser *parser,
 
   /* Parse the template-name.  */
   is_identifier = false;
-  token = cp_lexer_peek_token (parser->lexer);
   templ = cp_parser_template_name (parser, template_keyword_p,
                                   check_dependency_p,
                                   is_declaration,
@@ -10262,7 +11579,7 @@ cp_parser_template_id (cp_parser *parser,
   else
     {
       /* Look for the `<' that starts the template-argument-list.  */
-      if (!cp_parser_require (parser, CPP_LESS, "%<<%>"))
+      if (!cp_parser_require (parser, CPP_LESS, RT_LESS))
        {
          pop_deferring_access_checks ();
          return error_mark_node;
@@ -10314,7 +11631,7 @@ cp_parser_template_id (cp_parser *parser,
       token->type = CPP_TEMPLATE_ID;
       /* Retrieve any deferred checks.  Do not pop this access checks yet
         so the memory will not be reclaimed during token replacing below.  */
-      token->u.tree_check_value = GGC_CNEW (struct tree_check);
+      token->u.tree_check_value = ggc_alloc_cleared_tree_check ();
       token->u.tree_check_value->value = template_id;
       token->u.tree_check_value->checks = get_deferred_access_checks ();
       token->keyword = RID_MAX;
@@ -10483,12 +11800,11 @@ cp_parser_template_name (cp_parser* parser,
   /* Look up the name.  */
   decl = cp_parser_lookup_name (parser, identifier,
                                none_type,
-                               /*is_template=*/false,
+                               /*is_template=*/true,
                                /*is_namespace=*/false,
                                check_dependency_p,
                                /*ambiguous_decls=*/NULL,
                                token->location);
-  decl = maybe_get_template_decl_from_type_decl (decl);
 
   /* If DECL is a template, then the name was a template-name.  */
   if (TREE_CODE (decl) == TEMPLATE_DECL)
@@ -10613,6 +11929,9 @@ cp_parser_template_argument_list (cp_parser* parser)
   parser->non_integral_constant_expression_p = saved_non_ice_p;
   parser->integral_constant_expression_p = saved_ice_p;
   parser->in_template_argument_list_p = saved_in_template_argument_list_p;
+#ifdef ENABLE_CHECKING
+  SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec));
+#endif
   return vec;
 }
 
@@ -10775,18 +12094,26 @@ cp_parser_template_argument (cp_parser* parser)
        cp_parser_abort_tentative_parse (parser);
       else
        {
+         tree probe;
+
          if (TREE_CODE (argument) == INDIRECT_REF)
            {
              gcc_assert (REFERENCE_REF_P (argument));
              argument = TREE_OPERAND (argument, 0);
            }
 
-         if (TREE_CODE (argument) == VAR_DECL)
+         /* If we're in a template, we represent a qualified-id referring
+            to a static data member as a SCOPE_REF even if the scope isn't
+            dependent so that we can check access control later.  */
+         probe = argument;
+         if (TREE_CODE (probe) == SCOPE_REF)
+           probe = TREE_OPERAND (probe, 1);
+         if (TREE_CODE (probe) == VAR_DECL)
            {
              /* A variable without external linkage might still be a
                 valid constant-expression, so no error is issued here
                 if the external-linkage check fails.  */
-             if (!address_p && !DECL_EXTERNAL_LINKAGE_P (argument))
+             if (!address_p && !DECL_EXTERNAL_LINKAGE_P (probe))
                cp_parser_simulate_error (parser);
            }
          else if (is_overloaded_fn (argument))
@@ -10872,7 +12199,6 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   int declares_class_or_enum;
   cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
-  cp_token *token;
 
   /* Look for an (optional) storage-class-specifier or
      function-specifier.  */
@@ -10887,7 +12213,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     }
 
   /* Look for the `template' keyword.  */
-  cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
+  cp_parser_require_keyword (parser, RID_TEMPLATE, RT_TEMPLATE);
   /* Let the front end know that we are processing an explicit
      instantiation.  */
   begin_explicit_instantiation ();
@@ -10895,7 +12221,6 @@ cp_parser_explicit_instantiation (cp_parser* parser)
      control while processing explicit instantiation directives.  */
   push_deferring_access_checks (dk_no_check);
   /* Parse a decl-specifier-seq.  */
-  token = cp_lexer_peek_token (parser->lexer);
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_OPTIONAL,
                                &decl_specifiers,
@@ -10932,6 +12257,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
@@ -10973,11 +12305,11 @@ cp_parser_explicit_specialization (cp_parser* parser)
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Look for the `template' keyword.  */
-  cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
+  cp_parser_require_keyword (parser, RID_TEMPLATE, RT_TEMPLATE);
   /* Look for the `<'.  */
-  cp_parser_require (parser, CPP_LESS, "%<<%>");
+  cp_parser_require (parser, CPP_LESS, RT_LESS);
   /* Look for the `>'.  */
-  cp_parser_require (parser, CPP_GREATER, "%<>%>");
+  cp_parser_require (parser, CPP_GREATER, RT_GREATER);
   /* We have processed another parameter list.  */
   ++parser->num_template_parameter_lists;
   /* [temp]
@@ -11090,6 +12422,9 @@ cp_parser_type_specifier (cp_parser* parser,
   switch (keyword)
     {
     case RID_ENUM:
+      if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS))
+       goto elaborated_type_specifier;
+
       /* Look for the enum-specifier.  */
       type_spec = cp_parser_enum_specifier (parser);
       /* If that worked, we're done.  */
@@ -11112,6 +12447,9 @@ cp_parser_type_specifier (cp_parser* parser,
     case RID_CLASS:
     case RID_STRUCT:
     case RID_UNION:
+      if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS))
+       goto elaborated_type_specifier;
+
       /* Parse tentatively so that we can back up if we don't find a
         class-specifier.  */
       cp_parser_parse_tentatively (parser);
@@ -11235,6 +12573,7 @@ cp_parser_type_specifier (cp_parser* parser,
    GNU Extension:
 
    simple-type-specifier:
+     __int128
      __typeof__ unary-expression
      __typeof__ ( type-id )
 
@@ -11282,6 +12621,13 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
+    case RID_INT128:
+      if (!int128_integer_type_node)
+       break;
+      if (decl_specs)
+        decl_specs->explicit_int128_p = true;
+      type = int128_integer_type_node;
+      break;
     case RID_LONG:
       if (decl_specs)
        ++decl_specs->specs[(int) ds_long];
@@ -11308,7 +12654,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       break;
       
     case RID_AUTO:
-      maybe_warn_cpp0x ("C++0x auto");
+      maybe_warn_cpp0x (CPP0X_AUTO);
       type = make_auto ();
       break;
 
@@ -11346,8 +12692,6 @@ cp_parser_simple_type_specifier (cp_parser* parser,
   /* If the type-specifier was for a built-in type, we're done.  */
   if (type)
     {
-      tree id;
-
       /* Record the type.  */
       if (decl_specs
          && (token->keyword != RID_SIGNED
@@ -11362,7 +12706,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
        decl_specs->any_specifiers_p = true;
 
       /* Consume the token.  */
-      id = cp_lexer_consume_token (parser->lexer)->u.value;
+      cp_lexer_consume_token (parser->lexer);
 
       /* There is no valid C++ program where a non-template type is
         followed by a "<".  That usually indicates that the user thought
@@ -11450,7 +12794,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       /* 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 ()
+      if (c_dialect_objc () && !parser->scope
          && (objc_is_id (type) || objc_is_class_name (type)))
        {
          tree protos = cp_parser_objc_protocol_refs_opt (parser);
@@ -11550,7 +12894,7 @@ cp_parser_nonclass_name (cp_parser* parser)
     {
       if (!cp_parser_simulate_error (parser))
        cp_parser_name_lookup_error (parser, identifier, type_decl,
-                                    "is not a type", token->location);
+                                    NLE_TYPE, token->location);
       return error_mark_node;
     }
   /* Remember that the name was used in the definition of the
@@ -11609,17 +12953,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 ("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);
     }
@@ -11909,7 +13253,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
@@ -11919,6 +13267,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]
@@ -11930,11 +13281,18 @@ 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;
 
   /* Parse tentatively so that we can back up if we don't find a
      enum-specifier.  */
@@ -11951,8 +13309,8 @@ 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)
-        maybe_warn_cpp0x ("scoped enums");
+      if (cxx_dialect < cxx0x)
+        maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
 
       /* Consume the `struct' or `class' token.  */
       cp_lexer_consume_token (parser->lexer);
@@ -11962,32 +13320,89 @@ 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.  */
+  /* Check for the `:' that denotes a specified underlying type in C++0x.
+     Note that a ':' could also indicate a bitfield width, however.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
     {
       cp_decl_specifier_seq type_specifiers;
 
+      /* Consume the `:'.  */
+      cp_lexer_consume_token (parser->lexer);
+
+      /* Parse the type-specifier-seq.  */
+      cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+                                   /*is_trailing_return=*/false,
+                                    &type_specifiers);
+
       /* At this point this is surely not elaborated type specifier.  */
       if (!cp_parser_parse_definitely (parser))
        return NULL_TREE;
 
-      if (cxx_dialect == cxx98)
-        maybe_warn_cpp0x ("scoped enums");
-
-      /* Consume the `:'.  */
-      cp_lexer_consume_token (parser->lexer);
+      if (cxx_dialect < cxx0x)
+        maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
 
       has_underlying_type = true;
 
-      /* Parse the type-specifier-seq.  */
-      cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
-                                    &type_specifiers);
-
       /* If that didn't work, stop.  */
       if (type_specifiers.type != error_mark_node)
         {
@@ -12001,14 +13416,39 @@ 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)
+           return NULL_TREE;
+       }
+      /* 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)
+           return NULL_TREE;
+       }
     }
 
   if (!has_underlying_type && !cp_parser_parse_definitely (parser))
     return NULL_TREE;
 
+  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;
@@ -12016,23 +13456,89 @@ cp_parser_enum_specifier (cp_parser* parser)
     /* Create the new type.  We do this before consuming the opening
        brace so the enum will be recorded as being on the line of its
        tag (or the 'enum' keyword, if there is no tag).  */
-    type = start_enum (identifier, 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;
-    }
+      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, "%<}%>");
+      /* 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 ();
+    }
+  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.  */
@@ -12046,8 +13552,26 @@ 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);
+       }
+    }
   return type;
 }
 
@@ -12097,6 +13621,11 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
 {
   tree identifier;
   tree value;
+  location_t loc;
+
+  /* Save the input location because we are interested in the location
+     of the identifier and not the location of the explicit value.  */
+  loc = cp_lexer_peek_token (parser->lexer)->location;
 
   /* Look for the identifier.  */
   identifier = cp_parser_identifier (parser);
@@ -12122,7 +13651,7 @@ cp_parser_enumerator_definition (cp_parser* parser, tree type)
     value = error_mark_node;
 
   /* Create the enumerator.  */
-  build_enumerator (identifier, value, type);
+  build_enumerator (identifier, value, type, loc);
 }
 
 /* Parse a namespace-name.
@@ -12212,6 +13741,7 @@ cp_parser_namespace_definition (cp_parser* parser)
 
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_INLINE))
     {
+      maybe_warn_cpp0x (CPP0X_INLINE_NAMESPACES);
       is_inline = true;
       cp_lexer_consume_token (parser->lexer);
     }
@@ -12219,7 +13749,7 @@ cp_parser_namespace_definition (cp_parser* parser)
     is_inline = false;
 
   /* Look for the `namespace' keyword.  */
-  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE);
 
   /* Get the name of the namespace.  We do not attempt to distinguish
      between an original-namespace-definition and an
@@ -12234,7 +13764,7 @@ cp_parser_namespace_definition (cp_parser* parser)
   attribs = cp_parser_attributes_opt (parser);
 
   /* Look for the `{' to start the namespace.  */
-  cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
+  cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE);
   /* Start the namespace.  */
   push_namespace (identifier);
 
@@ -12260,13 +13790,13 @@ cp_parser_namespace_definition (cp_parser* parser)
 
 #ifdef HANDLE_PRAGMA_VISIBILITY
   if (has_visibility)
-    pop_visibility ();
+    pop_visibility (1);
 #endif
 
   /* Finish the namespace.  */
   pop_namespace ();
   /* Look for the final `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
 }
 
 /* Parse a namespace-body.
@@ -12294,7 +13824,7 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
   cp_token *token = cp_lexer_peek_token (parser->lexer);
 
   /* Look for the `namespace' keyword.  */
-  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE);
   /* Look for the identifier.  */
   identifier = cp_parser_identifier (parser);
   if (identifier == error_mark_node)
@@ -12310,12 +13840,12 @@ cp_parser_namespace_alias_definition (cp_parser* parser)
        cp_lexer_consume_token (parser->lexer);
       return;
     }
-  cp_parser_require (parser, CPP_EQ, "%<=%>");
+  cp_parser_require (parser, CPP_EQ, RT_EQ);
   /* Look for the qualified-namespace-specifier.  */
   namespace_specifier
     = cp_parser_qualified_namespace_specifier (parser);
   /* Look for the `;' token.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
   /* Register the alias in the symbol table.  */
   do_namespace_alias (identifier, namespace_specifier);
@@ -12374,7 +13904,7 @@ cp_parser_using_declaration (cp_parser* parser,
   else
     {
       /* Look for the `using' keyword.  */
-      cp_parser_require_keyword (parser, RID_USING, "%<using%>");
+      cp_parser_require_keyword (parser, RID_USING, RT_USING);
       
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -12465,7 +13995,7 @@ cp_parser_using_declaration (cp_parser* parser,
                                               token->location);
          if (decl == error_mark_node)
            cp_parser_name_lookup_error (parser, identifier,
-                                        decl, NULL,
+                                        decl, NLE_NULL,
                                         token->location);
          else if (check_for_bare_parameter_packs (decl))
            return false;
@@ -12477,7 +14007,7 @@ cp_parser_using_declaration (cp_parser* parser,
     }
 
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
   
   return true;
 }
@@ -12495,9 +14025,9 @@ cp_parser_using_directive (cp_parser* parser)
   tree attribs;
 
   /* Look for the `using' keyword.  */
-  cp_parser_require_keyword (parser, RID_USING, "%<using%>");
+  cp_parser_require_keyword (parser, RID_USING, RT_USING);
   /* And the `namespace' keyword.  */
-  cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
+  cp_parser_require_keyword (parser, RID_NAMESPACE, RT_NAMESPACE);
   /* Look for the optional `::' operator.  */
   cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
   /* And the optional nested-name-specifier.  */
@@ -12513,7 +14043,7 @@ cp_parser_using_directive (cp_parser* parser)
   /* Update the symbol table.  */
   parse_using_directive (namespace_decl, attribs);
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 }
 
 /* Parse an asm-definition.
@@ -12530,7 +14060,10 @@ cp_parser_using_directive (cp_parser* parser)
                          : asm-operand-list [opt] ) ;
      asm volatile [opt] ( string-literal : asm-operand-list [opt]
                          : asm-operand-list [opt]
-                         : asm-operand-list [opt] ) ;  */
+                         : asm-clobber-list [opt] ) ;
+     asm volatile [opt] goto ( string-literal : : asm-operand-list [opt]
+                              : asm-clobber-list [opt]
+                              : asm-goto-list ) ;  */
 
 static void
 cp_parser_asm_definition (cp_parser* parser)
@@ -12539,25 +14072,37 @@ cp_parser_asm_definition (cp_parser* parser)
   tree outputs = NULL_TREE;
   tree inputs = NULL_TREE;
   tree clobbers = NULL_TREE;
+  tree labels = NULL_TREE;
   tree asm_stmt;
   bool volatile_p = false;
   bool extended_p = false;
   bool invalid_inputs_p = false;
   bool invalid_outputs_p = false;
+  bool goto_p = false;
+  required_token missing = RT_NONE;
 
   /* Look for the `asm' keyword.  */
-  cp_parser_require_keyword (parser, RID_ASM, "%<asm%>");
+  cp_parser_require_keyword (parser, RID_ASM, RT_ASM);
   /* See if the next token is `volatile'.  */
   if (cp_parser_allow_gnu_extensions_p (parser)
-      && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
+      && cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
+    {
+      /* Remember that we saw the `volatile' keyword.  */
+      volatile_p = true;
+      /* Consume the token.  */
+      cp_lexer_consume_token (parser->lexer);
+    }
+  if (cp_parser_allow_gnu_extensions_p (parser)
+      && parser->in_function_body
+      && cp_lexer_next_token_is_keyword (parser->lexer, RID_GOTO))
     {
-      /* Remember that we saw the `volatile' keyword.  */
-      volatile_p = true;
+      /* Remember that we saw the `goto' keyword.  */
+      goto_p = true;
       /* Consume the token.  */
       cp_lexer_consume_token (parser->lexer);
     }
   /* Look for the opening `('.  */
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return;
   /* Look for the string.  */
   string = cp_parser_string_literal (parser, false, false);
@@ -12580,6 +14125,7 @@ cp_parser_asm_definition (cp_parser* parser)
     {
       bool inputs_p = false;
       bool clobbers_p = false;
+      bool labels_p = false;
 
       /* The extended syntax was used.  */
       extended_p = true;
@@ -12595,7 +14141,8 @@ cp_parser_asm_definition (cp_parser* parser)
              && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_SCOPE)
              && cp_lexer_next_token_is_not (parser->lexer,
-                                            CPP_CLOSE_PAREN))
+                                            CPP_CLOSE_PAREN)
+             && !goto_p)
            outputs = cp_parser_asm_operand_list (parser);
 
            if (outputs == error_mark_node)
@@ -12617,6 +14164,8 @@ cp_parser_asm_definition (cp_parser* parser)
          if (cp_lexer_next_token_is_not (parser->lexer,
                                          CPP_COLON)
              && cp_lexer_next_token_is_not (parser->lexer,
+                                            CPP_SCOPE)
+             && cp_lexer_next_token_is_not (parser->lexer,
                                             CPP_CLOSE_PAREN))
            inputs = cp_parser_asm_operand_list (parser);
 
@@ -12631,19 +14180,44 @@ cp_parser_asm_definition (cp_parser* parser)
       if (clobbers_p
          || cp_lexer_next_token_is (parser->lexer, CPP_COLON))
        {
+         clobbers_p = true;
          /* Consume the `:' or `::'.  */
          cp_lexer_consume_token (parser->lexer);
          /* Parse the clobbers.  */
          if (cp_lexer_next_token_is_not (parser->lexer,
-                                         CPP_CLOSE_PAREN))
+                                         CPP_COLON)
+             && cp_lexer_next_token_is_not (parser->lexer,
+                                            CPP_CLOSE_PAREN))
            clobbers = cp_parser_asm_clobber_list (parser);
        }
+      else if (goto_p
+              && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
+       /* The labels are coming next.  */
+       labels_p = true;
+
+      /* Look for labels.  */
+      if (labels_p
+         || (goto_p && cp_lexer_next_token_is (parser->lexer, CPP_COLON)))
+       {
+         labels_p = true;
+         /* Consume the `:' or `::'.  */
+         cp_lexer_consume_token (parser->lexer);
+         /* Parse the labels.  */
+         labels = cp_parser_asm_label_list (parser);
+       }
+
+      if (goto_p && !labels_p)
+       missing = clobbers_p ? RT_COLON : RT_COLON_SCOPE;
     }
+  else if (goto_p)
+    missing = RT_COLON_SCOPE;
+
   /* Look for the closing `)'.  */
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+  if (!cp_parser_require (parser, missing ? CPP_COLON : CPP_CLOSE_PAREN,
+                         missing ? missing : RT_CLOSE_PAREN))
     cp_parser_skip_to_closing_parenthesis (parser, true, false,
                                           /*consume_paren=*/true);
-  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
   if (!invalid_inputs_p && !invalid_outputs_p)
     {
@@ -12651,7 +14225,7 @@ cp_parser_asm_definition (cp_parser* parser)
       if (parser->in_function_body)
        {
          asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
-                                     inputs, clobbers);
+                                     inputs, clobbers, labels);
          /* If the extended syntax was not used, mark the ASM_EXPR.  */
          if (!extended_p)
            {
@@ -12780,6 +14354,11 @@ cp_parser_init_declarator (cp_parser* parser,
      we compute it now.  */
   scope = get_scope_of_declarator (declarator);
 
+  /* Perform any lookups in the declared type which were thought to be
+     dependent, but are not in the scope of the declarator.  */
+  decl_specifiers->type
+    = maybe_update_decl_type (decl_specifiers->type, scope);
+
   /* If we're allowing GNU extensions, look for an asm-specification
      and attributes.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
@@ -12927,6 +14506,13 @@ cp_parser_init_declarator (cp_parser* parser,
       decl = start_decl (declarator, decl_specifiers,
                         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
+        location would be different from input_location, and more accurate.  */
+      if (DECL_P (decl)
+         && declarator->id_loc != UNKNOWN_LOCATION
+         && DECL_SOURCE_LOCATION (decl) == input_location)
+       DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
     }
   else if (scope)
     /* Enter the SCOPE.  That way unqualified names appearing in the
@@ -12986,9 +14572,21 @@ cp_parser_init_declarator (cp_parser* parser,
             }
        }
       else
-       initializer = cp_parser_initializer (parser,
-                                            &is_direct_init,
-                                            &is_non_constant_init);
+       {
+         /* We want to record the extra mangling scope for in-class
+            initializers of class members and initializers of static data
+            member templates.  The former is a C++0x feature which isn't
+            implemented yet, and I expect it will involve deferring
+            parsing of the initializer until end of class as with default
+            arguments.  So right here we only handle the latter.  */
+         if (!member_p && processing_template_decl)
+           start_lambda_scope (decl);
+         initializer = cp_parser_initializer (parser,
+                                              &is_direct_init,
+                                              &is_non_constant_init);
+         if (!member_p && processing_template_decl)
+           finish_lambda_scope ();
+       }
     }
 
   /* The old parser allows attributes to appear after a parenthesized
@@ -13030,7 +14628,7 @@ cp_parser_init_declarator (cp_parser* parser,
                         `explicit' constructor is OK.  Otherwise, an
                         `explicit' constructor cannot be used.  */
                      ((is_direct_init || !is_initialized)
-                      ? 0 : LOOKUP_ONLYCONVERTING));
+                      ? LOOKUP_NORMAL : LOOKUP_IMPLICIT));
     }
   else if ((cxx_dialect != cxx98) && friend_p
           && decl && TREE_CODE (decl) == FUNCTION_DECL)
@@ -13092,7 +14690,6 @@ cp_parser_declarator (cp_parser* parser,
                      bool* parenthesized_p,
                      bool member_p)
 {
-  cp_token *token;
   cp_declarator *declarator;
   enum tree_code code;
   cp_cv_quals cv_quals;
@@ -13107,9 +14704,6 @@ cp_parser_declarator (cp_parser* parser,
   if (cp_parser_allow_gnu_extensions_p (parser))
     attributes = cp_parser_attributes_opt (parser);
 
-  /* Peek at the next token.  */
-  token = cp_lexer_peek_token (parser->lexer);
-
   /* Check for the ptr-operator production.  */
   cp_parser_parse_tentatively (parser);
   /* Parse the ptr-operator.  */
@@ -13299,7 +14893,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
                  first = false;
                  /* Consume the `)'.  */
-                 cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+                 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
                  /* Parse the cv-qualifier-seq.  */
                  cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
@@ -13323,7 +14917,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                }
 
              /* Remove the function parms from scope.  */
-             for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+             for (t = current_binding_level->names; t; t = DECL_CHAIN (t))
                pop_binding (DECL_NAME (t), t);
              leave_scope();
 
@@ -13353,7 +14947,7 @@ cp_parser_direct_declarator (cp_parser* parser,
              parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
              first = false;
              /* Expect a `)'.  */
-             if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+             if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
                declarator = cp_error_declarator;
              if (declarator == cp_error_declarator)
                break;
@@ -13390,15 +14984,17 @@ cp_parser_direct_declarator (cp_parser* parser,
                = cp_parser_constant_expression (parser,
                                                 /*allow_non_constant=*/true,
                                                 &non_constant_p);
-             if (!non_constant_p)
-               bounds = fold_non_dependent_expr (bounds);
+             if (!non_constant_p || cxx_dialect >= cxx0x)
+               /* OK */;
              /* Normally, the array bound must be an integral constant
                 expression.  However, as an extension, we allow VLAs
-                in function scopes.  */
-             else if (!parser->in_function_body)
+                in function scopes as long as they aren't part of a
+                parameter declaration.  */
+             else if (!parser->in_function_body
+                      || current_binding_level->kind == sk_function_parms)
                {
-                 error_at (token->location,
-                           "array bound is not an integer constant");
+                 cp_parser_error (parser,
+                                  "array bound is not an integer constant");
                  bounds = error_mark_node;
                }
              else if (processing_template_decl && !error_operand_p (bounds))
@@ -13411,7 +15007,7 @@ cp_parser_direct_declarator (cp_parser* parser,
          else
            bounds = NULL_TREE;
          /* Look for the closing `]'.  */
-         if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"))
+         if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
            {
              declarator = cp_error_declarator;
              break;
@@ -13516,10 +15112,17 @@ cp_parser_direct_declarator (cp_parser* parser,
                                              /*only_current_p=*/false);
                /* If that failed, the declarator is invalid.  */
                if (TREE_CODE (type) == TYPENAME_TYPE)
-                 error_at (declarator_id_start_token->location,
-                           "%<%T::%E%> is not a type",
-                           TYPE_CONTEXT (qualifying_scope),
-                           TYPE_IDENTIFIER (qualifying_scope));
+                 {
+                   if (typedef_variant_p (type))
+                     error_at (declarator_id_start_token->location,
+                               "cannot define member of dependent typedef "
+                               "%qT", type);
+                   else
+                     error_at (declarator_id_start_token->location,
+                               "%<%T::%E%> is not a type",
+                               TYPE_CONTEXT (qualifying_scope),
+                               TYPE_IDENTIFIER (qualifying_scope));
+                 }
                qualifying_scope = type;
              }
 
@@ -13585,6 +15188,10 @@ cp_parser_direct_declarator (cp_parser* parser,
                        unqualified_name = constructor_name (class_type);
                        sfk = sfk_constructor;
                      }
+                   else if (is_overloaded_fn (unqualified_name)
+                            && DECL_CONSTRUCTOR_P (get_first_fn
+                                                   (unqualified_name)))
+                     sfk = sfk_constructor;
 
                    if (ctor_dtor_or_conv_p && sfk != sfk_none)
                      *ctor_dtor_or_conv_p = -1;
@@ -13714,7 +15321,7 @@ cp_parser_ptr_operator (cp_parser* parser,
       /* If we found it, and the next token is a `*', then we are
         indeed looking at a pointer-to-member operator.  */
       if (!cp_parser_error_occurred (parser)
-         && cp_parser_require (parser, CPP_MULT, "%<*%>"))
+         && cp_parser_require (parser, CPP_MULT, RT_MULT))
        {
          /* Indicate that the `*' operator was used.  */
          code = INDIRECT_REF;
@@ -13811,7 +15418,7 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
 /* Parse a late-specified return type, if any.  This is not a separate
    non-terminal, but part of a function declarator, which looks like
 
-   -> type-id
+   -> trailing-type-specifier-seq abstract-declarator(opt)
 
    Returns the type indicated by the type-id.  */
 
@@ -13829,7 +15436,7 @@ cp_parser_late_return_type_opt (cp_parser* parser)
   /* Consume the ->.  */
   cp_lexer_consume_token (parser->lexer);
 
-  return cp_parser_type_id (parser);
+  return cp_parser_trailing_type_id (parser);
 }
 
 /* Parse a declarator-id.
@@ -13882,13 +15489,15 @@ cp_parser_declarator_id (cp_parser* parser, bool optional_p)
    Returns the TYPE specified.  */
 
 static tree
-cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
+                    bool is_trailing_return)
 {
   cp_decl_specifier_seq type_specifier_seq;
   cp_declarator *abstract_declarator;
 
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+  cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+                               is_trailing_return,
                                &type_specifier_seq);
   if (type_specifier_seq.type == error_mark_node)
     return error_mark_node;
@@ -13926,12 +15535,17 @@ cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
 
 static tree cp_parser_type_id (cp_parser *parser)
 {
-  return cp_parser_type_id_1 (parser, false);
+  return cp_parser_type_id_1 (parser, false, false);
 }
 
 static tree cp_parser_template_type_arg (cp_parser *parser)
 {
-  return cp_parser_type_id_1 (parser, true);
+  return cp_parser_type_id_1 (parser, true, false);
+}
+
+static tree cp_parser_trailing_type_id (cp_parser *parser)
+{
+  return cp_parser_type_id_1 (parser, false, true);
 }
 
 /* Parse a type-specifier-seq.
@@ -13944,14 +15558,18 @@ static tree cp_parser_template_type_arg (cp_parser *parser)
    type-specifier-seq:
      attributes type-specifier-seq [opt]
 
-   If IS_CONDITION is true, we are at the start of a "condition",
-   e.g., we've just seen "if (".
+   If IS_DECLARATION is true, we are at the start of a "condition" or
+   exception-declaration, so we might be followed by a declarator-id.
+
+   If IS_TRAILING_RETURN is true, we are in a trailing-return-type,
+   i.e. we've just seen "->".
 
    Sets *TYPE_SPECIFIER_SEQ to represent the sequence.  */
 
 static void
 cp_parser_type_specifier_seq (cp_parser* parser,
-                             bool is_condition,
+                             bool is_declaration,
+                             bool is_trailing_return,
                              cp_decl_specifier_seq *type_specifier_seq)
 {
   bool seen_type_specifier = false;
@@ -13961,6 +15579,12 @@ cp_parser_type_specifier_seq (cp_parser* parser,
   /* Clear the TYPE_SPECIFIER_SEQ.  */
   clear_decl_specs (type_specifier_seq);
 
+  /* In the context of a trailing return type, enum E { } is an
+     elaborated-type-specifier followed by a function-body, not an
+     enum-specifier.  */
+  if (is_trailing_return)
+    flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS;
+
   /* Parse the type-specifiers and attributes.  */
   while (true)
     {
@@ -14020,7 +15644,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
         would be clearer just to allow a decl-specifier-seq here, and
         then add a semantic restriction that if any decl-specifiers
         that are not type-specifiers appear, the program is invalid.  */
-      if (is_condition && !is_cv_qualifier)
+      if (is_declaration && !is_cv_qualifier)
        flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
     }
 
@@ -14093,7 +15717,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       cp_lexer_consume_token (parser->lexer);
       /* Expect an ellipsis.  */
       ellipsis_p
-       = (cp_parser_require (parser, CPP_ELLIPSIS, "%<...%>") != NULL);
+       = (cp_parser_require (parser, CPP_ELLIPSIS, RT_ELLIPSIS) != NULL);
     }
   /* It might also be `...' if the optional trailing `,' was
      omitted.  */
@@ -14276,7 +15900,6 @@ cp_parser_parameter_declaration (cp_parser *parser,
                                 bool *parenthesized_p)
 {
   int declares_class_or_enum;
-  bool greater_than_is_operator_p;
   cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
   tree default_argument;
@@ -14291,18 +15914,22 @@ cp_parser_parameter_declaration (cp_parser *parser,
      template-parameter, the first non-nested `>' is taken as the end
      of the template parameter-list rather than a greater-than
      operator.  */
-  greater_than_is_operator_p = !template_parm_p;
 
   /* Type definitions may not appear in parameter types.  */
   saved_message = parser->type_definition_forbidden_message;
   parser->type_definition_forbidden_message
-    = "types may not be defined in parameter types";
+    = G_("types may not be defined in parameter types");
 
   /* Parse the declaration-specifiers.  */
   cp_parser_decl_specifier_seq (parser,
                                CP_PARSER_FLAGS_NONE,
                                &decl_specifiers,
                                &declares_class_or_enum);
+
+  /* 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 an error occurred, there's no reason to attempt to parse the
      rest of the declaration.  */
   if (cp_parser_error_occurred (parser))
@@ -14406,7 +16033,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
       /* If we are defining a class, then the tokens that make up the
         default argument must be saved and processed later.  */
       if (!template_parm_p && at_class_scope_p ()
-         && TYPE_BEING_DEFINED (current_class_type))
+         && TYPE_BEING_DEFINED (current_class_type)
+         && !LAMBDA_TYPE_P (current_class_type))
        {
          unsigned depth = 0;
          int maybe_template_id = 0;
@@ -14439,6 +16067,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
                         the default argument; otherwise the default
                         argument continues.  */
                      bool error = false;
+                     tree t;
 
                      /* Set ITALP so cp_parser_parameter_declaration_list
                         doesn't decide to commit to this parse.  */
@@ -14447,7 +16076,11 @@ cp_parser_parameter_declaration (cp_parser *parser,
 
                      cp_parser_parse_tentatively (parser);
                      cp_lexer_consume_token (parser->lexer);
+                     begin_scope (sk_function_parms, NULL_TREE);
                      cp_parser_parameter_declaration_list (parser, &error);
+                     for (t = current_binding_level->names; t; t = DECL_CHAIN (t))
+                       pop_binding (DECL_NAME (t), t);
+                     leave_scope ();
                      if (!cp_parser_error_occurred (parser) && !error)
                        done = true;
                      cp_parser_abort_tentative_parse (parser);
@@ -14645,15 +16278,43 @@ 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
+      && (TREE_CODE (list) != STATEMENT_LIST
+         || (last == NULL && STATEMENT_LIST_TAIL (list) != NULL)
+         || (last != NULL && last != STATEMENT_LIST_TAIL (list)->stmt)))
+    {
+      error ("constexpr constructor does not have empty body");
+      DECL_DECLARED_CONSTEXPR_P (current_function_decl) = false;
+    }
   /* Finish the function body.  */
   finish_function_body (body);
 
@@ -14701,7 +16362,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_direct_init,
   else if (token->type == CPP_OPEN_PAREN)
     {
       VEC(tree,gc) *vec;
-      vec = cp_parser_parenthesized_expression_list (parser, false,
+      vec = cp_parser_parenthesized_expression_list (parser, non_attr,
                                                     /*cast_p=*/false,
                                                     /*allow_expansion_p=*/true,
                                                     non_constant_p);
@@ -14712,7 +16373,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_direct_init,
     }
   else if (token->type == CPP_OPEN_BRACE)
     {
-      maybe_warn_cpp0x ("extended initializer lists");
+      maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       init = cp_parser_braced_list (parser, non_constant_p);
       CONSTRUCTOR_IS_DIRECT_INIT (init) = 1;
     }
@@ -14756,7 +16417,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);
@@ -14797,7 +16466,7 @@ cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
        cp_lexer_consume_token (parser->lexer);
     }
   /* Now, there should be a trailing `}'.  */
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
   TREE_TYPE (initializer) = init_list_type_node;
   return initializer;
 }
@@ -14997,14 +16666,8 @@ cp_parser_class_name (cp_parser *parser,
                                        identifier_token->location);
          if (ambiguous_decls)
            {
-             error_at (identifier_token->location,
-                       "reference to %qD is ambiguous", identifier);
-             print_candidates (ambiguous_decls);
              if (cp_parser_parsing_tentatively (parser))
-               {
-                 identifier_token->ambiguous_p = true;
-                 cp_parser_simulate_error (parser);
-               }
+               cp_parser_simulate_error (parser);
              return error_mark_node;
            }
        }
@@ -15099,7 +16762,7 @@ cp_parser_class_specifier (cp_parser* parser)
     }
 
   /* Look for the `{'.  */
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
     {
       pop_deferring_access_checks ();
       return error_mark_node;
@@ -15150,7 +16813,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, "%<}%>");
+  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);
@@ -15180,10 +16843,11 @@ cp_parser_class_specifier (cp_parser* parser)
      there is no need to delay the parsing of `A::B::f'.  */
   if (--parser->num_classes_being_defined == 0)
     {
-      tree queue_entry;
       tree fn;
       tree class_type = NULL_TREE;
       tree pushed_scope = NULL_TREE;
+      unsigned ix;
+      cp_default_arg_entry *e;
 
       /* In a first pass, parse default arguments to the functions.
         Then, in a second pass, parse the bodies of the functions.
@@ -15195,20 +16859,17 @@ cp_parser_class_specifier (cp_parser* parser)
            };
 
         */
-      for (TREE_PURPOSE (parser->unparsed_functions_queues)
-            = nreverse (TREE_PURPOSE (parser->unparsed_functions_queues));
-          (queue_entry = TREE_PURPOSE (parser->unparsed_functions_queues));
-          TREE_PURPOSE (parser->unparsed_functions_queues)
-            = TREE_CHAIN (TREE_PURPOSE (parser->unparsed_functions_queues)))
+      FOR_EACH_VEC_ELT (cp_default_arg_entry, unparsed_funs_with_default_args,
+                       ix, e)
        {
-         fn = TREE_VALUE (queue_entry);
+         fn = e->decl;
          /* If there are default arguments that have not yet been processed,
             take care of them now.  */
-         if (class_type != TREE_PURPOSE (queue_entry))
+         if (class_type != e->class_type)
            {
              if (pushed_scope)
                pop_scope (pushed_scope);
-             class_type = TREE_PURPOSE (queue_entry);
+             class_type = e->class_type;
              pushed_scope = push_scope (class_type);
            }
          /* Make sure that any template parameters are in scope.  */
@@ -15220,18 +16881,11 @@ cp_parser_class_specifier (cp_parser* parser)
        }
       if (pushed_scope)
        pop_scope (pushed_scope);
+      VEC_truncate (cp_default_arg_entry, unparsed_funs_with_default_args, 0);
       /* Now parse the body of the functions.  */
-      for (TREE_VALUE (parser->unparsed_functions_queues)
-            = nreverse (TREE_VALUE (parser->unparsed_functions_queues));
-          (queue_entry = TREE_VALUE (parser->unparsed_functions_queues));
-          TREE_VALUE (parser->unparsed_functions_queues)
-            = TREE_CHAIN (TREE_VALUE (parser->unparsed_functions_queues)))
-       {
-         /* Figure out which function we need to process.  */
-         fn = TREE_VALUE (queue_entry);
-         /* Parse the function.  */
-         cp_parser_late_parsing_for_member (parser, fn);
-       }
+      FOR_EACH_VEC_ELT (tree, unparsed_funs_with_definitions, ix, fn)
+       cp_parser_late_parsing_for_member (parser, fn);
+      VEC_truncate (tree, unparsed_funs_with_definitions, 0);
     }
 
   /* Put back any saved access checks.  */
@@ -15653,6 +17307,9 @@ cp_parser_class_head (cp_parser* parser,
       end_specialization ();
       --parser->num_template_parameter_lists;
     }
+
+  if (type)
+    DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
   *attributes_p = attributes;
   return type;
 }
@@ -15674,7 +17331,7 @@ cp_parser_class_key (cp_parser* parser)
   enum tag_types tag_type;
 
   /* Look for the class-key.  */
-  token = cp_parser_require (parser, CPP_KEYWORD, "class-key");
+  token = cp_parser_require (parser, CPP_KEYWORD, RT_CLASS_KEY);
   if (!token)
     return none_type;
 
@@ -15719,7 +17376,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
          /* Remember which access-specifier is active.  */
          current_access_specifier = token->u.value;
          /* Look for the `:'.  */
-         cp_parser_require (parser, CPP_COLON, "%<:%>");
+         cp_parser_require (parser, CPP_COLON, RT_COLON);
          break;
 
        default:
@@ -15852,7 +17509,7 @@ cp_parser_member_declaration (cp_parser* parser)
   prefix_attributes = decl_specifiers.attributes;
   decl_specifiers.attributes = NULL_TREE;
   /* Check for an invalid type-name.  */
-  if (!decl_specifiers.type
+  if (!decl_specifiers.any_type_specifiers_p
       && cp_parser_parse_and_diagnose_invalid_type_name (parser))
     return;
   /* If there is no declarator, then the decl-specifier-seq should
@@ -16150,7 +17807,7 @@ cp_parser_member_declaration (cp_parser* parser)
        }
     }
 
-  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 }
 
 /* Parse a pure-specifier.
@@ -16167,7 +17824,7 @@ cp_parser_pure_specifier (cp_parser* parser)
   cp_token *token;
 
   /* Look for the `=' token.  */
-  if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
+  if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
     return error_mark_node;
   /* Look for the `0' token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -16182,7 +17839,7 @@ cp_parser_pure_specifier (cp_parser* parser)
   if (token->keyword == RID_DEFAULT
       || token->keyword == RID_DELETE)
     {
-      maybe_warn_cpp0x ("defaulted and deleted functions");
+      maybe_warn_cpp0x (CPP0X_DEFAULTED_DELETED);
       return token->u.value;
     }
 
@@ -16214,7 +17871,7 @@ static tree
 cp_parser_constant_initializer (cp_parser* parser)
 {
   /* Look for the `=' token.  */
-  if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
+  if (!cp_parser_require (parser, CPP_EQ, RT_EQ))
     return error_mark_node;
 
   /* It is invalid to write:
@@ -16231,7 +17888,7 @@ cp_parser_constant_initializer (cp_parser* parser)
       /* Skip the initializer.  */
       cp_parser_skip_to_closing_brace (parser);
       /* Look for the trailing `}'.  */
-      cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+      cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
 
       return error_mark_node;
     }
@@ -16265,7 +17922,7 @@ cp_parser_base_clause (cp_parser* parser)
   tree bases = NULL_TREE;
 
   /* Look for the `:' that begins the list.  */
-  cp_parser_require (parser, CPP_COLON, "%<:%>");
+  cp_parser_require (parser, CPP_COLON, RT_COLON);
 
   /* Scan the base-specifier-list.  */
   while (true)
@@ -16463,30 +18120,65 @@ cp_parser_exception_specification_opt (cp_parser* parser)
 {
   cp_token *token;
   tree type_id_list;
+  const char *saved_message;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
+
+  /* Is it a noexcept-specification?  */
+  if (cp_parser_is_keyword (token, RID_NOEXCEPT))
+    {
+      tree expr;
+      cp_lexer_consume_token (parser->lexer);
+
+      if (cp_lexer_peek_token (parser->lexer)->type == CPP_OPEN_PAREN)
+       {
+         cp_lexer_consume_token (parser->lexer);
+
+         /* Types may not be defined in an exception-specification.  */
+         saved_message = parser->type_definition_forbidden_message;
+         parser->type_definition_forbidden_message
+           = G_("types may not be defined in an exception-specification");
+
+         expr = cp_parser_constant_expression (parser, false, NULL);
+
+         /* Restore the saved message.  */
+         parser->type_definition_forbidden_message = saved_message;
+
+         cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+       }
+      else
+       expr = boolean_true_node;
+
+      return build_noexcept_spec (expr, tf_warning_or_error);
+    }
+
   /* If it's not `throw', then there's no exception-specification.  */
   if (!cp_parser_is_keyword (token, RID_THROW))
     return NULL_TREE;
 
+#if 0
+  /* 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.");
+#endif
+
   /* Consume the `throw'.  */
   cp_lexer_consume_token (parser->lexer);
 
   /* Look for the `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
   /* If it's not a `)', then there is a type-id-list.  */
   if (token->type != CPP_CLOSE_PAREN)
     {
-      const char *saved_message;
-
       /* Types may not be defined in an exception-specification.  */
       saved_message = parser->type_definition_forbidden_message;
       parser->type_definition_forbidden_message
-       = "types may not be defined in an exception-specification";
+       = G_("types may not be defined in an exception-specification");
       /* Parse the type-id-list.  */
       type_id_list = cp_parser_type_id_list (parser);
       /* Restore the saved message.  */
@@ -16496,7 +18188,7 @@ cp_parser_exception_specification_opt (cp_parser* parser)
     type_id_list = empty_except_spec;
 
   /* Look for the `)'.  */
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
   return type_id_list;
 }
@@ -16555,7 +18247,7 @@ cp_parser_try_block (cp_parser* parser)
 {
   tree try_block;
 
-  cp_parser_require_keyword (parser, RID_TRY, "%<try%>");
+  cp_parser_require_keyword (parser, RID_TRY, RT_TRY);
   try_block = begin_try_block ();
   cp_parser_compound_statement (parser, NULL, true);
   finish_try_block (try_block);
@@ -16578,7 +18270,7 @@ cp_parser_function_try_block (cp_parser* parser)
   bool ctor_initializer_p;
 
   /* Look for the `try' keyword.  */
-  if (!cp_parser_require_keyword (parser, RID_TRY, "%<try%>"))
+  if (!cp_parser_require_keyword (parser, RID_TRY, RT_TRY))
     return false;
   /* Let the rest of the front end know where we are.  */
   try_block = begin_function_try_block (&compound_stmt);
@@ -16628,12 +18320,12 @@ cp_parser_handler (cp_parser* parser)
   tree handler;
   tree declaration;
 
-  cp_parser_require_keyword (parser, RID_CATCH, "%<catch%>");
+  cp_parser_require_keyword (parser, RID_CATCH, RT_CATCH);
   handler = begin_handler ();
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
   declaration = cp_parser_exception_declaration (parser);
   finish_handler_parms (declaration, handler);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
   cp_parser_compound_statement (parser, NULL, false);
   finish_handler (handler);
 }
@@ -16667,10 +18359,11 @@ cp_parser_exception_declaration (cp_parser* parser)
   /* Types may not be defined in exception-declarations.  */
   saved_message = parser->type_definition_forbidden_message;
   parser->type_definition_forbidden_message
-    = "types may not be defined in exception-declarations";
+    = G_("types may not be defined in exception-declarations");
 
   /* Parse the type-specifier-seq.  */
-  cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+  cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+                               /*is_trailing_return=*/false,
                                &type_specifiers);
   /* If it's a `)', then there is no declarator.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
@@ -16703,7 +18396,7 @@ cp_parser_throw_expression (cp_parser* parser)
   tree expression;
   cp_token* token;
 
-  cp_parser_require_keyword (parser, RID_THROW, "%<throw%>");
+  cp_parser_require_keyword (parser, RID_THROW, RT_THROW);
   token = cp_lexer_peek_token (parser->lexer);
   /* Figure out whether or not there is an assignment-expression
      following the "throw" keyword.  */
@@ -16748,13 +18441,13 @@ cp_parser_asm_specification_opt (cp_parser* parser)
   /* Consume the `asm' token.  */
   cp_lexer_consume_token (parser->lexer);
   /* Look for the `('.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
   /* Look for the string-literal.  */
   asm_specification = cp_parser_string_literal (parser, false, false);
 
   /* Look for the `)'.  */
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
   return asm_specification;
 }
@@ -16798,7 +18491,7 @@ cp_parser_asm_operand_list (cp_parser* parser)
            name = build_string (IDENTIFIER_LENGTH (name),
                                 IDENTIFIER_POINTER (name));
          /* Look for the closing `]'.  */
-         cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+         cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
        }
       else
        name = NULL_TREE;
@@ -16806,11 +18499,11 @@ cp_parser_asm_operand_list (cp_parser* parser)
       string_literal = cp_parser_string_literal (parser, false, false);
 
       /* Look for the `('.  */
-      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+      cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
       /* Parse the expression.  */
       expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
       /* Look for the `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
       if (name == error_mark_node 
          || string_literal == error_mark_node 
@@ -16865,6 +18558,49 @@ cp_parser_asm_clobber_list (cp_parser* parser)
   return clobbers;
 }
 
+/* Parse an asm-label-list.
+
+   asm-label-list:
+     identifier
+     asm-label-list , identifier
+
+   Returns a TREE_LIST, indicating the labels in the order that they
+   appeared.  The TREE_VALUE of each node is a label.  */
+
+static tree
+cp_parser_asm_label_list (cp_parser* parser)
+{
+  tree labels = NULL_TREE;
+
+  while (true)
+    {
+      tree identifier, label, name;
+
+      /* Look for the identifier.  */
+      identifier = cp_parser_identifier (parser);
+      if (!error_operand_p (identifier))
+        {
+         label = lookup_label (identifier);
+         if (TREE_CODE (label) == LABEL_DECL)
+           {
+             TREE_USED (label) = 1;
+             check_goto (label);
+             name = build_string (IDENTIFIER_LENGTH (identifier),
+                                  IDENTIFIER_POINTER (identifier));
+             labels = tree_cons (name, label, labels);
+           }
+       }
+      /* If the next token is not a `,', then the list is
+        complete.  */
+      if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+       break;
+      /* Consume the `,' token.  */
+      cp_lexer_consume_token (parser->lexer);
+    }
+
+  return nreverse (labels);
+}
+
 /* Parse an (optional) series of attributes.
 
    attributes:
@@ -16894,8 +18630,8 @@ cp_parser_attributes_opt (cp_parser* parser)
       /* Consume the `__attribute__' keyword.  */
       cp_lexer_consume_token (parser->lexer);
       /* Look for the two `(' tokens.  */
-      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
-      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+      cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
+      cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
 
       /* Peek at the next token.  */
       token = cp_lexer_peek_token (parser->lexer);
@@ -16908,8 +18644,8 @@ cp_parser_attributes_opt (cp_parser* parser)
        attribute_list = NULL;
 
       /* Look for the two `)' tokens.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
       /* Add these new attributes to the list.  */
       attributes = chainon (attributes, attribute_list);
@@ -16975,8 +18711,10 @@ cp_parser_attribute_list (cp_parser* parser)
          if (token->type == CPP_OPEN_PAREN)
            {
              VEC(tree,gc) *vec;
+             int attr_flag = (attribute_takes_identifier_p (identifier)
+                              ? id_attr : normal_attr);
              vec = cp_parser_parenthesized_expression_list
-                   (parser, true, /*cast_p=*/false,
+                   (parser, attr_flag, /*cast_p=*/false,
                     /*allow_expansion_p=*/false,
                     /*non_constant_p=*/NULL);
              if (vec == NULL)
@@ -17052,7 +18790,7 @@ static void
 cp_parser_label_declaration (cp_parser* parser)
 {
   /* Look for the `__label__' keyword.  */
-  cp_parser_require_keyword (parser, RID_LABEL, "%<__label__%>");
+  cp_parser_require_keyword (parser, RID_LABEL, RT_LABEL);
 
   while (true)
     {
@@ -17069,11 +18807,11 @@ cp_parser_label_declaration (cp_parser* parser)
       if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
        break;
       /* Look for the `,' separating the label declarations.  */
-      cp_parser_require (parser, CPP_COMMA, "%<,%>");
+      cp_parser_require (parser, CPP_COMMA, RT_COMMA);
     }
 
   /* Look for the final `;'.  */
-  cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+  cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 }
 
 /* Support Functions */
@@ -17212,6 +18950,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
             lookup_member, we must enter the scope here.  */
          if (dependent_p)
            pushed_scope = push_scope (parser->scope);
+
          /* If the PARSER->SCOPE is a template specialization, it
             may be instantiated during name lookup.  In that case,
             errors may be issued.  Even if we rollback the current
@@ -17220,6 +18959,27 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
                                        tag_type != none_type,
                                        /*complain=*/true);
 
+         /* 3.4.3.1: In a lookup in which the constructor is an acceptable
+            lookup result and the nested-name-specifier nominates a class C:
+              * if the name specified after the nested-name-specifier, when
+              looked up in C, is the injected-class-name of C (Clause 9), or
+              * if the name specified after the nested-name-specifier is the
+              same as the identifier or the simple-template-id's template-
+              name in the last component of the nested-name-specifier,
+            the name is instead considered to name the constructor of
+            class C. [ Note: for example, the constructor is not an
+            acceptable lookup result in an elaborated-type-specifier so
+            the constructor would not be used in place of the
+            injected-class-name. --end note ] Such a constructor name
+            shall be used only in the declarator-id of a declaration that
+            names a constructor or in a using-declaration.  */
+         if (tag_type == none_type
+             && DECL_SELF_REFERENCE_P (decl)
+             && same_type_p (DECL_CONTEXT (decl), parser->scope))
+           decl = lookup_qualified_name (parser->scope, ctor_identifier,
+                                         tag_type != none_type,
+                                         /*complain=*/true);
+
          /* If we have a single function from a using decl, pull it out.  */
          if (TREE_CODE (decl) == OVERLOAD
              && !really_overloaded_fn (decl))
@@ -17296,6 +19056,10 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
   if (!decl || decl == error_mark_node)
     return error_mark_node;
 
+  /* Pull out the template from an injected-class-name (or multiple).  */
+  if (is_template)
+    decl = maybe_get_template_decl_from_type_decl (decl);
+
   /* If it's a TREE_LIST, the result of the lookup was ambiguous.  */
   if (TREE_CODE (decl) == TREE_LIST)
     {
@@ -17411,10 +19175,8 @@ cp_parser_check_declarator_template_parameters (cp_parser* parser,
       if (declarator->u.id.qualifying_scope)
        {
          tree scope;
-         tree member;
 
          scope = declarator->u.id.qualifying_scope;
-         member = declarator->u.id.unqualified_name;
 
          while (scope && CLASS_TYPE_P (scope))
            {
@@ -17493,11 +19255,15 @@ cp_parser_check_template_parameters (cp_parser* parser,
        template <class T> void S<T>::R<T>::f ();  */
   if (parser->num_template_parameter_lists < num_templates)
     {
-      if (declarator)
+      if (declarator && !current_function_decl)
        error_at (location, "specializing member %<%T::%E%> "
                  "requires %<template<>%> syntax", 
                  declarator->u.id.qualifying_scope,
                  declarator->u.id.unqualified_name);
+      else if (declarator)
+       error_at (location, "invalid declaration of %<%T::%E%>",
+                 declarator->u.id.qualifying_scope,
+                 declarator->u.id.unqualified_name);
       else 
        error_at (location, "too few template-parameter-lists");
       return false;
@@ -17555,8 +19321,7 @@ static bool
 cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
 {
   bool constructor_p;
-  tree type_decl = NULL_TREE;
-  bool nested_name_p;
+  tree nested_name_specifier;
   cp_token *next_token;
 
   /* The common case is that this is not a constructor declarator, so
@@ -17582,34 +19347,48 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
   cp_parser_global_scope_opt (parser,
                              /*current_scope_valid_p=*/false);
   /* Look for the nested-name-specifier.  */
-  nested_name_p
+  nested_name_specifier
     = (cp_parser_nested_name_specifier_opt (parser,
                                            /*typename_keyword_p=*/false,
                                            /*check_dependency_p=*/false,
                                            /*type_p=*/false,
-                                           /*is_declaration=*/false)
-       != NULL_TREE);
+                                           /*is_declaration=*/false));
   /* Outside of a class-specifier, there must be a
      nested-name-specifier.  */
-  if (!nested_name_p &&
+  if (!nested_name_specifier &&
       (!at_class_scope_p () || !TYPE_BEING_DEFINED (current_class_type)
        || friend_p))
     constructor_p = false;
+  else if (nested_name_specifier == error_mark_node)
+    constructor_p = false;
+
+  /* If we have a class scope, this is easy; DR 147 says that S::S always
+     names the constructor, and no other qualified name could.  */
+  if (constructor_p && nested_name_specifier
+      && TYPE_P (nested_name_specifier))
+    {
+      tree id = cp_parser_unqualified_id (parser,
+                                         /*template_keyword_p=*/false,
+                                         /*check_dependency_p=*/false,
+                                         /*declarator_p=*/true,
+                                         /*optional_p=*/false);
+      if (is_overloaded_fn (id))
+       id = DECL_NAME (get_first_fn (id));
+      if (!constructor_name_p (id, nested_name_specifier))
+       constructor_p = false;
+    }
   /* If we still think that this might be a constructor-declarator,
      look for a class-name.  */
-  if (constructor_p)
+  else if (constructor_p)
     {
       /* If we have:
 
-          template <typename T> struct S { S(); };
-          template <typename T> S<T>::S ();
-
-        we must recognize that the nested `S' names a class.
-        Similarly, for:
+          template <typename T> struct S {
+            S();
+          };
 
-          template <typename T> S<T>::S<T> ();
-
-        we must recognize that the nested `S' names a template.  */
+        we must recognize that the nested `S' names a class.  */
+      tree type_decl;
       type_decl = cp_parser_class_name (parser,
                                        /*typename_keyword_p=*/false,
                                        /*template_keyword_p=*/false,
@@ -17619,22 +19398,23 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
                                        /*is_declaration=*/false);
       /* If there was no class-name, then this is not a constructor.  */
       constructor_p = !cp_parser_error_occurred (parser);
-    }
 
-  /* If we're still considering a constructor, we have to see a `(',
-     to begin the parameter-declaration-clause, followed by either a
-     `)', an `...', or a decl-specifier.  We need to check for a
-     type-specifier to avoid being fooled into thinking that:
+      /* If we're still considering a constructor, we have to see a `(',
+        to begin the parameter-declaration-clause, followed by either a
+        `)', an `...', or a decl-specifier.  We need to check for a
+        type-specifier to avoid being fooled into thinking that:
 
-       S::S (f) (int);
+          S (f) (int);
 
-     is a constructor.  (It is actually a function named `f' that
-     takes one parameter (of type `int') and returns a value of type
-     `S::S'.  */
-  if (constructor_p
-      && cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
-    {
-      if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+        is a constructor.  (It is actually a function named `f' that
+        takes one parameter (of type `int') and returns a value of type
+        `S'.  */
+      if (constructor_p
+         && !cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
+       constructor_p = false;
+
+      if (constructor_p
+         && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
          /* A parameter declaration begins with a decl-specifier,
             which is either the "attribute" keyword, a storage class
@@ -17689,8 +19469,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
          constructor_p = !cp_parser_error_occurred (parser);
        }
     }
-  else
-    constructor_p = false;
+
   /* We did not really want to consume any tokens.  */
   cp_parser_abort_tentative_parse (parser);
 
@@ -17751,7 +19530,7 @@ cp_parser_function_definition_from_specifiers_and_declarator
 
 /* Parse the part of a function-definition that follows the
    declarator.  INLINE_P is TRUE iff this function is an inline
-   function defined with a class-specifier.
+   function defined within a class-specifier.
 
    Returns the function defined.  */
 
@@ -17803,6 +19582,9 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
   saved_num_template_parameter_lists
     = parser->num_template_parameter_lists;
   parser->num_template_parameter_lists = 0;
+
+  start_lambda_scope (current_function_decl);
+
   /* If the next token is `try', then we are looking at a
      function-try-block.  */
   if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY))
@@ -17813,6 +19595,8 @@ cp_parser_function_definition_after_declarator (cp_parser* parser,
     ctor_initializer_p
       = cp_parser_ctor_initializer_opt_and_function_body (parser);
 
+  finish_lambda_scope ();
+
   /* Finish the function.  */
   fn = finish_function ((ctor_initializer_p ? 1 : 0) |
                        (inline_p ? 2 : 0));
@@ -17844,11 +19628,11 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
 
   /* Look for the `template' keyword.  */
   token = cp_lexer_peek_token (parser->lexer);
-  if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
+  if (!cp_parser_require_keyword (parser, RID_TEMPLATE, RT_TEMPLATE))
     return;
 
   /* And the `<'.  */
-  if (!cp_parser_require (parser, CPP_LESS, "%<<%>"))
+  if (!cp_parser_require (parser, CPP_LESS, RT_LESS))
     return;
   if (at_class_scope_p () && current_function_decl)
     {
@@ -17954,9 +19738,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
   if (member_p && decl
       && (TREE_CODE (decl) == FUNCTION_DECL
          || DECL_FUNCTION_TEMPLATE_P (decl)))
-    TREE_VALUE (parser->unparsed_functions_queues)
-      = tree_cons (NULL_TREE, decl,
-                  TREE_VALUE (parser->unparsed_functions_queues));
+    VEC_safe_push (tree, gc, unparsed_funs_with_definitions, decl);
 }
 
 /* Perform the deferred access checks from a template-parameter-list.
@@ -18051,6 +19833,11 @@ cp_parser_single_declaration (cp_parser* parser,
          cp_parser_perform_template_parameter_access_checks (checks);
        }
     }
+
+  /* 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 it's not a template class, try for a template function.  If
      the next token is a `;', then this declaration does not declare
      anything.  But, if there were errors in the decl-specifiers, then
@@ -18092,7 +19879,7 @@ 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, "%<;%>")))
+         || !cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON)))
     cp_parser_skip_to_end_of_block_or_statement (parser);
 
   return decl;
@@ -18120,7 +19907,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
-      maybe_warn_cpp0x ("extended initializer lists");
+      maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
       expression_list = cp_parser_braced_list (parser, &nonconst_p);
       CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
       if (TREE_CODE (type) == TYPE_DECL)
@@ -18129,7 +19916,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
     }
 
 
-  vec = cp_parser_parenthesized_expression_list (parser, false,
+  vec = cp_parser_parenthesized_expression_list (parser, non_attr,
                                                 /*cast_p=*/true,
                                                 /*allow_expansion_p=*/true,
                                                 /*non_constant_p=*/NULL);
@@ -18149,8 +19936,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
     type = TREE_TYPE (type);
   if (cast != error_mark_node
       && !cast_valid_in_integral_constant_expression_p (type)
-      && (cp_parser_non_integral_constant_expression
-         (parser, "a call to a constructor")))
+      && cp_parser_non_integral_constant_expression (parser,
+                                                    NIC_CONSTRUCTOR))
     return error_mark_node;
   return cast;
 }
@@ -18171,8 +19958,8 @@ cp_parser_save_member_function_body (cp_parser* parser,
   cp_token *last;
   tree fn;
 
-  /* Create the function-declaration.  */
-  fn = start_method (decl_specifiers, declarator, attributes);
+  /* Create the FUNCTION_DECL.  */
+  fn = grokmethod (decl_specifiers, declarator, attributes);
   /* If something went badly wrong, bail out now.  */
   if (fn == error_mark_node)
     {
@@ -18220,13 +20007,8 @@ cp_parser_save_member_function_body (cp_parser* parser,
      friend templates are handled correctly.  */
   DECL_INITIALIZED_IN_CLASS_P (fn) = 1;
 
-  /* We're done with the inline definition.  */
-  finish_method (fn);
-
   /* Add FN to the queue of functions to be parsed later.  */
-  TREE_VALUE (parser->unparsed_functions_queues)
-    = tree_cons (NULL_TREE, fn,
-                TREE_VALUE (parser->unparsed_functions_queues));
+  VEC_safe_push (tree, gc, unparsed_funs_with_definitions, fn);
 
   return fn;
 }
@@ -18357,8 +20139,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
      classes.  We want to handle them right away, but we don't want
      them getting mixed up with functions that are currently in the
      queue.  */
-  parser->unparsed_functions_queues
-    = tree_cons (NULL_TREE, NULL_TREE, parser->unparsed_functions_queues);
+  push_unparsed_function_queues (parser);
 
   /* Make sure that any template parameters are in scope.  */
   maybe_begin_member_template_processing (member_function);
@@ -18410,8 +20191,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
   maybe_end_member_template_processing ();
 
   /* Restore the queue.  */
-  parser->unparsed_functions_queues
-    = TREE_CHAIN (parser->unparsed_functions_queues);
+  pop_unparsed_function_queues (parser);
 }
 
 /* If DECL contains any default args, remember it on the unparsed
@@ -18427,9 +20207,11 @@ cp_parser_save_default_args (cp_parser* parser, tree decl)
        probe = TREE_CHAIN (probe))
     if (TREE_PURPOSE (probe))
       {
-       TREE_PURPOSE (parser->unparsed_functions_queues)
-         = tree_cons (current_class_type, decl,
-                      TREE_PURPOSE (parser->unparsed_functions_queues));
+       cp_default_arg_entry *entry
+         = VEC_safe_push (cp_default_arg_entry, gc,
+                          unparsed_funs_with_default_args, NULL);
+       entry->class_type = current_class_type;
+       entry->decl = decl;
        break;
       }
 }
@@ -18443,23 +20225,24 @@ static void
 cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
 {
   bool saved_local_variables_forbidden_p;
-  tree parm;
+  tree parm, parmdecl;
 
   /* While we're parsing the default args, we might (due to the
      statement expression extension) encounter more classes.  We want
      to handle them right away, but we don't want them getting mixed
      up with default args that are currently in the queue.  */
-  parser->unparsed_functions_queues
-    = tree_cons (NULL_TREE, NULL_TREE, parser->unparsed_functions_queues);
+  push_unparsed_function_queues (parser);
 
   /* Local variable names (and the `this' keyword) may not appear
      in a default argument.  */
   saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
   parser->local_variables_forbidden_p = true;
 
-  for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
-       parm;
-       parm = TREE_CHAIN (parm))
+  for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn)),
+        parmdecl = DECL_ARGUMENTS (fn);
+       parm && parm != void_list_node;
+       parm = TREE_CHAIN (parm),
+        parmdecl = DECL_CHAIN (parmdecl))
     {
       cp_token_cache *tokens;
       tree default_arg = TREE_PURPOSE (parm);
@@ -18481,6 +20264,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       tokens = DEFARG_TOKENS (default_arg);
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
+      start_lambda_scope (parmdecl);
+
       /* Parse the assignment-expression.  */
       parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
       if (parsed_arg == error_mark_node)
@@ -18499,6 +20284,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
           VEC_iterate (tree, insts, ix, copy); ix++)
        TREE_PURPOSE (copy) = parsed_arg;
 
+      finish_lambda_scope ();
+
       /* If the token stream has not been completely used up, then
         there was extra junk after the end of the default
         argument.  */
@@ -18516,8 +20303,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
   parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
 
   /* Restore the queue.  */
-  parser->unparsed_functions_queues
-    = TREE_CHAIN (parser->unparsed_functions_queues);
+  pop_unparsed_function_queues (parser);
 }
 
 /* Parse the operand of `sizeof' (or a similar operator).  Returns
@@ -18586,7 +20372,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
       type = cp_parser_type_id (parser);
       parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
       /* Now, look for the trailing `)'.  */
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
       /* If all went well, then we're done.  */
       if (cp_parser_parse_definitely (parser))
        {
@@ -18759,6 +20545,171 @@ cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers)
   return decl_specifiers->specs[(int) ds_friend] != 0;
 }
 
+/* Issue an error message indicating that TOKEN_DESC was expected.
+   If KEYWORD is true, it indicated this function is called by
+   cp_parser_require_keword and the required token can only be
+   a indicated keyword. */
+
+static void
+cp_parser_required_error (cp_parser *parser,
+                         required_token token_desc,
+                         bool keyword)
+{
+  switch (token_desc)
+    {
+      case RT_NEW:
+       cp_parser_error (parser, "expected %<new%>");
+       return;
+      case RT_DELETE:
+       cp_parser_error (parser, "expected %<delete%>");
+       return;
+      case RT_RETURN:
+       cp_parser_error (parser, "expected %<return%>");
+       return;
+      case RT_WHILE:
+       cp_parser_error (parser, "expected %<while%>");
+       return;
+      case RT_EXTERN:
+       cp_parser_error (parser, "expected %<extern%>");
+       return;
+      case RT_STATIC_ASSERT:
+       cp_parser_error (parser, "expected %<static_assert%>");
+       return;
+      case RT_DECLTYPE:
+       cp_parser_error (parser, "expected %<decltype%>");
+       return;
+      case RT_OPERATOR:
+       cp_parser_error (parser, "expected %<operator%>");
+       return;
+      case RT_CLASS:
+       cp_parser_error (parser, "expected %<class%>");
+       return;
+      case RT_TEMPLATE:
+       cp_parser_error (parser, "expected %<template%>");
+       return;
+      case RT_NAMESPACE:
+       cp_parser_error (parser, "expected %<namespace%>");
+       return;
+      case RT_USING:
+       cp_parser_error (parser, "expected %<using%>");
+       return;
+      case RT_ASM:
+       cp_parser_error (parser, "expected %<asm%>");
+       return;
+      case RT_TRY:
+       cp_parser_error (parser, "expected %<try%>");
+       return;
+      case RT_CATCH:
+       cp_parser_error (parser, "expected %<catch%>");
+       return;
+      case RT_THROW:
+       cp_parser_error (parser, "expected %<throw%>");
+       return;
+      case RT_LABEL:
+       cp_parser_error (parser, "expected %<__label__%>");
+       return;
+      case RT_AT_TRY:
+       cp_parser_error (parser, "expected %<@try%>");
+       return;
+      case RT_AT_SYNCHRONIZED:
+       cp_parser_error (parser, "expected %<@synchronized%>");
+       return;
+      case RT_AT_THROW:
+       cp_parser_error (parser, "expected %<@throw%>");
+       return;
+      default:
+       break;
+    }
+  if (!keyword)
+    {
+      switch (token_desc)
+        {
+         case RT_SEMICOLON:
+           cp_parser_error (parser, "expected %<;%>");
+           return;
+         case RT_OPEN_PAREN:
+           cp_parser_error (parser, "expected %<(%>");
+           return;
+         case RT_CLOSE_BRACE:
+           cp_parser_error (parser, "expected %<}%>");
+           return;
+         case RT_OPEN_BRACE:
+           cp_parser_error (parser, "expected %<{%>");
+           return;
+         case RT_CLOSE_SQUARE:
+           cp_parser_error (parser, "expected %<]%>");
+           return;
+         case RT_OPEN_SQUARE:
+           cp_parser_error (parser, "expected %<[%>");
+           return;
+         case RT_COMMA:
+           cp_parser_error (parser, "expected %<,%>");
+           return;
+         case RT_SCOPE:
+           cp_parser_error (parser, "expected %<::%>");
+           return;
+         case RT_LESS:
+           cp_parser_error (parser, "expected %<<%>");
+           return;
+         case RT_GREATER:
+           cp_parser_error (parser, "expected %<>%>");
+           return;
+         case RT_EQ:
+           cp_parser_error (parser, "expected %<=%>");
+           return;
+         case RT_ELLIPSIS:
+           cp_parser_error (parser, "expected %<...%>");
+           return;
+         case RT_MULT:
+           cp_parser_error (parser, "expected %<*%>");
+           return;
+         case RT_COMPL:
+           cp_parser_error (parser, "expected %<~%>");
+           return;
+         case RT_COLON:
+           cp_parser_error (parser, "expected %<:%>");
+           return;
+         case RT_COLON_SCOPE:
+           cp_parser_error (parser, "expected %<:%> or %<::%>");
+           return;
+         case RT_CLOSE_PAREN:
+           cp_parser_error (parser, "expected %<)%>");
+           return;
+         case RT_COMMA_CLOSE_PAREN:
+           cp_parser_error (parser, "expected %<,%> or %<)%>");
+           return;
+         case RT_PRAGMA_EOL:
+           cp_parser_error (parser, "expected end of line");
+           return;
+         case RT_NAME:
+           cp_parser_error (parser, "expected identifier");
+           return;
+         case RT_SELECT:
+           cp_parser_error (parser, "expected selection-statement");
+           return;
+         case RT_INTERATION:
+           cp_parser_error (parser, "expected iteration-statement");
+           return;
+         case RT_JUMP:
+           cp_parser_error (parser, "expected jump-statement");
+           return;
+         case RT_CLASS_KEY:
+           cp_parser_error (parser, "expected class-key");
+           return;
+         case RT_CLASS_TYPENAME_TEMPLATE:
+           cp_parser_error (parser,
+                "expected %<class%>, %<typename%>, or %<template%>");
+           return;
+         default:
+           gcc_unreachable ();
+       }
+    }
+  else
+    gcc_unreachable ();
+}
+
+
+
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
    issue an error message indicating that TOKEN_DESC was expected.
 
@@ -18768,7 +20719,7 @@ cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers)
 static cp_token *
 cp_parser_require (cp_parser* parser,
                   enum cpp_ttype type,
-                  const char* token_desc)
+                  required_token token_desc)
 {
   if (cp_lexer_next_token_is (parser->lexer, type))
     return cp_lexer_consume_token (parser->lexer);
@@ -18776,11 +20727,7 @@ cp_parser_require (cp_parser* parser,
     {
       /* Output the MESSAGE -- unless we're parsing tentatively.  */
       if (!cp_parser_simulate_error (parser))
-       {
-         char *message = concat ("expected ", token_desc, NULL);
-         cp_parser_error (parser, message);
-         free (message);
-       }
+       cp_parser_required_error (parser, token_desc, /*keyword=*/false);
       return NULL;
     }
 }
@@ -18798,7 +20745,7 @@ cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
   unsigned nesting_depth = 0;
 
   /* Are we ready, yet?  If not, issue error message.  */
-  if (cp_parser_require (parser, CPP_GREATER, "%<>%>"))
+  if (cp_parser_require (parser, CPP_GREATER, RT_GREATER))
     return;
 
   /* Skip tokens until the desired token is found.  */
@@ -18875,20 +20822,13 @@ cp_parser_skip_to_end_of_template_parameter_list (cp_parser* parser)
 static cp_token *
 cp_parser_require_keyword (cp_parser* parser,
                           enum rid keyword,
-                          const char* token_desc)
+                          required_token token_desc)
 {
   cp_token *token = cp_parser_require (parser, CPP_KEYWORD, token_desc);
 
   if (token && token->keyword != keyword)
     {
-      dyn_string_t error_msg;
-
-      /* Format the error message.  */
-      error_msg = dyn_string_new (0);
-      dyn_string_append_cstr (error_msg, "expected ");
-      dyn_string_append_cstr (error_msg, token_desc);
-      cp_parser_error (parser, error_msg->s);
-      dyn_string_delete (error_msg);
+      cp_parser_required_error (parser, token_desc, /*keyword=*/true); 
       return NULL;
     }
 
@@ -19065,14 +21005,10 @@ cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
   checks = check_value->checks;
   if (checks)
     {
-      for (i = 0 ;
-          VEC_iterate (deferred_access_check, checks, i, chk) ;
-          ++i)
-       {
-         perform_or_defer_access_check (chk->binfo,
-                                        chk->decl,
-                                        chk->diag_decl);
-       }
+      FOR_EACH_VEC_ELT (deferred_access_check, checks, i, chk)
+       perform_or_defer_access_check (chk->binfo,
+                                      chk->decl,
+                                      chk->diag_decl);
     }
   /* Set the scope from the stored value.  */
   parser->scope = check_value->value;
@@ -19319,7 +21255,7 @@ cp_parser_objc_message_expression (cp_parser* parser)
   cp_lexer_consume_token (parser->lexer);  /* Eat '['.  */
   receiver = cp_parser_objc_message_receiver (parser);
   messageargs = cp_parser_objc_message_args (parser);
-  cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+  cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
 
   return objc_build_message_expr (build_tree_list (receiver, messageargs));
 }
@@ -19391,7 +21327,7 @@ cp_parser_objc_message_args (cp_parser* parser)
        return build_tree_list (selector, NULL_TREE);
 
       maybe_unary_selector_p = false;
-      cp_parser_require (parser, CPP_COLON, "%<:%>");
+      cp_parser_require (parser, CPP_COLON, RT_COLON);
       arg = cp_parser_assignment_expression (parser, false, NULL);
 
       sel_args
@@ -19416,6 +21352,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);
 }
 
@@ -19433,10 +21375,10 @@ cp_parser_objc_encode_expression (cp_parser* parser)
   cp_token *token;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@encode'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
   token = cp_lexer_peek_token (parser->lexer);
   type = complete_type (cp_parser_type_id (parser));
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
   if (!type)
     {
@@ -19445,6 +21387,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);
 }
 
@@ -19456,9 +21411,9 @@ cp_parser_objc_defs_expression (cp_parser *parser)
   tree name;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@defs'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
   name = cp_parser_identifier (parser);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
   return objc_get_class_ivars (name);
 }
@@ -19476,9 +21431,9 @@ cp_parser_objc_protocol_expression (cp_parser* parser)
   tree proto;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@protocol'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
   proto = cp_parser_identifier (parser);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
   return objc_build_protocol_expr (proto);
 }
@@ -19507,7 +21462,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
   location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@selector'.  */
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
   token = cp_lexer_peek_token (parser->lexer);
 
   while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
@@ -19554,7 +21509,7 @@ cp_parser_objc_selector_expression (cp_parser* parser)
     }
 
  finish_selector:
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
   return objc_build_selector_expr (loc, sel_seq);
 }
@@ -19570,18 +21525,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;
 }
 
@@ -19640,7 +21606,7 @@ cp_parser_objc_protocol_refs_opt (cp_parser* parser)
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '<'.  */
       protorefs = cp_parser_objc_identifier_list (parser);
-      cp_parser_require (parser, CPP_GREATER, "%<>%>");
+      cp_parser_require (parser, CPP_GREATER, RT_GREATER);
     }
 
   return protorefs;
@@ -19656,13 +21622,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;
@@ -19672,15 +21641,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.  */
@@ -19729,7 +21699,7 @@ cp_parser_objc_typename (cp_parser* parser)
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
        cp_type = cp_parser_type_id (parser);
 
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
       type_name = build_tree_list (proto_quals, cp_type);
     }
 
@@ -19782,7 +21752,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;
@@ -19791,6 +21761,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);
@@ -19798,29 +21772,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, "%<:%>");
+      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);
@@ -19838,9 +21848,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,
@@ -19851,6 +21863,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;
 }
 
@@ -19872,6 +21904,26 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
   /* Allow stray semicolons.  */
   else if (token->type == CPP_SEMICOLON)
     cp_lexer_consume_token (parser->lexer);
+  /* 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 `%s' 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);
@@ -19880,34 +21932,79 @@ cp_parser_objc_interstitial_code (cp_parser* parser)
 /* 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 (is_class_method, rettype, kwdparms, optparms, ellipsis);
+}
+
+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;
 
-  return objc_build_method_signature (rettype, kwdparms, optparms, ellipsis);
+  /* Otherwise, the attributes introduce some interstitial code, possibly so
+     rewind to allow that check.  */
+  cp_lexer_rollback_tokens (parser->lexer);
+  return false;  
 }
 
-/* Pars an Objective-C method prototype list.  */
+/* 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);
@@ -19915,7 +22012,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 ();
 }
 
@@ -19926,27 +22027,57 @@ 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);
 
          /* 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);
@@ -19954,7 +22085,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 ();
 }
 
@@ -19971,7 +22106,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;
@@ -19986,6 +22122,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;
 
@@ -20070,7 +22228,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);
@@ -20079,7 +22244,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;
@@ -20108,7 +22273,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);
     }
 }
@@ -20131,28 +22296,37 @@ cp_parser_objc_superclass_or_category (cp_parser *parser, tree *super,
     {
       cp_lexer_consume_token (parser->lexer);  /* Eat '('.  */
       *categ = cp_parser_identifier (parser);
-      cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
     }
 }
 
 /* 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;
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@interface'.  */
   name = cp_parser_identifier (parser);
+  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, &super, &categ);
   protos = cp_parser_objc_protocol_refs_opt (parser);
 
   /* We have either a class or a category on our hands.  */
   if (categ)
-    objc_start_category_interface (name, categ, protos);
+    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 ();
@@ -20170,6 +22344,16 @@ cp_parser_objc_class_implementation (cp_parser* parser)
 
   cp_lexer_consume_token (parser->lexer);  /* Eat '@implementation'.  */
   name = cp_parser_identifier (parser);
+  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, &super, &categ);
 
   /* We have either a class or a category on our hands.  */
@@ -20198,11 +22382,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:
@@ -20212,10 +22416,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);
@@ -20252,7 +22456,7 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
   location_t location;
   tree stmt;
 
-  cp_parser_require_keyword (parser, RID_AT_TRY, "%<@try%>");
+  cp_parser_require_keyword (parser, RID_AT_TRY, RT_AT_TRY);
   location = cp_lexer_peek_token (parser->lexer)->location;
   /* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
      node, lest it get absorbed into the surrounding block.  */
@@ -20266,13 +22470,13 @@ cp_parser_objc_try_catch_finally_statement (cp_parser *parser) {
       tree parm;
 
       cp_lexer_consume_token (parser->lexer);
-      cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+      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, "%<)%>");
+      cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
       objc_begin_catch_clause (parm);
       cp_parser_compound_statement (parser, NULL, false);
       objc_finish_catch_clause ();
@@ -20304,12 +22508,12 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
   location_t location;
   tree lock, stmt;
 
-  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "%<@synchronized%>");
+  cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, RT_AT_SYNCHRONIZED);
 
   location = cp_lexer_peek_token (parser->lexer)->location;
-  cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+  cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
   lock = cp_parser_expression (parser, false, NULL);
-  cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+  cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
   /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
      node, lest it get absorbed into the surrounding block.  */
@@ -20331,7 +22535,7 @@ 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, "%<@throw%>");
+  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);
@@ -20364,6 +22568,404 @@ 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))
+               {
+                 cp_parser_error (parser,
+                                  "getter/setter/ivar attribute must be followed by %<=%>");
+                 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;
+       }
+
+      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.  */
 
@@ -20489,7 +23091,8 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 
       decl = cp_parser_lookup_name_simple (parser, name, token->location);
       if (decl == error_mark_node)
-       cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
+       cp_parser_name_lookup_error (parser, name, decl, NLE_NULL,
+                                    token->location);
       else if (kind != 0)
        {
          tree u = build_omp_clause (token->location, kind);
@@ -20506,7 +23109,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
       cp_lexer_consume_token (parser->lexer);
     }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
     {
       int ending;
 
@@ -20530,7 +23133,7 @@ cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
 static tree
 cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
 {
-  if (cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return cp_parser_omp_var_list_no_open (parser, kind, list);
   return list;
 }
@@ -20546,12 +23149,12 @@ cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location
   HOST_WIDE_INT n;
 
   loc = cp_lexer_peek_token (parser->lexer)->location;
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
   num = cp_parser_constant_expression (parser, false, NULL);
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+  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);
@@ -20585,7 +23188,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
   enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
   tree c;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
     {
@@ -20618,7 +23221,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
       cp_parser_error (parser, "expected %<none%> or %<shared%>");
     }
 
-  if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+  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);
@@ -20642,13 +23245,13 @@ cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
 {
   tree t, c;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
   t = cp_parser_condition (parser);
 
   if (t == error_mark_node
-      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+      || !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);
@@ -20687,13 +23290,13 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
 {
   tree t, c;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
   t = cp_parser_expression (parser, false, NULL);
 
   if (t == error_mark_node
-      || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+      || !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);
@@ -20737,7 +23340,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
   enum tree_code code;
   tree nlist, c;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
   switch (cp_lexer_peek_token (parser->lexer)->type)
@@ -20777,7 +23380,7 @@ cp_parser_omp_clause_reduction (cp_parser *parser, tree list)
     }
   cp_lexer_consume_token (parser->lexer);
 
-  if (!cp_parser_require (parser, CPP_COLON, "%<:%>"))
+  if (!cp_parser_require (parser, CPP_COLON, RT_COLON))
     goto resync_fail;
 
   nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list);
@@ -20799,7 +23402,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location
 {
   tree c, t;
 
-  if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
     return list;
 
   c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE);
@@ -20860,10 +23463,10 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location
       else
        OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
 
-      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
        goto resync_fail;
     }
-  else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<,%> or %<)%>"))
+  else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_COMMA_CLOSE_PAREN))
     goto resync_fail;
 
   check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
@@ -21096,6 +23699,32 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
       rhs = integer_one_node;
       break;
 
+    case COMPOUND_EXPR:
+      if (TREE_CODE (TREE_OPERAND (lhs, 0)) == SAVE_EXPR
+        && TREE_CODE (TREE_OPERAND (lhs, 1)) == COMPOUND_EXPR
+        && TREE_CODE (TREE_OPERAND (TREE_OPERAND (lhs, 1), 0)) == MODIFY_EXPR
+        && TREE_OPERAND (TREE_OPERAND (lhs, 1), 1) == TREE_OPERAND (lhs, 0)
+        && TREE_CODE (TREE_TYPE (TREE_OPERAND (TREE_OPERAND
+                                            (TREE_OPERAND (lhs, 1), 0), 0)))
+           == BOOLEAN_TYPE)
+       /* Undo effects of boolean_increment for post {in,de}crement.  */
+       lhs = TREE_OPERAND (TREE_OPERAND (lhs, 1), 0);
+      /* FALLTHRU */
+    case MODIFY_EXPR:
+      if (TREE_CODE (lhs) == MODIFY_EXPR
+        && TREE_CODE (TREE_TYPE (TREE_OPERAND (lhs, 0))) == BOOLEAN_TYPE)
+       {
+        /* Undo effects of boolean_increment.  */
+        if (integer_onep (TREE_OPERAND (lhs, 1)))
+          {
+            /* This is pre or post increment.  */
+            rhs = TREE_OPERAND (lhs, 1);
+            lhs = TREE_OPERAND (lhs, 0);
+            code = NOP_EXPR;
+            break;
+          }
+       }
+      /* FALLTHRU */
     default:
       switch (cp_lexer_peek_token (parser->lexer)->type)
        {
@@ -21173,7 +23802,7 @@ cp_parser_omp_critical (cp_parser *parser, cp_token *pragma_tok)
       name = cp_parser_identifier (parser);
 
       if (name == error_mark_node
-         || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+         || !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);
@@ -21339,11 +23968,12 @@ static tree
 cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
 {
   tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
-  tree for_block = NULL_TREE, real_decl, initv, condv, incrv, declv;
+  tree real_decl, initv, condv, incrv, declv;
   tree this_pre_body, cl;
   location_t loc_first;
   bool collapse_err = false;
   int i, collapse = 1, nbraces = 0;
+  VEC(tree,gc) *for_block = make_tree_vector ();
 
   for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
     if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
@@ -21371,7 +24001,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
        }
       loc = cp_lexer_consume_token (parser->lexer)->location;
 
-      if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+      if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
        return NULL;
 
       init = decl = real_decl = NULL;
@@ -21392,7 +24022,8 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
             cp_parser_condition, from whence the bulk of this is copied.  */
 
          cp_parser_parse_tentatively (parser);
-         cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+         cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+                                       /*is_trailing_return=*/false,
                                        &type_specifiers);
          if (cp_parser_parse_definitely (parser))
            {
@@ -21430,7 +24061,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                               "OpenMP %<for%> loop");
                      else
                        /* Trigger an error.  */
-                       cp_parser_require (parser, CPP_EQ, "%<=%>");
+                       cp_parser_require (parser, CPP_EQ, RT_EQ);
 
                      init = error_mark_node;
                      cp_parser_skip_to_end_of_statement (parser);
@@ -21461,8 +24092,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                                      LOOKUP_ONLYCONVERTING);
                      if (CLASS_TYPE_P (TREE_TYPE (decl)))
                        {
-                         for_block
-                           = tree_cons (NULL, this_pre_body, for_block);
+                         VEC_safe_push (tree, gc, for_block, this_pre_body);
                          init = NULL_TREE;
                        }
                      else
@@ -21505,7 +24135,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                  tree rhs;
 
                  cp_parser_parse_definitely (parser);
-                 cp_parser_require (parser, CPP_EQ, "%<=%>");
+                 cp_parser_require (parser, CPP_EQ, RT_EQ);
                  rhs = cp_parser_assignment_expression (parser, false, NULL);
                  finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR,
                                                         rhs,
@@ -21526,7 +24156,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                }
            }
        }
-      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+      cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
       if (this_pre_body)
        {
          this_pre_body = pop_stmt_list (this_pre_body);
@@ -21613,7 +24243,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
       cond = NULL;
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
        cond = cp_parser_omp_for_cond (parser, decl);
-      cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+      cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
 
       incr = NULL;
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
@@ -21628,7 +24258,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
            incr = cp_parser_expression (parser, false, NULL);
        }
 
-      if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+      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);
@@ -21711,15 +24341,14 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
            }
          collapse_err = true;
          cp_parser_statement_seq_opt (parser, NULL);
-         cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+         if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+           break;
        }
     }
 
-  while (for_block)
-    {
-      add_stmt (pop_stmt_list (TREE_VALUE (for_block)));
-      for_block = TREE_CHAIN (for_block);
-    }
+  while (!VEC_empty (tree, for_block))
+    add_stmt (pop_stmt_list (VEC_pop (tree, for_block)));
+  release_tree_vector (for_block);
 
   return ret;
 }
@@ -21798,7 +24427,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
   bool error_suppress = false;
   cp_token *tok;
 
-  if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
+  if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
     return NULL_TREE;
 
   stmt = push_stmt_list ();
@@ -21853,7 +24482,7 @@ cp_parser_omp_sections_scope (cp_parser *parser)
       substmt = build1 (OMP_SECTION, void_type_node, substmt);
       add_stmt (substmt);
     }
-  cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+  cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
 
   substmt = pop_stmt_list (stmt);
 
@@ -22281,7 +24910,6 @@ pragma_lex (tree *value)
 void
 c_parse_file (void)
 {
-  bool error_occurred;
   static bool already_called = false;
 
   if (already_called)
@@ -22294,7 +24922,7 @@ c_parse_file (void)
   the_parser = cp_parser_new ();
   push_deferring_access_checks (flag_access_control
                                ? dk_no_deferred : dk_no_check);
-  error_occurred = cp_parser_translation_unit (the_parser);
+  cp_parser_translation_unit (the_parser);
   the_parser = NULL;
 }