OSDN Git Service

/cp
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index fd4e1bb..5675e9b 100644 (file)
@@ -1,6 +1,6 @@
 /* C++ Parser.
    Copyright (C) 2000, 2001, 2002, 2003, 2004,
-   2005, 2007, 2008  Free Software Foundation, Inc.
+   2005, 2007, 2008, 2009  Free Software Foundation, Inc.
    Written by Mark Mitchell <mark@codesourcery.com>.
 
    This file is part of GCC.
@@ -853,7 +853,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 *, cp_parameter_declarator *, cp_cv_quals, tree);
+  (cp_declarator *, tree, cp_cv_quals, tree, tree);
 static cp_declarator *make_array_declarator
   (cp_declarator *, tree);
 static cp_declarator *make_pointer_declarator
@@ -1013,9 +1013,10 @@ make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
 
 cp_declarator *
 make_call_declarator (cp_declarator *target,
-                     cp_parameter_declarator *parms,
+                     tree parms,
                      cp_cv_quals cv_qualifiers,
-                     tree exception_specification)
+                     tree exception_specification,
+                     tree late_return_type)
 {
   cp_declarator *declarator;
 
@@ -1024,6 +1025,7 @@ make_call_declarator (cp_declarator *target,
   declarator->u.function.parameters = parms;
   declarator->u.function.qualifiers = cv_qualifiers;
   declarator->u.function.exception_specification = exception_specification;
+  declarator->u.function.late_return_type = late_return_type;
   if (target)
     {
       declarator->parameter_pack_p = target->parameter_pack_p;
@@ -1581,10 +1583,10 @@ static tree cp_parser_nested_name_specifier_opt
   (cp_parser *, bool, bool, bool, bool);
 static tree cp_parser_nested_name_specifier
   (cp_parser *, bool, bool, bool, bool);
-static tree cp_parser_class_or_namespace_name
+static tree cp_parser_qualifying_entity
   (cp_parser *, bool, bool, bool, bool, bool);
 static tree cp_parser_postfix_expression
-  (cp_parser *, bool, bool, bool);
+  (cp_parser *, bool, bool, bool, cp_id_kind *);
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
@@ -1594,7 +1596,7 @@ static tree cp_parser_parenthesized_expression_list
 static void cp_parser_pseudo_destructor_name
   (cp_parser *, tree *, tree *);
 static tree cp_parser_unary_expression
-  (cp_parser *, bool, bool);
+  (cp_parser *, bool, bool, cp_id_kind *);
 static enum tree_code cp_parser_unary_operator
   (cp_token *);
 static tree cp_parser_new_expression
@@ -1612,17 +1614,17 @@ static tree cp_parser_new_initializer
 static tree cp_parser_delete_expression
   (cp_parser *);
 static tree cp_parser_cast_expression
-  (cp_parser *, bool, bool);
+  (cp_parser *, bool, bool, cp_id_kind *);
 static tree cp_parser_binary_expression
-  (cp_parser *, bool, enum cp_parser_prec);
+  (cp_parser *, bool, enum cp_parser_prec, cp_id_kind *);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
 static tree cp_parser_assignment_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, cp_id_kind *);
 static enum tree_code cp_parser_assignment_operator_opt
   (cp_parser *);
 static tree cp_parser_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, cp_id_kind *);
 static tree cp_parser_constant_expression
   (cp_parser *, bool, bool *);
 static tree cp_parser_builtin_offsetof
@@ -1726,15 +1728,17 @@ 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
+  (cp_parser *);
 static tree cp_parser_declarator_id
   (cp_parser *, bool);
 static tree cp_parser_type_id
   (cp_parser *);
 static void cp_parser_type_specifier_seq
   (cp_parser *, bool, cp_decl_specifier_seq *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_clause
+static tree cp_parser_parameter_declaration_clause
   (cp_parser *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_list
+static tree cp_parser_parameter_declaration_list
   (cp_parser *, bool *);
 static cp_parameter_declarator *cp_parser_parameter_declaration
   (cp_parser *, bool, bool *);
@@ -2162,9 +2166,8 @@ cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
            error ("%H%<long long long%> is too long for GCC", &location);
          else if (pedantic && !in_system_header && warn_long_long
                    && cxx_dialect == cxx98)
-           pedwarn (OPT_Wlong_long, 
-                    "%HISO C++ 1998 does not support %<long long%>",
-                    &location);
+           pedwarn (location, OPT_Wlong_long, 
+                    "ISO C++ 1998 does not support %<long long%>");
        }
       else if (count > 1)
        {
@@ -2229,8 +2232,9 @@ cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
       && declarator->kind == cdk_function)
     {
       error ("%Hnew types may not be defined in a return type", &type_location);
-      inform ("%H(perhaps a semicolon is missing after the definition of %qT)",
-             &type_location, type);
+      inform (type_location, 
+             "(perhaps a semicolon is missing after the definition of %qT)",
+             type);
     }
 }
 
@@ -2358,8 +2362,9 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser,
                    if (TREE_CODE (field) == TYPE_DECL
                        && DECL_NAME (field) == id)
                      {
-                       inform ("%H(perhaps %<typename %T::%E%> was intended)",
-                               &location, BINFO_TYPE (b), id);
+                       inform (location, 
+                               "(perhaps %<typename %T::%E%> was intended)",
+                               BINFO_TYPE (b), id);
                        break;
                      }
                  if (field)
@@ -3215,9 +3220,8 @@ cp_parser_primary_expression (cp_parser *parser,
            && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
          {
            /* Statement-expressions are not allowed by the standard.  */
-           pedwarn (OPT_pedantic, 
-                    "%HISO C++ forbids braced-groups within expressions",
-                    &token->location);
+           pedwarn (token->location, OPT_pedantic, 
+                    "ISO C++ forbids braced-groups within expressions");
 
            /* And they're not allowed outside of a function-body; you
               cannot, for example, write:
@@ -3247,7 +3251,7 @@ cp_parser_primary_expression (cp_parser *parser,
        else
          {
            /* Parse the parenthesized expression.  */
-           expr = cp_parser_expression (parser, cast_p);
+           expr = cp_parser_expression (parser, cast_p, idk);
            /* Let the front end know that this expression was
               enclosed in parentheses. This matters in case, for
               example, the expression is of the form `A::B', since
@@ -3304,16 +3308,39 @@ cp_parser_primary_expression (cp_parser *parser,
        case RID_FUNCTION_NAME:
        case RID_PRETTY_FUNCTION_NAME:
        case RID_C99_FUNCTION_NAME:
-         /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
-            __func__ are the names of variables -- but they are
-            treated specially.  Therefore, they are handled here,
-            rather than relying on the generic id-expression logic
-            below.  Grammatically, these names are id-expressions.
+         {
+           const char *name;
 
-            Consume the token.  */
-         token = cp_lexer_consume_token (parser->lexer);
-         /* Look up the name.  */
-         return finish_fname (token->u.value);
+           /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
+              __func__ are the names of variables -- but they are
+              treated specially.  Therefore, they are handled here,
+              rather than relying on the generic id-expression logic
+              below.  Grammatically, these names are id-expressions.
+
+              Consume the token.  */
+           token = cp_lexer_consume_token (parser->lexer);
+
+           switch (token->keyword)
+             {
+             case RID_FUNCTION_NAME:
+               name = "%<__FUNCTION__%>";
+               break;
+             case RID_PRETTY_FUNCTION_NAME:
+               name = "%<__PRETTY_FUNCTION__%>";
+               break;
+             case RID_C99_FUNCTION_NAME:
+               name = "%<__func__%>";
+               break;
+             default:
+               gcc_unreachable ();
+             }
+
+           if (cp_parser_non_integral_constant_expression (parser, name))
+             return error_mark_node;
+
+           /* Look up the name.  */
+           return finish_fname (token->u.value);
+         }
 
        case RID_VA_ARG:
          {
@@ -3327,7 +3354,7 @@ cp_parser_primary_expression (cp_parser *parser,
            cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
            /* Now, parse the assignment-expression.  */
            expression = cp_parser_assignment_expression (parser,
-                                                         /*cast_p=*/false);
+                                                         /*cast_p=*/false, NULL);
            /* Look for the `,'.  */
            cp_parser_require (parser, CPP_COMMA, "%<,%>");
            /* Parse the type-id.  */
@@ -3853,6 +3880,8 @@ cp_parser_unqualified_id (cp_parser* parser,
            parser->scope = NULL_TREE;
            parser->object_scope = NULL_TREE;
            parser->qualifying_scope = NULL_TREE;
+           if (processing_template_decl)
+             cp_parser_parse_tentatively (parser);
            type_decl
              = cp_parser_class_name (parser,
                                      /*typename_keyword_p=*/false,
@@ -3861,6 +3890,14 @@ cp_parser_unqualified_id (cp_parser* parser,
                                      /*check_dependency=*/false,
                                      /*class_head_p=*/false,
                                      declarator_p);
+           if (processing_template_decl
+               && ! cp_parser_parse_definitely (parser))
+             {
+               /* We couldn't find a type with this name, so just accept
+                  it and check for a match at instantiation time.  */
+               type_decl = cp_parser_identifier (parser);
+               return build_nt (BIT_NOT_EXPR, type_decl);
+             }
          }
        /* If an error occurred, assume that the name of the
           destructor is the same as the name of the qualifying
@@ -3932,10 +3969,16 @@ cp_parser_unqualified_id (cp_parser* parser,
 
 /* Parse an (optional) nested-name-specifier.
 
-   nested-name-specifier:
+   nested-name-specifier: [C++98]
      class-or-namespace-name :: nested-name-specifier [opt]
      class-or-namespace-name :: template nested-name-specifier [opt]
 
+   nested-name-specifier: [C++0x]
+     type-name ::
+     namespace-name ::
+     nested-name-specifier identifier ::
+     nested-name-specifier template [opt] simple-template-id ::
+
    PARSER->SCOPE should be set appropriately before this function is
    called.  TYPENAME_KEYWORD_P is TRUE if the `typename' keyword is in
    effect.  TYPE_P is TRUE if we non-type bindings should be ignored
@@ -4010,7 +4053,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
       else
        {
          /* If the next token is not an identifier, then it is
-            definitely not a class-or-namespace-name.  */
+            definitely not a type-name or namespace-name.  */
          if (token->type != CPP_NAME)
            break;
          /* If the following token is neither a `<' (to begin a
@@ -4050,12 +4093,12 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                                               /*only_current_p=*/false);
       /* Parse the qualifying entity.  */
       new_scope
-       = cp_parser_class_or_namespace_name (parser,
-                                            typename_keyword_p,
-                                            template_keyword_p,
-                                            check_dependency_p,
-                                            type_p,
-                                            is_declaration);
+       = cp_parser_qualifying_entity (parser,
+                                       typename_keyword_p,
+                                       template_keyword_p,
+                                       check_dependency_p,
+                                       type_p,
+                                       is_declaration);
       /* Look for the `::' token.  */
       cp_parser_require (parser, CPP_SCOPE, "%<::%>");
 
@@ -4107,10 +4150,14 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
                          decl = error_mark_node;
                        }
                      else
-                       cp_parser_name_lookup_error
-                         (parser, token->u.value, decl,
-                          "is not a class or namespace",
-                          token->location);
+                        {
+                          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,
+                            token->location);
+                        }
                    }
                  parser->scope = error_mark_node;
                  error_p = true;
@@ -4142,7 +4189,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
          && !(TREE_CODE (new_scope) == TYPENAME_TYPE
               && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
                   == TEMPLATE_ID_EXPR)))
-       permerror (TYPE_P (new_scope)
+       permerror (input_location, TYPE_P (new_scope)
                   ? "%qT is not a template"
                   : "%qD is not a template",
                   new_scope);
@@ -4229,11 +4276,11 @@ cp_parser_nested_name_specifier (cp_parser *parser,
   return scope;
 }
 
-/* Parse a class-or-namespace-name.
-
-   class-or-namespace-name:
-     class-name
-     namespace-name
+/* Parse the qualifying entity in a nested-name-specifier. For C++98,
+   this is either a class-name or a namespace-name (which corresponds
+   to the class-or-namespace-name production in the grammar). For
+   C++0x, it can also be a type-name that refers to an enumeration
+   type.
 
    TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect.
    TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect.
@@ -4247,18 +4294,19 @@ cp_parser_nested_name_specifier (cp_parser *parser,
    ERROR_MARK_NODE is returned.  */
 
 static tree
-cp_parser_class_or_namespace_name (cp_parser *parser,
-                                  bool typename_keyword_p,
-                                  bool template_keyword_p,
-                                  bool check_dependency_p,
-                                  bool type_p,
-                                  bool is_declaration)
+cp_parser_qualifying_entity (cp_parser *parser,
+                            bool typename_keyword_p,
+                            bool template_keyword_p,
+                            bool check_dependency_p,
+                            bool type_p,
+                            bool is_declaration)
 {
   tree saved_scope;
   tree saved_qualifying_scope;
   tree saved_object_scope;
   tree scope;
   bool only_class_p;
+  bool successful_parse_p;
 
   /* Before we try to parse the class-name, we must save away the
      current PARSER->SCOPE since cp_parser_class_name will destroy
@@ -4268,7 +4316,8 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
   saved_object_scope = parser->object_scope;
   /* Try for a class-name first.  If the SAVED_SCOPE is a type, then
      there is no need to look for a namespace-name.  */
-  only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope));
+  only_class_p = template_keyword_p 
+    || (saved_scope && TYPE_P (saved_scope) && cxx_dialect == cxx98);
   if (!only_class_p)
     cp_parser_parse_tentatively (parser);
   scope = cp_parser_class_name (parser,
@@ -4278,8 +4327,26 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
                                check_dependency_p,
                                /*class_head_p=*/false,
                                is_declaration);
+  successful_parse_p = only_class_p || cp_parser_parse_definitely (parser);
+  /* If that didn't work and we're in C++0x mode, try for a type-name.  */
+  if (!only_class_p 
+      && cxx_dialect != cxx98
+      && !successful_parse_p)
+    {
+      /* Restore the saved scope.  */
+      parser->scope = saved_scope;
+      parser->qualifying_scope = saved_qualifying_scope;
+      parser->object_scope = saved_object_scope;
+
+      /* Parse tentatively.  */
+      cp_parser_parse_tentatively (parser);
+     
+      /* Parse a typedef-name or enum-name.  */
+      scope = cp_parser_nonclass_name (parser);
+      successful_parse_p = cp_parser_parse_definitely (parser);
+    }
   /* If that didn't work, try for a namespace-name.  */
-  if (!only_class_p && !cp_parser_parse_definitely (parser))
+  if (!only_class_p && !successful_parse_p)
     {
       /* Restore the saved scope.  */
       parser->scope = saved_scope;
@@ -4342,7 +4409,8 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
 
 static tree
 cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
-                              bool member_access_only_p)
+                              bool member_access_only_p,
+                             cp_id_kind * pidk_return)
 {
   cp_token *token;
   enum rid keyword;
@@ -4386,7 +4454,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
 
        /* And the expression which is being cast.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
-       expression = cp_parser_expression (parser, /*cast_p=*/true);
+       expression = cp_parser_expression (parser, /*cast_p=*/true, & idk);
        cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
        /* Only type conversions to integral or enumeration types
@@ -4458,7 +4526,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
            tree expression;
 
            /* Look for an expression.  */
-           expression = cp_parser_expression (parser, /*cast_p=*/false);
+           expression = cp_parser_expression (parser, /*cast_p=*/false, & idk);
            /* Compute its typeid.  */
            postfix_expression = build_typeid (expression);
            /* Look for the `)' token.  */
@@ -4546,7 +4614,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
              {
                /* Warn the user that a compound literal is not
                   allowed in standard C++.  */
-               pedwarn (OPT_pedantic, "ISO C++ forbids compound-literals");
+               pedwarn (input_location, OPT_pedantic, "ISO C++ forbids compound-literals");
                /* For simplicity, we disallow compound literals in
                   constant-expressions.  We could
                   allow compound literals of integer type, whose
@@ -4710,6 +4778,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                  }
 
                if (BASELINK_P (fn))
+                 {
                  postfix_expression
                    = (build_new_method_call
                       (instance, fn, args, NULL_TREE,
@@ -4717,6 +4786,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
                         ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
                        /*fn_p=*/NULL,
                        tf_warning_or_error));
+                 }
                else
                  postfix_expression
                    = finish_call_expr (postfix_expression, args,
@@ -4805,6 +4875,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
          break;
 
        default:
+         if (pidk_return != NULL)
+           * pidk_return = idk;
           if (member_access_only_p)
             return is_member_access? postfix_expression : error_mark_node;
           else
@@ -4846,7 +4918,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
   if (for_offsetof)
     index = cp_parser_constant_expression (parser, false, NULL);
   else
-    index = cp_parser_expression (parser, /*cast_p=*/false);
+    index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
   /* Look for the closing `]'.  */
   cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
@@ -4899,6 +4971,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
   parser->qualifying_scope = NULL_TREE;
   parser->object_scope = NULL_TREE;
   *idk = CP_ID_KIND_NONE;
+
   /* Enter the scope corresponding to the type of the object
      given by the POSTFIX_EXPRESSION.  */
   if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
@@ -5128,7 +5201,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                  *non_constant_p = true;
              }
            else
