re PR c++/57979 (G++ accepts constant expression defined using floating point non-constexpr glvalue)

PR c++/57979
	* init.c (decl_really_constant_value): Rename from
	integral_constant_value.
	(scalar_constant_value): Similar but limited to scalar results.
	(decl_constant_value_safe): Remove.
	(constant_value_1): Respect return_aggregate_cst_ok_p.
	* typeck.c (decay_conversion): Use scalar_constant_value.
	* call.c (convert_like_real): Likewise.
	* cvt.c (ocp_convert): No need to check CLASS_TYPE_P.
	* typeck.c (decay_conversion): Or ARRAY_TYPE.
	* constexpr.c (struct constexpr_ctx): Add strict field.
	(cxx_eval_constant_expression) [VAR_DECL]: Use it to select between
	decl_constant_value and decl_really_constant_value.
	(cxx_eval_outermost_constant_expr): Add strict parm.
	(maybe_constant_init): Not strict.
	(potential_constant_expression_1): Add strict parm.
	Shorten most internal calls with RECUR macro.
	* cp-tree.h, pt.c, semantics.c: Adjust.

From-SVN: r217814
This commit is contained in:
Jason Merrill 2014-11-19 17:06:17 -05:00 committed by Jason Merrill
parent 6d06c429dc
commit 69eb4fde58
12 changed files with 147 additions and 128 deletions

View File

@ -1,3 +1,24 @@
2014-11-19 Jason Merrill <jason@redhat.com>
PR c++/57979
* init.c (decl_really_constant_value): Rename from
integral_constant_value.
(scalar_constant_value): Similar but limited to scalar results.
(decl_constant_value_safe): Remove.
(constant_value_1): Respect return_aggregate_cst_ok_p.
* typeck.c (decay_conversion): Use scalar_constant_value.
* call.c (convert_like_real): Likewise.
* cvt.c (ocp_convert): No need to check CLASS_TYPE_P.
* typeck.c (decay_conversion): Or ARRAY_TYPE.
* constexpr.c (struct constexpr_ctx): Add strict field.
(cxx_eval_constant_expression) [VAR_DECL]: Use it to select between
decl_constant_value and decl_really_constant_value.
(cxx_eval_outermost_constant_expr): Add strict parm.
(maybe_constant_init): Not strict.
(potential_constant_expression_1): Add strict parm.
Shorten most internal calls with RECUR macro.
* cp-tree.h, pt.c, semantics.c: Adjust.
2014-11-19 Jason Merrill <jason@redhat.com>
PR c++/63928

View File

