From 13f0eb203f1c4d5cfb52f559ab84725160d89f2e Mon Sep 17 00:00:00 2001 From: nathan Date: Thu, 16 Dec 2004 11:04:09 +0000 Subject: [PATCH] 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@92257 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 27 +++++++++++++++ gcc/cp/call.c | 12 +++---- gcc/cp/class.c | 5 +-- gcc/cp/cp-tree.h | 1 + gcc/cp/cvt.c | 7 ++-- gcc/cp/decl.c | 5 +-- gcc/cp/decl2.c | 9 +++-- gcc/cp/init.c | 64 ++++++++++++++++++----------------- gcc/cp/pt.c | 32 +++++------------- gcc/cp/typeck.c | 36 +++----------------- gcc/testsuite/ChangeLog | 8 ++++- gcc/testsuite/g++.dg/opt/static3.C | 1 + gcc/testsuite/g++.dg/template/init4.C | 15 ++++++++ 13 files changed, 112 insertions(+), 110 deletions(-) create mode 100644 gcc/testsuite/g++.dg/template/init4.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 11e90b8..96bb671 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,30 @@ +2004-12-16 Nathan Sidwell + + 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 PR c++/18825 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index ab31c99..af6f7d8 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -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; diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 9625acc..9c0a271 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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) { diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 668aa68..de3e1a6 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c index 7039bfe..2d73ab8 100644 --- a/gcc/cp/cvt.c +++ b/gcc/cp/cvt.c @@ -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); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index d711899..01a3312 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -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) { diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index c7d28e5..231939d 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -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 diff --git a/gcc/cp/init.c b/gcc/cp/init.c index a1a404c..90b84eb 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -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; } diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index db9b08f..a73f691 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -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; diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 9d347c2..778e331 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -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 diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c70c526..c9c86f2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2004-12-16 Nathan Sidwell + + PR c++/18905 + * g++.dg/template/init4.C: New. + * g++.dg/opt/static3.C: Enable optimizer. + 2004-12-16 Wolfgang Bangerth * g++.dg/other/complex1.C: New test. @@ -45,7 +51,7 @@ 2004-12-15 Nathan Sidwell - PR 18981 + PR c++/18981 * g++.dg/template/typename9.C: New test. 2004-12-14 Mark Mitchell diff --git a/gcc/testsuite/g++.dg/opt/static3.C b/gcc/testsuite/g++.dg/opt/static3.C index 00c7265..4f8f7a9 100644 --- a/gcc/testsuite/g++.dg/opt/static3.C +++ b/gcc/testsuite/g++.dg/opt/static3.C @@ -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 index 0000000..78c7c30 --- /dev/null +++ b/gcc/testsuite/g++.dg/template/init4.C @@ -0,0 +1,15 @@ +// { dg-do compile } + +// Copyright (C) 2004 Free Software Foundation, Inc. +// Contributed by Nathan Sidwell 15 Dec 2004 + +// PR 18905. bogus error +// Origin: Andrew Pinski + +int f1(char); +template +void f(void) +{ + const char* const suffixes = "plpv"; + f1(suffixes[t]); +} -- 2.7.4