aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2004-12-16 11:04:09 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2004-12-16 11:04:09 +0000
commit8a784e4a1772379577b0fe91de4b387390573435 (patch)
treea82d5b1b25a2b0a52f0c9e6f96bfb4fbbb2d9e1c /gcc
parent0c0cce420e1ced4cfd4e6daddb91e3f6b548bf29 (diff)
downloadgcc-8a784e4a1772379577b0fe91de4b387390573435.zip
gcc-8a784e4a1772379577b0fe91de4b387390573435.tar.gz
gcc-8a784e4a1772379577b0fe91de4b387390573435.tar.bz2
re PR c++/18905 (Strange error: subscripted value is neither array nor pointer)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog27
-rw-r--r--gcc/cp/call.c12
-rw-r--r--gcc/cp/class.c5
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/cvt.c7
-rw-r--r--gcc/cp/decl.c5
-rw-r--r--gcc/cp/decl2.c9
-rw-r--r--gcc/cp/init.c64
-rw-r--r--gcc/cp/pt.c32
-rw-r--r--gcc/cp/typeck.c36
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/opt/static3.C1
-rw-r--r--gcc/testsuite/g++.dg/template/init4.C15
13 files changed, 112 insertions, 110 deletions
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 <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
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 <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>
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 <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]);
+}