@ -6247,7 +6247,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
leave it as an lvalue. */
if (inner >= 0)
{
expr = decl_constant_value_safe (expr);
expr = scalar_constant_value (expr);
if (expr == null_node && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype))
/* If __null has been converted to an integer type, we do not
want to warn about uses of EXPR as an integer, rather than

View File

@ -869,6 +869,7 @@ struct constexpr_ctx {
tree ctor;
tree object;
bool quiet;
bool strict;
};
/* A table of all constexpr calls that have been evaluated by the
@ -2818,7 +2819,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
return t;
/* else fall through. */
case CONST_DECL:
r = integral_constant_value (t);
if (ctx->strict)
r = decl_really_constant_value (t);
else
r = decl_constant_value (t);
if (TREE_CODE (r) == TARGET_EXPR
&& TREE_CODE (TARGET_EXPR_INITIAL (r)) == CONSTRUCTOR)
r = TARGET_EXPR_INITIAL (r);
@ -3302,11 +3306,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
static tree
cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
tree object = NULL_TREE)
bool strict = true, tree object = NULL_TREE)
{
bool non_constant_p = false;
bool overflow_p = false;
constexpr_ctx ctx = { NULL, NULL, NULL, NULL, allow_non_constant };
constexpr_ctx ctx = { NULL, NULL, NULL, NULL, allow_non_constant, strict };
hash_map<tree,tree> map;
ctx.values = &map;
tree type = initialized_type (t);
@ -3415,7 +3419,7 @@ is_sub_constant_expr (tree t)
{
bool non_constant_p = false;
bool overflow_p = false;
constexpr_ctx ctx = { NULL, NULL, NULL, NULL, true };
constexpr_ctx ctx = { NULL, NULL, NULL, NULL, true, true };
hash_map <tree, tree> map;
ctx.values = &map;
cxx_eval_constant_expression (&ctx, t, false, &non_constant_p,
@ -3430,7 +3434,7 @@ is_sub_constant_expr (tree t)
tree
cxx_constant_value (tree t, tree decl)
{
return cxx_eval_outermost_constant_expr (t, false, decl);
return cxx_eval_outermost_constant_expr (t, false, true, decl);
}
/* If T is a constant expression, returns its reduced value.
@ -3455,7 +3459,7 @@ maybe_constant_value (tree t, tree decl)
return t;
}
r = cxx_eval_outermost_constant_expr (t, true, decl);
r = cxx_eval_outermost_constant_expr (t, true, true, decl);
#ifdef ENABLE_CHECKING
/* cp_tree_equal looks through NOPs, so allow them. */
gcc_assert (r == t
@ -3515,7 +3519,7 @@ fold_non_dependent_expr (tree t)
return t;
}
tree r = cxx_eval_outermost_constant_expr (t, true, NULL_TREE);
tree r = cxx_eval_outermost_constant_expr (t, true, true, NULL_TREE);
#ifdef ENABLE_CHECKING
/* cp_tree_equal looks through NOPs, so allow them. */
gcc_assert (r == t
@ -3550,7 +3554,13 @@ maybe_constant_init (tree t, tree decl)
t = TREE_OPERAND (t, 0);
if (TREE_CODE (t) == INIT_EXPR)
t = TREE_OPERAND (t, 1);
t = maybe_constant_value (t, decl);
if (instantiation_dependent_expression_p (t)
|| type_unknown_p (t)
|| BRACE_ENCLOSED_INITIALIZER_P (t)
|| !potential_static_init_expression (t))
/* Don't try to evaluate it. */;
else
t = cxx_eval_outermost_constant_expr (t, true, false, decl);
if (TREE_CODE (t) == TARGET_EXPR)
{
tree init = TARGET_EXPR_INITIAL (t);
@ -3604,8 +3614,10 @@ check_automatic_or_tls (tree ref)
not evaluated are not considered. */
static bool
potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
potential_constant_expression_1 (tree t, bool want_rval, bool strict,
tsubst_flags_t flags)
{
#define RECUR(T,RV) potential_constant_expression_1 ((T), (RV), strict, flags)
enum { any = false, rval = true };
int i;
tree tmp;
@ -3698,14 +3710,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
tree x = get_nth_callarg (t, 0);
if (is_this_parameter (x))
return true;
else if (!potential_constant_expression_1 (x, rval, flags))
else if (!RECUR (x, rval))
return false;
i = 1;
}
}
else
{
if (!potential_constant_expression_1 (fun, true, flags))
if (!RECUR (fun, true))
return false;
fun = get_first_fn (fun);
}
@ -3716,7 +3728,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
}
else
{
if (potential_constant_expression_1 (fun, rval, flags))
if (RECUR (fun, rval))
/* Might end up being a constant function pointer. */;
else
return false;
@ -3724,7 +3736,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
for (; i < nargs; ++i)
{
tree x = get_nth_callarg (t, i);
if (!potential_constant_expression_1 (x, rval, flags))
if (!RECUR (x, rval))
return false;
}
return true;
@ -3739,10 +3751,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
-- an lvalue of literal type that refers to non-volatile
object defined with constexpr, or that refers to a
sub-object of such an object; */
return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags);
return RECUR (TREE_OPERAND (t, 0), rval);
case VAR_DECL:
if (want_rval && !decl_constant_var_p (t)
if (want_rval
&& !decl_constant_var_p (t)
&& (strict
|| !CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (t))
|| !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t))
&& !var_in_constexpr_fn (t)
&& !dependent_type_p (TREE_TYPE (t)))
{
@ -3768,8 +3784,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
"reinterpret_cast from integer to pointer");
return false;
}
return (potential_constant_expression_1
(from, TREE_CODE (t) != VIEW_CONVERT_EXPR, flags));
return (RECUR (from, TREE_CODE (t) != VIEW_CONVERT_EXPR));
}
case ADDR_EXPR:
@ -3797,7 +3812,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
return false;
}
#endif
return potential_constant_expression_1 (t, any, flags);
return RECUR (t, any);
case COMPONENT_REF:
case BIT_FIELD_REF:
@ -3807,12 +3822,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
of literal type or of pointer to literal type. */
/* This test would be redundant, as it follows from the
postfix-expression being a potential constant expression. */
return potential_constant_expression_1 (TREE_OPERAND (t, 0),
want_rval, flags);
return RECUR (TREE_OPERAND (t, 0), want_rval);
case EXPR_PACK_EXPANSION:
return potential_constant_expression_1 (PACK_EXPANSION_PATTERN (t),
want_rval, flags);
return RECUR (PACK_EXPANSION_PATTERN (t), want_rval);
case INDIRECT_REF:
{
@ -3829,7 +3842,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
}
return true;
}
return potential_constant_expression_1 (x, rval, flags);
return RECUR (x, rval);
}
case STATEMENT_LIST:
@ -3837,7 +3850,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
tree_stmt_iterator i;
for (i = tsi_start (t); !tsi_end_p (i); tsi_next (&i))
{
if (!potential_constant_expression_1 (tsi_stmt (i), any, flags))
if (!RECUR (tsi_stmt (i), any))
return false;
}
return true;
@ -3847,64 +3860,64 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case MODIFY_EXPR:
if (cxx_dialect < cxx14)
goto fail;
if (!potential_constant_expression_1 (TREE_OPERAND (t, 0), any, flags))
if (!RECUR (TREE_OPERAND (t, 0), any))
return false;
if (!potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags))
if (!RECUR (TREE_OPERAND (t, 1), rval))
return false;
return true;
case MODOP_EXPR:
if (cxx_dialect < cxx14)
goto fail;
if (!potential_constant_expression_1 (TREE_OPERAND (t, 0), rval, flags))
if (!RECUR (TREE_OPERAND (t, 0), rval))
return false;
if (!potential_constant_expression_1 (TREE_OPERAND (t, 2), rval, flags))
if (!RECUR (TREE_OPERAND (t, 2), rval))
return false;
return true;
case IF_STMT:
if (!potential_constant_expression_1 (IF_COND (t), rval, flags))
if (!RECUR (IF_COND (t), rval))
return false;
if (!potential_constant_expression_1 (THEN_CLAUSE (t), any, flags))
if (!RECUR (THEN_CLAUSE (t), any))
return false;
if (!potential_constant_expression_1 (ELSE_CLAUSE (t), any, flags))
if (!RECUR (ELSE_CLAUSE (t), any))
return false;
return true;
case DO_STMT:
if (!potential_constant_expression_1 (DO_COND (t), rval, flags))
if (!RECUR (DO_COND (t), rval))
return false;
if (!potential_constant_expression_1 (DO_BODY (t), any, flags))
if (!RECUR (DO_BODY (t), any))
return false;
return true;
case FOR_STMT:
if (!potential_constant_expression_1 (FOR_INIT_STMT (t), any, flags))
if (!RECUR (FOR_INIT_STMT (t), any))
return false;
if (!potential_constant_expression_1 (FOR_COND (t), rval, flags))
if (!RECUR (FOR_COND (t), rval))
return false;
if (!potential_constant_expression_1 (FOR_EXPR (t), any, flags))
if (!RECUR (FOR_EXPR (t), any))
return false;
if (!potential_constant_expression_1 (FOR_BODY (t), any, flags))
if (!RECUR (FOR_BODY (t), any))
return false;
return true;
case WHILE_STMT:
if (!potential_constant_expression_1 (WHILE_COND (t), rval, flags))
if (!RECUR (WHILE_COND (t), rval))
return false;
if (!potential_constant_expression_1 (WHILE_BODY (t), any, flags))
if (!RECUR (WHILE_BODY (t), any))
return false;
return true;
case SWITCH_STMT:
if (!potential_constant_expression_1 (SWITCH_STMT_COND (t), rval, flags))
if (!RECUR (SWITCH_STMT_COND (t), rval))
return false;
if (!potential_constant_expression_1 (SWITCH_STMT_BODY (t), any, flags))
if (!RECUR (SWITCH_STMT_BODY (t), any))
return false;
return true;
case STMT_EXPR:
return potential_constant_expression_1 (STMT_EXPR_STMT (t), rval, flags);
return RECUR (STMT_EXPR_STMT (t), rval);
case LAMBDA_EXPR:
case DYNAMIC_CAST_EXPR:
@ -4002,8 +4015,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case FIXED_CONVERT_EXPR:
case UNARY_PLUS_EXPR:
unary:
return potential_constant_expression_1 (TREE_OPERAND (t, 0), rval,
flags);
return RECUR (TREE_OPERAND (t, 0), rval);
case CAST_EXPR:
case CONST_CAST_EXPR:
@ -4022,13 +4034,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
return false;
}
return (potential_constant_expression_1
(TREE_OPERAND (t, 0),
TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE, flags));
return (RECUR (TREE_OPERAND (t, 0),
TREE_CODE (TREE_TYPE (t)) != REFERENCE_TYPE));
case BIND_EXPR:
return potential_constant_expression_1 (BIND_EXPR_BODY (t),
want_rval, flags);
return RECUR (BIND_EXPR_BODY (t), want_rval);
case WITH_CLEANUP_EXPR:
case CLEANUP_POINT_EXPR:
@ -4041,12 +4051,10 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case NON_DEPENDENT_EXPR:
/* For convenience. */
case RETURN_EXPR:
return potential_constant_expression_1 (TREE_OPERAND (t, 0),
want_rval, flags);
return RECUR (TREE_OPERAND (t, 0), want_rval);
case SCOPE_REF:
return potential_constant_expression_1 (TREE_OPERAND (t, 1),
want_rval, flags);
return RECUR (TREE_OPERAND (t, 1), want_rval);
case TARGET_EXPR:
if (!literal_type_p (TREE_TYPE (t)))
@ -4060,15 +4068,14 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
return false;
}
case INIT_EXPR:
return potential_constant_expression_1 (TREE_OPERAND (t, 1),
rval, flags);
return RECUR (TREE_OPERAND (t, 1), rval);
case CONSTRUCTOR:
{
vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
constructor_elt *ce;
for (i = 0; vec_safe_iterate (v, i, &ce); ++i)
if (!potential_constant_expression_1 (ce->value, want_rval, flags))
if (!RECUR (ce->value, want_rval))
return false;
return true;
}
@ -4077,13 +4084,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
{
gcc_assert (TREE_PURPOSE (t) == NULL_TREE
|| DECL_P (TREE_PURPOSE (t)));
if (!potential_constant_expression_1 (TREE_VALUE (t), want_rval,
flags))
if (!RECUR (TREE_VALUE (t), want_rval))
return false;
if (TREE_CHAIN (t) == NULL_TREE)
return true;
return potential_constant_expression_1 (TREE_CHAIN (t), want_rval,
flags);
return RECUR (TREE_CHAIN (t), want_rval);
}
case TRUNC_DIV_EXPR:
@ -4095,7 +4100,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case ROUND_MOD_EXPR:
{
tree denom = TREE_OPERAND (t, 1);
if (!potential_constant_expression_1 (denom, rval, flags))
if (!RECUR (denom, rval))
return false;
/* We can't call cxx_eval_outermost_constant_expr on an expression
that hasn't been through instantiate_non_dependent_expr yet. */
@ -4110,8 +4115,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
else
{
want_rval = true;
return potential_constant_expression_1 (TREE_OPERAND (t, 0),
want_rval, flags);
return RECUR (TREE_OPERAND (t, 0), want_rval);
}
}
@ -4125,7 +4129,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
STRIP_NOPS (op1);
if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
|| TREE_CODE (op1) == EMPTY_CLASS_EXPR)
return potential_constant_expression_1 (op0, want_rval, flags);
return RECUR (op0, want_rval);
else
goto binary;
}
@ -4143,12 +4147,12 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
truth:
{
tree op = TREE_OPERAND (t, 0);
if (!potential_constant_expression_1 (op, rval, flags))
if (!RECUR (op, rval))
return false;
if (!processing_template_decl)
op = cxx_eval_outermost_constant_expr (op, true);
if (tree_int_cst_equal (op, tmp))
return potential_constant_expression_1 (TREE_OPERAND (t, 1), rval, flags);
return RECUR (TREE_OPERAND (t, 1), rval);
else
return true;
}
@ -4186,8 +4190,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case DOTSTAR_EXPR:
binary:
for (i = 0; i < 2; ++i)
if (!potential_constant_expression_1 (TREE_OPERAND (t, i),
want_rval, flags))
if (!RECUR (TREE_OPERAND (t, i), want_rval))
return false;
return true;
@ -4199,8 +4202,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
case FMA_EXPR:
case VEC_PERM_EXPR:
for (i = 0; i < 3; ++i)
if (!potential_constant_expression_1 (TREE_OPERAND (t, i),
true, flags))
if (!RECUR (TREE_OPERAND (t, i), true))
return false;
return true;
@ -4210,19 +4212,17 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
care about; otherwise we only require that the condition and
either of the legs be potentially constant. */
tmp = TREE_OPERAND (t, 0);
if (!potential_constant_expression_1 (tmp, rval, flags))
if (!RECUR (tmp, rval))
return false;
if (!processing_template_decl)
tmp = cxx_eval_outermost_constant_expr (tmp, true);
if (integer_zerop (tmp))
return potential_constant_expression_1 (TREE_OPERAND (t, 2),
want_rval, flags);
return RECUR (TREE_OPERAND (t, 2), want_rval);
else if (TREE_CODE (tmp) == INTEGER_CST)
return potential_constant_expression_1 (TREE_OPERAND (t, 1),
want_rval, flags);
return RECUR (TREE_OPERAND (t, 1), want_rval);
for (i = 1; i < 3; ++i)
if (potential_constant_expression_1 (TREE_OPERAND (t, i),
want_rval, tf_none))
want_rval, strict, tf_none))
return true;
if (flags & tf_error)
error ("expression %qE is not a constant-expression", t);
@ -4246,6 +4246,7 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
gcc_unreachable();
return false;
}
#undef RECUR
}
/* The main entry point to the above. */
@ -4253,7 +4254,13 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags)
bool
potential_constant_expression (tree t)
{
return potential_constant_expression_1 (t, false, tf_none);
return potential_constant_expression_1 (t, false, true, tf_none);
}
bool
potential_static_init_expression (tree t)
{
return potential_constant_expression_1 (t, false, false, tf_none);
}
/* As above, but require a constant rvalue. */
@ -4261,7 +4268,7 @@ potential_constant_expression (tree t)
bool
potential_rvalue_constant_expression (tree t)
{
return potential_constant_expression_1 (t, true, tf_none);
return potential_constant_expression_1 (t, true, true, tf_none);
}
/* Like above, but complain about non-constant expressions. */
@ -4269,7 +4276,7 @@ potential_rvalue_constant_expression (tree t)
bool
require_potential_constant_expression (tree t)
{
return potential_constant_expression_1 (t, false, tf_warning_or_error);
return potential_constant_expression_1 (t, false, true, tf_warning_or_error);
}
/* Cross product of the above. */
@ -4277,7 +4284,7 @@ require_potential_constant_expression (tree t)
bool
require_potential_rvalue_constant_expression (tree t)
{
return potential_constant_expression_1 (t, true, tf_warning_or_error);
return potential_constant_expression_1 (t, true, true, tf_warning_or_error);
}
#include "gt-cp-constexpr.h"