-             expr = cp_parser_assignment_expression (parser, cast_p);
+             expr = cp_parser_assignment_expression (parser, cast_p, NULL);
 
            if (fold_expr_p)
              expr = fold_non_dependent_expr (expr);
@@ -5230,7 +5303,7 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
                                            /*typename_keyword_p=*/false,
                                            /*check_dependency_p=*/true,
                                            /*type_p=*/false,
-                                           /*is_declaration=*/true)
+                                           /*is_declaration=*/false)
        != NULL_TREE);
   /* Now, if we saw a nested-name-specifier, we might be doing the
      second production.  */
@@ -5312,7 +5385,8 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
+                           cp_id_kind * pidk)
 {
   cp_token *token;
   enum tree_code unary_operator;
@@ -5423,13 +5497,14 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
        {
          tree identifier;
          tree expression;
+         location_t loc = cp_lexer_peek_token (parser->lexer)->location;
 
          /* Consume the '&&' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Look for the identifier.  */
          identifier = cp_parser_identifier (parser);
          /* Create an expression representing the address.  */
-         expression = finish_label_address_expr (identifier);
+         expression = finish_label_address_expr (identifier, loc);
          if (cp_parser_non_integral_constant_expression (parser,
                                                "the address of a label"))
            expression = error_mark_node;
@@ -5448,7 +5523,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
       cast_expression
        = cp_parser_cast_expression (parser,
                                     unary_operator == ADDR_EXPR,
-                                    /*cast_p=*/false);
+                                    /*cast_p=*/false, pidk);
       /* Now, build an appropriate representation.  */
       switch (unary_operator)
        {
@@ -5490,7 +5565,8 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
     }
 
   return cp_parser_postfix_expression (parser, address_p, cast_p,
-                                       /*member_access_only_p=*/false);
+                                       /*member_access_only_p=*/false,
+                                      pidk);
 }
 
 /* Returns ERROR_MARK if TOKEN is not a unary-operator.  If TOKEN is a
@@ -5576,8 +5652,8 @@ cp_parser_new_expression (cp_parser* parser)
        {
          error ("%Harray bound forbidden after parenthesized type-id",
                 &token->location);
-         inform ("%Htry removing the parentheses around the type-id",
-                &token->location);
+         inform (token->location, 
+                 "try removing the parentheses around the type-id");
          cp_parser_direct_new_declarator (parser);
        }
       nelts = NULL_TREE;
@@ -5755,7 +5831,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       if (!declarator)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
-         expression = cp_parser_expression (parser, /*cast_p=*/false);
+         expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
          /* The standard requires that the expression have integral
             type.  DR 74 adds enumeration types.  We believe that the
             real intent is that these expressions be handled like the
@@ -5875,6 +5951,61 @@ cp_parser_delete_expression (cp_parser* parser)
   return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
 }
 
+/* Returns true if TOKEN may start a cast-expression and false
+   otherwise.  */
+
+static bool
+cp_parser_token_starts_cast_expression (cp_token *token)
+{
+  switch (token->type)
+    {
+    case CPP_COMMA:
+    case CPP_SEMICOLON:
+    case CPP_QUERY:
+    case CPP_COLON:
+    case CPP_CLOSE_SQUARE:
+    case CPP_CLOSE_PAREN:
+    case CPP_CLOSE_BRACE:
+    case CPP_DOT:
+    case CPP_DOT_STAR:
+    case CPP_DEREF:
+    case CPP_DEREF_STAR:
+    case CPP_DIV:
+    case CPP_MOD:
+    case CPP_LSHIFT:
+    case CPP_RSHIFT:
+    case CPP_LESS:
+    case CPP_GREATER:
+    case CPP_LESS_EQ:
+    case CPP_GREATER_EQ:
+    case CPP_EQ_EQ:
+    case CPP_NOT_EQ:
+    case CPP_EQ:
+    case CPP_MULT_EQ:
+    case CPP_DIV_EQ:
+    case CPP_MOD_EQ:
+    case CPP_PLUS_EQ:
+    case CPP_MINUS_EQ:
+    case CPP_RSHIFT_EQ:
+    case CPP_LSHIFT_EQ:
+    case CPP_AND_EQ:
+    case CPP_XOR_EQ:
+    case CPP_OR_EQ:
+    case CPP_XOR:
+    case CPP_OR:
+    case CPP_OR_OR:
+    case CPP_EOF:
+      return false;
+
+      /* '[' may start a primary-expression in obj-c++.  */
+    case CPP_OPEN_SQUARE:
+      return c_dialect_objc ();
+
+    default:
+      return true;
+    }
+}
+
 /* Parse a cast-expression.
 
    cast-expression:
@@ -5888,7 +6019,8 @@ cp_parser_delete_expression (cp_parser* parser)
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
+                          cp_id_kind * pidk)
 {
   /* If it's a `(', then we might be looking at a cast.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
@@ -5953,17 +6085,18 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
       /* Restore the saved message.  */
       parser->type_definition_forbidden_message = saved_message;
 
-      /* If ok so far, parse the dependent expression. We cannot be
-        sure it is a cast. Consider `(T ())'.  It is a parenthesized
-        ctor of T, but looks like a cast to function returning T
-        without a dependent expression.  */
-      if (!cp_parser_error_occurred (parser))
-       expr = cp_parser_cast_expression (parser,
-                                         /*address_p=*/false,
-                                         /*cast_p=*/true);
-
-      if (cp_parser_parse_definitely (parser))
+      /* At this point this can only be either a cast or a
+        parenthesized ctor such as `(T ())' that looks like a cast to
+        function returning T.  */
+      if (!cp_parser_error_occurred (parser)
+         && cp_parser_token_starts_cast_expression (cp_lexer_peek_token
+                                                    (parser->lexer)))
        {
+         cp_parser_parse_definitely (parser);
+         expr = cp_parser_cast_expression (parser,
+                                           /*address_p=*/false,
+                                           /*cast_p=*/true, pidk);
+
          /* Warn about old-style casts, if so requested.  */
          if (warn_old_style_cast
              && !in_system_header
@@ -5984,11 +6117,13 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
          expr = build_c_cast (type, expr);
          return expr;
        }
+      else 
+        cp_parser_abort_tentative_parse (parser);
     }
 
   /* If we get here, then it's not a cast, so it must be a
      unary-expression.  */
-  return cp_parser_unary_expression (parser, address_p, cast_p);
+  return cp_parser_unary_expression (parser, address_p, cast_p, pidk);
 }
 
 /* Parse a binary expression of the general form:
@@ -6072,7 +6207,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
 
 static tree
 cp_parser_binary_expression (cp_parser* parser, bool cast_p,
-                            enum cp_parser_prec prec)
+                            enum cp_parser_prec prec,
+                            cp_id_kind * pidk)
 {
   cp_parser_expression_stack stack;
   cp_parser_expression_stack_entry *sp = &stack[0];
@@ -6083,7 +6219,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
   bool overloaded_p;
 
   /* Parse the first expression.  */
-  lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p);
+  lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p, pidk);
   lhs_type = ERROR_MARK;
 
   for (;;)
@@ -6170,6 +6306,13 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
        }
 
       overloaded_p = false;
+      /* ??? 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
+        involve unary operators.  For unary expressions we should
+        pass the correct tree_code unless the unary expression was
+        surrounded by parentheses.
+      */
       lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
                               &overloaded_p, tf_warning_or_error);
       lhs_type = tree_type;
@@ -6217,12 +6360,12 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
     expr = NULL_TREE;
   else
     /* Parse the expression.  */
-    expr = cp_parser_expression (parser, /*cast_p=*/false);
+    expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
   /* The next token should be a `:'.  */
   cp_parser_require (parser, CPP_COLON, "%<:%>");
   /* Parse the assignment-expression.  */
-  assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+  assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
 
   /* Build the conditional-expression.  */
   return build_x_conditional_expr (logical_or_expr,
@@ -6243,7 +6386,8 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
    Returns a representation for the expression.  */
 
 static tree
-cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
+cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
+                                cp_id_kind * pidk)
 {
   tree expr;
 
@@ -6256,7 +6400,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
   else
     {
       /* Parse the binary expressions (logical-or-expression).  */
-      expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR);
+      expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR, pidk);
       /* If the next token is a `?' then we're actually looking at a
         conditional-expression.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
@@ -6391,7 +6535,7 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_expression (cp_parser* parser, bool cast_p)
+cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
 {
   tree expression = NULL_TREE;
 
@@ -6401,7 +6545,7 @@ cp_parser_expression (cp_parser* parser, bool cast_p)
 
       /* Parse the next assignment-expression.  */
       assignment_expression
-       = cp_parser_assignment_expression (parser, cast_p);
+       = cp_parser_assignment_expression (parser, cast_p, pidk);
       /* If this is the first assignment-expression, we can just
         save it away.  */
       if (!expression)
