re PR c++/11547 (ICE with const temporaries)
authorMark Mitchell <mark@codesourcery.com>
Thu, 17 Jul 2003 04:31:42 +0000 (04:31 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Thu, 17 Jul 2003 04:31:42 +0000 (04:31 +0000)
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

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/parse/constant3.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/crash7.C [new file with mode: 0644]

index 536221ec0ac4c4b18e67703ea774e14843f00e72..c4d01e69579fc2293bb7b25af2fad7767354ce87 100644 (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>
 
        * lang-options.h: Remove.
index 40f3784fc9b3623b9b67cbed8630d86b048e6fda..1728b379353547b963ea148ff2ae5159fd832c1d 100644 (file)
@@ -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.  */
index 1dd2ddf7a9459ffcb01f9608a70a4fdffae3da0a..62ecbc487b4e66ec3ca55d7bc8fb1dac015587f5 100644 (file)
@@ -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
index 33f1d793ce0ce019d144a788432694ee089208a2..8af9f46d7f169160dc9393761c3fdb30fabc0c72 100644 (file)
@@ -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);
 }
index 1a8ea15c04092225c78be50cca5e76745dfce861..6c4a5a86815c8f524f68e2177ad44d54fdb16bfc 100644 (file)
@@ -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.  */
index 02783859cb42a545cdf156a7559d379e10becd7d..3d704ebe194258a5fd4c0c5a65e1f044f276a4d7 100644 (file)
@@ -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
            {
index 4b96542b92f24bccf7a08ef670c8d53316675f08..d6cced3bbc61653e2d5337d6a6e7dde4af1fa6f3 100644 (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>
 
        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 (file)
index 0000000..c029e33
--- /dev/null
@@ -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 (file)
index 0000000..86fa477
--- /dev/null
@@ -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;
+}