OSDN Git Service

2011-06-30 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 9ed3a1f..d79326d 100644 (file)
@@ -1,6 +1,6 @@
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005, 2007, 2008, 2009, 2010  Free Software Foundation, Inc.
+   2005, 2007, 2008, 2009, 2010, 2011  Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -23,6 +23,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "timevar.h"
 #include "cpplib.h"
 #include "tree.h"
 #include "cp-tree.h"
@@ -654,6 +655,7 @@ cp_lexer_next_token_is_decl_specifier_keyword (cp_lexer *lexer)
     case RID_TYPEOF:
       /* C++0x extensions.  */
     case RID_DECLTYPE:
+    case RID_UNDERLYING_TYPE:
       return true;
 
     default:
@@ -936,7 +938,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
    VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
 
 static cp_declarator *make_call_declarator
-  (cp_declarator *, tree, cp_cv_quals, tree, tree);
+  (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, tree, tree);
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
@@ -1101,6 +1103,7 @@ cp_declarator *
 make_call_declarator (cp_declarator *target,
                      tree parms,
                      cp_cv_quals cv_qualifiers,
+                     cp_virt_specifiers virt_specifiers,
                      tree exception_specification,
                      tree late_return_type)
 {
@@ -1110,6 +1113,7 @@ make_call_declarator (cp_declarator *target,
   declarator->declarator = target;
   declarator->u.function.parameters = parms;
   declarator->u.function.qualifiers = cv_qualifiers;
+  declarator->u.function.virt_specifiers = virt_specifiers;
   declarator->u.function.exception_specification = exception_specification;
   declarator->u.function.late_return_type = late_return_type;
   if (target)
@@ -1576,7 +1580,7 @@ static tree cp_parser_lambda_expression
   (cp_parser *);
 static void cp_parser_lambda_introducer
   (cp_parser *, tree);
-static void cp_parser_lambda_declarator_opt
+static bool cp_parser_lambda_declarator_opt
   (cp_parser *, tree);
 static void cp_parser_lambda_body
   (cp_parser *, tree);
@@ -1607,6 +1611,10 @@ static tree cp_parser_c_for
   (cp_parser *, tree, tree);
 static tree cp_parser_range_for
   (cp_parser *, tree, tree, tree);
+static tree cp_parser_perform_range_for_lookup
+  (tree, tree *, tree *);
+static tree cp_parser_range_for_member_function
+  (tree, tree);
 static tree cp_parser_jump_statement
   (cp_parser *);
 static void cp_parser_declaration_statement
@@ -1685,8 +1693,10 @@ static enum tree_code cp_parser_ptr_operator
   (cp_parser *, tree *, cp_cv_quals *);
 static cp_cv_quals cp_parser_cv_qualifier_seq_opt
   (cp_parser *);
-static tree cp_parser_late_return_type_opt
+static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
   (cp_parser *);
+static tree cp_parser_late_return_type_opt
+  (cp_parser *, cp_cv_quals);
 static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
@@ -2435,6 +2445,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
                                      location_t location)
 {
   tree decl, old_scope;
+  cp_parser_commit_to_tentative_parse (parser);
   /* Try to lookup the identifier.  */
   old_scope = parser->scope;
   parser->scope = scope;
@@ -2523,12 +2534,11 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
                  "%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",
+       error_at (location, "%qE in %q#T does not name a type",
                  id, parser->scope);
       else
        gcc_unreachable ();
     }
-  cp_parser_commit_to_tentative_parse (parser);
 }
 
 /* Check for a common situation where a type-name should be present,
@@ -3264,8 +3274,11 @@ cp_parser_translation_unit (cp_parser* parser)
      __is_convertible_to ( type-id , type-id )     
      __is_empty ( type-id )
      __is_enum ( type-id )
+     __is_literal_type ( type-id )
      __is_pod ( type-id )
      __is_polymorphic ( type-id )
+     __is_std_layout ( type-id )
+     __is_trivial ( type-id )
      __is_union ( type-id )
 
    Objective-C++ Extension:
@@ -3432,6 +3445,12 @@ cp_parser_primary_expression (cp_parser *parser,
               `&A::B' might be a pointer-to-member, but `&(A::B)' is
               not.  */
            finish_parenthesized_expr (expr);
+           /* DR 705: Wrapping an unqualified name in parentheses
+              suppresses arg-dependent lookup.  We want to pass back
+              CP_ID_KIND_QUALIFIED for suppressing vtable lookup
+              (c++/37862), but none of the others.  */
+           if (*idk != CP_ID_KIND_QUALIFIED)
+             *idk = CP_ID_KIND_NONE;
          }
        /* The `>' token might be the end of a template-id or
           template-parameter-list now.  */
@@ -3585,12 +3604,12 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_IS_CONVERTIBLE_TO:
        case RID_IS_EMPTY:
        case RID_IS_ENUM:
+       case RID_IS_LITERAL_TYPE:
        case RID_IS_POD:
        case RID_IS_POLYMORPHIC:
        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.  */
@@ -4050,7 +4069,8 @@ cp_parser_unqualified_id (cp_parser* parser,
            && (cp_lexer_peek_nth_token (parser->lexer, 2)->type
                != CPP_LESS)
            && (token->u.value == TYPE_IDENTIFIER (scope)
-               || constructor_name_p (token->u.value, scope)))
+               || (CLASS_TYPE_P (scope)
+                   && constructor_name_p (token->u.value, scope))))
          {
            cp_lexer_consume_token (parser->lexer);
            return build_nt (BIT_NOT_EXPR, scope);
@@ -4897,7 +4917,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                postfix_expression
                  = (finish_compound_literal
                     (type, build_constructor (init_list_type_node,
-                                              initializer_list)));
+                                              initializer_list),
+                     tf_warning_or_error));
                break;
              }
          }
