diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/call.c | 2 | ||||
-rw-r--r-- | gcc/cp/init.c | 62 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 2 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/init/float1.C | 19 |
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 () { +} |