re PR c++/21089 (C++ front-end does not "inline" the static const double)

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++/21089
	* g++.dg/init/float1.C: New test.

From-SVN: r105256
This commit is contained in:
Mark Mitchell 2005-10-11 20:58:46 +00:00 committed by Mark Mitchell
parent 8f4c0ef6a4
commit 393e756da7
6 changed files with 70 additions and 27 deletions

View File

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

View File

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

View File

@ -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
integral_constant_value (tree decl)
{
return constant_value_1 (decl, /*integral_p=*/true);
}
/* 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)
{
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 decl;
return constant_value_1 (decl,
/*integral_p=*/processing_template_decl);
}
/* Common subroutines of build_new and build_vec_delete. */

View File

@ -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. */

View File

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

View File

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