@@ -6480,7 +6624,7 @@ cp_parser_constant_expression (cp_parser* parser,
      For example, cp_parser_initializer_clauses uses this function to
      determine whether a particular assignment-expression is in fact
      constant.  */
-  expression = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+  expression = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
   /* Restore the old settings.  */
   parser->integral_constant_expression_p
     = saved_integral_constant_expression_p;
@@ -6504,7 +6648,8 @@ cp_parser_constant_expression (cp_parser* parser,
    offsetof-member-designator:
      id-expression
      | offsetof-member-designator "." id-expression
-     | offsetof-member-designator "[" expression "]"  */
+     | offsetof-member-designator "[" expression "]"
+     | offsetof-member-designator "->" id-expression  */
 
 static tree
 cp_parser_builtin_offsetof (cp_parser *parser)
@@ -6547,11 +6692,16 @@ cp_parser_builtin_offsetof (cp_parser *parser)
          expr = cp_parser_postfix_open_square_expression (parser, expr, true);
          break;
 
+       case CPP_DEREF:
+         /* offsetof-member-designator "->" identifier */
+         expr = grok_array_decl (expr, integer_zero_node);
+         /* FALLTHRU */
+
        case CPP_DOT:
          /* offsetof-member-designator "." identifier */
          cp_lexer_consume_token (parser->lexer);
-         expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
-                                                        true, &dummy,
+         expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT,
+                                                        expr, true, &dummy,
                                                         token->location);
          break;
 
@@ -6957,7 +7107,7 @@ cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
   /* 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);
+    statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
 
   /* Consume the final `;'.  */
   cp_parser_consume_semicolon_at_end_of_statement (parser);
@@ -7120,7 +7270,18 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
            /* Parse the then-clause.  */
            in_statement = parser->in_statement;
            parser->in_statement |= IN_IF_STMT;
-           cp_parser_implicitly_scoped_statement (parser, &nested_if);
+           if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+             {
+               location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+               add_stmt (build_empty_stmt ());
+               cp_lexer_consume_token (parser->lexer);
+               if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
+                 warning_at (loc, OPT_Wempty_body, "suggest braces around "
+                             "empty body in an %<if%> statement");
+               nested_if = false;
+             }
+           else
+             cp_parser_implicitly_scoped_statement (parser, &nested_if);
            parser->in_statement = in_statement;
 
            finish_then_clause (statement);
@@ -7133,7 +7294,17 @@ cp_parser_selection_statement (cp_parser* parser, bool *if_p)
                cp_lexer_consume_token (parser->lexer);
                begin_else_clause (statement);
                /* Parse the else-clause.  */
-               cp_parser_implicitly_scoped_statement (parser, NULL);
+               if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+                 {
+                   warning_at (cp_lexer_peek_token (parser->lexer)->location,
+                               OPT_Wempty_body, "suggest braces around "
+                               "empty body in an %<else%> statement");
+                   add_stmt (build_empty_stmt ());
+                   cp_lexer_consume_token (parser->lexer);
+                 }
+               else
+                 cp_parser_implicitly_scoped_statement (parser, NULL);
+
                finish_else_clause (statement);
 
                /* If we are currently parsing a then-clause, then
@@ -7277,7 +7448,7 @@ cp_parser_condition (cp_parser* parser)
          else
            {
              /* Consume the `='.  */
-             cp_lexer_consume_token (parser->lexer);
+             cp_parser_require (parser, CPP_EQ, "%<=%>");
              initializer = cp_parser_initializer_clause (parser, &non_constant_p);
            }
          if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
@@ -7304,49 +7475,7 @@ cp_parser_condition (cp_parser* parser)
     cp_parser_abort_tentative_parse (parser);
 
   /* Otherwise, we are looking at an expression.  */
-  return cp_parser_expression (parser, /*cast_p=*/false);
-}
-
-/* We check for a ) immediately followed by ; with no whitespacing
-   between.  This is used to issue a warning for:
-
-     while (...);
-
-   and:
-
-     for (...);
-
-   as the semicolon is probably extraneous.
-
-   On parse errors, the next token might not be a ), so do nothing in
-   that case. */
-
-static void
-check_empty_body (cp_parser* parser, const char* type)
-{
-  cp_token *token;
-  cp_token *close_paren;
-  expanded_location close_loc;
-  expanded_location semi_loc;
-  
-  close_paren = cp_lexer_peek_token (parser->lexer);
-  if (close_paren->type != CPP_CLOSE_PAREN)
-    return;
-
-  close_loc = expand_location (close_paren->location);
-  token = cp_lexer_peek_nth_token (parser->lexer, 2);
-
-  if (token->type != CPP_SEMICOLON
-      || (token->flags & PREV_WHITE))
-    return;
-
-  semi_loc =  expand_location (token->location);
-  if (close_loc.line == semi_loc.line
-      && close_loc.column+1 == semi_loc.column)
-    warning (OPT_Wempty_body,
-            "suggest a space before %<;%> or explicit braces around empty "
-            "body in %<%s%> statement",
-            type);
+  return cp_parser_expression (parser, /*cast_p=*/false, NULL);
 }
 
 /* Parse an iteration-statement.
@@ -7391,7 +7520,6 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Parse the condition.  */
        condition = cp_parser_condition (parser);
        finish_while_stmt_cond (condition, statement);
-       check_empty_body (parser, "while");
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
        /* Parse the dependent statement.  */
@@ -7419,7 +7547,7 @@ cp_parser_iteration_statement (cp_parser* parser)
        /* Look for the `('.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
        /* Parse the expression.  */
-       expression = cp_parser_expression (parser, /*cast_p=*/false);
+       expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
        /* We're done with the do-statement.  */
        finish_do_stmt (expression, statement);
        /* Look for the `)'.  */
@@ -7451,9 +7579,8 @@ cp_parser_iteration_statement (cp_parser* 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);
+         expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
        finish_for_expr (expression, statement);
-       check_empty_body (parser, "for");
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
@@ -7593,7 +7720,7 @@ cp_parser_jump_statement (cp_parser* parser)
            expr = cp_parser_braced_list (parser, &expr_non_constant_p);
          }
        else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-         expr = cp_parser_expression (parser, /*cast_p=*/false);
+         expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
        else
          /* If the next token is a `;', then there is no
             expression.  */
@@ -7610,11 +7737,11 @@ cp_parser_jump_statement (cp_parser* parser)
       if (cp_lexer_next_token_is (parser->lexer, CPP_MULT))
        {
          /* Issue a warning about this use of a GNU extension.  */
-         pedwarn (OPT_pedantic, "%HISO C++ forbids computed gotos", &token->location);
+         pedwarn (token->location, OPT_pedantic, "ISO C++ forbids computed gotos");
          /* Consume the '*' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Parse the dependent expression.  */
-         finish_goto_stmt (cp_parser_expression (parser, /*cast_p=*/false));
+         finish_goto_stmt (cp_parser_expression (parser, /*cast_p=*/false, NULL));
        }
       else
        finish_goto_stmt (cp_parser_identifier (parser));
@@ -7717,6 +7844,10 @@ 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, "%<{%>");
+      /* 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, "%<}%>");
     }
@@ -7750,7 +7881,7 @@ cp_parser_declaration_seq_opt (cp_parser* parser)
             invalid.  Allow it unless we're being pedantic.  */
          cp_lexer_consume_token (parser->lexer);
          if (!in_system_header)
-           pedwarn (OPT_pedantic, "extra %<;%>");
+           pedwarn (input_location, OPT_pedantic, "extra %<;%>");
          continue;
        }
 
@@ -8059,7 +8190,8 @@ cp_parser_simple_declaration (cp_parser* parser,
      (After "int (" we might be looking at a functional cast.)  */
   if (decl_specifiers.any_specifiers_p
       && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)
-      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+      && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
+      && !cp_parser_error_occurred (parser))
     cp_parser_commit_to_tentative_parse (parser);
 
   /* Keep going until we hit the `;' at the end of the simple
@@ -8294,11 +8426,11 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
             GNU Extension:
               thread  */
        case RID_AUTO:
-          /* Consume the token.  */
-          cp_lexer_consume_token (parser->lexer);
-
           if (cxx_dialect == cxx98) 
             {
+             /* Consume the token.  */
+             cp_lexer_consume_token (parser->lexer);
+
               /* Complain about `auto' as a storage specifier, if
                  we're complaining about C++0x compatibility.  */
               warning 
@@ -8310,10 +8442,9 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
               cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
                                           token->location);
             }
-          else 
-            /* We do not yet support the use of `auto' as a
-               type-specifier.  */
-            error ("%HC++0x %<auto%> specifier not supported", &token->location);
+          else
+           /* C++0x auto type-specifier.  */
+           found_decl_spec = false;
           break;
 
        case RID_REGISTER:
@@ -8751,7 +8882,7 @@ cp_parser_decltype (cp_parser *parser)
       /* Parse a class member access.  */
       expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
                                            /*cast_p=*/false,
-                                           /*member_access_only_p=*/true);
+                                           /*member_access_only_p=*/true, NULL);
 
       if (expr 
           && expr != error_mark_node
@@ -8770,7 +8901,7 @@ cp_parser_decltype (cp_parser *parser)
       cp_parser_abort_tentative_parse (parser);
 
       /* Parse a full expression.  */
-      expr = cp_parser_expression (parser, /*cast_p=*/false);
+      expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
     }
 
   /* Go back to evaluating expressions.  */
@@ -8890,6 +9021,16 @@ cp_parser_conversion_type_id (cp_parser* parser)
                                    /*initialized=*/0, &attributes);
   if (attributes)
     cplus_decl_attributes (&type_specified, attributes, /*flags=*/0);
+
+  /* Don't give this error when parsing tentatively.  This happens to
+     work because we always parse this definitively once.  */
+  if (! cp_parser_uncommitted_to_tentative_parse_p (parser)
+      && type_uses_auto (type_specified))
+    {
+      error ("invalid use of %<auto%> in conversion operator");
+      return error_mark_node;
+    }
+
   return type_specified;
 }
 
@@ -9046,8 +9187,8 @@ cp_parser_mem_initializer (cp_parser* parser)
   /* Find out what is being initialized.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
     {
-      permerror ("%Hanachronistic old-style base class initializer",
-                 &token->location);
+      permerror (token->location,
+                "anachronistic old-style base class initializer");
       mem_initializer_id = NULL_TREE;
     }
   else
@@ -9980,17 +10121,17 @@ cp_parser_template_id (cp_parser *parser,
        }
       /* Otherwise, emit an error about the invalid digraph, but continue
         parsing because we got our argument list.  */
-      if (permerror ("%H%<<::%> cannot begin a template-argument list",
-                    &next_token->location))
+      if (permerror (next_token->location,
+                    "%<<::%> cannot begin a template-argument list"))
        {
          static bool hint = false;
-         inform ("%H%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
-             "between %<<%> and %<::%>",
-             &next_token->location);
+         inform (next_token->location,
+                 "%<<:%> is an alternate spelling for %<[%>."
+                 " Insert whitespace between %<<%> and %<::%>");
          if (!hint && !flag_permissive)
            {
-             inform ("%H(if you use %<-fpermissive%> G++ will accept your code)",
-                      &next_token->location);
+             inform (next_token->location, "(if you use %<-fpermissive%>"
+                     " G++ will accept your code)");
              hint = true;
            }
        }
@@ -10180,7 +10321,7 @@ cp_parser_template_name (cp_parser* parser,
          /* Explain what went wrong.  */
          error ("%Hnon-template %qD used as template",
                 &token->location, identifier);
-         inform ("use %<%T::template %D%> to indicate that it is a template",
+         inform (input_location, "use %<%T::template %D%> to indicate that it is a template",
                  parser->scope, identifier);
          /* If parsing tentatively, find the location of the "<" token.  */
          if (cp_parser_simulate_error (parser))
@@ -11039,14 +11180,8 @@ cp_parser_simple_type_specifier (cp_parser* parser,
       break;
       
     case RID_AUTO:
-      if (cxx_dialect != cxx98)
-        {
-          /* Consume the token.  */
-          cp_lexer_consume_token (parser->lexer);
-          /* We do not yet support the use of `auto' as a
-             type-specifier.  */
-          error ("%HC++0x %<auto%> specifier not supported", &token->location);
-        }
+      maybe_warn_cpp0x ("C++0x auto");
+      type = make_auto ();
       break;
 
     case RID_DECLTYPE:
@@ -11307,7 +11442,7 @@ cp_parser_nonclass_name (cp_parser* parser)
    elaborated-type-specifier:
      class-key :: [opt] nested-name-specifier [opt] identifier
      class-key :: [opt] nested-name-specifier [opt] template [opt] template-id
-     enum :: [opt] nested-name-specifier [opt] identifier
+     enum-key :: [opt] nested-name-specifier [opt] identifier
      typename :: [opt] nested-name-specifier identifier
      typename :: [opt] nested-name-specifier template [opt]
        template-id
@@ -11345,6 +11480,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).  */
+      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);
+        }
       /* Parse the attributes.  */
       attributes = cp_parser_attributes_opt (parser);
     }
@@ -11358,7 +11504,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
       tag_type = typename_type;
       /* The `typename' keyword is only allowed in templates.  */
       if (!processing_template_decl)
-       permerror ("using %<typename%> outside of template");
+       permerror (input_location, "using %<typename%> outside of template");
     }
   /* Otherwise it must be a class-key.  */
   else
@@ -11632,11 +11778,19 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
 /* Parse an enum-specifier.
 
    enum-specifier:
-     enum identifier [opt] { enumerator-list [opt] }
+     enum-key identifier [opt] enum-base [opt] { enumerator-list [opt] }
+
+   enum-key:
+     enum
+     enum class   [C++0x]
+     enum struct  [C++0x]
+
+   enum-base:   [C++0x]
+     : type-specifier-seq
 
    GNU Extensions:
-     enum attributes[opt] identifier [opt] { enumerator-list [opt] }
-       attributes[opt]
+     enum-key attributes[opt] identifier [opt] enum-base [opt] 
+       { enumerator-list [opt] }attributes[opt]
 
    Returns an ENUM_TYPE representing the enumeration, or NULL_TREE
    if the token stream isn't an enum-specifier after all.  */
@@ -11647,6 +11801,9 @@ cp_parser_enum_specifier (cp_parser* parser)
   tree identifier;
   tree type;
   tree attributes;
+  bool scoped_enum_p = false;
+  bool has_underlying_type = false;
+  tree underlying_type = NULL_TREE;
 
   /* Parse tentatively so that we can back up if we don't find a
      enum-specifier.  */
@@ -11658,6 +11815,20 @@ cp_parser_enum_specifier (cp_parser* parser)
      the enumeration being defined.  */
   cp_lexer_consume_token (parser->lexer);
 
+  /* Parse the "class" or "struct", which indicates a scoped
+     enumeration type in C++0x.  */
+  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' token.  */
+      cp_lexer_consume_token (parser->lexer);
+
+      scoped_enum_p = true;
+    }
+
   attributes = cp_parser_attributes_opt (parser);
 
   if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
@@ -11665,11 +11836,46 @@ cp_parser_enum_specifier (cp_parser* parser)
   else
     identifier = make_anon_name ();
 
+  /* Check for the `:' that denotes a specified underlying type in C++0x.  */
+  if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+    {
+      cp_decl_specifier_seq 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);
+
+      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)
+        {
+          underlying_type = grokdeclarator (NULL, &type_specifiers, TYPENAME,
+                                            /*initialized=*/0, NULL);
+          if (underlying_type == error_mark_node)
+            underlying_type = NULL_TREE;
+        }
+    }
+
   /* Look for the `{' but don't consume it yet.  */
   if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
-    cp_parser_simulate_error (parser);
+    {
+      cp_parser_error (parser, "expected %<{%>");
+      if (has_underlying_type)
+       return NULL_TREE;
+    }
 
-  if (!cp_parser_parse_definitely (parser))
+  if (!has_underlying_type && !cp_parser_parse_definitely (parser))
     return NULL_TREE;
 
   /* Issue an error message if type-definitions are forbidden here.  */
@@ -11679,7 +11885,7 @@ 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);
+    type = start_enum (identifier, underlying_type, scoped_enum_p);
   
   /* Consume the opening brace.  */
   cp_lexer_consume_token (parser->lexer);
@@ -11738,7 +11944,7 @@ cp_parser_enumerator_list (cp_parser* parser, tree type)
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
        {
          if (!in_system_header)
-           pedwarn (OPT_pedantic, "comma at end of enumerator list");
+           pedwarn (input_location, OPT_pedantic, "comma at end of enumerator list");
          break;
        }
     }
@@ -11818,7 +12024,7 @@ cp_parser_namespace_name (cp_parser* parser)
        During the lookup of a name preceding the :: scope resolution
        operator, object, function, and enumerator names are ignored.
 
