This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: Disallow floating-point literals in integral-constant expressions


The standard says that floating-point literals are only allowed in
integral constant expressions if they are immediately cast to an
integral or enumeration type.  When I implemented checks for integral
constant-expressions, I failed to check this case.  Remedied with the
attached patch.

The standard library fell afound of this rule in std_limits.h; that's
now fixed too.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2005-01-31  Mark Mitchell  <mark@codesourcery.com>

	* decl.c (build_enumerator): Do not issue duplicate error messages
	about invalid enumeration constants.
	* parser.c (cp_parser_non_integral_constant_expression): Always
	set parser->non_integral_constant_expression_p.
	(cp_parser_primary_expression): Add cast_p parameter.  Issue
	errors about invalid uses of floating-point literals in
	cast-expressions.
	(cp_parser_postfix_expression): Add cast_p parameter.
	(cp_parser_open_square_expression): Pass it.
	(cp_parser_parenthesized_expression_list): Add cast_p parameter.
	(cp_parser_unary_expression): Likewise.
	(cp_parser_new_placement): Pass it.
	(cp_parser_direct_new_declarator): Likewise.
	(cp_parser_new_initializer): Likewise.
	(cp_parser_cast_expression): Add cast_p parameter.
	(cp_parser_binary_expression): Likewise.
	(cp_parser_question_colon_clause): Likewise.
	(cp_parser_assignment_expression): Likewise.
	(cp_parser_expression): Likewise.
	(cp_parser_constant_expression): If an integral constant
	expression is invalid, return error_mark_node.
	(cp_parser_expression_statement): Pass cast_p.
	(cp_parser_condition): Likewise.
	(cp_parser_iteration_statement): Likewise.
	(cp_parser_jump_statement): Likewise.
	(cp_parser_mem_initializer): Likewise.
	(cp_parser_template_argument): Likewise.
	(cp_parser_parameter_declaration): Likewise.
	(cp_parser_initializer): Likewise.
	(cp_parser_throw_expression): Likewise.
	(cp_parser_attribute_list): Likewise.
	(cp_parser_simple_cast_expression): Likewise.
	(cp_parser_functional_cast): Likewise.
	(cp_parser_late_parsing_default_args): Likewise.
	(cp_parser_sizeof_operand): Save/restore
	non_integral_constant_expression_p.

2005-01-31  Mark Mitchell  <mark@codesourcery.com>

	* include/std/std_limits.h (numeric_limits<float>::has_denorm):
	Add required cast.
	(numeric_limits<double>::has_denorm): Likewise.
	(numeric_limits<long double>::has_denorm): Likewise.

2005-01-31  Mark Mitchell  <mark@codesourcery.com>

	* g++.dg/other/warning1.C: Adjust error messags.
	* g++.dg/parse/constant5.C: New test.