@@ -4999,7 +5020,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                        if (!any_type_dependent_arguments_p (args))
                          postfix_expression
                            = perform_koenig_lookup (postfix_expression, args,
-                                                    /*include_std=*/false);
+                                                    /*include_std=*/false,
+                                                    tf_warning_or_error);
                      }
                    else
                      postfix_expression
@@ -5024,7 +5046,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                        if (!any_type_dependent_arguments_p (args))
                          postfix_expression
                            = perform_koenig_lookup (postfix_expression, args,
-                                                    /*include_std=*/false);
+                                                    /*include_std=*/false,
+                                                    tf_warning_or_error);
                      }
                  }
              }
@@ -5053,7 +5076,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                    = (build_new_method_call
                       (instance, fn, &args, NULL_TREE,
                        (idk == CP_ID_KIND_QUALIFIED
-                        ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
+                        ? LOOKUP_NORMAL|LOOKUP_NONVIRTUAL
+                        : LOOKUP_NORMAL),
                        /*fn_p=*/NULL,
                        tf_warning_or_error));
                  }
@@ -5618,6 +5642,11 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
 
   /* Look for the `~'.  */
   cp_parser_require (parser, CPP_COMPL, RT_COMPL);
+
+  /* Once we see the ~, this has to be a pseudo-destructor.  */
+  if (!processing_template_decl && !cp_parser_error_occurred (parser))
+    cp_parser_commit_to_tentative_parse (parser);
+
   /* 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);
@@ -6288,7 +6317,8 @@ cp_parser_delete_expression (cp_parser* parser)
   if (cp_parser_non_integral_constant_expression (parser, NIC_DEL))
     return error_mark_node;
 
-  return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
+  return delete_sanity (expression, NULL_TREE, array_p, global_scope_p,
+                       tf_warning_or_error);
 }
 
 /* Returns true if TOKEN may start a cast-expression and false
@@ -6555,7 +6585,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
   cp_token *token;
   enum tree_code tree_type, lhs_type, rhs_type;
   enum cp_parser_prec new_prec, lookahead_prec;
-  bool overloaded_p;
+  tree overload;
 
   /* Parse the first expression.  */
   lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p, pidk);
@@ -6658,7 +6688,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
       else if (tree_type == TRUTH_ORIF_EXPR)
        c_inhibit_evaluation_warnings -= lhs == truthvalue_true_node;
 
-      overloaded_p = false;
+      overload = NULL;
       /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
         ERROR_MARK for everything that is not a binary expression.
         This makes warn_about_parentheses miss some warnings that
@@ -6673,7 +6703,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
        lhs = build2 (tree_type, boolean_type_node, lhs, rhs);
       else
        lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
-                                &overloaded_p, tf_warning_or_error);
+                                &overload, tf_warning_or_error);
       lhs_type = tree_type;
 
       /* If the binary operator required the use of an overloaded operator,
@@ -6682,7 +6712,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
         otherwise permissible in an integral constant-expression if at
         least one of the operands is of enumeration type.  */
 
-      if (overloaded_p
+      if (overload
          && cp_parser_non_integral_constant_expression (parser,
                                                         NIC_OVERLOADED))
        return error_mark_node;
@@ -7020,8 +7050,6 @@ cp_parser_constant_expression (cp_parser* parser,
     }
   if (allow_non_constant_p)
     *non_constant_p = parser->non_integral_constant_expression_p;
-  else if (parser->non_integral_constant_expression_p)
-    expression = error_mark_node;
   parser->non_integral_constant_expression_p
     = saved_non_integral_constant_expression_p;
 
@@ -7123,7 +7151,10 @@ cp_parser_builtin_offsetof (cp_parser *parser)
   return expr;
 }
 
-/* Parse a trait expression.  */
+/* Parse a trait expression.
+
+   Returns a representation of the expression, the underlying type
+   of the type at issue when KEYWORD is RID_UNDERLYING_TYPE.  */
 
 static tree
 cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
@@ -7179,6 +7210,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
     case RID_IS_ENUM:
       kind = CPTK_IS_ENUM;
       break;
+    case RID_IS_LITERAL_TYPE:
+      kind = CPTK_IS_LITERAL_TYPE;
+      break;
     case RID_IS_POD:
       kind = CPTK_IS_POD;
       break;
@@ -7194,8 +7228,8 @@ 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;
+    case RID_UNDERLYING_TYPE:
+      kind = CPTK_UNDERLYING_TYPE;
       break;
     default:
       gcc_unreachable ();
@@ -7241,7 +7275,9 @@ cp_parser_trait_expr (cp_parser* parser, enum rid keyword)
 
   /* Complete the trait expression, which may mean either processing
      the trait expr now or saving it for template instantiation.  */
