aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-07-17 04:31:42 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-07-17 04:31:42 +0000
commit39703eb9e28d401299fb5c86d4b8d51981fa058d (patch)
treeeab02b08c217a06c773812f40a3bf9384443716d
parentdb5eed1873ad17205d6cf4ac15ca84f4822b5381 (diff)
downloadgcc-39703eb9e28d401299fb5c86d4b8d51981fa058d.zip
gcc-39703eb9e28d401299fb5c86d4b8d51981fa058d.tar.gz
gcc-39703eb9e28d401299fb5c86d4b8d51981fa058d.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog36
-rw-r--r--gcc/cp/cp-tree.h9
-rw-r--r--gcc/cp/decl.c2
-rw-r--r--gcc/cp/parser.c204
-rw-r--r--gcc/cp/pt.c9
-rw-r--r--gcc/cp/semantics.c10
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/g++.dg/parse/constant3.C7
-rw-r--r--gcc/testsuite/g++.dg/parse/crash7.C10
9 files changed, 200 insertions, 93 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 536221e..c4d01e6 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 40f3784f..1728b37 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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. */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 1dd2ddf..62ecbc4 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 33f1d79..8af9f46 100644
--- a/gcc/cp/parser.c
+++ b/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,20 +10856,25 @@ 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
syntax. */
@@ -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);
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1a8ea15..6c4a5a8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 0278385..3d704eb 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4b96542..d6cced3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/g++.dg/parse/constant3.C b/gcc/testsuite/g++.dg/parse/constant3.C
new file mode 100644
index 0000000..c029e33
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/constant3.C
@@ -0,0 +1,7 @@
+const int i = 1;
+const int j (2);
+const int k = { 3 };
+
+enum { a = i, b = j, c = k };
+
+
diff --git a/gcc/testsuite/g++.dg/parse/crash7.C b/gcc/testsuite/g++.dg/parse/crash7.C
new file mode 100644
index 0000000..86fa477
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/crash7.C
@@ -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;
+}