This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: Disallow floating-point literals in integral-constant expressions
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: libstdc++ at gcc dot gnu dot org
- Date: Mon, 31 Jan 2005 17:02:18 -0800
- Subject: C++ PATCH: Disallow floating-point literals in integral-constant expressions
- Reply-to: mark at codesourcery dot com
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 (); }