re PR c++/18905 (Strange error: subscripted value is neither array nor pointer)
authorNathan Sidwell <nathan@codesourcery.com>
Thu, 16 Dec 2004 11:04:09 +0000 (11:04 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Thu, 16 Dec 2004 11:04:09 +0000 (11:04 +0000)
cp:
PR c++/18905
* cp-tree.h (integral_constant_value): Declare.
* call.c (null_ptr_cst_p): Use integral_constant_value, not
decl_constant_value.
(convert_like_real): Likewise.
* class.c (check_bitfield_decl): Likewise.
* cvt.c (ocp_convert): Likewise.
(convert): Remove unnecessary decl_constant_value call.
* decl.c (compute_array_index_type): Use integral_constant_value,
not decl_constant_value.
(build_enumerator): Likewise.
* decl2.c (grokfield): Likewise.
* init.c (decl_constant_value): Simplify.
(integral_constant_value): New.
* pt.c (fold_decl_constant_value): Use integral_constant_value,
remove subsequent check.
(tsubst): Use integral_constant_value, not decl_constant_value.
(tsubst_copy, unify): Likewise.
* typeck.c (decay_conversion): Likewise.
(build_compound_expr): Remove unnecessary decl_constant_value
calls.
(build_static_cast_1, build_reinterpret_cast_1):
(convert_for_assignment): Remove comment about not calling
decl_constant_value.
testsuite:
PR c++/18905
* g++.dg/template/init4.C: New.
* g++.dg/opt/static3.C: Enable optimizer.

From-SVN: r92257

13 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/init.c
gcc/cp/pt.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/static3.C
gcc/testsuite/g++.dg/template/init4.C [new file with mode: 0644]

index 11e90b8b6c0554cb96ead63e7170faa8c0f6ca05..96bb671d1075a5b5ed318656e3f535b3c476348d 100644 (file)
@@ -1,3 +1,30 @@
+2004-12-16  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/18905
+       * cp-tree.h (integral_constant_value): Declare.
+       * call.c (null_ptr_cst_p): Use integral_constant_value, not
+       decl_constant_value.
+       (convert_like_real): Likewise.
+       * class.c (check_bitfield_decl): Likewise.
+       * cvt.c (ocp_convert): Likewise.
+       (convert): Remove unnecessary decl_constant_value call.
+       * decl.c (compute_array_index_type): Use integral_constant_value,
+       not decl_constant_value.
+       (build_enumerator): Likewise.
+       * decl2.c (grokfield): Likewise.
+       * init.c (decl_constant_value): Simplify.
+       (integral_constant_value): New.
+       * pt.c (fold_decl_constant_value): Use integral_constant_value,
+       remove subsequent check.
+       (tsubst): Use integral_constant_value, not decl_constant_value.
+       (tsubst_copy, unify): Likewise.
+       * typeck.c (decay_conversion): Likewise.
+       (build_compound_expr): Remove unnecessary decl_constant_value
+       calls.
+       (build_static_cast_1, build_reinterpret_cast_1):
+       (convert_for_assignment): Remove comment about not calling
+       decl_constant_value.
+
 2004-12-15  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        PR c++/18825
index ab31c99a51ed54f58bbfa5d375f911f067aa5f4f..af6f7d8225803e56df8006cdd57c6e962a33c344 100644 (file)
@@ -428,8 +428,7 @@ null_ptr_cst_p (tree t)
 
      A null pointer constant is an integral constant expression
      (_expr.const_) rvalue of integer type that evaluates to zero.  */
-  if (DECL_INTEGRAL_CONSTANT_VAR_P (t))
-    t = decl_constant_value (t);
+  t = integral_constant_value (t);
   if (t == null_node
       || (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
     return true;
@@ -4227,12 +4226,11 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
     case ck_identity:
       if (type_unknown_p (expr))
        expr = instantiate_type (totype, expr, tf_error | tf_warning);
-      /* Convert a non-array constant variable to its underlying value, unless we
-        are about to bind it to a reference, in which case we need to
+      /* Convert a constant to its underlying value, unless we are
+        about to bind it to a reference, in which case we need to
         leave it as an lvalue.  */
-      if (inner >= 0
-         && TREE_CODE (TREE_TYPE (expr)) != ARRAY_TYPE)
-       expr = decl_constant_value (expr);
+      if (inner >= 0)
+       expr = integral_constant_value (expr);
       if (convs->check_copy_constructor_p)
        check_constructor_callable (totype, expr);
       return expr;
index 9625acca7cea15077bbae4034b8118826c61e6ab..9c0a2718f5f618d4699765847f1722c391465cd0 100644 (file)
@@ -2613,10 +2613,7 @@ check_bitfield_decl (tree field)
       STRIP_NOPS (w);
 
       /* detect invalid field size.  */
-      if (TREE_CODE (w) == CONST_DECL)
-       w = DECL_INITIAL (w);
-      else
-       w = decl_constant_value (w);
+      w = integral_constant_value (w);
 
       if (TREE_CODE (w) != INTEGER_CST)
        {
index 668aa68575495f8478d93736de8637490a000a2b..de3e1a6c8dc9d95d793b6b00479c3388cc424283 100644 (file)
@@ -3917,6 +3917,7 @@ extern tree build_vec_delete                      (tree, tree, special_function_kind, int);
 extern tree create_temporary_var                (tree);
 extern void initialize_vtbl_ptrs                (tree);
 extern tree build_java_class_ref                (tree);
+extern tree integral_constant_value            (tree);
 
 /* in lex.c */
 extern void cxx_dup_lang_specific_decl         (tree);
index 7039bfe6fd0fc8b9f1fb2dd58c1567cb41b852db..2d73ab8569832154e8ce2f93de47af86152053de 100644 (file)
@@ -621,7 +621,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
   complete_type (type);
   complete_type (TREE_TYPE (expr));
 
-  e = decl_constant_value (e);
+  e = integral_constant_value (e);
 
   if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP)
       /* Some internal structures (vtable_entry_type, sigtbl_ptr_type)
@@ -945,10 +945,7 @@ convert (tree type, tree expr)
   intype = TREE_TYPE (expr);
 
   if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))
-    {
-      expr = decl_constant_value (expr);
-      return fold_if_not_in_template (build_nop (type, expr));
-    }
+    return fold_if_not_in_template (build_nop (type, expr));
 
   return ocp_convert (type, expr, CONV_OLD_CONVERT,
                      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);
index d711899bdaf0adcd7c3c5b86b804ac754ae93eba..01a3312bfb8b96e293782831bb9371cc3f316691 100644 (file)
@@ -4853,6 +4853,7 @@ cp_finish_decl (tree decl, tree init, tree asmspec_tree, int flags)
          && !DECL_PRETTY_FUNCTION_P (decl)
          && !dependent_type_p (TREE_TYPE (decl)))
        maybe_deduce_size_from_array_init (decl, init);
+      
       goto finish_end;
     }
 
@@ -6207,7 +6208,7 @@ compute_array_index_type (tree name, tree size)
   STRIP_TYPE_NOPS (size);
 
   /* It might be a const variable or enumeration constant.  */
-  size = decl_constant_value (size);
+  size = integral_constant_value (size);
 
   /* Normally, the array-bound will be a constant.  */
   if (TREE_CODE (size) == INTEGER_CST)
@@ -9792,7 +9793,7 @@ build_enumerator (tree name, tree value, tree enumtype)
       /* Validate and default VALUE.  */
       if (value != NULL_TREE)
        {
-         value = decl_constant_value (value);
+         value = integral_constant_value (value);
 
          if (TREE_CODE (value) == INTEGER_CST)
            {
index c7d28e502aedef0539c1ba3e13d2f244dc316b92..231939d638de0a22ba0cc3663d02fb756fc8200d 100644 (file)
@@ -917,12 +917,11 @@ grokfield (const cp_declarator *declarator,
 
          if (!processing_template_decl)
            {
-             if (TREE_CODE (init) == CONST_DECL)
-               init = DECL_INITIAL (init);
-             else if (TREE_READONLY_DECL_P (init))
-               init = decl_constant_value (init);
-             else if (TREE_CODE (init) == CONSTRUCTOR)
+             if (TREE_CODE (init) == CONSTRUCTOR)
                init = digest_init (TREE_TYPE (value), init, (tree *)0);
+             else
+               init = integral_constant_value (init);
+             
              if (init != error_mark_node && ! TREE_CONSTANT (init))
                {
                  /* We can allow references to things that are effectively
index a1a404c53f9a9fc8d76db9cde10ea5cecdab76e1..90b84eb6a45c2b5dc51a32422f0ac919bc28290a 100644 (file)
@@ -1558,46 +1558,48 @@ build_offset_ref (tree type, tree name, bool address_p)
   return member;
 }
 
-/* If DECL is a `const' declaration, and its value is a known
-   constant, then return that value.  */
+/* If DECL is a CONST_DECL, or a constant VAR_DECL initialized by
+   constant of integral or enumeration type, then return that value.
+   These are those variables permitted in constant expressions by
+   [5.19/1].  FIXME:If we did lazy folding, this could be localized.  */
 
 tree
-decl_constant_value (tree decl)
+integral_constant_value (tree decl)
 {
-  /* When we build a COND_EXPR, we don't know whether it will be used
-     as an lvalue or as an rvalue.  If it is an lvalue, it's not safe
-     to replace the second and third operands with their
-     initializers.  So, we do that here.  */
-  if (TREE_CODE (decl) == COND_EXPR)
-    {
-      tree d1;
-      tree d2;
-
-      d1 = decl_constant_value (TREE_OPERAND (decl, 1));
-      d2 = decl_constant_value (TREE_OPERAND (decl, 2));
+  if ((TREE_CODE (decl) == CONST_DECL
+      || (TREE_CODE (decl) == VAR_DECL
+         /* And so are variables with a 'const' type -- unless they
+            are also 'volatile'.  */
+         && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))
+         && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl)))
+      && DECL_INITIAL (decl)
+      && DECL_INITIAL (decl) != error_mark_node
+      && TREE_TYPE (DECL_INITIAL (decl))
+      && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (decl)))
+    return DECL_INITIAL (decl);
+  return decl;
+}
 
-      if (d1 != TREE_OPERAND (decl, 1) || d2 != TREE_OPERAND (decl, 2))
-       return build3 (COND_EXPR,
-                      TREE_TYPE (decl),
-                      TREE_OPERAND (decl, 0), d1, d2);
-    }
+/* A more relaxed version of integral_constant_value, for which type
+   is not considered.  This is used by the common C/C++ code, and not
+   directly by the C++ front end.  */
 
-  if (DECL_P (decl)
-      && (/* Enumeration constants are constant.  */
-         TREE_CODE (decl) == CONST_DECL
+tree
+decl_constant_value (tree decl)
+{
+  if ((TREE_CODE (decl) == CONST_DECL
+      || (TREE_CODE (decl) == VAR_DECL
          /* And so are variables with a 'const' type -- unless they
-            are also 'volatile'.  */
-         || CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))
-      && TREE_CODE (decl) != PARM_DECL
+             are also 'volatile'.  */
+         && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl))))
       && DECL_INITIAL (decl)
       && DECL_INITIAL (decl) != error_mark_node
-      /* This is invalid if initial value is not constant.
-        If it has either a function call, a memory reference,
-        or a variable, then re-evaluating it could give different results.  */
-      && TREE_CONSTANT (DECL_INITIAL (decl))
-      /* Check for cases where this is sub-optimal, even though valid.  */
-      && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR)
+      /* This is invalid if initial value is not constant.  If it has
+                either a function call, a memory reference, or a variable,
+                then re-evaluating it could give different results.  */
+      && TREE_CONSTANT (DECL_INITIAL (decl)))
     return DECL_INITIAL (decl);
+  
   return decl;
 }
 \f
index db9b08ffb9a1946aaff3c53243efd667f597af1e..a73f6916f02fd6a694ba3f461d18d9b4ab4568c0 100644 (file)
@@ -3310,37 +3310,23 @@ fold_non_dependent_expr (tree expr)
    For instance, it could be a VAR_DECL with a constant initializer.
    Extract the innest constant expression.
    
-   This is basically a more powerful version of decl_constant_value, which
-   can be used also in templates where initializers can maintain a
-   syntactic rather than semantic form (even if they are non-dependent, for
-   access-checking purposes).  */
+   This is basically a more powerful version of
+   integral_constant_value, which can be used also in templates where
+   initializers can maintain a syntactic rather than semantic form
+   (even if they are non-dependent, for access-checking purposes).  */
 
 tree
 fold_decl_constant_value (tree expr)
 {
   while (true)
     {
-      tree const_expr = decl_constant_value (expr);
-      /* In a template, the initializer for a VAR_DECL may not be
-        marked as TREE_CONSTANT, in which case decl_constant_value
-        will not return the initializer.  Handle that special case
-        here.  */
-      if (expr == const_expr
-         && TREE_CODE (expr) == VAR_DECL
-         && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (expr)
-         && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (expr))
-         /* DECL_INITIAL can be NULL if we are processing a
-            variable initialized to an expression involving itself.
-            We know it is initialized to a constant -- but not what
-            constant, yet.  */
-         && DECL_INITIAL (expr))
-       const_expr = DECL_INITIAL (expr);
+      tree const_expr = integral_constant_value (expr);
       if (expr == const_expr)
        break;
       expr = fold_non_dependent_expr (const_expr);
     }
 
-    return expr;
+  return expr;
 }
 
 /* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
@@ -6985,7 +6971,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
           in that we want to fold it as much as possible.  */
        max = tsubst_template_arg (omax, args, complain, in_decl);
        if (!processing_template_decl)
