OSDN Git Service

* parser.c (cp_parser_direct_declarator): Always complain about
[pf3gnuchains/gcc-fork.git] / gcc / cp / parser.c
index 86a96fb..b52ba95 100644 (file)
@@ -238,16 +238,19 @@ cp_lexer_new_main (void)
   size_t space;
   cp_token *buffer;
 
+  /* It's possible that lexing the first token will load a PCH file,
+     which is a GC collection point.  So we have to grab the first
+     token before allocating any memory.  Pragmas must not be deferred
+     as -fpch-preprocess can generate a pragma to load the PCH file in
+     the preprocessed output used by -save-temps.  */
+  cp_lexer_get_preprocessor_token (NULL, &first_token);
+
   /* Tell cpplib we want CPP_PRAGMA tokens.  */
   cpp_get_options (parse_in)->defer_pragmas = true;
 
   /* Tell c_lex not to merge string constants.  */
   c_lex_return_raw_strings = true;
 
-  /* It's possible that lexing the first token will load a PCH file,
-     which is a GC collection point.  So we have to grab the first
-     token before allocating any memory.  */
-  cp_lexer_get_preprocessor_token (NULL, &first_token);
   c_common_no_more_pch ();
 
   /* Allocate the memory.  */
@@ -703,7 +706,7 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
 static void
 cp_lexer_start_debugging (cp_lexer* lexer)
 {
-  ++lexer->debugging_p;
+  lexer->debugging_p = true;
 }
 
 /* Stop emitting debugging information.  */
@@ -711,7 +714,7 @@ cp_lexer_start_debugging (cp_lexer* lexer)
 static void
 cp_lexer_stop_debugging (cp_lexer* lexer)
 {
-  --lexer->debugging_p;
+  lexer->debugging_p = false;
 }
 
 #endif /* ENABLE_CHECKING */
@@ -1354,7 +1357,7 @@ static bool cp_parser_translation_unit
 /* Expressions [gram.expr]  */
 
 static tree cp_parser_primary_expression
-  (cp_parser *, cp_id_kind *, tree *);
+  (cp_parser *, bool, cp_id_kind *, tree *);
 static tree cp_parser_id_expression
   (cp_parser *, bool, bool, bool *, bool);
 static tree cp_parser_unqualified_id
@@ -1366,17 +1369,17 @@ static tree cp_parser_nested_name_specifier
 static tree cp_parser_class_or_namespace_name
   (cp_parser *, bool, bool, bool, bool, bool);
 static tree cp_parser_postfix_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, bool);
 static tree cp_parser_postfix_open_square_expression
   (cp_parser *, tree, bool);
 static tree cp_parser_postfix_dot_deref_expression
   (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *);
 static tree cp_parser_parenthesized_expression_list
-  (cp_parser *, bool, bool *);
+  (cp_parser *, bool, bool, bool *);
 static void cp_parser_pseudo_destructor_name
   (cp_parser *, tree *, tree *);
 static tree cp_parser_unary_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, bool);
 static enum tree_code cp_parser_unary_operator
   (cp_token *);
 static tree cp_parser_new_expression
@@ -1394,17 +1397,17 @@ static tree cp_parser_new_initializer
 static tree cp_parser_delete_expression
   (cp_parser *);
 static tree cp_parser_cast_expression
-  (cp_parser *, bool);
+  (cp_parser *, bool, bool);
 static tree cp_parser_binary_expression
-  (cp_parser *);
+  (cp_parser *, bool);
 static tree cp_parser_question_colon_clause
   (cp_parser *, tree);
 static tree cp_parser_assignment_expression
-  (cp_parser *);
+  (cp_parser *, bool);
 static enum tree_code cp_parser_assignment_operator_opt
   (cp_parser *);
 static tree cp_parser_expression
-  (cp_parser *);
+  (cp_parser *, bool);
 static tree cp_parser_constant_expression
   (cp_parser *, bool, bool *);
 static tree cp_parser_builtin_offsetof
