From 640aa28c350fee76a59e94625a2270ffee308dae Mon Sep 17 00:00:00 2001
From: mmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Date: Tue, 1 Feb 2005 01:01:34 +0000
Subject: [PATCH] 	* 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.

	* 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.

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


git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@94512 138bc75d-0d04-0410-961f-82ee72b054a4
---
 gcc/cp/ChangeLog                       |  39 +++++
 gcc/cp/decl.c                          |   5 +
 gcc/cp/parser.c                        | 210 +++++++++++++++++--------
 gcc/testsuite/ChangeLog                |   5 +
 gcc/testsuite/g++.dg/other/warning1.C  |   4 +-
 gcc/testsuite/g++.dg/parse/constant5.C |  14 ++
 libstdc++-v3/ChangeLog                 |   7 +
 libstdc++-v3/include/std/std_limits.h  |   6 +-
 8 files changed, 223 insertions(+), 67 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/parse/constant5.C

diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1baaf0b5849d..92cebfa46a99 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,42 @@
+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  Mike Stump  <mrs@apple.com>
 
 	* parser.c (cp_lexer_new_main): Get the first token, first, before
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 964feaa08fe4..9be5adf4af3c 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9682,6 +9682,11 @@ build_enumerator (tree name, tree value, tree enumtype)
   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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index ab2a103acec9..e5ea0699aae8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1357,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
@@ -1369,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
@@ -1397,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
@@ -1945,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)
@@ -1958,7 +1960,6 @@ 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;
 }
@@ -2639,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.
@@ -2650,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)
 {
@@ -2674,6 +2678,42 @@ 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)
+	{
+	  /* 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:
@@ -2724,7 +2764,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
@@ -2803,7 +2843,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.  */
@@ -3666,12 +3707,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;
@@ -3718,7 +3760,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
@@ -3791,7 +3833,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.  */
@@ -3923,6 +3965,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);
       }
@@ -3981,7 +4024,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)
 	      {
@@ -4174,7 +4219,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, "`]'");
@@ -4354,6 +4399,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.
@@ -4367,6 +4414,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;
@@ -4411,7 +4459,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);
@@ -4569,12 +4617,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;
@@ -4702,7 +4751,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)
 	{
@@ -4741,7 +4792,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
@@ -4862,7 +4913,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;
 }
@@ -5009,7 +5061,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
@@ -5065,7 +5117,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;
 
@@ -5124,10 +5177,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))
@@ -5197,7 +5254,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))
 	{
@@ -5227,7 +5286,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:
@@ -5297,6 +5356,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.  */
 
@@ -5306,7 +5367,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];
@@ -5317,7 +5378,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 (;;)
     {
@@ -5431,12 +5492,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,
@@ -5451,10 +5512,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;
 
@@ -5467,7 +5530,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))
@@ -5485,7 +5548,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,
@@ -5600,10 +5663,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;
 
@@ -5613,7 +5678,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)
@@ -5691,14 +5756,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;
 }
@@ -6009,18 +6078,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
@@ -6247,7 +6314,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,
@@ -6267,7 +6335,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.
@@ -6340,7 +6408,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 `)'.  */
@@ -6372,7 +6440,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, "`)'");
@@ -6489,7 +6557,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.  */
@@ -6509,7 +6577,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));
@@ -7624,6 +7692,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;
@@ -8828,6 +8897,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
@@ -8852,6 +8922,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)
@@ -11875,7 +11946,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;
@@ -11973,6 +12045,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
     {
@@ -13748,7 +13821,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);
 }
@@ -13838,7 +13912,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, "`)'");
 
@@ -13994,7 +14068,8 @@ cp_parser_attribute_list (cp_parser* parser)
 	  tree arguments;
 
 	  arguments = (cp_parser_parenthesized_expression_list
-		       (parser, true, /*non_constant_p=*/NULL));
+		       (parser, true, /*cast_p=*/false, 
+			/*non_constant_p=*/NULL));
 	  /* Save the identifier and arguments away.  */
 	  TREE_VALUE (attribute) = arguments;
 	}
@@ -14971,7 +15046,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
@@ -14985,6 +15061,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);
@@ -15268,7 +15345,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
@@ -15300,6 +15378,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)
@@ -15318,7 +15397,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.  */
@@ -15363,7 +15445,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;
 
@@ -15371,7 +15454,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;
 }
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 258e232e8882..4c7011ec9901 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2005-01-31  Mark Mitchell  <mark@codesourcery.com>
+
+	* g++.dg/other/warning1.C: Adjust error messags.
+	* g++.dg/parse/constant5.C: New test.
+
 2005-01-31  Steven Bosscher  <stevenb@suse.de>
 
 	PR c/19333
diff --git a/gcc/testsuite/g++.dg/other/warning1.C b/gcc/testsuite/g++.dg/other/warning1.C
index 109fc46aa22b..a5cce6ce0411 100644
--- a/gcc/testsuite/g++.dg/other/warning1.C
+++ b/gcc/testsuite/g++.dg/other/warning1.C
@@ -7,8 +7,8 @@ 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" }
+  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()
diff --git a/gcc/testsuite/g++.dg/parse/constant5.C b/gcc/testsuite/g++.dg/parse/constant5.C
new file mode 100644
index 000000000000..db11afb51b25
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/constant5.C
@@ -0,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);
+};
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index c3c526d0dc5c..f875fa4ab3af 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,10 @@
+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  Paolo Carlini  <pcarlini@suse.de>
 	    Gabriel Dos Reis  <gdr@integrable-solutions.net>
 
diff --git a/libstdc++-v3/include/std/std_limits.h b/libstdc++-v3/include/std/std_limits.h
index 9bc99e1a4e9c..6927de1ccb4e 100644
--- a/libstdc++-v3/include/std/std_limits.h
+++ b/libstdc++-v3/include/std/std_limits.h
@@ -1007,7 +1007,7 @@ namespace std
       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;
+	= bool(__FLT_DENORM_MIN__) ? denorm_present : denorm_absent;
       static const bool has_denorm_loss = __glibcxx_float_has_denorm_loss;
 
       static float infinity() throw()
@@ -1064,7 +1064,7 @@ namespace std
       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;
+	= bool(__DBL_DENORM_MIN__) ? denorm_present : denorm_absent;
       static const bool has_denorm_loss = __glibcxx_double_has_denorm_loss;
 
       static double infinity() throw()
@@ -1121,7 +1121,7 @@ namespace std
       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;
+	= bool(__LDBL_DENORM_MIN__) ? denorm_present : denorm_absent;
       static const bool has_denorm_loss
 	= __glibcxx_long_double_has_denorm_loss;
 
-- 
GitLab