re PR c++/11547 (ICE with const temporaries)

PR c++/11547
	* cp-tree.h (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P): New
	macro.
	(DECL_PRETTY_FUNCTION_P): Use VAR_DECL_CHECK.
	* decl.c (duplicate_decls): Merge
	DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.
	* parser.c (cp_parser_postfix_expression): Adjust call to
	cp_parser_initializer_list and
	cp_parser_parenthesized_expression_list.
	(cp_parser_parenthesized_expression_list): Add non_constant_p.
	(cp_parser_new_placement): Adjust call to
	cp_parser_parenthesized_expression_list.
	(cp_parser_direct_new_declarator): Likewise.
	(cp_parser_conditional_expression): Remove.
	(cp_parser_constant_expression): Parse an assignment-expression,
	not a conditional-expression.
	(cp_parser_simple_declaration): Resolve expression/declaration
	ambiguity more quickly.
	(cp_parser_mem_initializer): Adjust call to
	cp_parser_parenthesized_expression_list.
	(cp_parser_init_declarator): Keep track of whether or not the
	initializer is a constant-expression.
	(cp_parser_initializer): Add non_constant_p parameter.
	(cp_parser_initializer_clause): Likewise.
	(cp_parser_initializer_list): Likewise.
	(cp_parser_attribute_list): Adjust call to
	cp_parser_parenthesized_expression_list.
	(cp_parser_functional_cast): Likewise.
	* pt.c (tsubst_decl): Copy
	DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.
	(tsubst_expr): Tweak use of DECL_PRETTY_FUNCTION_P.
	* semantics.c (finish_id_expression): Use
	DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.

	PR c++/11547
	* g++.dg/parse/constant3.C: New test.
	* g++.dg/parse/crash7.C: Likewise.

From-SVN: r69493
This commit is contained in:
Mark Mitchell 2003-07-17 04:31:42 +00:00 committed by Mark Mitchell
parent db5eed1873
commit 39703eb9e2
9 changed files with 200 additions and 93 deletions

View File

@ -1,3 +1,39 @@
2003-07-16 Mark Mitchell <mark@codesourcery.com>
PR c++/11547
* cp-tree.h (DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P): New
macro.
(DECL_PRETTY_FUNCTION_P): Use VAR_DECL_CHECK.
* decl.c (duplicate_decls): Merge
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.
* parser.c (cp_parser_postfix_expression): Adjust call to
cp_parser_initializer_list and
cp_parser_parenthesized_expression_list.
(cp_parser_parenthesized_expression_list): Add non_constant_p.
(cp_parser_new_placement): Adjust call to
cp_parser_parenthesized_expression_list.
(cp_parser_direct_new_declarator): Likewise.
(cp_parser_conditional_expression): Remove.
(cp_parser_constant_expression): Parse an assignment-expression,
not a conditional-expression.
(cp_parser_simple_declaration): Resolve expression/declaration
ambiguity more quickly.
(cp_parser_mem_initializer): Adjust call to
cp_parser_parenthesized_expression_list.
(cp_parser_init_declarator): Keep track of whether or not the
initializer is a constant-expression.
(cp_parser_initializer): Add non_constant_p parameter.
(cp_parser_initializer_clause): Likewise.
(cp_parser_initializer_list): Likewise.
(cp_parser_attribute_list): Adjust call to
cp_parser_parenthesized_expression_list.
(cp_parser_functional_cast): Likewise.
* pt.c (tsubst_decl): Copy
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.
(tsubst_expr): Tweak use of DECL_PRETTY_FUNCTION_P.
* semantics.c (finish_id_expression): Use
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P.
2003-07-16 Neil Booth <neil@daikokuya.co.uk> 2003-07-16 Neil Booth <neil@daikokuya.co.uk>
* lang-options.h: Remove. * lang-options.h: Remove.

View File

