aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/call.c2
-rw-r--r--gcc/cp/init.c62
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/testsuite/ChangeLog3
-rw-r--r--gcc/testsuite/g++.dg/init/float1.C19
6 files changed, 70 insertions, 27 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7842a01..99ea5ec 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 400a805..b1a578d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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;
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 2b8d768..20c3b35 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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);
}
/* Common subroutines of build_new and build_vec_delete. */
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 76ae5104..7a9a561 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index c2d496e..b626cdd 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..d18ff3d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/float1.C
@@ -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 () {
+}