Index: gcc/cp/decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1358
diff -c -5 -p -r1.1358 decl.c
*** gcc/cp/decl.c	31 Jan 2005 16:16:16 -0000	1.1358
--- gcc/cp/decl.c	1 Feb 2005 00:45:10 -0000
*************** build_enumerator (tree name, tree value,
*** 9680,9689 ****
--- 9680,9694 ----
  {
    tree decl;
    tree context;
    tree type;
  
+   /* If the VALUE was erroneous, pretend it wasn't there; that will
+      result in the enum being assigned the next value in sequence.  */
+   if (value == error_mark_node)
+     value = NULL_TREE;
+ 
    /* Remove no-op casts from the value.  */
    if (value)
      STRIP_TYPE_NOPS (value);
  
    if (! processing_template_decl)
Index: gcc/cp/parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.304
diff -c -5 -p -r1.304 parser.c
*** gcc/cp/parser.c	29 Jan 2005 02:07:05 -0000	1.304
--- gcc/cp/parser.c	1 Feb 2005 00:45:16 -0000
*************** static bool cp_parser_translation_unit
*** 1352,1362 ****
    (cp_parser *);
  
  /* Expressions [gram.expr]  */
  
  static tree cp_parser_primary_expression
!   (cp_parser *, cp_id_kind *, tree *);
  static tree cp_parser_id_expression
    (cp_parser *, bool, bool, bool *, bool);
  static tree cp_parser_unqualified_id
    (cp_parser *, bool, bool, bool);
  static tree cp_parser_nested_name_specifier_opt
--- 1352,1362 ----
    (cp_parser *);
  
  /* Expressions [gram.expr]  */
  
  static tree cp_parser_primary_expression
!   (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
    (cp_parser *, bool, bool, bool);
  static tree cp_parser_nested_name_specifier_opt
*************** static tree cp_parser_nested_name_specif
*** 1364,1384 ****
  static tree cp_parser_nested_name_specifier
    (cp_parser *, bool, bool, bool, bool);
  static tree cp_parser_class_or_namespace_name
    (cp_parser *, bool, bool, bool, bool, bool);
  static tree cp_parser_postfix_expression
!   (cp_parser *, 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 *);
  static void cp_parser_pseudo_destructor_name
    (cp_parser *, tree *, tree *);
  static tree cp_parser_unary_expression
!   (cp_parser *, bool);
  static enum tree_code cp_parser_unary_operator
    (cp_token *);
  static tree cp_parser_new_expression
    (cp_parser *);
  static tree cp_parser_new_placement
--- 1364,1384 ----
  static tree cp_parser_nested_name_specifier
    (cp_parser *, bool, bool, bool, bool);
  static tree cp_parser_class_or_namespace_name
    (cp_parser *, bool, bool, bool, bool, bool);
  static tree cp_parser_postfix_expression
!   (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, bool *);
  static void cp_parser_pseudo_destructor_name
    (cp_parser *, tree *, tree *);
  static tree cp_parser_unary_expression
!   (cp_parser *, bool, bool);
  static enum tree_code cp_parser_unary_operator
    (cp_token *);
  static tree cp_parser_new_expression
    (cp_parser *);
  static tree cp_parser_new_placement
*************** static cp_declarator *cp_parser_direct_n
*** 1392,1412 ****
  static tree cp_parser_new_initializer
    (cp_parser *);
  static tree cp_parser_delete_expression
    (cp_parser *);
  static tree cp_parser_cast_expression
!   (cp_parser *, bool);
  static tree cp_parser_binary_expression
!   (cp_parser *);
  static tree cp_parser_question_colon_clause
    (cp_parser *, tree);
  static tree cp_parser_assignment_expression
!   (cp_parser *);
  static enum tree_code cp_parser_assignment_operator_opt
    (cp_parser *);
  static tree cp_parser_expression
!   (cp_parser *);
  static tree cp_parser_constant_expression
    (cp_parser *, bool, bool *);
  static tree cp_parser_builtin_offsetof
    (cp_parser *);
  
--- 1392,1412 ----
  static tree cp_parser_new_initializer
    (cp_parser *);
  static tree cp_parser_delete_expression
    (cp_parser *);
  static tree cp_parser_cast_expression
!   (cp_parser *, bool, bool);
  static tree cp_parser_binary_expression
!   (cp_parser *, bool);
  static tree cp_parser_question_colon_clause
    (cp_parser *, tree);
  static tree cp_parser_assignment_expression
!   (cp_parser *, bool);
  static enum tree_code cp_parser_assignment_operator_opt
    (cp_parser *);
  static tree cp_parser_expression
!   (cp_parser *, bool);
  static tree cp_parser_constant_expression
    (cp_parser *, bool, bool *);
  static tree cp_parser_builtin_offsetof
    (cp_parser *);
  
*************** cp_parser_check_for_invalid_template_id 
*** 1940,1963 ****
      }
  }
  
  /* 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.  */
  
  static bool
  cp_parser_non_integral_constant_expression (cp_parser  *parser,
  					    const char *thing)
  {
    if (parser->integral_constant_expression_p)
      {
        if (!parser->allow_non_integral_constant_expression_p)
  	{
  	  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
--- 1940,1964 ----
      }
  }
  
  /* If parsing an integral constant-expression, issue an error message
     about the fact that THING appeared and return true.  Otherwise,
!    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)
  	{
  	  error ("%s cannot appear in a constant-expression", thing);
  	  return true;
  	}
      }
    return false;
  }
  
  /* Emit a diagnostic for an invalid type name.  SCOPE is the
*************** cp_parser_translation_unit (cp_parser* p
*** 2634,2643 ****
--- 2635,2646 ----
       __builtin_va_arg ( assignment-expression , type-id )
  
     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.
  
     *QUALIFYING_CLASS is set to a non-NULL value if the id-expression can be
*************** cp_parser_translation_unit (cp_parser* p
*** 2645,2654 ****
--- 2648,2658 ----
     *QUALIFYING_CLASS gives the class that is used as the qualifying
     class in the pointer-to-member.  */
  
  static tree
  cp_parser_primary_expression (cp_parser *parser,
+ 			      bool cast_p,
  			      cp_id_kind *idk,
  			      tree *qualifying_class)
  {
    cp_token *token;
  
*************** cp_parser_primary_expression (cp_parser 
*** 2669,2678 ****
--- 2673,2718 ----
  	   boolean-literal  */
      case CPP_CHAR:
      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)
+ 	{
+ 	  /* 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:
      case CPP_WSTRING:
        /* ??? Should wide strings be allowed when parser->translate_strings_p
*************** cp_parser_primary_expression (cp_parser 
*** 2719,2729 ****
  	    expr = finish_stmt_expr (expr, false);
  	  }
  	else
  	  {
  	    /* Parse the parenthesized expression.  */
! 	    expr = cp_parser_expression (parser);
  	    /* 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
  	       `&A::B' might be a pointer-to-member, but `&(A::B)' is
  	       not.  */
--- 2759,2769 ----
  	    expr = finish_stmt_expr (expr, false);
  	  }
  	else
  	  {
  	    /* Parse the parenthesized expression.  */
! 	    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
  	       `&A::B' might be a pointer-to-member, but `&(A::B)' is
  	       not.  */
*************** cp_parser_primary_expression (cp_parser 
*** 2798,2808 ****
  	       `va_arg'.  Consume the `__builtin_va_arg' token.  */
  	    cp_lexer_consume_token (parser->lexer);
  	    /* Look for the opening `('.  */
  	    cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
  	    /* Now, parse the assignment-expression.  */
! 	    expression = cp_parser_assignment_expression (parser);
  	    /* Look for the `,'.  */
  	    cp_parser_require (parser, CPP_COMMA, "`,'");
  	    /* Parse the type-id.  */
  	    type = cp_parser_type_id (parser);
  	    /* Look for the closing `)'.  */
--- 2838,2849 ----
  	       `va_arg'.  Consume the `__builtin_va_arg' token.  */
  	    cp_lexer_consume_token (parser->lexer);
  	    /* Look for the opening `('.  */
  	    cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
  	    /* Now, parse the assignment-expression.  */
! 	    expression = cp_parser_assignment_expression (parser,
! 							  /*cast_p=*/false);
  	    /* Look for the `,'.  */
  	    cp_parser_require (parser, CPP_COMMA, "`,'");
  	    /* Parse the type-id.  */
  	    type = cp_parser_type_id (parser);
  	    /* Look for the closing `)'.  */
*************** cp_parser_class_or_namespace_name (cp_pa
*** 3661,3676 ****
     This extension is a GNU version of the C99 compound-literal
     construct.  (The C99 grammar uses `type-name' instead of `type-id',
     but they are essentially the same concept.)
  
     If ADDRESS_P is true, the postfix expression is the operand of the
!    `&' operator.
  
     Returns a representation of the expression.  */
  
  static tree
! cp_parser_postfix_expression (cp_parser *parser, bool address_p)
  {
    cp_token *token;
    enum rid keyword;
    cp_id_kind idk = CP_ID_KIND_NONE;
    tree postfix_expression = NULL_TREE;
--- 3702,3718 ----
     This extension is a GNU version of the C99 compound-literal
     construct.  (The C99 grammar uses `type-name' instead of `type-id',
     but they are essentially the same concept.)
  
     If ADDRESS_P is true, the postfix expression is 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_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
  {
    cp_token *token;
    enum rid keyword;
    cp_id_kind idk = CP_ID_KIND_NONE;
    tree postfix_expression = NULL_TREE;
*************** cp_parser_postfix_expression (cp_parser 
*** 3713,3723 ****
  	/* Restore the old message.  */
  	parser->type_definition_forbidden_message = saved_message;
  
  	/* And the expression which is being cast.  */
  	cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
! 	expression = cp_parser_expression (parser);
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  
  	/* Only type conversions to integral or enumeration types
  	   can be used in constant-expressions.  */
  	if (parser->integral_constant_expression_p
--- 3755,3765 ----
  	/* Restore the old message.  */
  	parser->type_definition_forbidden_message = saved_message;
  
  	/* And the expression which is being cast.  */
  	cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
! 	expression = cp_parser_expression (parser, /*cast_p=*/true);
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  
  	/* Only type conversions to integral or enumeration types
  	   can be used in constant-expressions.  */
  	if (parser->integral_constant_expression_p
*************** cp_parser_postfix_expression (cp_parser 
*** 3786,3796 ****
  	else
  	  {
  	    tree expression;
  
  	    /* Look for an expression.  */
! 	    expression = cp_parser_expression (parser);
  	    /* Compute its typeid.  */
  	    postfix_expression = build_typeid (expression);
  	    /* Look for the `)' token.  */
  	    cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	  }
--- 3828,3838 ----
  	else
  	  {
  	    tree expression;
  
  	    /* Look for an expression.  */
! 	    expression = cp_parser_expression (parser, /*cast_p=*/false);
  	    /* Compute its typeid.  */
  	    postfix_expression = build_typeid (expression);
  	    /* Look for the `)' token.  */
  	    cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	  }
*************** cp_parser_postfix_expression (cp_parser 
*** 3918,3927 ****
--- 3960,3970 ----
  	      }
  	  }
  
  	/* It must be a primary-expression.  */
  	postfix_expression = cp_parser_primary_expression (parser,
+ 							   cast_p,
  							   &idk,
  							   &qualifying_class);
        }
        break;
      }
*************** cp_parser_postfix_expression (cp_parser 
*** 3976,3986 ****
  	case CPP_OPEN_PAREN:
  	  /* postfix-expression ( expression-list [opt] ) */
  	  {
  	    bool koenig_p;
  	    tree args = (cp_parser_parenthesized_expression_list
! 			 (parser, false, /*non_constant_p=*/NULL));
  
  	    if (args == error_mark_node)
  	      {
  		postfix_expression = error_mark_node;
  		break;
--- 4019,4031 ----
  	case CPP_OPEN_PAREN:
  	  /* postfix-expression ( expression-list [opt] ) */
  	  {
  	    bool koenig_p;
  	    tree args = (cp_parser_parenthesized_expression_list
! 			 (parser, false, 
! 			  /*cast_p=*/false,
! 			  /*non_constant_p=*/NULL));
  
  	    if (args == error_mark_node)
  	      {
  		postfix_expression = error_mark_node;
  		break;
*************** cp_parser_postfix_open_square_expression
*** 4169,4179 ****
       Rather than open the barn door too wide right away, allow only integer
       constant expressions here.  */
    if (for_offsetof)
      index = cp_parser_constant_expression (parser, false, NULL);
    else
!     index = cp_parser_expression (parser);
  
    /* Look for the closing `]'.  */
    cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
  
    /* Build the ARRAY_REF.  */
--- 4214,4224 ----
       Rather than open the barn door too wide right away, allow only integer
       constant expressions here.  */
    if (for_offsetof)
      index = cp_parser_constant_expression (parser, false, NULL);
    else
!     index = cp_parser_expression (parser, /*cast_p=*/false);
  
    /* Look for the closing `]'.  */
    cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
  
    /* Build the ARRAY_REF.  */
*************** cp_parser_postfix_dot_deref_expression (
*** 4349,4358 ****
--- 4394,4405 ----
     attribute-list:
       expression-list
       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.
     error_mark_node is returned if the ( and or ) are
     missing. NULL_TREE is returned on no expressions. The parentheses
*************** cp_parser_postfix_dot_deref_expression (
*** 4362,4371 ****
--- 4409,4419 ----
     constant.  */
  
  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;
    bool fold_expr_p = is_attribute_list;
    tree identifier = NULL_TREE;
*************** cp_parser_parenthesized_expression_list 
*** 4406,4416 ****
  			 &expr_non_constant_p));
  		if (expr_non_constant_p)
  		  *non_constant_p = true;
  	      }
  	    else
! 	      expr = cp_parser_assignment_expression (parser);
  
  	    if (fold_expr_p)
  	      expr = fold_non_dependent_expr (expr);
  
  	     /* Add it to the list.  We add error_mark_node
--- 4454,4464 ----
  			 &expr_non_constant_p));
  		if (expr_non_constant_p)
  		  *non_constant_p = true;
  	      }
  	    else
! 	      expr = cp_parser_assignment_expression (parser, cast_p);
  
  	    if (fold_expr_p)
  	      expr = fold_non_dependent_expr (expr);
  
  	     /* Add it to the list.  We add error_mark_node
*************** cp_parser_pseudo_destructor_name (cp_par
*** 4564,4579 ****
       __real__ cast-expression
       __imag__ cast-expression
       && identifier
  
     ADDRESS_P is true iff the unary-expression is appearing as the
!    operand of the `&' operator.
  
     Returns a representation of the expression.  */
  
  static tree
! cp_parser_unary_expression (cp_parser *parser, bool address_p)
  {
    cp_token *token;
    enum tree_code unary_operator;
  
    /* Peek at the next token.  */
--- 4612,4628 ----
       __real__ cast-expression
       __imag__ cast-expression
       && identifier
  
     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_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
  {
    cp_token *token;
    enum tree_code unary_operator;
  
    /* Peek at the next token.  */
*************** cp_parser_unary_expression (cp_parser *p
*** 4697,4707 ****
  
        /* Consume the operator token.  */
        token = cp_lexer_consume_token (parser->lexer);
        /* Parse the cast-expression.  */
        cast_expression
! 	= cp_parser_cast_expression (parser, unary_operator == ADDR_EXPR);
        /* Now, build an appropriate representation.  */
        switch (unary_operator)
  	{
  	case INDIRECT_REF:
  	  non_constant_p = "`*'";
--- 4746,4758 ----
  
        /* Consume the operator token.  */
        token = cp_lexer_consume_token (parser->lexer);
        /* Parse the cast-expression.  */
        cast_expression
! 	= cp_parser_cast_expression (parser, 
! 				     unary_operator == ADDR_EXPR,
! 				     /*cast_p=*/false);
        /* Now, build an appropriate representation.  */
        switch (unary_operator)
  	{
  	case INDIRECT_REF:
  	  non_constant_p = "`*'";
*************** cp_parser_unary_expression (cp_parser *p
*** 4736,4746 ****
  	expression = error_mark_node;
  
        return expression;
      }
  
!   return cp_parser_postfix_expression (parser, address_p);
  }
  
  /* Returns ERROR_MARK if TOKEN is not a unary-operator.  If TOKEN is a
     unary-operator, the corresponding tree code is returned.  */
  
--- 4787,4797 ----
  	expression = error_mark_node;
  
        return expression;
      }
  
!   return cp_parser_postfix_expression (parser, address_p, cast_p);
  }
  
  /* Returns ERROR_MARK if TOKEN is not a unary-operator.  If TOKEN is a
     unary-operator, the corresponding tree code is returned.  */
  
*************** cp_parser_new_placement (cp_parser* pars
*** 4857,4867 ****
  {
    tree expression_list;
  
    /* Parse the expression-list.  */
    expression_list = (cp_parser_parenthesized_expression_list
! 		     (parser, false, /*non_constant_p=*/NULL));
  
    return expression_list;
  }
  
  /* Parse a new-type-id.
--- 4908,4919 ----
  {
    tree expression_list;
  
    /* Parse the expression-list.  */
    expression_list = (cp_parser_parenthesized_expression_list
! 		     (parser, false, /*cast_p=*/false,
! 		      /*non_constant_p=*/NULL));
  
    return expression_list;
  }
  
  /* Parse a new-type-id.
*************** cp_parser_direct_new_declarator (cp_pars
*** 5004,5014 ****
        /* Look for the opening `['.  */
        cp_parser_require (parser, CPP_OPEN_SQUARE, "`['");
        /* The first expression is not required to be constant.  */
        if (!declarator)
  	{
! 	  expression = cp_parser_expression (parser);
  	  /* 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
  	     expression in a `switch' condition, which also allows
  	     classes with a single conversion to integral or
--- 5056,5066 ----
        /* Look for the opening `['.  */
        cp_parser_require (parser, CPP_OPEN_SQUARE, "`['");
        /* The first expression is not required to be constant.  */
        if (!declarator)
  	{
! 	  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
  	     expression in a `switch' condition, which also allows
  	     classes with a single conversion to integral or
*************** static tree
*** 5060,5070 ****
  cp_parser_new_initializer (cp_parser* parser)
  {
    tree expression_list;
  
    expression_list = (cp_parser_parenthesized_expression_list
! 		     (parser, false, /*non_constant_p=*/NULL));
    if (!expression_list)
      expression_list = void_zero_node;
  
    return expression_list;
  }
--- 5112,5123 ----
  cp_parser_new_initializer (cp_parser* parser)
  {
    tree expression_list;
  
    expression_list = (cp_parser_parenthesized_expression_list
! 		     (parser, false, /*cast_p=*/false,
! 		      /*non_constant_p=*/NULL));
    if (!expression_list)
      expression_list = void_zero_node;
  
    return expression_list;
  }
*************** cp_parser_delete_expression (cp_parser* 
*** 5119,5132 ****
  
     cast-expression:
       unary-expression
       ( type-id ) cast-expression
  
     Returns a representation of the expression.  */
  
  static tree
! cp_parser_cast_expression (cp_parser *parser, bool address_p)
  {
    /* If it's a `(', then we might be looking at a cast.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
      {
        tree type = NULL_TREE;
--- 5172,5189 ----
  
     cast-expression:
       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, 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))
      {
        tree type = NULL_TREE;
*************** cp_parser_cast_expression (cp_parser *pa
*** 5192,5202 ****
        /* 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_simple_cast_expression (parser);
  
        if (cp_parser_parse_definitely (parser))
  	{
  	  /* Warn about old-style casts, if so requested.  */
  	  if (warn_old_style_cast
--- 5249,5261 ----
        /* 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))
  	{
  	  /* Warn about old-style casts, if so requested.  */
  	  if (warn_old_style_cast
*************** cp_parser_cast_expression (cp_parser *pa
*** 5222,5232 ****
  	}
      }
  
    /* 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);
  }
  
  /* Parse a binary expression of the general form:
  
     pm-expression:
--- 5281,5291 ----
  	}
      }
  
    /* 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);
  }
  
  /* Parse a binary expression of the general form:
  
     pm-expression:
*************** cp_parser_cast_expression (cp_parser *pa
*** 5292,5322 ****
  
     binary-expression:
       simple-cast-expression
       binary-expression <token> binary-expression
  
     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.  */
  
  #define TOKEN_PRECEDENCE(token) \
    ((token->type == CPP_GREATER && !parser->greater_than_is_operator_p) \
     ? PREC_NOT_OPERATOR \
     : binops_by_token[token->type].prec)
  
  static tree
! cp_parser_binary_expression (cp_parser* parser)
  {
    cp_parser_expression_stack stack;
    cp_parser_expression_stack_entry *sp = &stack[0];
    tree lhs, rhs;
    cp_token *token;
    enum tree_code tree_type;
    enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
    bool overloaded_p;
  
    /* Parse the first expression.  */
!   lhs = cp_parser_simple_cast_expression (parser);
  
    for (;;)
      {
        /* Get an operator token.  */
        token = cp_lexer_peek_token (parser->lexer);
--- 5351,5383 ----
  
     binary-expression:
       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.  */
  
  #define TOKEN_PRECEDENCE(token) \
    ((token->type == CPP_GREATER && !parser->greater_than_is_operator_p) \
     ? PREC_NOT_OPERATOR \
     : binops_by_token[token->type].prec)
  
  static tree
! cp_parser_binary_expression (cp_parser* parser, bool cast_p)
  {
    cp_parser_expression_stack stack;
    cp_parser_expression_stack_entry *sp = &stack[0];
    tree lhs, rhs;
    cp_token *token;
    enum tree_code tree_type;
    enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
    bool overloaded_p;
  
    /* Parse the first expression.  */
!   lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p);
  
    for (;;)
      {
        /* Get an operator token.  */
        token = cp_lexer_peek_token (parser->lexer);
*************** cp_parser_question_colon_clause (cp_pars
*** 5426,5441 ****
        && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
      /* Implicit true clause.  */
      expr = NULL_TREE;
    else
      /* Parse the expression.  */
!     expr = cp_parser_expression (parser);
  
    /* The next token should be a `:'.  */
    cp_parser_require (parser, CPP_COLON, "`:'");
    /* Parse the assignment-expression.  */
!   assignment_expr = cp_parser_assignment_expression (parser);
  
    /* Build the conditional-expression.  */
    return build_x_conditional_expr (logical_or_expr,
  				   expr,
  				   assignment_expr);
--- 5487,5502 ----
        && cp_lexer_next_token_is (parser->lexer, CPP_COLON))
      /* Implicit true clause.  */
      expr = NULL_TREE;
    else
      /* Parse the expression.  */
!     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, /*cast_p=*/false);
  
    /* Build the conditional-expression.  */
    return build_x_conditional_expr (logical_or_expr,
  				   expr,
  				   assignment_expr);
*************** cp_parser_question_colon_clause (cp_pars
*** 5446,5459 ****
     assignment-expression:
       conditional-expression
       logical-or-expression assignment-operator assignment_expression
       throw-expression
  
     Returns a representation for the expression.  */
  
  static tree
! cp_parser_assignment_expression (cp_parser* parser)
  {
    tree expr;
  
    /* If the next token is the `throw' keyword, then we're looking at
       a throw-expression.  */
--- 5507,5522 ----
     assignment-expression:
       conditional-expression
       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, bool cast_p)
  {
    tree expr;
  
    /* If the next token is the `throw' keyword, then we're looking at
       a throw-expression.  */
*************** cp_parser_assignment_expression (cp_pars
*** 5462,5472 ****
    /* Otherwise, it must be that we are looking at a
       logical-or-expression.  */
    else
      {
        /* Parse the binary expressions (logical-or-expression).  */
!       expr = cp_parser_binary_expression (parser);
        /* 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))
  	return cp_parser_question_colon_clause (parser, expr);
        else
--- 5525,5535 ----
    /* Otherwise, it must be that we are looking at a
       logical-or-expression.  */
    else
      {
        /* Parse the binary expressions (logical-or-expression).  */
!       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))
  	return cp_parser_question_colon_clause (parser, expr);
        else
*************** cp_parser_assignment_expression (cp_pars
*** 5480,5490 ****
  	  if (assignment_operator != ERROR_MARK)
  	    {
  	      tree rhs;
  
  	      /* Parse the right-hand side of the assignment.  */
! 	      rhs = cp_parser_assignment_expression (parser);
  	      /* An assignment may not appear in a
  		 constant-expression.  */
  	      if (cp_parser_non_integral_constant_expression (parser,
  							      "an assignment"))
  		return error_mark_node;
--- 5543,5553 ----
  	  if (assignment_operator != ERROR_MARK)
  	    {
  	      tree rhs;
  
  	      /* Parse the right-hand side of the assignment.  */
! 	      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,
  							      "an assignment"))
  		return error_mark_node;
*************** cp_parser_assignment_operator_opt (cp_pa
*** 5595,5618 ****
  
     expression:
       assignment-expression
       expression , assignment-expression
  
     Returns a representation of the expression.  */
  
  static tree
! cp_parser_expression (cp_parser* parser)
  {
    tree expression = NULL_TREE;
  
    while (true)
      {
        tree assignment_expression;
  
        /* Parse the next assignment-expression.  */
        assignment_expression
! 	= cp_parser_assignment_expression (parser);
        /* If this is the first assignment-expression, we can just
  	 save it away.  */
        if (!expression)
  	expression = assignment_expression;
        else
--- 5658,5683 ----
  
     expression:
       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, bool cast_p)
  {
    tree expression = NULL_TREE;
  
    while (true)
      {
        tree assignment_expression;
  
        /* Parse the next assignment-expression.  */
        assignment_expression
! 	= cp_parser_assignment_expression (parser, cast_p);
        /* If this is the first assignment-expression, we can just
  	 save it away.  */
        if (!expression)
  	expression = assignment_expression;
        else
*************** cp_parser_constant_expression (cp_parser
*** 5686,5703 ****
       otherwise.  In the case that ALLOW_NON_CONSTANT_P is true, it is
       actually essential that we look for an assignment-expression.
       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);
    /* Restore the old settings.  */
!   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;
  
    return expression;
  }
  
  /* Parse __builtin_offsetof.
--- 5751,5772 ----
       otherwise.  In the case that ALLOW_NON_CONSTANT_P is true, it is
       actually essential that we look for an assignment-expression.
       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);
    /* Restore the old settings.  */
!   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;
!   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;
  }
  
  /* Parse __builtin_offsetof.
*************** cp_parser_expression_statement (cp_parse
*** 6004,6025 ****
    tree statement = NULL_TREE;
  
    /* 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);
  
    /* 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);
!     }
    else if (statement)
      statement = finish_expr_stmt (statement);
    else
      finish_stmt ();
  
--- 6073,6092 ----
    tree statement = NULL_TREE;
  
    /* 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);
  
    /* 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);
    else if (statement)
      statement = finish_expr_stmt (statement);
    else
      finish_stmt ();
  
*************** cp_parser_condition (cp_parser* parser)
*** 6242,6252 ****
  	  decl = start_decl (declarator, &type_specifiers,
  			     /*initialized_p=*/true,
  			     attributes, /*prefix_attributes=*/NULL_TREE,
  			     &pushed_scope);
  	  /* Parse the assignment-expression.  */
! 	  initializer = cp_parser_assignment_expression (parser);
  
  	  /* Process the initializer.  */
  	  cp_finish_decl (decl,
  			  initializer,
  			  asm_specification,
--- 6309,6320 ----
  	  decl = start_decl (declarator, &type_specifiers,
  			     /*initialized_p=*/true,
  			     attributes, /*prefix_attributes=*/NULL_TREE,
  			     &pushed_scope);
  	  /* Parse the assignment-expression.  */
! 	  initializer = cp_parser_assignment_expression (parser,
! 							 /*cast_p=*/false);
  
  	  /* Process the initializer.  */
  	  cp_finish_decl (decl,
  			  initializer,
  			  asm_specification,
*************** cp_parser_condition (cp_parser* parser)
*** 6262,6272 ****
       definitely not looking at a declaration.  */
    else
      cp_parser_abort_tentative_parse (parser);
  
    /* Otherwise, we are looking at an expression.  */
!   return cp_parser_expression (parser);
  }
  
  /* Parse an iteration-statement.
  
     iteration-statement:
--- 6330,6340 ----
       definitely not looking at a declaration.  */
    else
      cp_parser_abort_tentative_parse (parser);
  
    /* Otherwise, we are looking at an expression.  */
!   return cp_parser_expression (parser, /*cast_p=*/false);
  }
  
  /* Parse an iteration-statement.
  
     iteration-statement:
*************** cp_parser_iteration_statement (cp_parser
*** 6335,6345 ****
  	/* Look for the `while' keyword.  */
  	cp_parser_require_keyword (parser, RID_WHILE, "`while'");
  	/* Look for the `('.  */
  	cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
  	/* Parse the expression.  */
! 	expression = cp_parser_expression (parser);
  	/* We're done with the do-statement.  */
  	finish_do_stmt (expression, statement);
  	/* Look for the `)'.  */
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	/* Look for the `;'.  */
--- 6403,6413 ----
  	/* Look for the `while' keyword.  */
  	cp_parser_require_keyword (parser, RID_WHILE, "`while'");
  	/* Look for the `('.  */
  	cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
  	/* Parse the expression.  */
! 	expression = cp_parser_expression (parser, /*cast_p=*/false);
  	/* We're done with the do-statement.  */
  	finish_do_stmt (expression, statement);
  	/* Look for the `)'.  */
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  	/* Look for the `;'.  */
*************** cp_parser_iteration_statement (cp_parser
*** 6367,6377 ****
  	/* Look for the `;'.  */
  	cp_parser_require (parser, CPP_SEMICOLON, "`;'");
  
  	/* If there's an expression, process it.  */
  	if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
! 	  expression = cp_parser_expression (parser);
  	finish_for_expr (expression, statement);
  	/* Look for the `)'.  */
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  
  	/* Parse the body of the for-statement.  */
--- 6435,6445 ----
  	/* Look for the `;'.  */
  	cp_parser_require (parser, CPP_SEMICOLON, "`;'");
  
  	/* If there's an expression, process it.  */
  	if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
! 	  expression = cp_parser_expression (parser, /*cast_p=*/false);
  	finish_for_expr (expression, statement);
  	/* Look for the `)'.  */
  	cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  
  	/* Parse the body of the for-statement.  */
*************** cp_parser_jump_statement (cp_parser* par
*** 6484,6494 ****
  	tree expr;
  
  	/* 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);
  	else
  	  expr = NULL_TREE;
  	/* Build the return-statement.  */
  	statement = finish_return_stmt (expr);
  	/* Look for the final `;'.  */
--- 6552,6562 ----
  	tree expr;
  
  	/* 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, /*cast_p=*/false);
  	else
  	  expr = NULL_TREE;
  	/* Build the return-statement.  */
  	statement = finish_return_stmt (expr);
  	/* Look for the final `;'.  */
*************** cp_parser_jump_statement (cp_parser* par
*** 6504,6514 ****
  	  if (pedantic)
  	    pedwarn ("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));
  	}
        else
  	finish_goto_stmt (cp_parser_identifier (parser));
        /* Look for the final `;'.  */
        cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
--- 6572,6582 ----
  	  if (pedantic)
  	    pedwarn ("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));
  	}
        else
  	finish_goto_stmt (cp_parser_identifier (parser));
        /* Look for the final `;'.  */
        cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
*************** cp_parser_mem_initializer (cp_parser* pa
*** 7619,7628 ****
--- 7687,7697 ----
    if (member && !DECL_P (member))
      in_base_initializer = 1;
  
    expression_list
      = cp_parser_parenthesized_expression_list (parser, false,
+ 					       /*cast_p=*/false,
  					       /*non_constant_p=*/NULL);
    if (!expression_list)
      expression_list = void_type_node;
  
    in_base_initializer = 0;
*************** cp_parser_template_argument (cp_parser* 
*** 8823,8832 ****
--- 8892,8902 ----
    /* Look for a non-type template parameter.  */
    if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
      {
        cp_parser_parse_tentatively (parser);
        argument = cp_parser_primary_expression (parser,
+ 					       /*cast_p=*/false,
  					       &idk,
  					       &qualifying_class);
        if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX
  	  || !cp_parser_next_token_ends_template_argument_p (parser))
  	cp_parser_simulate_error (parser);
*************** cp_parser_template_argument (cp_parser* 
*** 8847,8856 ****
--- 8917,8927 ----
        || token->type == CPP_TEMPLATE_ID
        || token->type == CPP_NESTED_NAME_SPECIFIER)
      {
        cp_parser_parse_tentatively (parser);
        argument = cp_parser_primary_expression (parser,
+ 					       /*cast_p=*/false,
  					       &idk,
  					       &qualifying_class);
        if (cp_parser_error_occurred (parser)
  	  || !cp_parser_next_token_ends_template_argument_p (parser))
  	cp_parser_abort_tentative_parse (parser);
*************** cp_parser_parameter_declaration (cp_pars
*** 11870,11880 ****
  	     appear in a default argument.  */
  	  saved_local_variables_forbidden_p
  	    = parser->local_variables_forbidden_p;
  	  parser->local_variables_forbidden_p = true;
  	  /* Parse the assignment-expression.  */
! 	  default_argument = cp_parser_assignment_expression (parser);
  	  /* Restore saved state.  */
  	  parser->greater_than_is_operator_p
  	    = saved_greater_than_is_operator_p;
  	  parser->local_variables_forbidden_p
  	    = saved_local_variables_forbidden_p;
--- 11941,11952 ----
  	     appear in a default argument.  */
  	  saved_local_variables_forbidden_p
  	    = parser->local_variables_forbidden_p;
  	  parser->local_variables_forbidden_p = true;
  	  /* Parse the assignment-expression.  */
! 	  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;
  	  parser->local_variables_forbidden_p
  	    = saved_local_variables_forbidden_p;
*************** cp_parser_initializer (cp_parser* parser
*** 11968,11977 ****
--- 12040,12050 ----
        /* Parse the initializer-clause.  */
        init = cp_parser_initializer_clause (parser, non_constant_p);
      }
    else if (token->type == CPP_OPEN_PAREN)
      init = cp_parser_parenthesized_expression_list (parser, false,
+ 						    /*cast_p=*/false,
  						    non_constant_p);
    else
      {
        /* Anything else is an error.  */
        cp_parser_error (parser, "expected initializer");
*************** cp_parser_throw_expression (cp_parser* p
*** 13743,13753 ****
        || token->type == CPP_CLOSE_SQUARE
        || token->type == CPP_CLOSE_BRACE
        || token->type == CPP_COLON)
      expression = NULL_TREE;
    else
!     expression = cp_parser_assignment_expression (parser);
  
    return build_throw (expression);
  }
  
  /* GNU Extensions */
--- 13816,13827 ----
        || token->type == CPP_CLOSE_SQUARE
        || token->type == CPP_CLOSE_BRACE
        || token->type == CPP_COLON)
      expression = NULL_TREE;
    else
!     expression = cp_parser_assignment_expression (parser,
! 						  /*cast_p=*/false);
  
    return build_throw (expression);
  }
  
  /* GNU Extensions */
*************** cp_parser_asm_operand_list (cp_parser* p
*** 13833,13843 ****
        string_literal = cp_parser_string_literal (parser, false, false);
  
        /* Look for the `('.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
        /* Parse the expression.  */
!       expression = cp_parser_expression (parser);
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  
        /* Add this operand to the list.  */
        asm_operands = tree_cons (build_tree_list (name, string_literal),
--- 13907,13917 ----
        string_literal = cp_parser_string_literal (parser, false, false);
  
        /* Look for the `('.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
        /* Parse the expression.  */
!       expression = cp_parser_expression (parser, /*cast_p=*/false);
        /* Look for the `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  
        /* Add this operand to the list.  */
        asm_operands = tree_cons (build_tree_list (name, string_literal),
*************** cp_parser_attribute_list (cp_parser* par
*** 13989,13999 ****
        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;
  	}
  
        /* Add this attribute to the list.  */
--- 14063,14074 ----
        if (token->type == CPP_OPEN_PAREN)
  	{
  	  tree 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.  */
*************** cp_parser_single_declaration (cp_parser*
*** 14966,14976 ****
  /* Parse a cast-expression that is not the operand of a unary "&".  */
  
  static tree
  cp_parser_simple_cast_expression (cp_parser *parser)
  {
!   return cp_parser_cast_expression (parser, /*address_p=*/false);
  }
  
  /* Parse a functional cast to TYPE.  Returns an expression
     representing the cast.  */
  
--- 15041,15052 ----
  /* Parse a cast-expression that is not the operand of a unary "&".  */
  
  static tree
  cp_parser_simple_cast_expression (cp_parser *parser)
  {
!   return cp_parser_cast_expression (parser, /*address_p=*/false,
! 				    /*cast_p=*/false);
  }
  
  /* Parse a functional cast to TYPE.  Returns an expression
     representing the cast.  */
  
*************** cp_parser_functional_cast (cp_parser* pa
*** 14980,14989 ****
--- 15056,15066 ----
    tree expression_list;
    tree cast;
  
    expression_list
      = cp_parser_parenthesized_expression_list (parser, false,
+ 					       /*cast_p=*/true,
  					       /*non_constant_p=*/NULL);
  
    cast = build_functional_cast (type, expression_list);
    /* [expr.const]/1: In an integral constant expression "only type
       conversions to integral or enumeration type can be used".  */
*************** cp_parser_late_parsing_default_args (cp_
*** 15263,15273 ****
  	  lexer stack.  */
        tokens = DEFARG_TOKENS (TREE_PURPOSE (parm));
        cp_parser_push_lexer_for_tokens (parser, tokens);
  
        /* Parse the assignment-expression.  */
!       TREE_PURPOSE (parm) = cp_parser_assignment_expression (parser);
  
        /* If the token stream has not been completely used up, then
  	 there was extra junk after the end of the default
  	 argument.  */
        if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF))
--- 15340,15351 ----
  	  lexer stack.  */
        tokens = DEFARG_TOKENS (TREE_PURPOSE (parm));
        cp_parser_push_lexer_for_tokens (parser, tokens);
  
        /* Parse the assignment-expression.  */
!       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
  	 argument.  */
        if (!cp_lexer_next_token_is (parser->lexer, CPP_EOF))
*************** cp_parser_sizeof_operand (cp_parser* par
*** 15295,15304 ****
--- 15373,15383 ----
  {
    static const char *format;
    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)
      format = "types may not be defined in '%s' expressions";
  
*************** cp_parser_sizeof_operand (cp_parser* par
*** 15313,15323 ****
    sprintf ((char *) parser->type_definition_forbidden_message,
  	   format, IDENTIFIER_POINTER (ridpointers[keyword]));
  
    /* The restrictions on constant-expressions do not apply inside
       sizeof expressions.  */
!   saved_integral_constant_expression_p = parser->integral_constant_expression_p;
    parser->integral_constant_expression_p = false;
  
    /* Do not actually evaluate the expression.  */
    ++skip_evaluation;
    /* If it's a `(', then we might be looking at the type-id
--- 15392,15405 ----
    sprintf ((char *) parser->type_definition_forbidden_message,
  	   format, IDENTIFIER_POINTER (ridpointers[keyword]));
  
    /* The restrictions on constant-expressions do not apply inside
       sizeof expressions.  */
!   saved_integral_constant_expression_p 
!     = parser->integral_constant_expression_p;
!   saved_non_integral_constant_expression_p
!     = parser->non_integral_constant_expression_p;
    parser->integral_constant_expression_p = false;
  
    /* Do not actually evaluate the expression.  */
    ++skip_evaluation;
    /* If it's a `(', then we might be looking at the type-id
*************** cp_parser_sizeof_operand (cp_parser* par
*** 15358,15376 ****
      }
  
    /* 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);
    /* Go back to evaluating expressions.  */
    --skip_evaluation;
  
    /* Free the message we created.  */
    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;
  
    return expr;
  }
  
  /* If the current declaration has no declarator, return true.  */
--- 15440,15462 ----
      }
  
    /* 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,
! 				       /*cast_p=*/false);
    /* Go back to evaluating expressions.  */
    --skip_evaluation;
  
    /* Free the message we created.  */
    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->non_integral_constant_expression_p
!     = saved_non_integral_constant_expression_p;
  
    return expr;
  }
  
  /* If the current declaration has no declarator, return true.  */
Index: gcc/testsuite/g++.dg/other/warning1.C
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/g++.dg/other/warning1.C,v
retrieving revision 1.1
diff -c -5 -p -r1.1 warning1.C
*** gcc/testsuite/g++.dg/other/warning1.C	5 Oct 2002 12:28:16 -0000	1.1
--- gcc/testsuite/g++.dg/other/warning1.C	1 Feb 2005 00:46:05 -0000
***************
*** 5,16 ****
  
  extern "C" int printf(const char *, ...);
  
  struct S
  {
!   static const float inf = 1.0f / 0.0f; // { dg-warning "1.0|initialization" }
!   static const float nan = 0.0f / 0.0f; // { dg-warning "0.0|initialization" }
  };
  
  int main()
  {
    printf("%f\n%f\n", S::inf, S::nan);
--- 5,16 ----
  
  extern "C" int printf(const char *, ...);
  
  struct S
  {
!   static const float inf = 1.0f / 0.0f; // { dg-warning "1.0|float|initialization" }
!   static const float nan = 0.0f / 0.0f; // { dg-warning "0.0|float|initialization" }
  };
  
  int main()
  {
    printf("%f\n%f\n", S::inf, S::nan);
Index: gcc/testsuite/g++.dg/parse/constant5.C
===================================================================
RCS file: gcc/testsuite/g++.dg/parse/constant5.C
diff -N gcc/testsuite/g++.dg/parse/constant5.C
*** /dev/null	1 Jan 1970 00:00:00 -0000
--- gcc/testsuite/g++.dg/parse/constant5.C	1 Feb 2005 00:46:05 -0000
***************
*** 0 ****
--- 1,14 ----
+ enum E { 
+   a = 24.2, // { dg-error "constant" }
+   b = (int)3.7, 
+   c = int(4.2),
+   d = (int)(4.2 + 3.7), // { dg-error "constant" }
+   e = int(4.2 - 3.7), // { dg-error "constant" }
+   f = (int)17.25
+ };
+ 
+ struct S {
+   static const int i = (int)4.2;
+   int j[(int)4.2];
+   static const int k = static_cast<short>(3.7);
+ };
Index: libstdc++-v3/include/std/std_limits.h
===================================================================
RCS file: /cvs/gcc/gcc/libstdc++-v3/include/std/std_limits.h,v
retrieving revision 1.26
diff -c -5 -p -r1.26 std_limits.h
*** libstdc++-v3/include/std/std_limits.h	24 Nov 2004 04:11:15 -0000	1.26
--- libstdc++-v3/include/std/std_limits.h	1 Feb 2005 00:46:05 -0000
*************** namespace std
*** 1005,1015 ****
  
        static const bool has_infinity = __FLT_HAS_INFINITY__;
        static const bool has_quiet_NaN = __FLT_HAS_QUIET_NAN__;
        static const bool has_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
! 	= __FLT_DENORM_MIN__ ? denorm_present : denorm_absent;
        static const bool has_denorm_loss = __glibcxx_float_has_denorm_loss;
  
        static float infinity() throw()
        { return __builtin_huge_valf (); }
        static float quiet_NaN() throw()
--- 1005,1015 ----
  
        static const bool has_infinity = __FLT_HAS_INFINITY__;
        static const bool has_quiet_NaN = __FLT_HAS_QUIET_NAN__;
        static const bool has_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
! 	= bool(__FLT_DENORM_MIN__) ? denorm_present : denorm_absent;
        static const bool has_denorm_loss = __glibcxx_float_has_denorm_loss;
  
        static float infinity() throw()
        { return __builtin_huge_valf (); }
        static float quiet_NaN() throw()
*************** namespace std
*** 1062,1072 ****
  
        static const bool has_infinity = __DBL_HAS_INFINITY__;
        static const bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__;
        static const bool has_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
! 	= __DBL_DENORM_MIN__ ? denorm_present : denorm_absent;
        static const bool has_denorm_loss = __glibcxx_double_has_denorm_loss;
  
        static double infinity() throw()
        { return __builtin_huge_val(); }
        static double quiet_NaN() throw()
--- 1062,1072 ----
  
        static const bool has_infinity = __DBL_HAS_INFINITY__;
        static const bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__;
        static const bool has_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
! 	= bool(__DBL_DENORM_MIN__) ? denorm_present : denorm_absent;
        static const bool has_denorm_loss = __glibcxx_double_has_denorm_loss;
  
        static double infinity() throw()
        { return __builtin_huge_val(); }
        static double quiet_NaN() throw()
*************** namespace std
*** 1119,1129 ****
  
        static const bool has_infinity = __LDBL_HAS_INFINITY__;
        static const bool has_quiet_NaN = __LDBL_HAS_QUIET_NAN__;
        static const bool has_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
! 	= __LDBL_DENORM_MIN__ ? denorm_present : denorm_absent;
        static const bool has_denorm_loss
  	= __glibcxx_long_double_has_denorm_loss;
  
        static long double infinity() throw()
        { return __builtin_huge_vall (); }
--- 1119,1129 ----
  
        static const bool has_infinity = __LDBL_HAS_INFINITY__;
        static const bool has_quiet_NaN = __LDBL_HAS_QUIET_NAN__;
        static const bool has_signaling_NaN = has_quiet_NaN;
        static const float_denorm_style has_denorm
! 	= bool(__LDBL_DENORM_MIN__) ? denorm_present : denorm_absent;
        static const bool has_denorm_loss
  	= __glibcxx_long_double_has_denorm_loss;
  
        static long double infinity() throw()
        { return __builtin_huge_vall (); }
  


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]