@ -45,6 +45,7 @@ struct diagnostic_context;
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR) AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF) PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
PARMLIST_ELLIPSIS_P (in PARMLIST) PARMLIST_ELLIPSIS_P (in PARMLIST)
DECL_PRETTY_FUNCTION_P (in VAR_DECL)
1: IDENTIFIER_VIRTUAL_P. 1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG. TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE. TEMPLATE_PARMS_FOR_INLINE.
@ -59,6 +60,7 @@ struct diagnostic_context;
ICS_THIS_FLAG (in _CONV) ICS_THIS_FLAG (in _CONV)
BINFO_LOST_PRIMARY_P (in BINFO) BINFO_LOST_PRIMARY_P (in BINFO)
TREE_PARMLIST (in TREE_LIST) TREE_PARMLIST (in TREE_LIST)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
BINFO_VTABLE_PATH_MARKED. BINFO_VTABLE_PATH_MARKED.
BINFO_PUSHDECLS_MARKED. BINFO_PUSHDECLS_MARKED.
@ -1926,6 +1928,11 @@ struct lang_decl GTY(())
#define DECL_INITIALIZED_P(NODE) \ #define DECL_INITIALIZED_P(NODE) \
(TREE_LANG_FLAG_1 (VAR_DECL_CHECK (NODE))) (TREE_LANG_FLAG_1 (VAR_DECL_CHECK (NODE)))
/* Nonzero for a VAR_DECL that was initialized with a
constant-expression. */
#define DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P(NODE) \
(TREE_LANG_FLAG_2 (VAR_DECL_CHECK (NODE)))
/* Nonzero if the DECL was initialized in the class definition itself, /* Nonzero if the DECL was initialized in the class definition itself,
rather than outside the class. This is used for both static member rather than outside the class. This is used for both static member
VAR_DECLS, and FUNTION_DECLS that are defined in the class. */ VAR_DECLS, and FUNTION_DECLS that are defined in the class. */
@ -2033,7 +2040,7 @@ struct lang_decl GTY(())
/* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a /* Nonzero if this DECL is the __PRETTY_FUNCTION__ variable in a
template function. */ template function. */
#define DECL_PRETTY_FUNCTION_P(NODE) \ #define DECL_PRETTY_FUNCTION_P(NODE) \
(TREE_LANG_FLAG_0 (NODE)) (TREE_LANG_FLAG_0 (VAR_DECL_CHECK (NODE)))
/* The _TYPE context in which this _DECL appears. This field holds the /* The _TYPE context in which this _DECL appears. This field holds the
class where a virtual function instance is actually defined. */ class where a virtual function instance is actually defined. */

View File