View File

@ -5551,8 +5551,8 @@ extern tree build_vec_delete (tree, tree,
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);
extern tree decl_constant_value_safe (tree);
extern tree scalar_constant_value (tree);
extern tree decl_really_constant_value (tree);
extern int diagnose_uninitialized_cst_or_ref_member (tree, bool, bool);
extern tree build_vtbl_address (tree);
@ -6349,6 +6349,7 @@ extern tree register_constexpr_fundef (tree, tree);
extern bool check_constexpr_ctor_body (tree, tree, bool);
extern tree ensure_literal_type_for_constexpr_object (tree);
extern bool potential_constant_expression (tree);
extern bool potential_static_init_expression (tree);
extern bool potential_rvalue_constant_expression (tree);
extern bool require_potential_constant_expression (tree);
extern bool require_potential_rvalue_constant_expression (tree);

View File

@ -675,9 +675,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags,
}
/* FIXME remove when moving to c_fully_fold model. */
/* FIXME do we still need this test? */
if (!CLASS_TYPE_P (type))
e = integral_constant_value (e);
e = scalar_constant_value (e);
if (error_operand_p (e))
return error_mark_node;

View File

@ -12993,7 +12993,7 @@ build_enumerator (tree name, tree value, tree enumtype, location_t loc)
tree context;
tree type;
/* integral_constant_value will pull out this expression, so make sure
/* scalar_constant_value will pull out this expression, so make sure
it's folded as appropriate. */
if (processing_template_decl)
value = fold_non_dependent_expr (value);

View File

@ -2004,16 +2004,16 @@ build_offset_ref (tree type, tree member, bool address_p,
/* 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
recursively); otherwise, return DECL. If STRICT_P, the
initializer is only returned if DECL is a
constant-expression. If RETURN_AGGREGATE_CST_OK_P, it is ok to
return an aggregate constant. */
static tree
constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p)
constant_value_1 (tree decl, bool strict_p, bool return_aggregate_cst_ok_p)
{
while (TREE_CODE (decl) == CONST_DECL
|| (integral_p
|| (strict_p
? decl_constant_var_p (decl)
: (VAR_P (decl)
&& CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (decl)))))
@ -2047,7 +2047,7 @@ constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p)
if (!init
|| !TREE_TYPE (init)
|| !TREE_CONSTANT (init)
|| (!integral_p && !return_aggregate_cst_ok_p
|| (!return_aggregate_cst_ok_p
/* Unless RETURN_AGGREGATE_CST_OK_P is true, do not
return an aggregate constant (of which string
literals are a special case), as we do not want
@ -2062,37 +2062,36 @@ constant_value_1 (tree decl, bool integral_p, bool return_aggregate_cst_ok_p)
return decl;
}
/* 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]. */
/* If DECL is a CONST_DECL, or a constant VAR_DECL initialized by constant
of integral or enumeration type, or a constexpr variable of scalar type,
then return that value. These are those variables permitted in constant
expressions by [5.19/1]. */
tree
integral_constant_value (tree decl)
scalar_constant_value (tree decl)
{
return constant_value_1 (decl, /*integral_p=*/true,
return constant_value_1 (decl, /*strict_p=*/true,
/*return_aggregate_cst_ok_p=*/false);
}
/* A more relaxed version of integral_constant_value, used by the
/* Like scalar_constant_value, but can also return aggregate initializers. */
tree
decl_really_constant_value (tree decl)
{
return constant_value_1 (decl, /*strict_p=*/true,
/*return_aggregate_cst_ok_p=*/true);
}
/* A more relaxed version of scalar_constant_value, used by the
common C/C++ code. */
tree
decl_constant_value (tree decl)
{
return constant_value_1 (decl, /*integral_p=*/processing_template_decl,
return constant_value_1 (decl, /*strict_p=*/processing_template_decl,
/*return_aggregate_cst_ok_p=*/true);
}
/* A version of integral_constant_value used by the C++ front end for
optimization purposes. */
tree
decl_constant_value_safe (tree decl)
{
return constant_value_1 (decl, /*integral_p=*/processing_template_decl,
/*return_aggregate_cst_ok_p=*/false);
}
/* Common subroutines of build_new and build_vec_delete. */

View File

@ -12805,7 +12805,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 integral_constant_value (t);
return scalar_constant_value (t);
/* Unfortunately, we cannot just call lookup_name here.
Consider:
@ -12936,7 +12936,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
else if (decl_constant_var_p (r))
/* A use of a local constant decays to its value.
FIXME update for core DR 696. */
r = integral_constant_value (r);
r = scalar_constant_value (r);
}
}
/* Remember this for subsequent uses. */
@ -18420,7 +18420,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, explain_p);
if (arg != integral_constant_value (parm))
if (arg != scalar_constant_value (parm))
return unify_template_argument_mismatch (explain_p, parm, arg);
return unify_success (explain_p);

View File

@ -3125,7 +3125,7 @@ process_outer_var_ref (tree decl, tsubst_flags_t complain)
form, so wait until instantiation time. */
return decl;
else if (decl_constant_var_p (decl))
return integral_constant_value (decl);
return scalar_constant_value (decl);
}
if (parsing_nsdmi ())

View File

@ -1936,17 +1936,10 @@ decay_conversion (tree exp, tsubst_flags_t complain)
code = TREE_CODE (type);
/* For an array decl decay_conversion should not try to return its
initializer. */
if (code != ARRAY_TYPE)
{
/* FIXME remove? at least need to remember that this isn't really a
constant expression if EXP isn't decl_constant_var_p, like with
C_MAYBE_CONST_EXPR. */
exp = decl_constant_value_safe (exp);
if (error_operand_p (exp))
return error_mark_node;
}
/* FIXME remove for delayed folding. */
exp = scalar_constant_value (exp);
if (error_operand_p (exp))
return error_mark_node;
if (NULLPTR_TYPE_P (type) && !TREE_SIDE_EFFECTS (exp))
return nullptr_node;

View File

@ -3,9 +3,9 @@
constexpr int verysquare(int x) { return x * x; }
const double mass = 9.8;
constexpr double energy = mass * verysquare(56.6); // { dg-error "mass" "" { xfail *-*-* } }
constexpr double energy = mass * verysquare(56.6); // { dg-error "mass" }
int arr[(int)mass]; // { dg-error "mass" "" { xfail *-*-* } }
int arr[(int)mass]; // { dg-error "" }
float array[verysquare(9)]; // OK -- not C99 VLA

View File

@ -4,7 +4,7 @@
#define assert_true(b) do { char c[2 * bool(b) - 1]; } while(0)
char* const cp1 = nullptr;
constexpr char* cp1 = nullptr;
void fun()
{