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
This commit is contained in:
Nathan Sidwell 2004-12-16 11:04:09 +00:00 committed by Nathan Sidwell
parent 0c0cce420e
commit 8a784e4a17
13 changed files with 113 additions and 111 deletions

View File

@ -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

View File

@ -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;

View File

@ -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)
{

View File

@ -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);

View File

@ -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);

View File

@ -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)
{

View File

@ -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

View File

@ -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
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_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;
}
/* 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. */
tree
decl_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 (d1 != TREE_OPERAND (decl, 1) || d2 != TREE_OPERAND (decl, 2))
return build3 (COND_EXPR,
TREE_TYPE (decl),
TREE_OPERAND (decl, 0), d1, d2);
}
if (DECL_P (decl)
&& (/* Enumeration constants are constant. */
TREE_CODE (decl) == CONST_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;
}

View File

@ -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;

View File

@ -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

View File

@ -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>

View File

@ -1,4 +1,5 @@
// { dg-do link }
// { dg-options "-O2" }
class Foo {
public:

View File

@ -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]);
}