@ -3306,6 +3306,8 @@ duplicate_decls (tree newdecl, tree olddecl)
{ {
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl); DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl); DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (olddecl);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (newdecl)
|= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (olddecl);
} }
/* Do this after calling `merge_types' so that default /* Do this after calling `merge_types' so that default

View File

@ -1311,7 +1311,7 @@ static tree cp_parser_class_or_namespace_name
static tree cp_parser_postfix_expression static tree cp_parser_postfix_expression
(cp_parser *, bool); (cp_parser *, bool);
static tree cp_parser_parenthesized_expression_list static tree cp_parser_parenthesized_expression_list
(cp_parser *, bool); (cp_parser *, bool, bool *);
static void cp_parser_pseudo_destructor_name static void cp_parser_pseudo_destructor_name
(cp_parser *, tree *, tree *); (cp_parser *, tree *, tree *);
static tree cp_parser_unary_expression static tree cp_parser_unary_expression
@ -1356,8 +1356,6 @@ static tree cp_parser_logical_and_expression
(cp_parser *); (cp_parser *);
static tree cp_parser_logical_or_expression static tree cp_parser_logical_or_expression
(cp_parser *); (cp_parser *);
static tree cp_parser_conditional_expression
(cp_parser *);
static tree cp_parser_question_colon_clause static tree cp_parser_question_colon_clause
(cp_parser *, tree); (cp_parser *, tree);
static tree cp_parser_assignment_expression static tree cp_parser_assignment_expression
@ -1479,11 +1477,11 @@ static tree cp_parser_function_definition
static void cp_parser_function_body static void cp_parser_function_body
(cp_parser *); (cp_parser *);
static tree cp_parser_initializer static tree cp_parser_initializer
(cp_parser *, bool *); (cp_parser *, bool *, bool *);
static tree cp_parser_initializer_clause static tree cp_parser_initializer_clause
(cp_parser *); (cp_parser *, bool *);
static tree cp_parser_initializer_list static tree cp_parser_initializer_list
(cp_parser *); (cp_parser *, bool *);
static bool cp_parser_ctor_initializer_opt_and_function_body static bool cp_parser_ctor_initializer_opt_and_function_body
(cp_parser *); (cp_parser *);
@ -3375,9 +3373,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
keep going. */ keep going. */
if (!cp_parser_error_occurred (parser)) if (!cp_parser_error_occurred (parser))
{ {
bool non_constant_p;
/* Parse the initializer-list. */ /* Parse the initializer-list. */
initializer_list initializer_list
= cp_parser_initializer_list (parser); = cp_parser_initializer_list (parser, &non_constant_p);
/* Allow a trailing `,'. */ /* Allow a trailing `,'. */
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
@ -3472,7 +3471,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
case CPP_OPEN_PAREN: case CPP_OPEN_PAREN:
/* postfix-expression ( expression-list [opt] ) */ /* postfix-expression ( expression-list [opt] ) */
{ {
tree args = cp_parser_parenthesized_expression_list (parser, false); tree args = (cp_parser_parenthesized_expression_list
(parser, false, /*non_constant_p=*/NULL));
if (args == error_mark_node) if (args == error_mark_node)
{ {
@ -3735,14 +3735,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
error_mark_node is returned if the ( and or ) are error_mark_node is returned if the ( and or ) are
missing. NULL_TREE is returned on no expressions. The parentheses missing. NULL_TREE is returned on no expressions. The parentheses
are eaten. IS_ATTRIBUTE_LIST is true if this is really an attribute are eaten. IS_ATTRIBUTE_LIST is true if this is really an attribute
list being parsed. */ list being parsed. If NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P
indicates whether or not all of the expressions in the list were
constant. */
static tree static tree
cp_parser_parenthesized_expression_list (cp_parser* parser, bool is_attribute_list) cp_parser_parenthesized_expression_list (cp_parser* parser,
bool is_attribute_list,
bool *non_constant_p)
{ {
tree expression_list = NULL_TREE; tree expression_list = NULL_TREE;
tree identifier = NULL_TREE; tree identifier = NULL_TREE;
/* Assume all the expressions will be constant. */
if (non_constant_p)
*non_constant_p = false;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('")) if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
return error_mark_node; return error_mark_node;
@ -3767,7 +3775,17 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, bool is_attribute_li
else else
{ {
/* Parse the next assignment-expression. */ /* Parse the next assignment-expression. */
expr = cp_parser_assignment_expression (parser); if (non_constant_p)
{
bool expr_non_constant_p;
expr = (cp_parser_constant_expression
(parser, /*allow_non_constant_p=*/true,
&expr_non_constant_p));
if (expr_non_constant_p)
*non_constant_p = true;
}
else
expr = cp_parser_assignment_expression (parser);
/* Add it to the list. We add error_mark_node /* Add it to the list. We add error_mark_node
expressions to the list, so that we can still tell if expressions to the list, so that we can still tell if
@ -4177,7 +4195,8 @@ cp_parser_new_placement (cp_parser* parser)
tree expression_list; tree expression_list;
/* Parse the expression-list. */ /* Parse the expression-list. */
expression_list = cp_parser_parenthesized_expression_list (parser, false); expression_list = (cp_parser_parenthesized_expression_list
(parser, false, /*non_constant_p=*/NULL));
return expression_list; return expression_list;
} }
@ -4341,7 +4360,8 @@ cp_parser_new_initializer (cp_parser* parser)
{ {
tree expression_list; tree expression_list;
expression_list = cp_parser_parenthesized_expression_list (parser, false); expression_list = (cp_parser_parenthesized_expression_list
(parser, false, /*non_constant_p=*/NULL));
if (!expression_list) if (!expression_list)
expression_list = void_zero_node; expression_list = void_zero_node;
@ -4755,43 +4775,12 @@ cp_parser_logical_or_expression (cp_parser* parser)
cp_parser_logical_and_expression); cp_parser_logical_and_expression);
} }
/* Parse a conditional-expression.
conditional-expression:
logical-or-expression
logical-or-expression ? expression : assignment-expression
GNU Extensions:
conditional-expression:
logical-or-expression ? : assignment-expression
Returns a representation of the expression. */
static tree
cp_parser_conditional_expression (cp_parser* parser)
{
tree logical_or_expr;
/* Parse the logical-or-expression. */
logical_or_expr = cp_parser_logical_or_expression (parser);
/* If the next token is a `?', then we have a real conditional
expression. */
if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
return cp_parser_question_colon_clause (parser, logical_or_expr);
/* Otherwise, the value is simply the logical-or-expression. */
else
return logical_or_expr;
}
/* Parse the `? expression : assignment-expression' part of a /* Parse the `? expression : assignment-expression' part of a
conditional-expression. The LOGICAL_OR_EXPR is the conditional-expression. The LOGICAL_OR_EXPR is the
logical-or-expression that started the conditional-expression. logical-or-expression that started the conditional-expression.
Returns a representation of the entire conditional-expression. Returns a representation of the entire conditional-expression.
This routine exists only so that it can be shared between This routine is used by cp_parser_assignment_expression.
cp_parser_conditional_expression and
cp_parser_assignment_expression.
? expression : assignment-expression ? expression : assignment-expression
@ -5071,8 +5060,16 @@ cp_parser_constant_expression (cp_parser* parser,
parser->constant_expression_p = true; parser->constant_expression_p = true;
parser->allow_non_constant_expression_p = allow_non_constant_p; parser->allow_non_constant_expression_p = allow_non_constant_p;
parser->non_constant_expression_p = false; parser->non_constant_expression_p = false;
/* Parse the conditional-expression. */ /* Although the grammar says "conditional-expression", we parse an
expression = cp_parser_conditional_expression (parser); "assignment-expression", which also permits "throw-expression"
and the use of assignment operators. In the case that
ALLOW_NON_CONSTANT_P is false, we get better errors than we would
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. */ /* Restore the old settings. */
parser->constant_expression_p = saved_constant_expression_p; parser->constant_expression_p = saved_constant_expression_p;
parser->allow_non_constant_expression_p parser->allow_non_constant_expression_p
@ -6081,6 +6078,15 @@ cp_parser_simple_declaration (cp_parser* parser,
/* We no longer need to defer access checks. */ /* We no longer need to defer access checks. */
stop_deferring_access_checks (); stop_deferring_access_checks ();
/* In a block scope, a valid declaration must always have a
decl-specifier-seq. By not trying to parse declarators, we can
resolve the declaration/expression ambiguity more quickly. */
if (!function_definition_allowed_p && !decl_specifiers)
{
cp_parser_error (parser, "expected declaration");
goto done;
}
/* If the next two tokens are both identifiers, the code is /* If the next two tokens are both identifiers, the code is
erroneous. The usual cause of this situation is code like: erroneous. The usual cause of this situation is code like:
@ -6093,7 +6099,7 @@ cp_parser_simple_declaration (cp_parser* parser,
looking at a declaration. */ looking at a declaration. */
cp_parser_commit_to_tentative_parse (parser); cp_parser_commit_to_tentative_parse (parser);
/* Give up. */ /* Give up. */
return; goto done;
} }
/* Keep going until we hit the `;' at the end of the simple /* Keep going until we hit the `;' at the end of the simple
@ -6116,10 +6122,7 @@ cp_parser_simple_declaration (cp_parser* parser,
statement is treated as a declaration-statement until proven statement is treated as a declaration-statement until proven
otherwise.) */ otherwise.) */
if (cp_parser_error_occurred (parser)) if (cp_parser_error_occurred (parser))
{ goto done;
pop_deferring_access_checks ();
return;
}
/* Handle function definitions specially. */ /* Handle function definitions specially. */
if (function_definition_p) if (function_definition_p)
{ {
@ -6152,8 +6155,7 @@ cp_parser_simple_declaration (cp_parser* parser,
cp_parser_error (parser, "expected `,' or `;'"); cp_parser_error (parser, "expected `,' or `;'");
/* Skip tokens until we reach the end of the statement. */ /* Skip tokens until we reach the end of the statement. */
cp_parser_skip_to_end_of_statement (parser); cp_parser_skip_to_end_of_statement (parser);
pop_deferring_access_checks (); goto done;
return;
} }
/* After the first time around, a function-definition is not /* After the first time around, a function-definition is not
allowed -- even if it was OK at first. For example: allowed -- even if it was OK at first. For example:
@ -6175,14 +6177,15 @@ cp_parser_simple_declaration (cp_parser* parser,
perform_deferred_access_checks (); perform_deferred_access_checks ();
} }
pop_deferring_access_checks ();
/* Consume the `;'. */ /* Consume the `;'. */
cp_parser_require (parser, CPP_SEMICOLON, "`;'"); cp_parser_require (parser, CPP_SEMICOLON, "`;'");
/* Mark all the classes that appeared in the decl-specifier-seq as /* Mark all the classes that appeared in the decl-specifier-seq as
having received a `;'. */ having received a `;'. */
note_list_got_semicolon (decl_specifiers); note_list_got_semicolon (decl_specifiers);
done:
pop_deferring_access_checks ();
} }
/* Parse a decl-specifier-seq. /* Parse a decl-specifier-seq.
@ -6774,7 +6777,9 @@ cp_parser_mem_initializer (cp_parser* parser)
if (member && !DECL_P (member)) if (member && !DECL_P (member))
in_base_initializer = 1; in_base_initializer = 1;
expression_list = cp_parser_parenthesized_expression_list (parser, false); expression_list
= cp_parser_parenthesized_expression_list (parser, false,
/*non_constant_p=*/NULL);
if (!expression_list) if (!expression_list)
expression_list = void_type_node; expression_list = void_type_node;
@ -9156,6 +9161,7 @@ cp_parser_init_declarator (cp_parser* parser,
tree scope; tree scope;
bool is_initialized; bool is_initialized;
bool is_parenthesized_init; bool is_parenthesized_init;
bool is_non_constant_init;
int ctor_dtor_or_conv_p; int ctor_dtor_or_conv_p;
bool friend_p; bool friend_p;
@ -9325,11 +9331,14 @@ cp_parser_init_declarator (cp_parser* parser,
/* Parse the initializer. */ /* Parse the initializer. */
if (is_initialized) if (is_initialized)
initializer = cp_parser_initializer (parser, &is_parenthesized_init); initializer = cp_parser_initializer (parser,
&is_parenthesized_init,
&is_non_constant_init);
else else
{ {
initializer = NULL_TREE; initializer = NULL_TREE;
is_parenthesized_init = false; is_parenthesized_init = false;
is_non_constant_init = true;
} }
/* The old parser allows attributes to appear after a parenthesized /* The old parser allows attributes to appear after a parenthesized
@ -9371,6 +9380,12 @@ cp_parser_init_declarator (cp_parser* parser,
((is_parenthesized_init || !is_initialized) ((is_parenthesized_init || !is_initialized)
? 0 : LOOKUP_ONLYCONVERTING)); ? 0 : LOOKUP_ONLYCONVERTING));
/* Remember whether or not variables were initialized by
constant-expressions. */
if (decl && TREE_CODE (decl) == VAR_DECL
&& is_initialized && !is_non_constant_init)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = true;
return decl; return decl;
} }
@ -10729,10 +10744,13 @@ cp_parser_ctor_initializer_opt_and_function_body (cp_parser *parser)
*IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )' *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )'
production is used, and zero otherwise. *IS_PARENTHESIZED_INIT is production is used, and zero otherwise. *IS_PARENTHESIZED_INIT is
set to FALSE if there is no initializer present. */ set to FALSE if there is no initializer present. If there is an
initializer, and it is not a constant-expression, *NON_CONSTANT_P
is set to true; otherwise it is set to false. */
static tree static tree
cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init) cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
bool* non_constant_p)
{ {
cp_token *token; cp_token *token;
tree init; tree init;
@ -10743,16 +10761,19 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init)
/* Let our caller know whether or not this initializer was /* Let our caller know whether or not this initializer was
parenthesized. */ parenthesized. */
*is_parenthesized_init = (token->type == CPP_OPEN_PAREN); *is_parenthesized_init = (token->type == CPP_OPEN_PAREN);
/* Assume that the initializer is constant. */
*non_constant_p = false;
if (token->type == CPP_EQ) if (token->type == CPP_EQ)
{ {
/* Consume the `='. */ /* Consume the `='. */
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
/* Parse the initializer-clause. */ /* Parse the initializer-clause. */
init = cp_parser_initializer_clause (parser); init = cp_parser_initializer_clause (parser, non_constant_p);
} }
else if (token->type == CPP_OPEN_PAREN) else if (token->type == CPP_OPEN_PAREN)
init = cp_parser_parenthesized_expression_list (parser, false); init = cp_parser_parenthesized_expression_list (parser, false,
non_constant_p);
else else
{ {
/* Anything else is an error. */ /* Anything else is an error. */
@ -10779,17 +10800,21 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init)
the elements of the initializer-list (or NULL_TREE, if the last the elements of the initializer-list (or NULL_TREE, if the last
production is used). The TREE_TYPE for the CONSTRUCTOR will be production is used). The TREE_TYPE for the CONSTRUCTOR will be
NULL_TREE. There is no way to detect whether or not the optional NULL_TREE. There is no way to detect whether or not the optional
trailing `,' was provided. */ trailing `,' was provided. NON_CONSTANT_P is as for
cp_parser_initializer. */
static tree static tree
cp_parser_initializer_clause (cp_parser* parser) cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
{ {
tree initializer; tree initializer;
/* If it is not a `{', then we are looking at an /* If it is not a `{', then we are looking at an
assignment-expression. */ assignment-expression. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)) if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
initializer = cp_parser_assignment_expression (parser); initializer
= cp_parser_constant_expression (parser,
/*allow_non_constant_p=*/true,
non_constant_p);
else else
{ {
/* Consume the `{' token. */ /* Consume the `{' token. */
@ -10805,12 +10830,11 @@ cp_parser_initializer_clause (cp_parser* parser)
{ {
/* Parse the initializer list. */ /* Parse the initializer list. */
CONSTRUCTOR_ELTS (initializer) CONSTRUCTOR_ELTS (initializer)
= cp_parser_initializer_list (parser); = cp_parser_initializer_list (parser, non_constant_p);
/* A trailing `,' token is allowed. */ /* A trailing `,' token is allowed. */
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA)) if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer); cp_lexer_consume_token (parser->lexer);
} }
/* Now, there should be a trailing `}'. */ /* Now, there should be a trailing `}'. */
cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'"); cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
} }
@ -10832,20 +10856,25 @@ cp_parser_initializer_clause (cp_parser* parser)
Returns a TREE_LIST. The TREE_VALUE of each node is an expression Returns a TREE_LIST. The TREE_VALUE of each node is an expression
for the initializer. If the TREE_PURPOSE is non-NULL, it is the for the initializer. If the TREE_PURPOSE is non-NULL, it is the
IDENTIFIER_NODE naming the field to initialize. */ IDENTIFIER_NODE naming the field to initialize. NON_CONSTANT_P is
as for cp_parser_initializer. */
static tree static tree
cp_parser_initializer_list (cp_parser* parser) cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
{ {
tree initializers = NULL_TREE; tree initializers = NULL_TREE;
/* Assume all of the expressions are constant. */
*non_constant_p = false;
/* Parse the rest of the list. */ /* Parse the rest of the list. */
while (true) while (true)
{ {
cp_token *token; cp_token *token;
tree identifier; tree identifier;
tree initializer; tree initializer;
bool clause_non_constant_p;
/* If the next token is an identifier and the following one is a /* If the next token is an identifier and the following one is a
colon, we are looking at the GNU designated-initializer colon, we are looking at the GNU designated-initializer
syntax. */ syntax. */
@ -10862,8 +10891,11 @@ cp_parser_initializer_list (cp_parser* parser)
identifier = NULL_TREE; identifier = NULL_TREE;
/* Parse the initializer. */ /* Parse the initializer. */
initializer = cp_parser_initializer_clause (parser); initializer = cp_parser_initializer_clause (parser,
&clause_non_constant_p);
/* If any clause is non-constant, so is the entire initializer. */
if (clause_non_constant_p)
*non_constant_p = true;
/* Add it to the list. */ /* Add it to the list. */
initializers = tree_cons (identifier, initializer, initializers); initializers = tree_cons (identifier, initializer, initializers);
@ -11821,12 +11853,18 @@ cp_parser_member_declaration (cp_parser* parser)
(cp_lexer_peek_token (parser->lexer))) (cp_lexer_peek_token (parser->lexer)))
decl = error_mark_node; decl = error_mark_node;
else else
/* Create the declaration. */ {
decl = grokfield (declarator, /* Create the declaration. */
decl_specifiers, decl = grokfield (declarator,
initializer, decl_specifiers,
asm_specification, initializer,
attributes); asm_specification,
attributes);
/* Any initialization must have been from a
constant-expression. */
if (decl && TREE_CODE (decl) == VAR_DECL && initializer)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl) = 1;
}
} }
/* Reset PREFIX_ATTRIBUTES. */ /* Reset PREFIX_ATTRIBUTES. */
@ -12616,8 +12654,8 @@ cp_parser_attribute_list (cp_parser* parser)
{ {
tree arguments; tree arguments;
arguments = cp_parser_parenthesized_expression_list (parser, true); arguments = (cp_parser_parenthesized_expression_list
(parser, true, /*non_constant_p=*/NULL));
/* Save the identifier and arguments away. */ /* Save the identifier and arguments away. */
TREE_VALUE (attribute) = arguments; TREE_VALUE (attribute) = arguments;
} }
@ -13583,7 +13621,9 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
{ {
tree expression_list; tree expression_list;
expression_list = cp_parser_parenthesized_expression_list (parser, false); expression_list
= cp_parser_parenthesized_expression_list (parser, false,
/*non_constant_p=*/NULL);
return build_functional_cast (type, expression_list); return build_functional_cast (type, expression_list);
} }

View File

@ -6190,7 +6190,11 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
r = copy_decl (t); r = copy_decl (t);
if (TREE_CODE (r) == VAR_DECL) if (TREE_CODE (r) == VAR_DECL)
type = complete_type (type); {
type = complete_type (type);
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (r)
= DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t);
}
else if (DECL_SELF_REFERENCE_P (t)) else if (DECL_SELF_REFERENCE_P (t))
SET_DECL_SELF_REFERENCE_P (r); SET_DECL_SELF_REFERENCE_P (r);
TREE_TYPE (r) = type; TREE_TYPE (r) = type;
@ -7620,7 +7624,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else else
{ {
maybe_push_decl (decl); maybe_push_decl (decl);
if (DECL_PRETTY_FUNCTION_P (decl)) if (TREE_CODE (decl) == VAR_DECL
&& DECL_PRETTY_FUNCTION_P (decl))
{ {
/* For __PRETTY_FUNCTION__ we have to adjust the /* For __PRETTY_FUNCTION__ we have to adjust the
initializer. */ initializer. */

View File

@ -2478,17 +2478,11 @@ finish_id_expression (tree id_expression,
; ;
/* Const variables or static data members of integral or /* Const variables or static data members of integral or
enumeration types initialized with constant expressions enumeration types initialized with constant expressions
are OK. We also accept dependent initializers; they may are OK. */
turn out to be constant at instantiation-time. */
else if (TREE_CODE (decl) == VAR_DECL else if (TREE_CODE (decl) == VAR_DECL
&& CP_TYPE_CONST_P (TREE_TYPE (decl)) && CP_TYPE_CONST_P (TREE_TYPE (decl))
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)) && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
&& DECL_INITIAL (decl) && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
&& (TREE_CONSTANT (DECL_INITIAL (decl))
|| type_dependent_expression_p (DECL_INITIAL
(decl))
|| value_dependent_expression_p (DECL_INITIAL
(decl))))
; ;
else else
{ {

View File

@ -1,3 +1,9 @@
2003-07-16 Mark Mitchell <mark@codesourcery.com>
PR c++/11547
* g++.dg/parse/constant3.C: New test.
* g++.dg/parse/crash7.C: Likewise.
2003-07-16 Andrew Pinski <pinskia@physics.uc.edu> 2003-07-16 Andrew Pinski <pinskia@physics.uc.edu>
PR target/11008 PR target/11008

View File

@ -0,0 +1,7 @@
const int i = 1;
const int j (2);
const int k = { 3 };
enum { a = i, b = j, c = k };

View File

@ -0,0 +1,10 @@
struct A
{
int foo () const { return 0; }
};
template <typename> void bar (int x[], const A &a)
{
const int i=a.foo();
x[i]=0;
}