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:
parent
db5eed1873
commit
39703eb9e2
|
@ -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>
|
||||
|
||||
* lang-options.h: Remove.
|
||||
|
|
|
@ -45,6 +45,7 @@ struct diagnostic_context;
|
|||
AGGR_INIT_VIA_CTOR_P (in AGGR_INIT_EXPR)
|
||||
PTRMEM_OK_P (in ADDR_EXPR, OFFSET_REF)
|
||||
PARMLIST_ELLIPSIS_P (in PARMLIST)
|
||||
DECL_PRETTY_FUNCTION_P (in VAR_DECL)
|
||||
1: IDENTIFIER_VIRTUAL_P.
|
||||
TI_PENDING_TEMPLATE_FLAG.
|
||||
TEMPLATE_PARMS_FOR_INLINE.
|
||||
|
@ -59,6 +60,7 @@ struct diagnostic_context;
|
|||
ICS_THIS_FLAG (in _CONV)
|
||||
BINFO_LOST_PRIMARY_P (in BINFO)
|
||||
TREE_PARMLIST (in TREE_LIST)
|
||||
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
|
||||
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
|
||||
BINFO_VTABLE_PATH_MARKED.
|
||||
BINFO_PUSHDECLS_MARKED.
|
||||
|
@ -1926,6 +1928,11 @@ struct lang_decl GTY(())
|
|||
#define DECL_INITIALIZED_P(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,
|
||||
rather than outside the class. This is used for both static member
|
||||
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
|
||||
template function. */
|
||||
#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
|
||||
class where a virtual function instance is actually defined. */
|
||||
|
|
|
@ -3306,6 +3306,8 @@ duplicate_decls (tree newdecl, tree olddecl)
|
|||
{
|
||||
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (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
|
||||
|
|
200
gcc/cp/parser.c
200
gcc/cp/parser.c
|
@ -1311,7 +1311,7 @@ static tree cp_parser_class_or_namespace_name
|
|||
static tree cp_parser_postfix_expression
|
||||
(cp_parser *, bool);
|
||||
static tree cp_parser_parenthesized_expression_list
|
||||
(cp_parser *, bool);
|
||||
(cp_parser *, bool, bool *);
|
||||
static void cp_parser_pseudo_destructor_name
|
||||
(cp_parser *, tree *, tree *);
|
||||
static tree cp_parser_unary_expression
|
||||
|
@ -1356,8 +1356,6 @@ static tree cp_parser_logical_and_expression
|
|||
(cp_parser *);
|
||||
static tree cp_parser_logical_or_expression
|
||||
(cp_parser *);
|
||||
static tree cp_parser_conditional_expression
|
||||
(cp_parser *);
|
||||
static tree cp_parser_question_colon_clause
|
||||
(cp_parser *, tree);
|
||||
static tree cp_parser_assignment_expression
|
||||
|
@ -1479,11 +1477,11 @@ static tree cp_parser_function_definition
|
|||
static void cp_parser_function_body
|
||||
(cp_parser *);
|
||||
static tree cp_parser_initializer
|
||||
(cp_parser *, bool *);
|
||||
(cp_parser *, bool *, bool *);
|
||||
static tree cp_parser_initializer_clause
|
||||
(cp_parser *);
|
||||
(cp_parser *, bool *);
|
||||
static tree cp_parser_initializer_list
|
||||
(cp_parser *);
|
||||
(cp_parser *, bool *);
|
||||
|
||||
static bool cp_parser_ctor_initializer_opt_and_function_body
|
||||
(cp_parser *);
|
||||
|
@ -3375,9 +3373,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
|||
keep going. */
|
||||
if (!cp_parser_error_occurred (parser))
|
||||
{
|
||||
bool non_constant_p;
|
||||
/* Parse the initializer-list. */
|
||||
initializer_list
|
||||
= cp_parser_initializer_list (parser);
|
||||
= cp_parser_initializer_list (parser, &non_constant_p);
|
||||
/* Allow a trailing `,'. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
|
@ -3472,7 +3471,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
|||
case CPP_OPEN_PAREN:
|
||||
/* 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)
|
||||
{
|
||||
|
@ -3735,14 +3735,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
|||
error_mark_node is returned if the ( and or ) are
|
||||
missing. NULL_TREE is returned on no expressions. The parentheses
|
||||
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
|
||||
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 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, "`('"))
|
||||
return error_mark_node;
|
||||
|
||||
|
@ -3767,7 +3775,17 @@ cp_parser_parenthesized_expression_list (cp_parser* parser, bool is_attribute_li
|
|||
else
|
||||
{
|
||||
/* 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
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -4341,7 +4360,8 @@ cp_parser_new_initializer (cp_parser* parser)
|
|||
{
|
||||
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)
|
||||
expression_list = void_zero_node;
|
||||
|
||||
|
@ -4755,43 +4775,12 @@ cp_parser_logical_or_expression (cp_parser* parser)
|
|||
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
|
||||
conditional-expression. The LOGICAL_OR_EXPR is the
|
||||
logical-or-expression that started the conditional-expression.
|
||||
Returns a representation of the entire conditional-expression.
|
||||
|
||||
This routine exists only so that it can be shared between
|
||||
cp_parser_conditional_expression and
|
||||
cp_parser_assignment_expression.
|
||||
This routine is used by cp_parser_assignment_expression.
|
||||
|
||||
? expression : assignment-expression
|
||||
|
||||
|
@ -5071,8 +5060,16 @@ cp_parser_constant_expression (cp_parser* parser,
|
|||
parser->constant_expression_p = true;
|
||||
parser->allow_non_constant_expression_p = allow_non_constant_p;
|
||||
parser->non_constant_expression_p = false;
|
||||
/* Parse the conditional-expression. */
|
||||
expression = cp_parser_conditional_expression (parser);
|
||||
/* Although the grammar says "conditional-expression", we parse an
|
||||
"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. */
|
||||
parser->constant_expression_p = saved_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. */
|
||||
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
|
||||
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. */
|
||||
cp_parser_commit_to_tentative_parse (parser);
|
||||
/* Give up. */
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* 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
|
||||
otherwise.) */
|
||||
if (cp_parser_error_occurred (parser))
|
||||
{
|
||||
pop_deferring_access_checks ();
|
||||
return;
|
||||
}
|
||||
goto done;
|
||||
/* Handle function definitions specially. */
|
||||
if (function_definition_p)
|
||||
{
|
||||
|
@ -6152,8 +6155,7 @@ cp_parser_simple_declaration (cp_parser* parser,
|
|||
cp_parser_error (parser, "expected `,' or `;'");
|
||||
/* Skip tokens until we reach the end of the statement. */
|
||||
cp_parser_skip_to_end_of_statement (parser);
|
||||
pop_deferring_access_checks ();
|
||||
return;
|
||||
goto done;
|
||||
}
|
||||
/* After the first time around, a function-definition is not
|
||||
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 ();
|
||||
}
|
||||
|
||||
pop_deferring_access_checks ();
|
||||
|
||||
/* Consume the `;'. */
|
||||
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
|
||||
|
||||
/* Mark all the classes that appeared in the decl-specifier-seq as
|
||||
having received a `;'. */
|
||||
note_list_got_semicolon (decl_specifiers);
|
||||
|
||||
done:
|
||||
pop_deferring_access_checks ();
|
||||
}
|
||||
|
||||
/* Parse a decl-specifier-seq.
|
||||
|
@ -6774,7 +6777,9 @@ cp_parser_mem_initializer (cp_parser* parser)
|
|||
if (member && !DECL_P (member))
|
||||
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)
|
||||
expression_list = void_type_node;
|
||||
|
||||
|
@ -9156,6 +9161,7 @@ cp_parser_init_declarator (cp_parser* parser,
|
|||
tree scope;
|
||||
bool is_initialized;
|
||||
bool is_parenthesized_init;
|
||||
bool is_non_constant_init;
|
||||
int ctor_dtor_or_conv_p;
|
||||
bool friend_p;
|
||||
|
||||
|
@ -9325,11 +9331,14 @@ cp_parser_init_declarator (cp_parser* parser,
|
|||
|
||||
/* Parse the initializer. */
|
||||
if (is_initialized)
|
||||
initializer = cp_parser_initializer (parser, &is_parenthesized_init);
|
||||
initializer = cp_parser_initializer (parser,
|
||||
&is_parenthesized_init,
|
||||
&is_non_constant_init);
|
||||
else
|
||||
{
|
||||
initializer = NULL_TREE;
|
||||
is_parenthesized_init = false;
|
||||
is_non_constant_init = true;
|
||||
}
|
||||
|
||||
/* 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)
|
||||
? 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;
|
||||
}
|
||||
|
||||
|
@ -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 )'
|
||||
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
|
||||
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;
|
||||
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
|
||||
parenthesized. */
|
||||
*is_parenthesized_init = (token->type == CPP_OPEN_PAREN);
|
||||
/* Assume that the initializer is constant. */
|
||||
*non_constant_p = false;
|
||||
|
||||
if (token->type == CPP_EQ)
|
||||
{
|
||||
/* Consume the `='. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
/* 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)
|
||||
init = cp_parser_parenthesized_expression_list (parser, false);
|
||||
init = cp_parser_parenthesized_expression_list (parser, false,
|
||||
non_constant_p);
|
||||
else
|
||||
{
|
||||
/* 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
|
||||
production is used). The TREE_TYPE for the CONSTRUCTOR will be
|
||||
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
|
||||
cp_parser_initializer_clause (cp_parser* parser)
|
||||
cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
|
||||
{
|
||||
tree initializer;
|
||||
|
||||
/* If it is not a `{', then we are looking at an
|
||||
assignment-expression. */
|
||||
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
|
||||
initializer = cp_parser_assignment_expression (parser);
|
||||
initializer
|
||||
= cp_parser_constant_expression (parser,
|
||||
/*allow_non_constant_p=*/true,
|
||||
non_constant_p);
|
||||
else
|
||||
{
|
||||
/* Consume the `{' token. */
|
||||
|
@ -10805,12 +10830,11 @@ cp_parser_initializer_clause (cp_parser* parser)
|
|||
{
|
||||
/* Parse the initializer list. */
|
||||
CONSTRUCTOR_ELTS (initializer)
|
||||
= cp_parser_initializer_list (parser);
|
||||
= cp_parser_initializer_list (parser, non_constant_p);
|
||||
/* A trailing `,' token is allowed. */
|
||||
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
}
|
||||
|
||||
/* Now, there should be a trailing `}'. */
|
||||
cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
|
||||
}
|
||||
|
@ -10832,19 +10856,24 @@ cp_parser_initializer_clause (cp_parser* parser)
|
|||
|
||||
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
|
||||
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
|
||||
cp_parser_initializer_list (cp_parser* parser)
|
||||
cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
|
||||
{
|
||||
tree initializers = NULL_TREE;
|
||||
|
||||
/* Assume all of the expressions are constant. */
|
||||
*non_constant_p = false;
|
||||
|
||||
/* Parse the rest of the list. */
|
||||
while (true)
|
||||
{
|
||||
cp_token *token;
|
||||
tree identifier;
|
||||
tree initializer;
|
||||
bool clause_non_constant_p;
|
||||
|
||||
/* If the next token is an identifier and the following one is a
|
||||
colon, we are looking at the GNU designated-initializer
|
||||
|
@ -10862,8 +10891,11 @@ cp_parser_initializer_list (cp_parser* parser)
|
|||
identifier = NULL_TREE;
|
||||
|
||||
/* 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. */
|
||||
initializers = tree_cons (identifier, initializer, initializers);
|
||||
|
||||
|
@ -11821,12 +11853,18 @@ cp_parser_member_declaration (cp_parser* parser)
|
|||
(cp_lexer_peek_token (parser->lexer)))
|
||||
decl = error_mark_node;
|
||||
else
|
||||
/* Create the declaration. */
|
||||
decl = grokfield (declarator,
|
||||
decl_specifiers,
|
||||
initializer,
|
||||
asm_specification,
|
||||
attributes);
|
||||
{
|
||||
/* Create the declaration. */
|
||||
decl = grokfield (declarator,
|
||||
decl_specifiers,
|
||||
initializer,
|
||||
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. */
|
||||
|
@ -12616,8 +12654,8 @@ cp_parser_attribute_list (cp_parser* parser)
|
|||
{
|
||||
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. */
|
||||
TREE_VALUE (attribute) = arguments;
|
||||
}
|
||||
|
@ -13583,7 +13621,9 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
|
|||
{
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -6190,7 +6190,11 @@ tsubst_decl (tree t, tree args, tree type, tsubst_flags_t complain)
|
|||
|
||||
r = copy_decl (t);
|
||||
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))
|
||||
SET_DECL_SELF_REFERENCE_P (r);
|
||||
TREE_TYPE (r) = type;
|
||||
|
@ -7620,7 +7624,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl)
|
|||
else
|
||||
{
|
||||
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
|
||||
initializer. */
|
||||
|
|
|
@ -2478,17 +2478,11 @@ finish_id_expression (tree id_expression,
|
|||
;
|
||||
/* Const variables or static data members of integral or
|
||||
enumeration types initialized with constant expressions
|
||||
are OK. We also accept dependent initializers; they may
|
||||
turn out to be constant at instantiation-time. */
|
||||
are OK. */
|
||||
else if (TREE_CODE (decl) == VAR_DECL
|
||||
&& CP_TYPE_CONST_P (TREE_TYPE (decl))
|
||||
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl))
|
||||
&& DECL_INITIAL (decl)
|
||||
&& (TREE_CONSTANT (DECL_INITIAL (decl))
|
||||
|| type_dependent_expression_p (DECL_INITIAL
|
||||
(decl))
|
||||
|| value_dependent_expression_p (DECL_INITIAL
|
||||
(decl))))
|
||||
&& DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))
|
||||
;
|
||||
else
|
||||
{
|
||||
|
|
|
@ -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>
|
||||
|
||||
PR target/11008
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
const int i = 1;
|
||||
const int j (2);
|
||||
const int k = { 3 };
|
||||
|
||||
enum { a = i, b = j, c = k };
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue