PR c++/21089
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Oct 2005 20:58:46 +0000 (20:58 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Oct 2005 20:58:46 +0000 (20:58 +0000)
* call.c (convert_like_real): Use decl_constant_value, not
integral_constant_value.
* init.c (constant_value_1): New function.
(integral_constant_value): Use it.
(decl_constant_value): Likewise.
* typeck.c (decay_conversion): Use decl_constant_value, not
integral_constant_value.
PR c++/21089
* g++.dg/init/float1.C: New test.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@105256 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/init.c
gcc/cp/typeck.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/init/float1.C [new file with mode: 0644]

index 7842a01..99ea5ec 100644 (file)
@@ -1,5 +1,14 @@
 2005-10-11  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/21089
+       * call.c (convert_like_real): Use decl_constant_value, not
+       integral_constant_value.
+       * init.c (constant_value_1): New function.
+       (integral_constant_value): Use it.
+       (decl_constant_value): Likewise.
+       * typeck.c (decay_conversion): Use decl_constant_value, not
+       integral_constant_value.
+
        PR c++/21369
        * parser.c (cp_parser_elaborated_type_specifier): Don't treat
        class types as templates if the type is not appearing as part of a
index 400a805..b1a578d 100644 (file)
@@ -4298,7 +4298,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
         about to bind it to a reference, in which case we need to
         leave it as an lvalue.  */
       if (inner >= 0)
-       expr = integral_constant_value (expr);
+       expr = decl_constant_value (expr);
       if (convs->check_copy_constructor_p)
        check_constructor_callable (totype, expr);
       return expr;
index 2b8d768..20c3b35 100644 (file)
@@ -1559,16 +1559,20 @@ build_offset_ref (tree type, tree name, bool address_p)
   return member;
 }
 
-/* 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.  */
+/* If DECL is a scalar enumeration constant or variable with a
+   constant initializer, return the initializer (or, its initializers,
+   recursively); otherwise, return DECL.  If INTEGRAL_P, the
+   initializer is only returned if DECL is an integral
+   constant-expression.  */
 
-tree
-integral_constant_value (tree decl)
+static tree
+constant_value_1 (tree decl, bool integral_p)
 {
   while (TREE_CODE (decl) == CONST_DECL
-        || DECL_INTEGRAL_CONSTANT_VAR_P (decl))
+        || (integral_p 
+            ? DECL_INTEGRAL_CONSTANT_VAR_P (decl)
+            : (TREE_CODE (decl) == VAR_DECL
+               && CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
     {
       tree init;
       /* If DECL is a static data member in a template class, we must
@@ -1583,34 +1587,42 @@ integral_constant_value (tree decl)
        init = fold_non_dependent_expr (init);
       if (!(init || init == error_mark_node)
          || !TREE_TYPE (init)
-         || !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init)))
+         || (integral_p
+             ? !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (init))
+             : (!TREE_CONSTANT (init)
+                /* Do not return an aggregate constant (of which
+                   string literals are a special case), as we do not
+                   want to make inadvertant copies of such entities,
+                   and we must be sure that their addresses are the
+                   same everywhere.  */
+                || TREE_CODE (init) == CONSTRUCTOR
+                || TREE_CODE (init) == STRING_CST)))
        break;
       decl = init;
     }
   return decl;
 }
 
-/* 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 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].  */
 
 tree
-decl_constant_value (tree decl)
+integral_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))))
-      && 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)))
-    return DECL_INITIAL (decl);
+  return constant_value_1 (decl, /*integral_p=*/true);
+}
 
-  return decl;
+/* A more relaxed version of integral_constant_value, used by the
+   common C/C++ code and by the C++ front-end for optimization
+   purposes.  */
+
+tree
+decl_constant_value (tree decl)
+{
+  return constant_value_1 (decl, 
+                          /*integral_p=*/processing_template_decl);
 }
 \f
 /* Common subroutines of build_new and build_vec_delete.  */
index 76ae510..7a9a561 100644 (file)
@@ -1356,7 +1356,7 @@ decay_conversion (tree exp)
       return error_mark_node;
     }
 
-  exp = integral_constant_value (exp);
+  exp = decl_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.  */
index c2d496e..b626cdd 100644 (file)
@@ -1,5 +1,8 @@
 2005-10-11  Mark Mitchell  <mark@codesourcery.com>
 
+       PR c++/21089
+       * g++.dg/init/float1.C: New test.
+
        PR c++/24277
        * g++.dg/init/member1.C: Tweak error markers.
 
diff --git a/gcc/testsuite/g++.dg/init/float1.C b/gcc/testsuite/g++.dg/init/float1.C
new file mode 100644 (file)
index 0000000..d18ff3d
--- /dev/null
@@ -0,0 +1,19 @@
+// PR c++/21089
+// { dg-do run }
+
+extern "C" void abort();
+
+static const double a = 1.0;
+struct S {
+  S();
+};
+static S s;
+static const double b = a + 1.0;
+
+S::S() {
+  if (b < 1.9 || b > 2.1)
+    abort ();
+}
+
+int main () {
+}