-     (Note that cp_parser_class_or_namespace_name only calls this
+     (Note that cp_parser_qualifying_entity only calls this
      function if the token after the name is the scope resolution
      operator.)  */
   namespace_decl = cp_parser_lookup_name (parser, identifier,
@@ -12471,6 +12677,9 @@ cp_parser_init_declarator (cp_parser* parser,
        }
       else
        {
+         location_t func_brace_location
+           = cp_lexer_peek_token (parser->lexer)->location;
+
          /* Neither attributes nor an asm-specification are allowed
             on a function-definition.  */
          if (asm_specification)
@@ -12494,6 +12703,13 @@ cp_parser_init_declarator (cp_parser* parser,
              = (cp_parser_function_definition_from_specifiers_and_declarator
                 (parser, decl_specifiers, prefix_attributes, declarator));
 
+         if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl))
+           {
+             /* This is where the prologue starts...  */
+             DECL_STRUCT_FUNCTION (decl)->function_start_locus
+               = func_brace_location;
+           }
+
          return decl;
        }
     }
@@ -12518,7 +12734,7 @@ cp_parser_init_declarator (cp_parser* parser,
       || token->type == CPP_OPEN_PAREN
       || token->type == CPP_OPEN_BRACE)
     {
-      is_initialized = 1;
+      is_initialized = SD_INITIALIZED;
       initialization_kind = token->type;
 
       if (token->type == CPP_EQ
@@ -12526,9 +12742,9 @@ cp_parser_init_declarator (cp_parser* parser,
        {
          cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
          if (t2->keyword == RID_DEFAULT)
-           is_initialized = 2;
+           is_initialized = SD_DEFAULTED;
          else if (t2->keyword == RID_DELETE)
-           is_initialized = 3;
+           is_initialized = SD_DELETED;
        }
     }
   else
@@ -12541,7 +12757,7 @@ cp_parser_init_declarator (cp_parser* parser,
          cp_parser_error (parser, "expected initializer");
          return error_mark_node;
        }
-      is_initialized = 0;
+      is_initialized = SD_UNINITIALIZED;
       initialization_kind = CPP_EOF;
     }
 
@@ -12894,8 +13110,10 @@ cp_parser_direct_declarator (cp_parser* parser,
 
          if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
            {
-             cp_parameter_declarator *params;
+             tree params;
              unsigned saved_num_template_parameter_lists;
+             bool is_declarator = false;
+             tree t;
 
              /* In a member-declarator, the only valid interpretation
                 of a parenthesis is the start of a
@@ -12922,6 +13140,8 @@ cp_parser_direct_declarator (cp_parser* parser,
                = parser->num_template_parameter_lists;
              parser->num_template_parameter_lists = 0;
 
+             begin_scope (sk_function_parms, NULL_TREE);
+
              /* Parse the parameter-declaration-clause.  */
              params = cp_parser_parameter_declaration_clause (parser);
 
@@ -12934,6 +13154,9 @@ cp_parser_direct_declarator (cp_parser* parser,
                {
                  cp_cv_quals cv_quals;
                  tree exception_specification;
+                 tree late_return;
+
+                 is_declarator = true;
 
                  if (ctor_dtor_or_conv_p)
                    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
@@ -12947,19 +13170,29 @@ cp_parser_direct_declarator (cp_parser* parser,
                  exception_specification
                    = cp_parser_exception_specification_opt (parser);
 
+                 late_return
+                   = cp_parser_late_return_type_opt (parser);
+
                  /* Create the function-declarator.  */
                  declarator = make_call_declarator (declarator,
                                                     params,
                                                     cv_quals,
-                                                    exception_specification);
+                                                    exception_specification,
+                                                    late_return);
                  /* Any subsequent parameter lists are to do with
                     return type, so are not those of the declared
                     function.  */
                  parser->default_arg_ok_p = false;
-
-                 /* Repeat the main loop.  */
-                 continue;
                }
+
+             /* Remove the function parms from scope.  */
+             for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+               pop_binding (DECL_NAME (t), t);
+             leave_scope();
+
+             if (is_declarator)
+               /* Repeat the main loop.  */
+               continue;
            }
 
          /* If this is the first, we can try a parenthesized
@@ -13168,7 +13401,7 @@ cp_parser_direct_declarator (cp_parser* parser,
                        {
                          error ("%Hinvalid use of constructor as a template",
                                 &declarator_id_start_token->location);
-                         inform ("use %<%T::%D%> instead of %<%T::%D%> to "
+                         inform (input_location, "use %<%T::%D%> instead of %<%T::%D%> to "
                                  "name the constructor in a qualified name",
                                  class_type,
                                  DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
@@ -13429,6 +13662,30 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
   return cv_quals;
 }
 
+/* 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
+
+   Returns the type indicated by the type-id.  */
+
+static tree
+cp_parser_late_return_type_opt (cp_parser* parser)
+{
+  cp_token *token;
+
+  /* Peek at the next token.  */
+  token = cp_lexer_peek_token (parser->lexer);
+  /* A late-specified return type is indicated by an initial '->'. */
+  if (token->type != CPP_DEREF)
+    return NULL_TREE;
+
+  /* Consume the ->.  */
+  cp_lexer_consume_token (parser->lexer);
+
+  return cp_parser_type_id (parser);
+}
+
 /* Parse a declarator-id.
 
    declarator-id:
@@ -13501,6 +13758,13 @@ cp_parser_type_id (cp_parser* parser)
   if (!cp_parser_parse_definitely (parser))
     abstract_declarator = NULL;
 
+  if (type_specifier_seq.type
+      && type_uses_auto (type_specifier_seq.type))
+    {
+      error ("invalid use of %<auto%>");
+      return error_mark_node;
+    }
+  
   return groktypename (&type_specifier_seq, abstract_declarator);
 }
 
@@ -13607,10 +13871,10 @@ cp_parser_type_specifier_seq (cp_parser* parser,
    value of NULL indicates a parameter-declaration-clause consisting
    only of an ellipsis.  */
 
-static cp_parameter_declarator *
+static tree
 cp_parser_parameter_declaration_clause (cp_parser* parser)
 {
-  cp_parameter_declarator *parameters;
+  tree parameters;
   cp_token *token;
   bool ellipsis_p;
   bool is_error;
@@ -13622,7 +13886,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     {
       /* Consume the `...' token.  */
       cp_lexer_consume_token (parser->lexer);
-      return NULL;
+      return NULL_TREE;
     }
   else if (token->type == CPP_CLOSE_PAREN)
     /* There are no parameters.  */
@@ -13630,10 +13894,10 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
 #ifndef NO_IMPLICIT_EXTERN_C
       if (in_system_header && current_class_type == NULL
          && current_lang_name == lang_name_c)
-       return NULL;
+       return NULL_TREE;
       else
 #endif
-       return no_parameters;
+       return void_list_node;
     }
   /* Check for `(void)', too, which is a special case.  */
   else if (token->keyword == RID_VOID
@@ -13643,7 +13907,7 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
       /* Consume the `void' token.  */
       cp_lexer_consume_token (parser->lexer);
       /* There are no parameters.  */
-      return no_parameters;
+      return void_list_node;
     }
 
   /* Parse the parameter-declaration-list.  */
@@ -13678,8 +13942,8 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
     ellipsis_p = false;
 
   /* Finish the parameter list.  */
-  if (parameters && ellipsis_p)
-    parameters->ellipsis_p = true;
+  if (!ellipsis_p)
+    parameters = chainon (parameters, void_list_node);
 
   return parameters;
 }
@@ -13695,11 +13959,11 @@ cp_parser_parameter_declaration_clause (cp_parser* parser)
    `void_list_node' is never appended to the list.  Upon return,
    *IS_ERROR will be true iff an error occurred.  */
 
-static cp_parameter_declarator *
+static tree
 cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
 {
-  cp_parameter_declarator *parameters = NULL;
-  cp_parameter_declarator **tail = &parameters;
+  tree parameters = NULL_TREE;
+  tree *tail = &parameters; 
   bool saved_in_unbraced_linkage_specification_p;
 
   /* Assume all will go well.  */
@@ -13715,6 +13979,7 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
   while (true)
     {
       cp_parameter_declarator *parameter;
+      tree decl = error_mark_node;
       bool parenthesized_p;
       /* Parse the parameter.  */
       parameter
@@ -13722,17 +13987,38 @@ cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
                                           /*template_parm_p=*/false,
                                           &parenthesized_p);
 
+      /* We don't know yet if the enclosing context is deprecated, so wait
+        and warn in grokparms if appropriate.  */
+      deprecated_state = DEPRECATED_SUPPRESS;
+
+      if (parameter)
+       decl = grokdeclarator (parameter->declarator,
+                              &parameter->decl_specifiers,
+                              PARM,
+                              parameter->default_argument != NULL_TREE,
+                              &parameter->decl_specifiers.attributes);
+
+      deprecated_state = DEPRECATED_NORMAL;
+
       /* If a parse error occurred parsing the parameter declaration,
         then the entire parameter-declaration-list is erroneous.  */
-      if (!parameter)
+      if (decl == error_mark_node)
        {
          *is_error = true;
-         parameters = NULL;
+         parameters = error_mark_node;
          break;
        }
+
+      if (parameter->decl_specifiers.attributes)
+       cplus_decl_attributes (&decl,
+                              parameter->decl_specifiers.attributes,
+                              0);
+      if (DECL_NAME (decl))
+       decl = pushdecl (decl);
+
       /* Add the new parameter to the list.  */
-      *tail = parameter;
-      tail = &parameter->next;
+      *tail = build_tree_list (parameter->default_argument, decl);
+      tail = &TREE_CHAIN (*tail);
 
       /* Peek at the next token.  */
       if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
@@ -14163,7 +14449,7 @@ cp_parser_default_argument (cp_parser *parser, bool template_parm_p)
   if (template_parm_p)
     push_deferring_access_checks (dk_no_deferred);
   default_argument
-    = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+    = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
   if (template_parm_p)
     pop_deferring_access_checks ();
   /* Restore saved state.  */
@@ -14382,7 +14668,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
          && cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
        {
          /* Warn the user that they are using an extension.  */
-         pedwarn (OPT_pedantic, 
+         pedwarn (input_location, OPT_pedantic, 
                   "ISO C++ does not allow designated initializers");
          /* Consume the identifier.  */
          identifier = cp_lexer_consume_token (parser->lexer)->u.value;
@@ -14465,6 +14751,7 @@ cp_parser_class_name (cp_parser *parser,
   tree scope;
   bool typename_p;
   cp_token *token;
+  tree identifier = NULL_TREE;
 
   /* All class-names start with an identifier.  */
   token = cp_lexer_peek_token (parser->lexer);
@@ -14490,7 +14777,6 @@ cp_parser_class_name (cp_parser *parser,
       && !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
     {
       cp_token *identifier_token;
-      tree identifier;
       bool ambiguous_p;
 
       /* Look for the identifier.  */
@@ -14595,6 +14881,8 @@ cp_parser_class_name (cp_parser *parser,
 
   if (decl == error_mark_node)
     cp_parser_error (parser, "expected class-name");
+  else if (identifier && !parser->scope)
+    maybe_note_name_used_in_class (identifier, decl);
 
   return decl;
 }
@@ -14616,6 +14904,7 @@ cp_parser_class_specifier (cp_parser* parser)
   bool nested_name_specifier_p;
   unsigned saved_num_template_parameter_lists;
   bool saved_in_function_body;
+  bool saved_in_unbraced_linkage_specification_p;
   tree old_scope = NULL_TREE;
   tree scope = NULL_TREE;
   tree bases;
@@ -14667,6 +14956,10 @@ cp_parser_class_specifier (cp_parser* parser)
   /* We are not in a function body.  */
   saved_in_function_body = parser->in_function_body;
   parser->in_function_body = false;
+  /* We are not immediately inside an extern "lang" block.  */
+  saved_in_unbraced_linkage_specification_p
+    = parser->in_unbraced_linkage_specification_p;
+  parser->in_unbraced_linkage_specification_p = false;
 
   /* Start the class.  */
   if (nested_name_specifier_p)
@@ -14779,6 +15072,8 @@ cp_parser_class_specifier (cp_parser* parser)
   parser->in_function_body = saved_in_function_body;
   parser->num_template_parameter_lists
     = saved_num_template_parameter_lists;
+  parser->in_unbraced_linkage_specification_p
+    = saved_in_unbraced_linkage_specification_p;
 
   return type;
 }
@@ -15031,7 +15326,7 @@ cp_parser_class_head (cp_parser* parser,
         class member of a namespace outside of its namespace.  */
       if (scope == nested_name_specifier)
        {
-         permerror ("%Hextra qualification not allowed",
+         permerror (input_location, "%Hextra qualification not allowed",
                     &nested_name_specifier_token_start->location);
          nested_name_specifier = NULL_TREE;
          num_templates = 0;
@@ -15406,7 +15701,7 @@ cp_parser_member_declaration (cp_parser* parser)
        {
          cp_token *token = cp_lexer_peek_token (parser->lexer);
          if (!in_system_header_at (token->location))
-           pedwarn (OPT_pedantic, "%Hextra %<;%>", &token->location);
+           pedwarn (token->location, OPT_pedantic, "extra %<;%>");
        }
       else
        {
@@ -15636,6 +15931,8 @@ cp_parser_member_declaration (cp_parser* parser)
                  return;
                }
              else
+               if (declarator->kind == cdk_function)
+                 declarator->id_loc = token->location;
                /* Create the declaration.  */
                decl = grokfield (declarator, &decl_specifiers,
                                  initializer, /*init_const_expr_p=*/true,
@@ -15700,7 +15997,13 @@ cp_parser_pure_specifier (cp_parser* parser)
   if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
     return error_mark_node;
   /* Look for the `0' token.  */
-  token = cp_lexer_consume_token (parser->lexer);
+  token = cp_lexer_peek_token (parser->lexer);
+
+  if (token->type == CPP_EOF
+      || token->type == CPP_PRAGMA_EOL)
+    return error_mark_node;
+
+  cp_lexer_consume_token (parser->lexer);
 
   /* Accept = default or = delete in c++0x mode.  */
   if (token->keyword == RID_DEFAULT
@@ -16240,7 +16543,7 @@ cp_parser_throw_expression (cp_parser* parser)
     expression = NULL_TREE;
   else
     expression = cp_parser_assignment_expression (parser,
-                                                 /*cast_p=*/false);
+                                                 /*cast_p=*/false, NULL);
 
   return build_throw (expression);
 }
@@ -16332,7 +16635,7 @@ cp_parser_asm_operand_list (cp_parser* parser)
       /* Look for the `('.  */
       cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
       /* Parse the expression.  */
-      expression = cp_parser_expression (parser, /*cast_p=*/false);
+      expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
       /* Look for the `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
@@ -17603,7 +17906,7 @@ static tree
 cp_parser_simple_cast_expression (cp_parser *parser)
 {
   return cp_parser_cast_expression (parser, /*address_p=*/false,
-                                   /*cast_p=*/false);
+                                   /*cast_p=*/false, NULL);
 }
 
 /* Parse a functional cast to TYPE.  Returns an expression
@@ -17969,7 +18272,7 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
       /* Parse the assignment-expression.  */