-  return finish_trait_expr (kind, type1, type2);
+  return kind != CPTK_UNDERLYING_TYPE
+    ? finish_trait_expr (kind, type1, type2)
+    : finish_underlying_type (type1);
 }
 
 /* Lambdas that appear in variable initializer or default argument scope
@@ -7309,6 +7345,7 @@ cp_parser_lambda_expression (cp_parser* parser)
 {
   tree lambda_expr = build_lambda_expr ();
   tree type;
+  bool ok;
 
   LAMBDA_EXPR_LOCATION (lambda_expr)
     = cp_lexer_peek_token (parser->lexer)->location;
@@ -7344,9 +7381,12 @@ cp_parser_lambda_expression (cp_parser* parser)
     /* 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);
+    ok = cp_parser_lambda_declarator_opt (parser, lambda_expr);
 
-    cp_parser_lambda_body (parser, lambda_expr);
+    if (ok)
+      cp_parser_lambda_body (parser, lambda_expr);
+    else if (cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+      cp_parser_skip_to_end_of_block_or_statement (parser);
 
     /* The capture list was built up in reverse order; fix that now.  */
     {
@@ -7356,31 +7396,15 @@ cp_parser_lambda_expression (cp_parser* parser)
       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;
     }
 
-    maybe_add_lambda_conv_op (type);
+    if (ok)
+      maybe_add_lambda_conv_op (type);
 
     type = finish_struct (type, /*attributes=*/NULL_TREE);
 
@@ -7389,7 +7413,18 @@ cp_parser_lambda_expression (cp_parser* parser)
 
   pop_deferring_access_checks ();
 
-  return build_lambda_object (lambda_expr);
+  /* This field is only used during parsing of the lambda.  */
+  LAMBDA_EXPR_THIS_CAPTURE (lambda_expr) = NULL_TREE;
+
+  /* This lambda shouldn't have any proxies left at this point.  */
+  gcc_assert (LAMBDA_EXPR_PENDING_PROXIES (lambda_expr) == NULL);
+  /* And now that we're done, push proxies for an enclosing lambda.  */
+  insert_pending_capture_proxies ();
+
+  if (ok)
+    return build_lambda_object (lambda_expr);
+  else
+    return error_mark_node;
 }
 
 /* Parse the beginning of a lambda expression.
@@ -7450,9 +7485,13 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
       /* Possibly capture `this'.  */
       if (cp_lexer_next_token_is_keyword (parser->lexer, RID_THIS))
        {
+         location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+         if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY)
+           pedwarn (loc, 0, "explicit by-copy capture of %<this%> redundant "
+                    "with by-copy capture default");
          cp_lexer_consume_token (parser->lexer);
          add_capture (lambda_expr,
-                      /*id=*/get_identifier ("__this"),
+                      /*id=*/this_identifier,
                       /*initializer=*/finish_this_expr(),
                       /*by_reference_p=*/false,
                       explicit_init_p);
@@ -7533,6 +7572,21 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
        capture_init_expr
          = unqualified_name_lookup_error (capture_init_expr);
 
+      if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
+         && !explicit_init_p)
+       {
+         if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_COPY
+             && capture_kind == BY_COPY)
+           pedwarn (capture_token->location, 0, "explicit by-copy capture "
+                    "of %qD redundant with by-copy capture default",
+                    capture_id);
+         if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) == CPLD_REFERENCE
+             && capture_kind == BY_REFERENCE)
+           pedwarn (capture_token->location, 0, "explicit by-reference "
+                    "capture of %qD redundant with by-reference capture "
+                    "default", capture_id);
+       }
+
       add_capture (lambda_expr,
                   capture_id,
                   capture_init_expr,
@@ -7554,7 +7608,7 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
 
    LAMBDA_EXPR is the current representation of the lambda expression.  */
 
-static void
+static bool
 cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
 {
   /* 5.1.1.4 of the standard says:
@@ -7642,6 +7696,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
     quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
             ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
     declarator = make_call_declarator (declarator, param_list, quals,
+                                      VIRT_SPEC_UNSPECIFIED,
                                       exception_spec,
                                        /*late_return_type=*/NULL_TREE);
     declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
@@ -7649,12 +7704,19 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
     fco = grokmethod (&return_type_specs,
                      declarator,
                      attributes);
-    DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
-    DECL_ARTIFICIAL (fco) = 1;
+    if (fco != error_mark_node)
+      {
+       DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
+       DECL_ARTIFICIAL (fco) = 1;
+       /* Give the object parameter a different name.  */
+       DECL_NAME (DECL_ARGUMENTS (fco)) = get_identifier ("__closure");
+      }
 
     finish_member_declaration (fco);
 
     obstack_free (&declarator_obstack, p);
+
+    return (fco != error_mark_node);
   }
 }
 
@@ -7681,6 +7743,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
     tree fco = lambda_function (lambda_expr);
     tree body;
     bool done = false;
+    tree compound_stmt;
+    tree cap;
 
     /* Let the front end know that we are going to be defining this
        function.  */
@@ -7691,6 +7755,16 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
     start_lambda_scope (fco);
     body = begin_function_body ();
 
+    if (!cp_parser_require (parser, CPP_OPEN_BRACE, RT_OPEN_BRACE))
+      goto out;
+
+    /* Push the proxies for any explicit captures.  */
+    for (cap = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr); cap;
+        cap = TREE_CHAIN (cap))
+      build_capture_proxy (TREE_PURPOSE (cap));
+
+    compound_stmt = begin_compound_stmt (0);
+
     /* 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:
@@ -7707,11 +7781,9 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
        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)
+        && cp_lexer_peek_nth_token (parser->lexer, 1)->keyword == RID_RETURN
+        && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_SEMICOLON)
       {
-       tree compound_stmt;
        tree expr = NULL_TREE;
        cp_id_kind idk = CP_ID_KIND_NONE;
 
@@ -7719,7 +7791,6 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
           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);
@@ -7731,10 +7802,8 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
          {
            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;
          }
@@ -7744,12 +7813,16 @@ cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
       {
        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);
+       while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
+         cp_parser_label_declaration (parser);
+       cp_parser_statement_seq_opt (parser, NULL_TREE);
+       cp_parser_require (parser, CPP_CLOSE_BRACE, RT_CLOSE_BRACE);
        LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = false;
       }
 
+    finish_compound_stmt (compound_stmt);
+
+  out:
     finish_function_body (body);
     finish_lambda_scope ();
 
@@ -8555,14 +8628,20 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
       }
 
    If RANGE_EXPR is an array:
-       BEGIN_EXPR = __range
-       END_EXPR = __range + ARRAY_SIZE(__range)
+       BEGIN_EXPR = __range
+       END_EXPR = __range + ARRAY_SIZE(__range)
+   Else if RANGE_EXPR has a member 'begin' or 'end':
+       BEGIN_EXPR = __range.begin()
+       END_EXPR = __range.end()
    Else:
        BEGIN_EXPR = begin(__range)
        END_EXPR = end(__range);
 
-   When calling begin()/end() we must use argument dependent
-   lookup, but always considering 'std' as an associated namespace.  */
+   If __range has a member 'begin' but not 'end', or vice versa, we must
+   still use the second alternative (it will surely fail, however).
+   When calling begin()/end() in the third alternative we must use
+   argument dependent lookup, but always considering 'std' as an associated
+   namespace.  */
 
 tree
 cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