-         max = decl_constant_value (max);
+         max = integral_constant_value (max);
 
        if (integer_zerop (omax))
          {
@@ -7688,7 +7674,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
          return t;
        /* If ARGS is NULL, then T is known to be non-dependent.  */
        if (args == NULL_TREE)
-         return decl_constant_value (t);
+         return integral_constant_value (t);
 
        /* Unfortunately, we cannot just call lookup_name here.
           Consider:
@@ -10316,7 +10302,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
     case CONST_DECL:
       if (DECL_TEMPLATE_PARM_P (parm))
        return unify (tparms, targs, DECL_INITIAL (parm), arg, strict);
-      if (arg != decl_constant_value (parm)) 
+      if (arg != integral_constant_value (parm)) 
        return 1;
       return 0;
 
index 9d347c299d19050aa548a508b39416c7b7b5588d..778e3311b90f14d3db910a27ddea8c6618c0e615 100644 (file)
@@ -1351,20 +1351,9 @@ decay_conversion (tree exp)
       cxx_incomplete_type_error (exp, TREE_TYPE (exp));
       return error_mark_node;
     }
-  
-  /* Constants can be used directly unless they're not loadable.  */
-  if (TREE_CODE (exp) == CONST_DECL)
-    exp = DECL_INITIAL (exp);
-  /* Replace a nonvolatile const static variable with its value.  We
-     don't do this for arrays, though; we want the address of the
-     first element of the array, not the address of the first element
-     of its initializing constant.  */
-  else if (code != ARRAY_TYPE)
-    {
-      exp = decl_constant_value (exp);
-      type = TREE_TYPE (exp);
-    }
 
+  exp = integral_constant_value (exp);
+  
   /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
      Leave such NOP_EXPRs, since RHS is being used in non-lvalue context.  */
 
@@ -4450,7 +4439,6 @@ build_x_compound_expr (tree op1, tree op2)
 tree
 build_compound_expr (tree lhs, tree rhs)
 {
-  lhs = decl_constant_value (lhs);
   lhs = convert_to_void (lhs, "left-hand operand of comma");
   
   if (lhs == error_mark_node || rhs == error_mark_node)
@@ -4666,7 +4654,6 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       || (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
          && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
     {
-      expr = decl_constant_value (expr);
       expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
 
       /* Ignore any integer overflow caused by the cast.  */
@@ -4918,10 +4905,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
     ;
   else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
           || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
-    {
-      expr = decl_constant_value (expr);
-      return fold_if_not_in_template (build_nop (type, expr));
-    }
+    return fold_if_not_in_template (build_nop (type, expr));
   else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
           || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype)))
     {
@@ -4938,7 +4922,7 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
        warning ("cast from %qT to %qT increases required alignment of "
                 "target type",
                 intype, type);
-      expr = decl_constant_value (expr);
+      
       return fold_if_not_in_template (build_nop (type, expr));
     }
   else if ((TYPE_PTRFN_P (type) && TYPE_PTROBV_P (intype))
@@ -4950,8 +4934,6 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
           addresses this issue, but as of 2004/10/26 is still in
           drafting.  */
        warning ("ISO C++ forbids casting between pointer-to-function and pointer-to-object");
-      
-      expr = decl_constant_value (expr);
       return fold_if_not_in_template (build_nop (type, expr));
     }
   else if (TREE_CODE (type) == VECTOR_TYPE)
@@ -5926,16 +5908,6 @@ convert_for_assignment (tree type, tree rhs,
   if (TREE_CODE (rhs) == CONST_DECL)
     rhs = DECL_INITIAL (rhs);
   
-  /* We do not use decl_constant_value here because of this case:
-
-       const char* const s = "s";
-     The conversion rules for a string literal are more lax than for a
-     variable; in particular, a string literal can be converted to a
-     "char *" but the variable "s" cannot be converted in the same
-     way.  If the conversion is allowed, the optimization should be
-     performed while creating the converted expression.  */
-
   /* [expr.ass]
 
      The expression is implicitly converted (clause _conv_) to the
index c70c5262714711ddb84e6a36104a61bdadea859a..c9c86f2f7b5c24fe54cea536f23018594b632fec 100644 (file)
@@ -1,3 +1,9 @@
+2004-12-16  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/18905
+       * g++.dg/template/init4.C: New.
+       * g++.dg/opt/static3.C: Enable optimizer.
+
 2004-12-16  Wolfgang Bangerth  <bangerth@dealii.com>
 
        * g++.dg/other/complex1.C: New test.
@@ -45,7 +51,7 @@
 
 2004-12-15  Nathan Sidwell  <nathan@codesourcery.com>
 
-       PR 18981
+       PR c++/18981
        * g++.dg/template/typename9.C: New test.
 
 2004-12-14  Mark Mitchell  <mark@codesourcery.com>
index 00c72651be35ea10fb6a6c05c64ce27ceef3b076..4f8f7a9ba682f401930f11f46404fb19d8ecb6ba 100644 (file)
@@ -1,4 +1,5 @@
 // { dg-do link }
+// { dg-options "-O2" }
 
 class Foo {
 public:
diff --git a/gcc/testsuite/g++.dg/template/init4.C b/gcc/testsuite/g++.dg/template/init4.C
new file mode 100644 (file)
index 0000000..78c7c30
--- /dev/null
@@ -0,0 +1,15 @@
+// { dg-do compile }
+
+// Copyright (C) 2004 Free Software Foundation, Inc.
+// Contributed by Nathan Sidwell 15 Dec 2004 <nathan@codesourcery.com>
+
+// PR 18905. bogus error
+// Origin:  Andrew Pinski  <pinskia@gcc.gnu.org>
+
+int f1(char);
+template <int t>
+void f(void)
+{
+ const char* const suffixes = "plpv";
+ f1(suffixes[t]);
+}