-      parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+      parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
 
       if (!processing_template_decl)
        parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg);
@@ -18090,7 +18393,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
      looking at the unary-expression production.  */
   if (!expr)
     expr = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                      /*cast_p=*/false);
+                                      /*cast_p=*/false, NULL);
 
   if (pack_expansion_p)
     /* Build a pack expansion. */
@@ -18469,7 +18772,7 @@ static void
 cp_parser_check_class_key (enum tag_types class_key, tree type)
 {
   if ((TREE_CODE (type) == UNION_TYPE) != (class_key == union_type))
-    permerror ("%qs tag used in naming %q#T",
+    permerror (input_location, "%qs tag used in naming %q#T",
            class_key == union_type ? "union"
             : class_key == record_type ? "struct" : "class",
             type);
@@ -18818,7 +19121,7 @@ cp_parser_objc_message_receiver (cp_parser* parser)
   /* An Objective-C message receiver may be either (1) a type
      or (2) an expression.  */
   cp_parser_parse_tentatively (parser);
-  rcv = cp_parser_expression (parser, false);
+  rcv = cp_parser_expression (parser, false, NULL);
 
   if (cp_parser_parse_definitely (parser))
     return rcv;
@@ -18870,7 +19173,7 @@ cp_parser_objc_message_args (cp_parser* parser)
 
       maybe_unary_selector_p = false;
       cp_parser_require (parser, CPP_COLON, "%<:%>");
-      arg = cp_parser_assignment_expression (parser, false);
+      arg = cp_parser_assignment_expression (parser, false, NULL);
 
       sel_args
        = chainon (sel_args,
@@ -18885,7 +19188,7 @@ cp_parser_objc_message_args (cp_parser* parser)
       tree arg;
 
       cp_lexer_consume_token (parser->lexer);
-      arg = cp_parser_assignment_expression (parser, false);
+      arg = cp_parser_assignment_expression (parser, false, NULL);
 
       addl_args
        = chainon (addl_args,
@@ -19785,7 +20088,7 @@ cp_parser_objc_synchronized_statement (cp_parser *parser) {
 
   location = cp_lexer_peek_token (parser->lexer)->location;
   cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
-  lock = cp_parser_expression (parser, false);
+  lock = cp_parser_expression (parser, false, NULL);
   cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
 
   /* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
@@ -19810,7 +20113,7 @@ cp_parser_objc_throw_statement (cp_parser *parser) {
   cp_parser_require_keyword (parser, RID_AT_THROW, "%<@throw%>");
 
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-    expr = cp_parser_assignment_expression (parser, false);
+    expr = cp_parser_assignment_expression (parser, false, NULL);
 
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
@@ -19918,7 +20221,7 @@ cp_parser_omp_clause_name (cp_parser *parser)
 /* Validate that a clause of the given type does not already exist.  */
 
 static void
-check_no_duplicate_clause (tree clauses, enum tree_code code,
+check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
                           const char *name, location_t location)
 {
   tree c;
@@ -20167,7 +20470,7 @@ cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
   if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
     return list;
 
-  t = cp_parser_expression (parser, false);
+  t = cp_parser_expression (parser, false, NULL);
 
   if (t == error_mark_node
       || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
@@ -20324,7 +20627,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location
       cp_lexer_consume_token (parser->lexer);
 
       token = cp_lexer_peek_token (parser->lexer);
-      t = cp_parser_assignment_expression (parser, false);
+      t = cp_parser_assignment_expression (parser, false, NULL);
 
       if (t == error_mark_node)
        goto resync_fail;
@@ -20553,7 +20856,7 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
   cp_parser_require_pragma_eol (parser, pragma_tok);
 
   lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
-                                   /*cast_p=*/false);
+                                   /*cast_p=*/false, NULL);
   switch (TREE_CODE (lhs))
     {
     case ERROR_MARK:
@@ -20610,7 +20913,7 @@ cp_parser_omp_atomic (cp_parser *parser, cp_token *pragma_tok)
        }
       cp_lexer_consume_token (parser->lexer);
 
-      rhs = cp_parser_expression (parser, false);
+      rhs = cp_parser_expression (parser, false, NULL);
       if (rhs == error_mark_node)
        goto saw_error;
       break;
@@ -20684,7 +20987,7 @@ cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
 static tree
 cp_parser_omp_for_cond (cp_parser *parser, tree decl)
 {
-  tree lhs = cp_parser_cast_expression (parser, false, false), rhs;
+  tree lhs = cp_parser_cast_expression (parser, false, false, NULL), rhs;
   enum tree_code op;
   cp_token *token;
 
@@ -20710,7 +21013,7 @@ cp_parser_omp_for_cond (cp_parser *parser, tree decl)
 
   cp_lexer_consume_token (parser->lexer);
   rhs = cp_parser_binary_expression (parser, false,
-                                    PREC_RELATIONAL_EXPRESSION);
+                                    PREC_RELATIONAL_EXPRESSION, NULL);
   if (rhs == error_mark_node
       || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
     {
@@ -20737,7 +21040,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
       op = (token->type == CPP_PLUS_PLUS
            ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
       cp_lexer_consume_token (parser->lexer);
-      lhs = cp_parser_cast_expression (parser, false, false);
+      lhs = cp_parser_cast_expression (parser, false, false, NULL);
       if (lhs != decl)
        return error_mark_node;
       return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
@@ -20762,13 +21065,13 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 
   if (op != NOP_EXPR)
     {
-      rhs = cp_parser_assignment_expression (parser, false);
+      rhs = cp_parser_assignment_expression (parser, false, NULL);
       rhs = build2 (op, TREE_TYPE (decl), decl, rhs);
       return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
     }
 
   lhs = cp_parser_binary_expression (parser, false,
-                                    PREC_ADDITIVE_EXPRESSION);
+                                    PREC_ADDITIVE_EXPRESSION, NULL);
   token = cp_lexer_peek_token (parser->lexer);
   decl_first = lhs == decl;
   if (decl_first)
@@ -20782,7 +21085,7 @@ cp_parser_omp_for_incr (cp_parser *parser, tree decl)
       op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
       cp_lexer_consume_token (parser->lexer);
       rhs = cp_parser_binary_expression (parser, false,
-                                        PREC_ADDITIVE_EXPRESSION);
+                                        PREC_ADDITIVE_EXPRESSION, NULL);
       token = cp_lexer_peek_token (parser->lexer);
       if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
        {
@@ -20857,6 +21160,14 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
       this_pre_body = push_stmt_list ();
       if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
        {
+         /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
+
+            init-expr:
+                      var = lb
+                      integer-type var = lb
+                      random-access-iterator-type var = lb
+                      pointer-type var = lb
+         */
          cp_decl_specifier_seq type_specifiers;
 
          /* First, try to parse as an initialized declaration.  See
@@ -20865,8 +21176,10 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
          cp_parser_parse_tentatively (parser);
          cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
                                        &type_specifiers);
-         if (!cp_parser_error_occurred (parser))
+         if (cp_parser_parse_definitely (parser))
            {
+             /* If parsing a type specifier seq succeeded, then this
+                MUST be a initialized declaration.  */
              tree asm_specification, attributes;
              cp_declarator *declarator;
 
@@ -20878,19 +21191,35 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
              attributes = cp_parser_attributes_opt (parser);
              asm_specification = cp_parser_asm_specification_opt (parser);
 
-             if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
-               cp_parser_require (parser, CPP_EQ, "%<=%>");
-             if (cp_parser_parse_definitely (parser))
+             if (declarator == cp_error_declarator) 
+               cp_parser_skip_to_end_of_statement (parser);
+
+             else 
                {
-                 tree pushed_scope;
+                 tree pushed_scope, auto_node;
 
                  decl = start_decl (declarator, &type_specifiers,
-                                    /*initialized_p=*/false, attributes,
+                                    SD_INITIALIZED, attributes,
                                     /*prefix_attributes=*/NULL_TREE,
                                     &pushed_scope);
 
-                 if (CLASS_TYPE_P (TREE_TYPE (decl))
-                     || type_dependent_expression_p (decl))
+                 auto_node = type_uses_auto (TREE_TYPE (decl));
+                 if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
+                   {
+                     if (cp_lexer_next_token_is (parser->lexer, 
+                                                 CPP_OPEN_PAREN))
+                       error ("parenthesized initialization is not allowed in "
+                              "OpenMP %<for%> loop");
+                     else
+                       /* Trigger an error.  */
+                       cp_parser_require (parser, CPP_EQ, "%<=%>");
+
+                     init = error_mark_node;
+                     cp_parser_skip_to_end_of_statement (parser);
+                   }
+                 else if (CLASS_TYPE_P (TREE_TYPE (decl))
+                          || type_dependent_expression_p (decl)
+                          || auto_node)
                    {
                      bool is_direct_init, is_non_constant_init;
 
@@ -20898,6 +21227,17 @@ 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))
+                       {
+                         TREE_TYPE (decl)
+                           = do_auto_deduction (TREE_TYPE (decl), init,
+                                                auto_node);
+
+                         if (!CLASS_TYPE_P (TREE_TYPE (decl))
+                             && !type_dependent_expression_p (decl))
+                           goto non_class;
+                       }
+                     
                      cp_finish_decl (decl, init, !is_non_constant_init,
                                      asm_specification,
                                      LOOKUP_ONLYCONVERTING);
@@ -20913,9 +21253,11 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                    }
                  else
                    {
-                     cp_parser_require (parser, CPP_EQ, "%<=%>");
-                     init = cp_parser_assignment_expression (parser, false);
+                     /* Consume '='.  */
+                     cp_lexer_consume_token (parser->lexer);
+                     init = cp_parser_assignment_expression (parser, false, NULL);
 
+                   non_class:
                      if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
                        init = error_mark_node;
                      else
@@ -20929,14 +21271,11 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                    pop_scope (pushed_scope);
                }
            }
-         else
-           cp_parser_abort_tentative_parse (parser);
-
-         /* If parsing as an initialized declaration failed, try again as
-            a simple expression.  */
-         if (decl == NULL)
+         else 
            {
              cp_id_kind idk;
+             /* If parsing a type specifier sequence failed, then
+                this MUST be a simple expression.  */
              cp_parser_parse_tentatively (parser);
              decl = cp_parser_primary_expression (parser, false, false,
                                                   false, &idk);
@@ -20949,7 +21288,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
 
                  cp_parser_parse_definitely (parser);
                  cp_parser_require (parser, CPP_EQ, "%<=%>");
-                 rhs = cp_parser_assignment_expression (parser, false);
+                 rhs = cp_parser_assignment_expression (parser, false, NULL);
                  finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR,
                                                         rhs,
                                                         tf_warning_or_error));
@@ -20959,7 +21298,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                {
                  decl = NULL;
                  cp_parser_abort_tentative_parse (parser);
-                 init = cp_parser_expression (parser, false);
+                 init = cp_parser_expression (parser, false, NULL);
                  if (init)
                    {
                      if (TREE_CODE (init) == MODIFY_EXPR
@@ -21076,7 +21415,7 @@ cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
                  || CLASS_TYPE_P (TREE_TYPE (decl))))
            incr = cp_parser_omp_for_incr (parser, decl);
          else
-           incr = cp_parser_expression (parser, false);
+           incr = cp_parser_expression (parser, false, NULL);
        }
 
       if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))