@@ -8579,12 +8658,12 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
   else
     {
       /* Find out the type deduced by the declaration
-       * `auto &&__range = range_expr' */
+         `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 */
+      /* Create the __range variable */
       range_temp = build_decl (input_location, VAR_DECL,
                               get_identifier ("__for_range"), range_type);
       TREE_USED (range_temp) = 1;
@@ -8595,51 +8674,11 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
                      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));
-       }
+      iter_type = cp_parser_perform_range_for_lookup (range_temp,
+                                                     &begin_expr, &end_expr);
     }
 
-  /* The new for initialization statement */
+  /* The new for initialization statement */
   begin = build_decl (input_location, VAR_DECL,
                      get_identifier ("__for_begin"), iter_type);
   TREE_USED (begin) = 1;
@@ -8660,18 +8699,18 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
 
   finish_for_init_stmt (statement);
 
-/* The new for condition */
+  /* 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 */
+  /* 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 */
+  /* 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,
@@ -8680,6 +8719,126 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
   return statement;
 }
 
+/* Solves BEGIN_EXPR and END_EXPR as described in cp_convert_range_for.
+   We need to solve both at the same time because the method used
+   depends on the existence of members begin or end.
+   Returns the type deduced for the iterator expression.  */
+
+static tree
+cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
+{
+  if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (range))))
+    {
+      error ("range-based %<for%> expression of type %qT "
+            "has incomplete type", TREE_TYPE (range));
+      *begin = *end = error_mark_node;
+      return error_mark_node;
+    }
+  if (TREE_CODE (TREE_TYPE (range)) == ARRAY_TYPE)
+    {
+      /* If RANGE is an array, we will use pointer arithmetic.  */
+      *begin = range;
+      *end = build_binary_op (input_location, PLUS_EXPR,
+                             range,
+                             array_type_nelts_top (TREE_TYPE (range)),
+                             0);
+      return build_pointer_type (TREE_TYPE (TREE_TYPE (range)));
+    }
+  else
+    {
+      /* If it is not an array, we must do a bit of magic.  */
+      tree id_begin, id_end;
+      tree member_begin, member_end;
+
+      *begin = *end = error_mark_node;
+
+      id_begin = get_identifier ("begin");
+      id_end = get_identifier ("end");
+      member_begin = lookup_member (TREE_TYPE (range), id_begin,
+                                   /*protect=*/2, /*want_type=*/false);
+      member_end = lookup_member (TREE_TYPE (range), id_end,
+                                 /*protect=*/2, /*want_type=*/false);
+
+      if (member_begin != NULL_TREE || member_end != NULL_TREE)
+       {
+         /* Use the member functions.  */
+         if (member_begin != NULL_TREE)
+           *begin = cp_parser_range_for_member_function (range, id_begin);
+         else
+           error ("range-based %<for%> expression of type %qT has an "
+                  "%<end%> member but not a %<begin%>", TREE_TYPE (range));
+
+         if (member_end != NULL_TREE)
+           *end = cp_parser_range_for_member_function (range, id_end);
+         else
+           error ("range-based %<for%> expression of type %qT has a "
+                  "%<begin%> member but not an %<end%>", TREE_TYPE (range));
+       }
+      else
+       {
+         /* Use global functions with ADL.  */
+         VEC(tree,gc) *vec;
+         vec = make_tree_vector ();
+
+         VEC_safe_push (tree, gc, vec, range);
+
+         member_begin = perform_koenig_lookup (id_begin, vec,
+                                               /*include_std=*/true,
+                                               tf_warning_or_error);
+         *begin = finish_call_expr (member_begin, &vec, false, true,
+                                    tf_warning_or_error);
+         member_end = perform_koenig_lookup (id_end, vec,
+                                             /*include_std=*/true,
+                                             tf_warning_or_error);
+         *end = finish_call_expr (member_end, &vec, false, true,
+                                  tf_warning_or_error);
+
+         release_tree_vector (vec);
+       }
+
+      /* Last common checks.  */
+      if (*begin == error_mark_node || *end == error_mark_node)
+       {
+         /* If one of the expressions is an error do no more checks.  */
+         *begin = *end = error_mark_node;
+         return error_mark_node;
+       }
+      else
+       {
+         tree iter_type = cv_unqualified (TREE_TYPE (*begin));
+         /* The unqualified type of the __begin and __end temporaries should
+            be the same, as required by the multiple auto declaration.  */
+         if (!same_type_p (iter_type, cv_unqualified (TREE_TYPE (*end))))
+           error ("inconsistent begin/end types in range-based %<for%> "
+                  "statement: %qT and %qT",
+                  TREE_TYPE (*begin), TREE_TYPE (*end));
+         return iter_type;
+       }
+    }
+}
+
+/* Helper function for cp_parser_perform_range_for_lookup.
+   Builds a tree for RANGE.IDENTIFIER().  */
+
+static tree
+cp_parser_range_for_member_function (tree range, tree identifier)
+{
+  tree member, res;
+  VEC(tree,gc) *vec;
+
+  member = finish_class_member_access_expr (range, identifier,
+                                           false, tf_warning_or_error);
+  if (member == error_mark_node)
+    return error_mark_node;
+
+  vec = make_tree_vector ();
+  res = finish_call_expr (member, &vec,
+                         /*disallow_virtual=*/false,
+                         /*koenig_p=*/false,
+                         tf_warning_or_error);
+  release_tree_vector (vec);
+  return res;
+}
 
 /* Parse an iteration-statement.
 
@@ -8828,7 +8987,7 @@ cp_parser_for_init_statement (cp_parser* parser, tree *decl)
          if (cxx_dialect < cxx0x)
            {
              error_at (cp_lexer_peek_token (parser->lexer)->location,
-                       "range-based-for loops are not allowed "
+                       "range-based %<for%> loops are not allowed "
                        "in C++98 mode");
              *decl = error_mark_node;
            }
@@ -10197,7 +10356,8 @@ cp_parser_decltype (cp_parser *parser)
       return error_mark_node;
     }
 
-  return finish_decltype_type (expr, id_expression_or_member_access_p);
+  return finish_decltype_type (expr, id_expression_or_member_access_p,
+                              tf_warning_or_error);
 }
 
 /* Special member functions [gram.special] */
@@ -12045,6 +12205,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
 
+  timevar_push (TV_TEMPLATE_INST);
+
   /* Look for an (optional) storage-class-specifier or
      function-specifier.  */
   if (cp_parser_allow_gnu_extensions_p (parser))
@@ -12128,6 +12290,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
   end_explicit_instantiation ();
 
   cp_parser_consume_semicolon_at_end_of_statement (parser);
+
+  timevar_pop (TV_TEMPLATE_INST);
 }
 
 /* Parse an explicit-specialization.
@@ -12414,6 +12578,7 @@ cp_parser_type_specifier (cp_parser* parser,
      decltype ( expression )   
      char16_t
      char32_t
+     __underlying_type ( type-id )
 
    GNU Extension:
 
@@ -12530,6 +12695,16 @@ cp_parser_simple_type_specifier (cp_parser* parser,
 
       return type;
 
+    case RID_UNDERLYING_TYPE:
+      type = cp_parser_trait_expr (parser, RID_UNDERLYING_TYPE);
+
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     token->location,
+                                     /*user_defined_p=*/true);
+
+      return type;
+
     default:
       break;
     }
@@ -13328,6 +13503,7 @@ cp_parser_enum_specifier (cp_parser* parser)
      elaborated-type-specifier.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
     {
+      timevar_push (TV_PARSE_ENUM);
       if (nested_name_specifier)
        {
          /* The following catches invalid code such as:
@@ -13389,6 +13565,7 @@ cp_parser_enum_specifier (cp_parser* parser)
 
       if (scoped_enum_p)
        finish_scope ();
+      timevar_pop (TV_PARSE_ENUM);
     }
   else
     {
@@ -14184,7 +14361,7 @@ cp_parser_init_declarator (cp_parser* parser,
   bool is_non_constant_init;
   int ctor_dtor_or_conv_p;
   bool friend_p;
-  tree pushed_scope = NULL;
+  tree pushed_scope = NULL_TREE;
   bool range_for_decl_p = false;
 
   /* Gather the attributes that were provided with the
@@ -14491,7 +14668,7 @@ cp_parser_init_declarator (cp_parser* parser,
       if (pushed_scope)
        {
          pop_scope (pushed_scope);
-         pushed_scope = false;
+         pushed_scope = NULL_TREE;
        }
       decl = grokfield (declarator, decl_specifiers,
                        initializer, !is_non_constant_init,
@@ -14764,11 +14941,15 @@ cp_parser_direct_declarator (cp_parser* parser,
              parser->num_template_parameter_lists
                = saved_num_template_parameter_lists;
 
+             /* Consume the `)'.  */
+             cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
+
              /* If all went well, parse the cv-qualifier-seq and the
                 exception-specification.  */
              if (member_p || cp_parser_parse_definitely (parser))
                {
                  cp_cv_quals cv_quals;
+                 cp_virt_specifiers virt_specifiers;
                  tree exception_specification;
                  tree late_return;
 
@@ -14777,22 +14958,23 @@ cp_parser_direct_declarator (cp_parser* parser,
                  if (ctor_dtor_or_conv_p)
                    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
                  first = false;
-                 /* Consume the `)'.  */
-                 cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
 
                  /* Parse the cv-qualifier-seq.  */
                  cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
                  /* And the exception-specification.  */
                  exception_specification
                    = cp_parser_exception_specification_opt (parser);
+                 /* Parse the virt-specifier-seq.  */
+                 virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
 
                  late_return
-                   = cp_parser_late_return_type_opt (parser);
+                   = cp_parser_late_return_type_opt (parser, cv_quals);
 
                  /* Create the function-declarator.  */
                  declarator = make_call_declarator (declarator,
                                                     params,
                                                     cv_quals,
+                                                    virt_specifiers,
                                                     exception_specification,
                                                     late_return);
                  /* Any subsequent parameter lists are to do with
@@ -15300,6 +15482,53 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
   return cv_quals;
 }
 
+/* Parse an (optional) virt-specifier-seq.
+
+   virt-specifier-seq:
+     virt-specifier virt-specifier-seq [opt]
+
+   virt-specifier:
+     override
+     final
+
+   Returns a bitmask representing the virt-specifiers.  */
+
+static cp_virt_specifiers
+cp_parser_virt_specifier_seq_opt (cp_parser* parser)
+{
+  cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
+
+  while (true)
+    {
+      cp_token *token;
+      cp_virt_specifiers virt_specifier;
+
+      /* Peek at the next token.  */
+      token = cp_lexer_peek_token (parser->lexer);
+      /* See if it's a virt-specifier-qualifier.  */
+      if (token->type != CPP_NAME)
+        break;
+      if (!strcmp (IDENTIFIER_POINTER(token->u.value), "override"))
+       virt_specifier = VIRT_SPEC_OVERRIDE;
+      else if (!strcmp (IDENTIFIER_POINTER(token->u.value), "final"))
+       virt_specifier = VIRT_SPEC_FINAL;
+      else
+       break;
+
+      if (virt_specifiers & virt_specifier)
+       {
+         error_at (token->location, "duplicate virt-specifier");
+         cp_lexer_purge_token (parser->lexer);
+       }
+      else
+       {
+         cp_lexer_consume_token (parser->lexer);
+         virt_specifiers |= virt_specifier;
+       }
+    }
+  return virt_specifiers;
+}
+
 /* Parse a late-specified return type, if any.  This is not a separate
    non-terminal, but part of a function declarator, which looks like
 
@@ -15308,9 +15537,10 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
    Returns the type indicated by the type-id.  */
 
 static tree
-cp_parser_late_return_type_opt (cp_parser* parser)
+cp_parser_late_return_type_opt (cp_parser* parser, cp_cv_quals quals)
 {
   cp_token *token;
+  tree type;
 
   /* Peek at the next token.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -15321,7 +15551,23 @@ cp_parser_late_return_type_opt (cp_parser* parser)
   /* Consume the ->.  */
   cp_lexer_consume_token (parser->lexer);
 
-  return cp_parser_trailing_type_id (parser);
+  if (current_class_type)
+    {
+      /* DR 1207: 'this' is in scope in the trailing return type.  */
+      tree this_parm = build_this_parm (current_class_type, quals);
+      gcc_assert (current_class_ptr == NULL_TREE);
+      current_class_ref
+       = cp_build_indirect_ref (this_parm, RO_NULL, tf_warning_or_error);
+      /* Set this second to avoid shortcut in cp_build_indirect_ref.  */
+      current_class_ptr = this_parm;
+    }
+
+  type = cp_parser_trailing_type_id (parser);
+
+  if (current_class_type)
+    current_class_ptr = current_class_ref = NULL_TREE;
+
+  return type;
 }
 
 /* Parse a declarator-id.
@@ -15865,6 +16111,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
             of some object of type "char" to "int".  */
          && !parser->in_type_id_in_expr_p
          && cp_parser_uncommitted_to_tentative_parse_p (parser)
+         && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
          && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
        cp_parser_commit_to_tentative_parse (parser);
       /* Parse the declarator.  */
@@ -16302,16 +16549,6 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
        = cp_parser_constant_expression (parser,
                                        /*allow_non_constant_p=*/true,
                                        non_constant_p);
-      if (!*non_constant_p)
-       {
-         /* 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);
@@ -16624,7 +16861,7 @@ cp_parser_class_name (cp_parser *parser,
    Returns the TREE_TYPE representing the class.  */
 
 static tree
-cp_parser_class_specifier (cp_parser* parser)
+cp_parser_class_specifier_1 (cp_parser* parser)
 {
   tree type;
   tree attributes = NULL_TREE;
@@ -16887,14 +17124,27 @@ cp_parser_class_specifier (cp_parser* parser)
   return type;
 }
 
+static tree
+cp_parser_class_specifier (cp_parser* parser)
+{
+  tree ret;
+  timevar_push (TV_PARSE_STRUCT);
+  ret = cp_parser_class_specifier_1 (parser);
+  timevar_pop (TV_PARSE_STRUCT);
+  return ret;
+}
+
 /* Parse a class-head.
 
    class-head:
      class-key identifier [opt] base-clause [opt]
-     class-key nested-name-specifier identifier base-clause [opt]
+     class-key nested-name-specifier identifier class-virt-specifier [opt] base-clause [opt]
      class-key nested-name-specifier [opt] template-id
        base-clause [opt]
 
+   class-virt-specifier:
+     final
+
    GNU Extensions:
      class-key attributes identifier [opt] base-clause [opt]
      class-key attributes nested-name-specifier identifier base-clause [opt]
@@ -16926,6 +17176,7 @@ cp_parser_class_head (cp_parser* parser,
   tree id = NULL_TREE;
   tree type = NULL_TREE;
   tree attributes;
+  cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
   bool template_id_p = false;
   bool qualified_p = false;
   bool invalid_nested_name_p = false;
@@ -17069,8 +17320,11 @@ cp_parser_class_head (cp_parser* parser,
   pop_deferring_access_checks ();
 
   if (id)
-    cp_parser_check_for_invalid_template_id (parser, id,
-                                            type_start_token->location);
+    {
+      cp_parser_check_for_invalid_template_id (parser, id,
+                                               type_start_token->location);
+      virt_specifiers = cp_parser_virt_specifier_seq_opt (parser);
+    }
 
   /* If it's not a `:' or a `{' then we can't really be looking at a
      class-head, since a class-head only appears as part of a
@@ -17086,6 +17340,13 @@ cp_parser_class_head (cp_parser* parser,
   /* At this point, we're going ahead with the class-specifier, even
      if some other problem occurs.  */
   cp_parser_commit_to_tentative_parse (parser);
+  if (virt_specifiers & VIRT_SPEC_OVERRIDE)
+    {
+      cp_parser_error (parser,
+                       "cannot specify %<override%> for a class");
+      type = error_mark_node;
+      goto out;
+    }
   /* Issue the error about the overly-qualified name now.  */
   if (qualified_p)
     {
@@ -17302,6 +17563,8 @@ cp_parser_class_head (cp_parser* parser,
   if (type)
     DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
   *attributes_p = attributes;
+  if (type && (virt_specifiers & VIRT_SPEC_FINAL))
+    CLASSTYPE_FINAL (type) = 1;
  out:
   parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
   return type;
@@ -17542,9 +17805,10 @@ cp_parser_member_declaration (cp_parser* parser)
            {
              /* If the `friend' keyword was present, the friend must
                 be introduced with a class-key.  */
-              if (!declares_class_or_enum)
-                error_at (decl_spec_token_start->location,
-                          "a class-key must be used when declaring a friend");
+              if (!declares_class_or_enum && cxx_dialect < cxx0x)
+                pedwarn (decl_spec_token_start->location, OPT_pedantic,
+                         "in C++03 a class-key must be used "
+                         "when declaring a friend");
               /* In this case:
 
                    template <typename T> struct A {
@@ -17553,10 +17817,12 @@ cp_parser_member_declaration (cp_parser* parser)
 
                  A<T>::B will be represented by a TYPENAME_TYPE, and
                  therefore not recognized by check_tag_decl.  */
-              if (!type
-                  && decl_specifiers.type
-                  && TYPE_P (decl_specifiers.type))
-                type = decl_specifiers.type;
+              if (!type)
+                {
+                  type = decl_specifiers.type;
+                  if (type && TREE_CODE (type) == TYPE_DECL)
+                    type = TREE_TYPE (type);
+                }
               if (!type || !TYPE_P (type))
                 error_at (decl_spec_token_start->location,
                           "friend declaration does not name a class or "
@@ -19375,7 +19641,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
   /* 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))
+      && CLASS_TYPE_P (nested_name_specifier))
     {
       tree id = cp_parser_unqualified_id (parser,
                                          /*template_keyword_p=*/false,
@@ -19532,8 +19798,17 @@ cp_parser_function_definition_from_specifiers_and_declarator
        pop_nested_class ();
     }
   else
-    fn = cp_parser_function_definition_after_declarator (parser,
+    {
+      timevar_id_t tv;
+      if (DECL_DECLARED_INLINE_P (current_function_decl))
+        tv = TV_PARSE_INLINE;
+      else
+        tv = TV_PARSE_FUNC;
+      timevar_push (tv);
+      fn = cp_parser_function_definition_after_declarator (parser,
                                                         /*inline_p=*/false);
+      timevar_pop (tv);
+    }
 
   return fn;
 }
@@ -19935,7 +20210,8 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
       CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
       if (TREE_CODE (type) == TYPE_DECL)
        type = TREE_TYPE (type);
-      return finish_compound_literal (type, expression_list);
+      return finish_compound_literal (type, expression_list,
+                                     tf_warning_or_error);
     }
 
 
@@ -20149,6 +20425,7 @@ cp_parser_enclosed_template_argument_list (cp_parser* parser)
 static void
 cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
 {
+  timevar_push (TV_PARSE_INMETH);
   /* If this member is a template, get the underlying
      FUNCTION_DECL.  */
   if (DECL_FUNCTION_TEMPLATE_P (member_function))
@@ -20215,6 +20492,7 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
 
   /* Restore the queue.  */
   pop_unparsed_function_queues (parser);
+  timevar_pop (TV_PARSE_INMETH);
 }
 
 /* If DECL contains any default args, remember it on the unparsed
@@ -21286,7 +21564,7 @@ cp_parser_objc_message_expression (cp_parser* parser)
   messageargs = cp_parser_objc_message_args (parser);
   cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
 
-  return objc_build_message_expr (build_tree_list (receiver, messageargs));
+  return objc_build_message_expr (receiver, messageargs);
 }
 
 /* Parse an objc-message-receiver.
@@ -21612,7 +21890,21 @@ static void
 cp_parser_objc_class_declaration (cp_parser* parser)
 {
   cp_lexer_consume_token (parser->lexer);  /* Eat '@class'.  */
-  objc_declare_class (cp_parser_objc_identifier_list (parser));
+  while (true)
+    {
+      tree id;
+      
+      id = cp_parser_identifier (parser);
+      if (id == error_mark_node)
+       break;
+      
+      objc_declare_class (id);
+
+      if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+       cp_lexer_consume_token (parser->lexer);
+      else
+       break;
+    }
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 }
 
@@ -22095,7 +22387,8 @@ cp_parser_objc_method_definition_list (cp_parser* parser)
              token = cp_lexer_peek_token (parser->lexer);
              continue;
            }
-         objc_start_method_definition (is_class_method, sig, attribute);
+         objc_start_method_definition (is_class_method, sig, attribute,
+                                       NULL_TREE);
 
          /* For historical reasons, we accept an optional semicolon.  */
          if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
@@ -22253,7 +22546,8 @@ cp_parser_objc_class_ivars (cp_parser* parser)
                              NULL_TREE, attributes);
 
          /* Add the instance variable.  */
-         objc_add_instance_variable (decl);
+         if (decl != error_mark_node && decl != NULL_TREE)
+           objc_add_instance_variable (decl);
 
          /* Reset PREFIX_ATTRIBUTES.  */
          while (attributes && TREE_CHAIN (attributes) != first_attribute)
@@ -22301,7 +22595,8 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
     {
       tok = cp_lexer_peek_token (parser->lexer);
       error_at (tok->location, "identifier expected after %<@protocol%>");
-      goto finish;
+      cp_parser_consume_semicolon_at_end_of_statement (parser);
+      return;
     }
 
   /* See if we have a forward declaration or a definition.  */
@@ -22310,9 +22605,21 @@ cp_parser_objc_protocol_declaration (cp_parser* parser, tree attributes)
   /* Try a forward declaration first.  */
   if (tok->type == CPP_COMMA || tok->type == CPP_SEMICOLON)
     {
-      objc_declare_protocols (cp_parser_objc_identifier_list (parser), 
-                             attributes);
-     finish:
+      while (true)
+       {
+         tree id;
+         
+         id = cp_parser_identifier (parser);
+         if (id == error_mark_node)
+           break;
+         
+         objc_declare_protocol (id, attributes);
+         
+         if(cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+           cp_lexer_consume_token (parser->lexer);
+         else
+           break;
+       }
       cp_parser_consume_semicolon_at_end_of_statement (parser);
     }
 
@@ -22908,7 +23215,7 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
                  break;
                }
              cp_lexer_consume_token (parser->lexer); /* eat the = */
-             if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
+             if (!cp_parser_objc_selector_p (cp_lexer_peek_token (parser->lexer)->type))
                {
                  cp_parser_error (parser, "expected identifier");
                  syntax_error = true;
@@ -22917,10 +23224,12 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
              if (keyword == RID_SETTER)
                {
                  if (property_setter_ident != NULL_TREE)
-                   cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
+                   {
+                     cp_parser_error (parser, "the %<setter%> attribute may only be specified once");
+                     cp_lexer_consume_token (parser->lexer);
+                   }
                  else
-                   property_setter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
-                 cp_lexer_consume_token (parser->lexer);
+                   property_setter_ident = cp_parser_objc_selector (parser);
                  if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
                    cp_parser_error (parser, "setter name must terminate with %<:%>");
                  else
@@ -22929,10 +23238,12 @@ cp_parser_objc_at_property_declaration (cp_parser *parser)
              else
                {
                  if (property_getter_ident != NULL_TREE)
-                   cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
+                   {
+                     cp_parser_error (parser, "the %<getter%> attribute may only be specified once");
+                     cp_lexer_consume_token (parser->lexer);
+                   }
                  else
-                   property_getter_ident = cp_lexer_peek_token (parser->lexer)->u.value;
-                 cp_lexer_consume_token (parser->lexer);
+                   property_getter_ident = cp_parser_objc_selector (parser);
                }
              break;
            default:
@@ -23964,8 +24275,6 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl)
 {
   tree cond = cp_parser_binary_expression (parser, false, true,
                                           PREC_NOT_OPERATOR, NULL);
-  bool overloaded_p;
-
   if (cond == error_mark_node
       || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     {
@@ -23994,7 +24303,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl)
   return build_x_binary_op (TREE_CODE (cond),
                            TREE_OPERAND (cond, 0), ERROR_MARK,
                            TREE_OPERAND (cond, 1), ERROR_MARK,
-                           &overloaded_p, tf_warning_or_error);
+                           /*overload=*/NULL, tf_warning_or_error);
 }
 
 /* Helper function, to parse omp for increment expression.  */
@@ -24202,7 +24511,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                                                    &is_direct_init,
                                                    &is_non_constant_init);
 
-                     if (auto_node && describable_type (init))
+                     if (auto_node)
                        {
                          TREE_TYPE (decl)
                            = do_auto_deduction (TREE_TYPE (decl), init,
@@ -24377,7 +24686,8 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
          /* If decl is an iterator, preserve the operator on decl
             until finish_omp_for.  */
          if (decl
-             && (type_dependent_expression_p (decl)
+             && ((type_dependent_expression_p (decl)
+                  && !POINTER_TYPE_P (TREE_TYPE (decl)))
                  || CLASS_TYPE_P (TREE_TYPE (decl))))
            incr = cp_parser_omp_for_incr (parser, decl);
          else