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>
|
2003-07-16 Neil Booth <neil@daikokuya.co.uk>
|
||||||
|
|
||||||
* lang-options.h: Remove.
|
* lang-options.h: Remove.
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
|
|
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
|
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,19 +10856,24 @@ 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
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. */
|
||||||
|
|
|
@ -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
|
||||||
{
|
{
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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