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:
parent
0c0cce420e
commit
8a784e4a17
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
32
gcc/cp/pt.c
32
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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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>
|
||||
|
@ -1,4 +1,5 @@
|
||||
// { dg-do link }
|
||||
// { dg-options "-O2" }
|
||||
|
||||
class Foo {
|
||||
public:
|
||||
|
15
gcc/testsuite/g++.dg/template/init4.C
Normal file
15
gcc/testsuite/g++.dg/template/init4.C
Normal 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]);
|
||||
}
|
Loading…
Reference in New Issue
Block a user