@@ -1942,12 +1945,14 @@ cp_parser_check_for_invalid_template_id (cp_parser* parser,
 
 /* If parsing an integral constant-expression, issue an error message
    about the fact that THING appeared and return true.  Otherwise,
-   return false, marking the current expression as non-constant.  */
+   return false.  In either case, set
+   PARSER->NON_INTEGRAL_CONSTANT_EXPRESSION_P.  */ 
 
 static bool
 cp_parser_non_integral_constant_expression (cp_parser  *parser,
                                            const char *thing)
 {
+  parser->non_integral_constant_expression_p = true;
   if (parser->integral_constant_expression_p)
     {
       if (!parser->allow_non_integral_constant_expression_p)
@@ -1955,13 +1960,15 @@ cp_parser_non_integral_constant_expression (cp_parser  *parser,
          error ("%s cannot appear in a constant-expression", thing);
          return true;
        }
-      parser->non_integral_constant_expression_p = true;
     }
   return false;
 }
 
 /* Emit a diagnostic for an invalid type name.  SCOPE is the
-   qualifying scope (or NULL, if none) for ID.  */
+   qualifying scope (or NULL, if none) for ID.  This function commits
+   to the current active tentative parse, if any.  (Otherwise, the
+   problematic construct might be encountered again later, resulting
+   in duplicate error messages.)  */
 
 static void
 cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
@@ -2033,6 +2040,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
       else
        gcc_unreachable ();
     }
+  cp_parser_commit_to_tentative_parse (parser);
 }
 
 /* Check for a common situation where a type-name should be present,
@@ -2632,6 +2640,8 @@ cp_parser_translation_unit (cp_parser* parser)
    literal:
      __null
 
+   CAST_P is true if this primary expression is the target of a cast.
+
    Returns a representation of the expression.
 
    *IDK indicates what kind of id-expression (if any) was present.
@@ -2643,6 +2653,7 @@ cp_parser_translation_unit (cp_parser* parser)
 
 static tree
 cp_parser_primary_expression (cp_parser *parser,
+                             bool cast_p,
                              cp_id_kind *idk,
                              tree *qualifying_class)
 {
@@ -2667,6 +2678,43 @@ cp_parser_primary_expression (cp_parser *parser,
     case CPP_WCHAR:
     case CPP_NUMBER:
       token = cp_lexer_consume_token (parser->lexer);
+      /* Floating-point literals are only allowed in an integral
+        constant expression if they are cast to an integral or
+        enumeration type.  */
+      if (TREE_CODE (token->value) == REAL_CST
+         && parser->integral_constant_expression_p
+         && pedantic)
+       {
+         /* CAST_P will be set even in invalid code like "int(2.7 +
+            ...)".   Therefore, we have to check that the next token
+            is sure to end the cast.  */
+         if (cast_p)
+           {
+             cp_token *next_token;
+
+             next_token = cp_lexer_peek_token (parser->lexer);
+             if (/* The comma at the end of an
+                    enumerator-definition.  */
+                 next_token->type != CPP_COMMA
+                 /* The curly brace at the end of an enum-specifier.  */
+                 && next_token->type != CPP_CLOSE_BRACE
+                 /* The end of a statement.  */
+                 && next_token->type != CPP_SEMICOLON
+                 /* The end of the cast-expression.  */
+                 && next_token->type != CPP_CLOSE_PAREN
+                 /* The end of an array bound.  */
+                 && next_token->type != CPP_CLOSE_SQUARE)
+               cast_p = false;
+           }
+
+         /* If we are within a cast, then the constraint that the
+            cast is to an integral or enumeration type will be
+            checked at that point.  If we are not within a cast, then
+            this code is invalid.  */
+         if (!cast_p)
+           cp_parser_non_integral_constant_expression 
+             (parser, "floating-point literal");
+       }
       return token->value;
 
     case CPP_STRING:
@@ -2717,7 +2765,7 @@ cp_parser_primary_expression (cp_parser *parser,
        else
          {
            /* Parse the parenthesized expression.  */
-           expr = cp_parser_expression (parser);
+           expr = cp_parser_expression (parser, cast_p);
            /* 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
@@ -2796,7 +2844,8 @@ cp_parser_primary_expression (cp_parser *parser,
            /* Look for the opening `('.  */
            cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
            /* Now, parse the assignment-expression.  */
-           expression = cp_parser_assignment_expression (parser);
+           expression = cp_parser_assignment_expression (parser,
+                                                         /*cast_p=*/false);
            /* Look for the `,'.  */
            cp_parser_require (parser, CPP_COMMA, "`,'");
            /* Parse the type-id.  */
@@ -3124,6 +3173,7 @@ cp_parser_unqualified_id (cp_parser* parser,
        tree qualifying_scope;
        tree object_scope;
        tree scope;
+       bool done;
 
        /* Consume the `~' token.  */
        cp_lexer_consume_token (parser->lexer);
@@ -3180,6 +3230,8 @@ cp_parser_unqualified_id (cp_parser* parser,
 
        /* If there was an explicit qualification (S::~T), first look
           in the scope given by the qualification (i.e., S).  */
+       done = false;
+       type_decl = NULL_TREE;
        if (scope)
          {
            cp_parser_parse_tentatively (parser);
@@ -3191,10 +3243,10 @@ cp_parser_unqualified_id (cp_parser* parser,
                                              /*class_head_p=*/false,
                                              declarator_p);
            if (cp_parser_parse_definitely (parser))
-             return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+             done = true;
          }
        /* In "N::S::~S", look in "N" as well.  */
-       if (scope && qualifying_scope)
+       if (!done && scope && qualifying_scope)
          {
            cp_parser_parse_tentatively (parser);
            parser->scope = qualifying_scope;
@@ -3209,10 +3261,10 @@ cp_parser_unqualified_id (cp_parser* parser,
                                      /*class_head_p=*/false,
                                      declarator_p);
            if (cp_parser_parse_definitely (parser))
-             return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+             done = true;
          }
        /* In "p->S::~T", look in the scope given by "*p" as well.  */
-       else if (object_scope)
+       else if (!done && object_scope)
          {
            cp_parser_parse_tentatively (parser);
            parser->scope = object_scope;
@@ -3227,20 +3279,23 @@ cp_parser_unqualified_id (cp_parser* parser,
                                      /*class_head_p=*/false,
                                      declarator_p);
            if (cp_parser_parse_definitely (parser))
-             return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+             done = true;
          }
        /* Look in the surrounding context.  */
-       parser->scope = NULL_TREE;
-       parser->object_scope = NULL_TREE;
-       parser->qualifying_scope = NULL_TREE;
-       type_decl
-         = cp_parser_class_name (parser,
-                                 /*typename_keyword_p=*/false,
-                                 /*template_keyword_p=*/false,
-                                 none_type,
-                                 /*check_dependency=*/false,
-                                 /*class_head_p=*/false,
-                                 declarator_p);
+       if (!done)
+         {
+           parser->scope = NULL_TREE;
+           parser->object_scope = NULL_TREE;
+           parser->qualifying_scope = NULL_TREE;
+           type_decl
+             = cp_parser_class_name (parser,
+                                     /*typename_keyword_p=*/false,
+                                     /*template_keyword_p=*/false,
+                                     none_type,
+                                     /*check_dependency=*/false,
+                                     /*class_head_p=*/false,
+                                     declarator_p);
+         }
        /* If an error occurred, assume that the name of the
           destructor is the same as the name of the qualifying
           class.  That allows us to keep parsing after running
@@ -3659,12 +3714,13 @@ cp_parser_class_or_namespace_name (cp_parser *parser,
    but they are essentially the same concept.)
 
    If ADDRESS_P is true, the postfix expression is the operand of the
-   `&' operator.
+   `&' operator.  CAST_P is true if this expression is the target of a
+   cast. 
 
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_postfix_expression (cp_parser *parser, bool address_p)
+cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
 {
   cp_token *token;
   enum rid keyword;
@@ -3711,7 +3767,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
 
        /* And the expression which is being cast.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
-       expression = cp_parser_expression (parser);
+       expression = cp_parser_expression (parser, /*cast_p=*/true);
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
        /* Only type conversions to integral or enumeration types
@@ -3784,7 +3840,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
            tree expression;
 
            /* Look for an expression.  */
-           expression = cp_parser_expression (parser);
+           expression = cp_parser_expression (parser, /*cast_p=*/false);
            /* Compute its typeid.  */
            postfix_expression = build_typeid (expression);
            /* Look for the `)' token.  */
@@ -3916,6 +3972,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
 
        /* It must be a primary-expression.  */
        postfix_expression = cp_parser_primary_expression (parser,
+                                                          cast_p,
                                                           &idk,
                                                           &qualifying_class);
       }
@@ -3974,7 +4031,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
          {
            bool koenig_p;
            tree args = (cp_parser_parenthesized_expression_list
-                        (parser, false, /*non_constant_p=*/NULL));
+                        (parser, false, 
+                         /*cast_p=*/false,
+                         /*non_constant_p=*/NULL));
 
            if (args == error_mark_node)
              {
@@ -3984,8 +4043,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
 
            /* Function calls are not permitted in
               constant-expressions.  */
-           if (cp_parser_non_integral_constant_expression (parser,
-                                                           "a function call"))
+           if (! builtin_valid_in_constant_expr_p (postfix_expression)
+               && cp_parser_non_integral_constant_expression (parser,
+                                                              "a function call"))
              {
                postfix_expression = error_mark_node;
                break;
@@ -4167,7 +4227,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);
+    index = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* Look for the closing `]'.  */
   cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
@@ -4347,6 +4407,8 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
      identifier
      identifier, expression-list
 
+   CAST_P is true if this expression is the target of a cast.
+
    Returns a TREE_LIST.  The TREE_VALUE of each node is a
    representation of an assignment-expression.  Note that a TREE_LIST
    is returned even if there is only a single expression in the list.
@@ -4360,6 +4422,7 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
 static tree
 cp_parser_parenthesized_expression_list (cp_parser* parser,
                                         bool is_attribute_list,
+                                        bool cast_p,
                                         bool *non_constant_p)
 {
   tree expression_list = NULL_TREE;
@@ -4404,7 +4467,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
                  *non_constant_p = true;
              }
            else
-             expr = cp_parser_assignment_expression (parser);
+             expr = cp_parser_assignment_expression (parser, cast_p);
 
            if (fold_expr_p)
              expr = fold_non_dependent_expr (expr);
@@ -4562,12 +4625,13 @@ cp_parser_pseudo_destructor_name (cp_parser* parser,
      && identifier
 
    ADDRESS_P is true iff the unary-expression is appearing as the
-   operand of the `&' operator.
+   operand of the `&' operator.   CAST_P is true if this expression is
+   the target of a cast.
 
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_unary_expression (cp_parser *parser, bool address_p)
+cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
 {
   cp_token *token;
   enum tree_code unary_operator;
@@ -4695,7 +4759,9 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
       token = cp_lexer_consume_token (parser->lexer);
       /* Parse the cast-expression.  */
       cast_expression
-       = cp_parser_cast_expression (parser, unary_operator == ADDR_EXPR);
+       = cp_parser_cast_expression (parser, 
+                                    unary_operator == ADDR_EXPR,
+                                    /*cast_p=*/false);
       /* Now, build an appropriate representation.  */
       switch (unary_operator)
        {
@@ -4734,7 +4800,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
       return expression;
     }
 
-  return cp_parser_postfix_expression (parser, address_p);
+  return cp_parser_postfix_expression (parser, address_p, cast_p);
 }
 
 /* Returns ERROR_MARK if TOKEN is not a unary-operator.  If TOKEN is a
@@ -4855,7 +4921,8 @@ cp_parser_new_placement (cp_parser* parser)
 
   /* Parse the expression-list.  */
   expression_list = (cp_parser_parenthesized_expression_list
-                    (parser, false, /*non_constant_p=*/NULL));
+                    (parser, false, /*cast_p=*/false,
+                     /*non_constant_p=*/NULL));
 
   return expression_list;
 }
@@ -5002,7 +5069,7 @@ cp_parser_direct_new_declarator (cp_parser* parser)
       /* The first expression is not required to be constant.  */
       if (!declarator)
        {
-         expression = cp_parser_expression (parser);
+         expression = cp_parser_expression (parser, /*cast_p=*/false);
          /* 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
@@ -5058,7 +5125,8 @@ cp_parser_new_initializer (cp_parser* parser)
   tree expression_list;
 
   expression_list = (cp_parser_parenthesized_expression_list
-                    (parser, false, /*non_constant_p=*/NULL));
+                    (parser, false, /*cast_p=*/false,
+                     /*non_constant_p=*/NULL));
   if (!expression_list)
     expression_list = void_zero_node;
 
@@ -5117,10 +5185,14 @@ cp_parser_delete_expression (cp_parser* parser)
      unary-expression
      ( type-id ) cast-expression
 
+   ADDRESS_P is true iff the unary-expression is appearing as the
+   operand of the `&' operator.   CAST_P is true if this expression is
+   the target of a cast.
+
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_cast_expression (cp_parser *parser, bool address_p)
+cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
 {
   /* If it's a `(', then we might be looking at a cast.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
@@ -5190,7 +5262,9 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
          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_simple_cast_expression (parser);
+       expr = cp_parser_cast_expression (parser, 
+                                         /*address_p=*/false,
+                                         /*cast_p=*/true);
 
       if (cp_parser_parse_definitely (parser))
        {
@@ -5220,7 +5294,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
 
   /* 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);
+  return cp_parser_unary_expression (parser, address_p, cast_p);
 }
 
 /* Parse a binary expression of the general form:
@@ -5290,6 +5364,8 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
      simple-cast-expression
      binary-expression <token> binary-expression
 
+   CAST_P is true if this expression is the target of a cast.
+
    The binops_by_token map is used to get the tree codes for each <token> type.
    binary-expressions are associated according to a precedence table.  */
 
@@ -5299,7 +5375,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
    : binops_by_token[token->type].prec)
 
 static tree
-cp_parser_binary_expression (cp_parser* parser)
+cp_parser_binary_expression (cp_parser* parser, bool cast_p)
 {
   cp_parser_expression_stack stack;
   cp_parser_expression_stack_entry *sp = &stack[0];
@@ -5310,7 +5386,7 @@ cp_parser_binary_expression (cp_parser* parser)
   bool overloaded_p;
 
   /* Parse the first expression.  */
-  lhs = cp_parser_simple_cast_expression (parser);
+  lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p);
 
   for (;;)
     {
@@ -5424,12 +5500,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);
+    expr = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* The next token should be a `:'.  */
   cp_parser_require (parser, CPP_COLON, "`:'");
   /* Parse the assignment-expression.  */
-  assignment_expr = cp_parser_assignment_expression (parser);
+  assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false);
 
   /* Build the conditional-expression.  */
   return build_x_conditional_expr (logical_or_expr,
@@ -5444,10 +5520,12 @@ cp_parser_question_colon_clause (cp_parser* parser, tree logical_or_expr)
      logical-or-expression assignment-operator assignment_expression
      throw-expression
 
+   CAST_P is true if this expression is the target of a cast.
+
    Returns a representation for the expression.  */
 
 static tree
-cp_parser_assignment_expression (cp_parser* parser)
+cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
 {
   tree expr;
 
@@ -5460,7 +5538,7 @@ cp_parser_assignment_expression (cp_parser* parser)
   else
     {
       /* Parse the binary expressions (logical-or-expression).  */
-      expr = cp_parser_binary_expression (parser);
+      expr = cp_parser_binary_expression (parser, cast_p);
       /* 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))
@@ -5478,7 +5556,7 @@ cp_parser_assignment_expression (cp_parser* parser)
              tree rhs;
 
              /* Parse the right-hand side of the assignment.  */
-             rhs = cp_parser_assignment_expression (parser);
+             rhs = cp_parser_assignment_expression (parser, cast_p);
              /* An assignment may not appear in a
                 constant-expression.  */
              if (cp_parser_non_integral_constant_expression (parser,
@@ -5593,10 +5671,12 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
      assignment-expression
      expression , assignment-expression
 
+   CAST_P is true if this expression is the target of a cast.
+
    Returns a representation of the expression.  */
 
 static tree
-cp_parser_expression (cp_parser* parser)
+cp_parser_expression (cp_parser* parser, bool cast_p)
 {
   tree expression = NULL_TREE;
 
@@ -5606,7 +5686,7 @@ cp_parser_expression (cp_parser* parser)
 
       /* Parse the next assignment-expression.  */
       assignment_expression
-       = cp_parser_assignment_expression (parser);
+       = cp_parser_assignment_expression (parser, cast_p);
       /* If this is the first assignment-expression, we can just
         save it away.  */
       if (!expression)
@@ -5684,14 +5764,18 @@ 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);
+  expression = cp_parser_assignment_expression (parser, /*cast_p=*/false);
   /* Restore the old settings.  */
-  parser->integral_constant_expression_p = saved_integral_constant_expression_p;
+  parser->integral_constant_expression_p 
+    = saved_integral_constant_expression_p;
   parser->allow_non_integral_constant_expression_p
     = saved_allow_non_integral_constant_expression_p;
   if (allow_non_constant_p)
     *non_constant_p = parser->non_integral_constant_expression_p;
-  parser->non_integral_constant_expression_p = saved_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;
 
   return expression;
 }
@@ -6002,18 +6086,16 @@ 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);
+    statement = cp_parser_expression (parser, /*cast_p=*/false);
 
   /* Consume the final `;'.  */
   cp_parser_consume_semicolon_at_end_of_statement (parser);
 
   if (in_statement_expr
       && cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
-    {
-      /* This is the final expression statement of a statement
-        expression.  */
-      statement = finish_stmt_expr_expr (statement, in_statement_expr);
-    }
+    /* This is the final expression statement of a statement
+       expression.  */
+    statement = finish_stmt_expr_expr (statement, in_statement_expr);
   else if (statement)
     statement = finish_expr_stmt (statement);
   else
@@ -6240,7 +6322,8 @@ cp_parser_condition (cp_parser* parser)
                             attributes, /*prefix_attributes=*/NULL_TREE,
                             &pushed_scope);
          /* Parse the assignment-expression.  */
-         initializer = cp_parser_assignment_expression (parser);
+         initializer = cp_parser_assignment_expression (parser,
+                                                        /*cast_p=*/false);
 
          /* Process the initializer.  */
          cp_finish_decl (decl,
@@ -6260,7 +6343,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);
+  return cp_parser_expression (parser, /*cast_p=*/false);
 }
 
 /* Parse an iteration-statement.
@@ -6333,7 +6416,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);
+       expression = cp_parser_expression (parser, /*cast_p=*/false);
        /* We're done with the do-statement.  */
        finish_do_stmt (expression, statement);
        /* Look for the `)'.  */
@@ -6365,7 +6448,7 @@ 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);
+         expression = cp_parser_expression (parser, /*cast_p=*/false);
        finish_for_expr (expression, statement);
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
@@ -6482,7 +6565,7 @@ cp_parser_jump_statement (cp_parser* parser)
        /* If the next token is a `;', then there is no
           expression.  */
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
-         expr = cp_parser_expression (parser);
+         expr = cp_parser_expression (parser, /*cast_p=*/false);
        else
          expr = NULL_TREE;
        /* Build the return-statement.  */
@@ -6502,7 +6585,7 @@ cp_parser_jump_statement (cp_parser* parser)
          /* Consume the '*' token.  */
          cp_lexer_consume_token (parser->lexer);
          /* Parse the dependent expression.  */
-         finish_goto_stmt (cp_parser_expression (parser));
+         finish_goto_stmt (cp_parser_expression (parser, /*cast_p=*/false));
        }
       else
        finish_goto_stmt (cp_parser_identifier (parser));
@@ -7617,6 +7700,7 @@ cp_parser_mem_initializer (cp_parser* parser)
 
   expression_list
     = cp_parser_parenthesized_expression_list (parser, false,
+                                              /*cast_p=*/false,
                                               /*non_constant_p=*/NULL);
   if (!expression_list)
     expression_list = void_type_node;
@@ -8436,9 +8520,8 @@ cp_parser_template_id (cp_parser *parser,
      should we re-parse the token stream, we will not have to repeat
      the effort required to do the parse, nor will we issue duplicate
      error messages about problems during instantiation of the
-     template.  Do so only if parsing succeeded, otherwise we may
-     silently accept template arguments with syntax errors.  */
-  if (start_of_id && !cp_parser_error_occurred (parser))
+     template.  */
+  if (start_of_id)
     {
       cp_token *token = cp_lexer_token_at (parser->lexer, start_of_id);
       
@@ -8449,6 +8532,13 @@ cp_parser_template_id (cp_parser *parser,
       
       /* Purge all subsequent tokens.  */
       cp_lexer_purge_tokens_after (parser->lexer, start_of_id);
+
+      /* ??? Can we actually assume that, if template_id ==
+        error_mark_node, we will have issued a diagnostic to the
+        user, as opposed to simply marking the tentative parse as
+        failed?  */
+      if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
+       error ("parse error in template argument list");
     }
 
   pop_deferring_access_checks ();
@@ -8821,6 +8911,7 @@ cp_parser_template_argument (cp_parser* parser)
     {
       cp_parser_parse_tentatively (parser);
       argument = cp_parser_primary_expression (parser,
+                                              /*cast_p=*/false,
                                               &idk,
                                               &qualifying_class);
       if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX
@@ -8845,6 +8936,7 @@ cp_parser_template_argument (cp_parser* parser)
     {
       cp_parser_parse_tentatively (parser);
       argument = cp_parser_primary_expression (parser,
+                                              /*cast_p=*/false,
                                               &idk,
                                               &qualifying_class);
       if (cp_parser_error_occurred (parser)
@@ -11013,6 +11105,9 @@ cp_parser_direct_declarator (cp_parser* parser,
                                                 &non_constant_p);
              if (!non_constant_p)
                bounds = fold_non_dependent_expr (bounds);
+             /* Normally, the array bound must be an integral constant
+                expression.  However, as an extension, we allow VLAs
+                in function scopes.  */  
              else if (!at_function_scope_p ())
                {
                  error ("array bound is not an integer constant");
@@ -11868,7 +11963,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
            = parser->local_variables_forbidden_p;
          parser->local_variables_forbidden_p = true;
          /* Parse the assignment-expression.  */
-         default_argument = cp_parser_assignment_expression (parser);
+         default_argument 
+           = cp_parser_assignment_expression (parser, /*cast_p=*/false);
          /* Restore saved state.  */
          parser->greater_than_is_operator_p
            = saved_greater_than_is_operator_p;
@@ -11966,6 +12062,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
     }
   else if (token->type == CPP_OPEN_PAREN)
     init = cp_parser_parenthesized_expression_list (parser, false,
+                                                   /*cast_p=*/false,
                                                    non_constant_p);
   else
     {
@@ -12001,6 +12098,9 @@ cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
 {
   tree initializer;
 
+  /* Assume the expression is constant.  */
+  *non_constant_p = false;
+
   /* If it is not a `{', then we are looking at an
      assignment-expression.  */
   if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
@@ -13241,13 +13341,18 @@ cp_parser_pure_specifier (cp_parser* parser)
   if (!cp_parser_require (parser, CPP_EQ, "`='"))
     return error_mark_node;
   /* Look for the `0' token.  */
-  token = cp_parser_require (parser, CPP_NUMBER, "`0'");
-  /* Unfortunately, this will accept `0L' and `0x00' as well.  We need
-     to get information from the lexer about how the number was
-     spelled in order to fix this problem.  */
-  if (!token || !integer_zerop (token->value))
-    return error_mark_node;
+  token = cp_lexer_consume_token (parser->lexer);
+  if (token->type != CPP_NUMBER || !integer_zerop (token->value))
+    {
+      cp_parser_error (parser,
+                      "invalid pure specifier (only `= 0' is allowed)");
+      cp_parser_skip_to_end_of_statement (parser);
+      return error_mark_node;
+    }
 
+  /* FIXME: Unfortunately, this will accept `0L' and `0x00' as well.
+     We need to get information from the lexer about how the number
+     was spelled in order to fix this problem.  */
   return integer_zero_node;
 }
 
@@ -13738,7 +13843,8 @@ cp_parser_throw_expression (cp_parser* parser)
       || token->type == CPP_COLON)
     expression = NULL_TREE;
   else
-    expression = cp_parser_assignment_expression (parser);
+    expression = cp_parser_assignment_expression (parser,
+                                                 /*cast_p=*/false);
 
   return build_throw (expression);
 }
@@ -13828,7 +13934,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);
+      expression = cp_parser_expression (parser, /*cast_p=*/false);
       /* Look for the `)'.  */
       cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
 
@@ -13945,10 +14051,10 @@ cp_parser_attributes_opt (cp_parser* parser)
      identifier ( identifier , expression-list )
      identifier ( expression-list )
 
-   Returns a TREE_LIST.  Each node corresponds to an attribute.  THe
-   TREE_PURPOSE of each node is the identifier indicating which
-   attribute is in use.  The TREE_VALUE represents the arguments, if
-   any.  */
+   Returns a TREE_LIST, or NULL_TREE on error.  Each node corresponds
+   to an attribute.  The TREE_PURPOSE of each node is the identifier
+   indicating which attribute is in use.  The TREE_VALUE represents
+   the arguments, if any.  */
 
 static tree
 cp_parser_attribute_list (cp_parser* parser)
@@ -13966,36 +14072,39 @@ cp_parser_attribute_list (cp_parser* parser)
       /* Look for the identifier.  We also allow keywords here; for
         example `__attribute__ ((const))' is legal.  */
       token = cp_lexer_peek_token (parser->lexer);
-      if (token->type != CPP_NAME
-         && token->type != CPP_KEYWORD)
-       return error_mark_node;
-      /* Consume the token.  */
-      token = cp_lexer_consume_token (parser->lexer);
+      if (token->type == CPP_NAME
+         || token->type == CPP_KEYWORD)
+       {
+         /* Consume the token.  */
+         token = cp_lexer_consume_token (parser->lexer);
 
-      /* Save away the identifier that indicates which attribute this is.  */
-      identifier = token->value;
-      attribute = build_tree_list (identifier, NULL_TREE);
+         /* Save away the identifier that indicates which attribute
+            this is.  */ 
+         identifier = token->value;
+         attribute = build_tree_list (identifier, NULL_TREE);
 
-      /* Peek at the next token.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If it's an `(', then parse the attribute arguments.  */
-      if (token->type == CPP_OPEN_PAREN)
-       {
-         tree arguments;
+         /* Peek at the next token.  */
+         token = cp_lexer_peek_token (parser->lexer);
+         /* If it's an `(', then parse the attribute arguments.  */
+         if (token->type == CPP_OPEN_PAREN)
+           {
+             tree arguments;
 
-         arguments = (cp_parser_parenthesized_expression_list
-                      (parser, true, /*non_constant_p=*/NULL));
-         /* Save the identifier and arguments away.  */
-         TREE_VALUE (attribute) = arguments;
-       }
+             arguments = (cp_parser_parenthesized_expression_list
+                          (parser, true, /*cast_p=*/false, 
+                           /*non_constant_p=*/NULL));
+             /* Save the identifier and arguments away.  */
+             TREE_VALUE (attribute) = arguments;
+           }
 
-      /* Add this attribute to the list.  */
-      TREE_CHAIN (attribute) = attribute_list;
-      attribute_list = attribute;
+         /* Add this attribute to the list.  */
+         TREE_CHAIN (attribute) = attribute_list;
+         attribute_list = attribute;
 
-      /* Now, look for more attributes.  */
-      token = cp_lexer_peek_token (parser->lexer);
-      /* If the next token isn't a `,', we're done.  */
+         token = cp_lexer_peek_token (parser->lexer);
+       }
+      /* Now, look for more attributes.  If the next token isn't a
+        `,', we're done.  */
       if (token->type != CPP_COMMA)
        break;
 
@@ -14154,6 +14263,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
       /* If that's not a class type, there is no destructor.  */
       if (!type || !CLASS_TYPE_P (type))
        return error_mark_node;
+      if (CLASSTYPE_LAZY_DESTRUCTOR (type))
+       lazily_declare_fn (sfk_destructor, type);
       if (!CLASSTYPE_DESTRUCTORS (type))
          return error_mark_node;
       /* If it was a class type, return the destructor.  */
@@ -14961,7 +15072,8 @@ cp_parser_single_declaration (cp_parser* parser,
 static tree
 cp_parser_simple_cast_expression (cp_parser *parser)
 {
-  return cp_parser_cast_expression (parser, /*address_p=*/false);
+  return cp_parser_cast_expression (parser, /*address_p=*/false,
+                                   /*cast_p=*/false);
 }
 
 /* Parse a functional cast to TYPE.  Returns an expression
@@ -14975,6 +15087,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
 
   expression_list
     = cp_parser_parenthesized_expression_list (parser, false,
+                                              /*cast_p=*/true,
                                               /*non_constant_p=*/NULL);
 
   cast = build_functional_cast (type, expression_list);
@@ -15166,9 +15279,10 @@ cp_parser_late_parsing_for_member (cp_parser* parser, tree member_function)
       tokens = DECL_PENDING_INLINE_INFO (member_function);
       DECL_PENDING_INLINE_INFO (member_function) = NULL;
       DECL_PENDING_INLINE_P (member_function) = 0;
-      /* If this was an inline function in a local class, enter the scope
-        of the containing function.  */
-      function_scope = decl_function_context (member_function);
+      
+      /* If this is a local class, enter the scope of the containing
+        function.  */
+      function_scope = current_function_decl;
       if (function_scope)
        push_function_context_to (function_scope);
 
@@ -15258,7 +15372,8 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
       cp_parser_push_lexer_for_tokens (parser, tokens);
 
       /* Parse the assignment-expression.  */
-      TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser);
+      TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser,
+                                                            /*cast_p=*/false);
 
       /* If the token stream has not been completely used up, then
         there was extra junk after the end of the default
@@ -15290,6 +15405,7 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   tree expr = NULL_TREE;
   const char *saved_message;
   bool saved_integral_constant_expression_p;
+  bool saved_non_integral_constant_expression_p;
 
   /* Initialize FORMAT the first time we get here.  */
   if (!format)
@@ -15308,7 +15424,10 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
 
   /* The restrictions on constant-expressions do not apply inside
      sizeof expressions.  */
-  saved_integral_constant_expression_p = parser->integral_constant_expression_p;
+  saved_integral_constant_expression_p 
+    = parser->integral_constant_expression_p;
+  saved_non_integral_constant_expression_p
+    = parser->non_integral_constant_expression_p;
   parser->integral_constant_expression_p = false;
 
   /* Do not actually evaluate the expression.  */
@@ -15353,7 +15472,8 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   /* If the type-id production did not work out, then we must be
      looking at the unary-expression production.  */
   if (!expr)
-    expr = cp_parser_unary_expression (parser, /*address_p=*/false);
+    expr = cp_parser_unary_expression (parser, /*address_p=*/false,
+                                      /*cast_p=*/false);
   /* Go back to evaluating expressions.  */
   --skip_evaluation;
 
@@ -15361,7 +15481,10 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
   free ((char *) parser->type_definition_forbidden_message);
   /* And restore the old one.  */
   parser->type_definition_forbidden_message = saved_message;
-  parser->integral_constant_expression_p = saved_integral_constant_expression_p;
+  parser->integral_constant_expression_p 
+    = saved_integral_constant_expression_p;
+  parser->non_integral_constant_expression_p
+    = saved_non_integral_constant_expression_p;
 
   return expr;
 }