c++: discarded-value and constexpr
I've been thinking for a while that the 'lval' parameter needed a third value for discarded-value expressions; most importantly, cxx_eval_store_expression does extra work for an lvalue result, and we also don't want to do the l->r conversion. Mostly this is pretty mechanical. Apart from the _store_ fix, I also use vc_discard for substatements of a STATEMENT_LIST other than a stmt-expr result, and avoid building _REFs to be ignored in a few other places. gcc/cp/ChangeLog: * constexpr.cc (enum value_cat): New. Change all 'lval' parameters from int to value_cat. Change most false to vc_prvalue, most true to vc_glvalue, cases where the return value is ignored to vc_discard. (cxx_eval_statement_list): Only vc_prvalue for stmt-expr result. (cxx_eval_store_expression): Only build _REF for vc_glvalue. (cxx_eval_array_reference, cxx_eval_component_reference) (cxx_eval_indirect_ref, cxx_eval_constant_expression): Likewise.
This commit is contained in:
parent
2540e2c604
commit
72f76540ad
|
@ -1210,9 +1210,6 @@ uid_sensitive_constexpr_evaluation_checker::evaluation_restricted_p () const
|
||||||
|
|
||||||
static GTY (()) hash_table<constexpr_call_hasher> *constexpr_call_table;
|
static GTY (()) hash_table<constexpr_call_hasher> *constexpr_call_table;
|
||||||
|
|
||||||
static tree cxx_eval_constant_expression (const constexpr_ctx *, tree,
|
|
||||||
bool, bool *, bool *, tree * = NULL);
|
|
||||||
|
|
||||||
/* Compute a hash value for a constexpr call representation. */
|
/* Compute a hash value for a constexpr call representation. */
|
||||||
|
|
||||||
inline hashval_t
|
inline hashval_t
|
||||||
|
@ -1346,13 +1343,25 @@ get_nth_callarg (tree t, int n)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Whether our evaluation wants a prvalue (e.g. CONSTRUCTOR or _CST),
|
||||||
|
a glvalue (e.g. VAR_DECL or _REF), or nothing. */
|
||||||
|
|
||||||
|
enum value_cat {
|
||||||
|
vc_prvalue = 0,
|
||||||
|
vc_glvalue = 1,
|
||||||
|
vc_discard = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
static tree cxx_eval_constant_expression (const constexpr_ctx *, tree,
|
||||||
|
value_cat, bool *, bool *, tree * = NULL);
|
||||||
|
|
||||||
/* Attempt to evaluate T which represents a call to a builtin function.
|
/* Attempt to evaluate T which represents a call to a builtin function.
|
||||||
We assume here that all builtin functions evaluate to scalar types
|
We assume here that all builtin functions evaluate to scalar types
|
||||||
represented by _CST nodes. */
|
represented by _CST nodes. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
|
cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
const int nargs = call_expr_nargs (t);
|
const int nargs = call_expr_nargs (t);
|
||||||
|
@ -1458,7 +1467,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
|
||||||
|| potential_constant_expression (arg))
|
|| potential_constant_expression (arg))
|
||||||
{
|
{
|
||||||
bool dummy1 = false, dummy2 = false;
|
bool dummy1 = false, dummy2 = false;
|
||||||
arg = cxx_eval_constant_expression (&new_ctx, arg, false,
|
arg = cxx_eval_constant_expression (&new_ctx, arg, vc_prvalue,
|
||||||
&dummy1, &dummy2);
|
&dummy1, &dummy2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1703,7 +1712,7 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t, tree fun,
|
||||||
/* Normally we would strip a TARGET_EXPR in an initialization context
|
/* Normally we would strip a TARGET_EXPR in an initialization context
|
||||||
such as this, but here we do the elision differently: we keep the
|
such as this, but here we do the elision differently: we keep the
|
||||||
TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */
|
TARGET_EXPR, and use its CONSTRUCTOR as the value of the parm. */
|
||||||
arg = cxx_eval_constant_expression (ctx, x, /*lval=*/false,
|
arg = cxx_eval_constant_expression (ctx, x, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
/* Don't VERIFY_CONSTANT here. */
|
/* Don't VERIFY_CONSTANT here. */
|
||||||
if (*non_constant_p && ctx->quiet)
|
if (*non_constant_p && ctx->quiet)
|
||||||
|
@ -1807,7 +1816,7 @@ cx_error_context (void)
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
|
cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
enum tree_code opcode = ERROR_MARK;
|
enum tree_code opcode = ERROR_MARK;
|
||||||
|
@ -1832,12 +1841,13 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
case IFN_LAUNDER:
|
case IFN_LAUNDER:
|
||||||
return cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0),
|
return cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0),
|
||||||
false, non_constant_p, overflow_p);
|
vc_prvalue, non_constant_p,
|
||||||
|
overflow_p);
|
||||||
|
|
||||||
case IFN_VEC_CONVERT:
|
case IFN_VEC_CONVERT:
|
||||||
{
|
{
|
||||||
tree arg = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0),
|
tree arg = cxx_eval_constant_expression (ctx, CALL_EXPR_ARG (t, 0),
|
||||||
false, non_constant_p,
|
vc_prvalue, non_constant_p,
|
||||||
overflow_p);
|
overflow_p);
|
||||||
if (TREE_CODE (arg) == VECTOR_CST)
|
if (TREE_CODE (arg) == VECTOR_CST)
|
||||||
if (tree r = fold_const_call (CFN_VEC_CONVERT, TREE_TYPE (t), arg))
|
if (tree r = fold_const_call (CFN_VEC_CONVERT, TREE_TYPE (t), arg))
|
||||||
|
@ -2103,7 +2113,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Evaluate the object so that we know its dynamic type. */
|
/* Evaluate the object so that we know its dynamic type. */
|
||||||
obj = cxx_eval_constant_expression (ctx, obj, /*lval*/false, non_constant_p,
|
obj = cxx_eval_constant_expression (ctx, obj, vc_prvalue, non_constant_p,
|
||||||
overflow_p);
|
overflow_p);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return call;
|
return call;
|
||||||
|
@ -2138,7 +2148,7 @@ cxx_eval_dynamic_cast_fn (const constexpr_ctx *ctx, tree call,
|
||||||
considered to be a most derived object that has the type of the
|
considered to be a most derived object that has the type of the
|
||||||
constructor or destructor's class. */
|
constructor or destructor's class. */
|
||||||
tree vtable = build_vfield_ref (obj, objtype);
|
tree vtable = build_vfield_ref (obj, objtype);
|
||||||
vtable = cxx_eval_constant_expression (ctx, vtable, /*lval*/false,
|
vtable = cxx_eval_constant_expression (ctx, vtable, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return call;
|
return call;
|
||||||
|
@ -2301,7 +2311,7 @@ replace_decl (tree *tp, tree decl, tree replacement)
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl,
|
cxx_eval_thunk_call (const constexpr_ctx *ctx, tree t, tree thunk_fndecl,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
tree function = THUNK_TARGET (thunk_fndecl);
|
tree function = THUNK_TARGET (thunk_fndecl);
|
||||||
|
@ -2362,7 +2372,7 @@ cxx_set_object_constness (const constexpr_ctx *ctx, tree object,
|
||||||
{
|
{
|
||||||
/* Subobjects might not be stored in ctx->global->values but we
|
/* Subobjects might not be stored in ctx->global->values but we
|
||||||
can get its CONSTRUCTOR by evaluating *this. */
|
can get its CONSTRUCTOR by evaluating *this. */
|
||||||
tree e = cxx_eval_constant_expression (ctx, object, /*lval*/false,
|
tree e = cxx_eval_constant_expression (ctx, object, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p)
|
if (TREE_CODE (e) == CONSTRUCTOR && !*non_constant_p)
|
||||||
TREE_READONLY (e) = readonly_p;
|
TREE_READONLY (e) = readonly_p;
|
||||||
|
@ -2375,7 +2385,7 @@ cxx_set_object_constness (const constexpr_ctx *ctx, tree object,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
/* Handle concept checks separately. */
|
/* Handle concept checks separately. */
|
||||||
|
@ -2395,9 +2405,8 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||||
if (TREE_CODE (fun) != FUNCTION_DECL)
|
if (TREE_CODE (fun) != FUNCTION_DECL)
|
||||||
{
|
{
|
||||||
/* Might be a constexpr function pointer. */
|
/* Might be a constexpr function pointer. */
|
||||||
fun = cxx_eval_constant_expression (ctx, fun,
|
fun = cxx_eval_constant_expression (ctx, fun, vc_prvalue,
|
||||||
/*lval*/false, non_constant_p,
|
non_constant_p, overflow_p);
|
||||||
overflow_p);
|
|
||||||
STRIP_NOPS (fun);
|
STRIP_NOPS (fun);
|
||||||
if (TREE_CODE (fun) == ADDR_EXPR)
|
if (TREE_CODE (fun) == ADDR_EXPR)
|
||||||
fun = TREE_OPERAND (fun, 0);
|
fun = TREE_OPERAND (fun, 0);
|
||||||
|
@ -2463,7 +2472,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||||
for (int i = 0; i < nargs; ++i)
|
for (int i = 0; i < nargs; ++i)
|
||||||
{
|
{
|
||||||
tree arg = CALL_EXPR_ARG (t, i);
|
tree arg = CALL_EXPR_ARG (t, i);
|
||||||
arg = cxx_eval_constant_expression (ctx, arg, false,
|
arg = cxx_eval_constant_expression (ctx, arg, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (arg);
|
VERIFY_CONSTANT (arg);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
|
@ -2571,7 +2580,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||||
for (int i = 0; i < nargs; ++i)
|
for (int i = 0; i < nargs; ++i)
|
||||||
{
|
{
|
||||||
tree arg = CALL_EXPR_ARG (t, i);
|
tree arg = CALL_EXPR_ARG (t, i);
|
||||||
arg = cxx_eval_constant_expression (ctx, arg, false,
|
arg = cxx_eval_constant_expression (ctx, arg, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (i == 1)
|
if (i == 1)
|
||||||
arg1 = arg;
|
arg1 = arg;
|
||||||
|
@ -2852,7 +2861,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
tree jump_target = NULL_TREE;
|
tree jump_target = NULL_TREE;
|
||||||
cxx_eval_constant_expression (&ctx_with_save_exprs, body,
|
cxx_eval_constant_expression (&ctx_with_save_exprs, body,
|
||||||
lval, non_constant_p, overflow_p,
|
vc_discard, non_constant_p, overflow_p,
|
||||||
&jump_target);
|
&jump_target);
|
||||||
|
|
||||||
if (DECL_CONSTRUCTOR_P (fun))
|
if (DECL_CONSTRUCTOR_P (fun))
|
||||||
|
@ -3213,7 +3222,7 @@ cxx_eval_unary_expression (const constexpr_ctx *ctx, tree t,
|
||||||
{
|
{
|
||||||
tree r;
|
tree r;
|
||||||
tree orig_arg = TREE_OPERAND (t, 0);
|
tree orig_arg = TREE_OPERAND (t, 0);
|
||||||
tree arg = cxx_eval_constant_expression (ctx, orig_arg, /*lval*/false,
|
tree arg = cxx_eval_constant_expression (ctx, orig_arg, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (arg);
|
VERIFY_CONSTANT (arg);
|
||||||
location_t loc = EXPR_LOCATION (t);
|
location_t loc = EXPR_LOCATION (t);
|
||||||
|
@ -3259,8 +3268,8 @@ cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1));
|
t = fold_convert_loc (loc, ssizetype, TREE_OPERAND (lhs, 1));
|
||||||
tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0)));
|
tree nelts = array_type_nelts_top (TREE_TYPE (TREE_OPERAND (lhs, 0)));
|
||||||
nelts = cxx_eval_constant_expression (ctx, nelts, false, non_constant_p,
|
nelts = cxx_eval_constant_expression (ctx, nelts, vc_prvalue,
|
||||||
overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
/* Don't fold an out-of-bound access. */
|
/* Don't fold an out-of-bound access. */
|
||||||
|
@ -3281,7 +3290,7 @@ cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
|
||||||
t, NULL_TREE, NULL_TREE);
|
t, NULL_TREE, NULL_TREE);
|
||||||
t = cp_build_addr_expr (t, tf_warning_or_error);
|
t = cp_build_addr_expr (t, tf_warning_or_error);
|
||||||
t = cp_fold_convert (orig_type, t);
|
t = cp_fold_convert (orig_type, t);
|
||||||
return cxx_eval_constant_expression (ctx, t, /*lval*/false,
|
return cxx_eval_constant_expression (ctx, t, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3325,20 +3334,20 @@ cxx_maybe_fold_addr_pointer_plus (tree t)
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
|
cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
tree r = NULL_TREE;
|
tree r = NULL_TREE;
|
||||||
tree orig_lhs = TREE_OPERAND (t, 0);
|
tree orig_lhs = TREE_OPERAND (t, 0);
|
||||||
tree orig_rhs = TREE_OPERAND (t, 1);
|
tree orig_rhs = TREE_OPERAND (t, 1);
|
||||||
tree lhs, rhs;
|
tree lhs, rhs;
|
||||||
lhs = cxx_eval_constant_expression (ctx, orig_lhs, /*lval*/false,
|
lhs = cxx_eval_constant_expression (ctx, orig_lhs, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
/* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer
|
/* Don't VERIFY_CONSTANT here, it's unnecessary and will break pointer
|
||||||
subtraction. */
|
subtraction. */
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return t;
|
return t;
|
||||||
rhs = cxx_eval_constant_expression (ctx, orig_rhs, /*lval*/false,
|
rhs = cxx_eval_constant_expression (ctx, orig_rhs, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return t;
|
return t;
|
||||||
|
@ -3457,12 +3466,12 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t,
|
cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p,
|
bool *non_constant_p, bool *overflow_p,
|
||||||
tree *jump_target)
|
tree *jump_target)
|
||||||
{
|
{
|
||||||
tree val = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
|
tree val = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
|
||||||
/*lval*/false,
|
vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (val);
|
VERIFY_CONSTANT (val);
|
||||||
if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t))
|
if (TREE_CODE (t) == IF_STMT && IF_STMT_CONSTEVAL_P (t))
|
||||||
|
@ -3504,15 +3513,15 @@ cxx_eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
tree arg1 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
|
tree arg1 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
|
||||||
/*lval*/false,
|
vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (arg1);
|
VERIFY_CONSTANT (arg1);
|
||||||
tree arg2 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
|
tree arg2 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
|
||||||
/*lval*/false,
|
vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (arg2);
|
VERIFY_CONSTANT (arg2);
|
||||||
tree arg3 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2),
|
tree arg3 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2),
|
||||||
/*lval*/false,
|
vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (arg3);
|
VERIFY_CONSTANT (arg3);
|
||||||
location_t loc = EXPR_LOCATION (t);
|
location_t loc = EXPR_LOCATION (t);
|
||||||
|
@ -3844,7 +3853,7 @@ get_array_or_vector_nelts (const constexpr_ctx *ctx, tree type,
|
||||||
gcc_unreachable ();
|
gcc_unreachable ();
|
||||||
|
|
||||||
/* For VLAs, the number of elements won't be an integer constant. */
|
/* For VLAs, the number of elements won't be an integer constant. */
|
||||||
nelts = cxx_eval_constant_expression (ctx, nelts, false,
|
nelts = cxx_eval_constant_expression (ctx, nelts, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
return nelts;
|
return nelts;
|
||||||
}
|
}
|
||||||
|
@ -3881,7 +3890,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx,
|
||||||
location_t loc = cp_expr_loc_or_input_loc (t);
|
location_t loc = cp_expr_loc_or_input_loc (t);
|
||||||
tree ary = TREE_OPERAND (t, 0);
|
tree ary = TREE_OPERAND (t, 0);
|
||||||
t = TREE_OPERAND (t, 1);
|
t = TREE_OPERAND (t, 1);
|
||||||
tree index = cxx_eval_constant_expression (ctx, t, false,
|
tree index = cxx_eval_constant_expression (ctx, t, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (index);
|
VERIFY_CONSTANT (index);
|
||||||
|
|
||||||
|
@ -3913,7 +3922,7 @@ eval_and_check_array_index (const constexpr_ctx *ctx,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
|
cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
tree oldary = TREE_OPERAND (t, 0);
|
tree oldary = TREE_OPERAND (t, 0);
|
||||||
|
@ -3936,6 +3945,8 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
if (lval && ary == oldary && index == oldidx)
|
if (lval && ary == oldary && index == oldidx)
|
||||||
return t;
|
return t;
|
||||||
|
else if (lval == vc_discard)
|
||||||
|
return t;
|
||||||
else if (lval)
|
else if (lval)
|
||||||
return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
|
return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
|
||||||
|
|
||||||
|
@ -4043,7 +4054,7 @@ cxx_eval_array_reference (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
|
cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
unsigned HOST_WIDE_INT i;
|
unsigned HOST_WIDE_INT i;
|
||||||
|
@ -4067,6 +4078,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
|
||||||
whole = cplus_expand_constant (whole);
|
whole = cplus_expand_constant (whole);
|
||||||
if (whole == orig_whole)
|
if (whole == orig_whole)
|
||||||
return t;
|
return t;
|
||||||
|
if (lval == vc_discard)
|
||||||
|
return t;
|
||||||
if (lval)
|
if (lval)
|
||||||
return fold_build3 (COMPONENT_REF, TREE_TYPE (t),
|
return fold_build3 (COMPONENT_REF, TREE_TYPE (t),
|
||||||
whole, part, NULL_TREE);
|
whole, part, NULL_TREE);
|
||||||
|
@ -4152,7 +4165,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t,
|
cxx_eval_bit_field_ref (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
tree orig_whole = TREE_OPERAND (t, 0);
|
tree orig_whole = TREE_OPERAND (t, 0);
|
||||||
|
@ -4449,7 +4462,7 @@ cxx_eval_bit_cast (const constexpr_ctx *ctx, tree t, bool *non_constant_p,
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
tree op = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false,
|
tree op = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return t;
|
return t;
|
||||||
|
@ -4569,14 +4582,14 @@ cxx_eval_logical_expression (const constexpr_ctx *ctx, tree t,
|
||||||
{
|
{
|
||||||
tree r;
|
tree r;
|
||||||
tree lhs = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
|
tree lhs = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0),
|
||||||
/*lval*/false, non_constant_p,
|
vc_prvalue, non_constant_p,
|
||||||
overflow_p);
|
overflow_p);
|
||||||
VERIFY_CONSTANT (lhs);
|
VERIFY_CONSTANT (lhs);
|
||||||
if (tree_int_cst_equal (lhs, bailout_value))
|
if (tree_int_cst_equal (lhs, bailout_value))
|
||||||
return lhs;
|
return lhs;
|
||||||
gcc_assert (tree_int_cst_equal (lhs, continue_value));
|
gcc_assert (tree_int_cst_equal (lhs, continue_value));
|
||||||
r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
|
r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
|
||||||
/*lval*/false, non_constant_p,
|
vc_prvalue, non_constant_p,
|
||||||
overflow_p);
|
overflow_p);
|
||||||
VERIFY_CONSTANT (r);
|
VERIFY_CONSTANT (r);
|
||||||
return r;
|
return r;
|
||||||
|
@ -4725,7 +4738,7 @@ verify_ctor_sanity (const constexpr_ctx *ctx, tree type)
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
|
cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
|
vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (t);
|
||||||
|
@ -4858,7 +4871,7 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
|
cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
|
||||||
bool value_init, bool lval,
|
bool value_init, value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
tree elttype = TREE_TYPE (atype);
|
tree elttype = TREE_TYPE (atype);
|
||||||
|
@ -5000,7 +5013,7 @@ cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_vec_init (const constexpr_ctx *ctx, tree t,
|
cxx_eval_vec_init (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
tree atype = TREE_TYPE (t);
|
tree atype = TREE_TYPE (t);
|
||||||
|
@ -5070,7 +5083,7 @@ cxx_union_active_member (const constexpr_ctx *ctx, tree t)
|
||||||
constexpr_ctx new_ctx = *ctx;
|
constexpr_ctx new_ctx = *ctx;
|
||||||
new_ctx.quiet = true;
|
new_ctx.quiet = true;
|
||||||
bool non_constant_p = false, overflow_p = false;
|
bool non_constant_p = false, overflow_p = false;
|
||||||
tree ctor = cxx_eval_constant_expression (&new_ctx, t, false,
|
tree ctor = cxx_eval_constant_expression (&new_ctx, t, vc_prvalue,
|
||||||
&non_constant_p,
|
&non_constant_p,
|
||||||
&overflow_p);
|
&overflow_p);
|
||||||
if (TREE_CODE (ctor) == CONSTRUCTOR
|
if (TREE_CODE (ctor) == CONSTRUCTOR
|
||||||
|
@ -5306,7 +5319,7 @@ cxx_fold_indirect_ref (const constexpr_ctx *ctx, location_t loc, tree type,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
|
cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
tree orig_op0 = TREE_OPERAND (t, 0);
|
tree orig_op0 = TREE_OPERAND (t, 0);
|
||||||
|
@ -5330,7 +5343,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
|
||||||
{
|
{
|
||||||
/* If that didn't work, evaluate the operand first. */
|
/* If that didn't work, evaluate the operand first. */
|
||||||
tree op0 = cxx_eval_constant_expression (ctx, orig_op0,
|
tree op0 = cxx_eval_constant_expression (ctx, orig_op0,
|
||||||
/*lval*/false, non_constant_p,
|
vc_prvalue, non_constant_p,
|
||||||
overflow_p);
|
overflow_p);
|
||||||
/* Don't VERIFY_CONSTANT here. */
|
/* Don't VERIFY_CONSTANT here. */
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
|
@ -5366,7 +5379,7 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lval && op0 != orig_op0)
|
if (lval == vc_glvalue && op0 != orig_op0)
|
||||||
return build1 (INDIRECT_REF, TREE_TYPE (t), op0);
|
return build1 (INDIRECT_REF, TREE_TYPE (t), op0);
|
||||||
if (!lval)
|
if (!lval)
|
||||||
VERIFY_CONSTANT (t);
|
VERIFY_CONSTANT (t);
|
||||||
|
@ -5462,7 +5475,7 @@ non_const_var_error (location_t loc, tree r)
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t,
|
cxx_eval_trinary_expression (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
|
@ -5594,7 +5607,7 @@ modifying_const_object_p (tree_code code, tree obj, bool mutable_p)
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
|
cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
constexpr_ctx new_ctx = *ctx;
|
constexpr_ctx new_ctx = *ctx;
|
||||||
|
@ -5617,19 +5630,19 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
|
||||||
stored in, so that any side-effects happen first. */
|
stored in, so that any side-effects happen first. */
|
||||||
if (!SCALAR_TYPE_P (type))
|
if (!SCALAR_TYPE_P (type))
|
||||||
new_ctx.ctor = new_ctx.object = NULL_TREE;
|
new_ctx.ctor = new_ctx.object = NULL_TREE;
|
||||||
init = cxx_eval_constant_expression (&new_ctx, init, false,
|
init = cxx_eval_constant_expression (&new_ctx, init, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool evaluated = false;
|
bool evaluated = false;
|
||||||
if (lval)
|
if (lval == vc_glvalue)
|
||||||
{
|
{
|
||||||
/* If we want to return a reference to the target, we need to evaluate it
|
/* If we want to return a reference to the target, we need to evaluate it
|
||||||
as a whole; otherwise, only evaluate the innermost piece to avoid
|
as a whole; otherwise, only evaluate the innermost piece to avoid
|
||||||
building up unnecessary *_REFs. */
|
building up unnecessary *_REFs. */
|
||||||
target = cxx_eval_constant_expression (ctx, target, true,
|
target = cxx_eval_constant_expression (ctx, target, lval,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
evaluated = true;
|
evaluated = true;
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
|
@ -5681,7 +5694,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
|
||||||
object = probe;
|
object = probe;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
probe = cxx_eval_constant_expression (ctx, probe, true,
|
probe = cxx_eval_constant_expression (ctx, probe, vc_glvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
evaluated = true;
|
evaluated = true;
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
|
@ -5893,7 +5906,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
|
||||||
if (TREE_CODE (init) == TARGET_EXPR)
|
if (TREE_CODE (init) == TARGET_EXPR)
|
||||||
if (tree tinit = TARGET_EXPR_INITIAL (init))
|
if (tree tinit = TARGET_EXPR_INITIAL (init))
|
||||||
init = tinit;
|
init = tinit;
|
||||||
init = cxx_eval_constant_expression (&new_ctx, init, false,
|
init = cxx_eval_constant_expression (&new_ctx, init, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
/* The hash table might have moved since the get earlier, and the
|
/* The hash table might have moved since the get earlier, and the
|
||||||
initializer might have mutated the underlying CONSTRUCTORs, so we must
|
initializer might have mutated the underlying CONSTRUCTORs, so we must
|
||||||
|
@ -5992,7 +6005,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
|
cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p)
|
bool *non_constant_p, bool *overflow_p)
|
||||||
{
|
{
|
||||||
enum tree_code code = TREE_CODE (t);
|
enum tree_code code = TREE_CODE (t);
|
||||||
|
@ -6006,12 +6019,12 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t,
|
||||||
offset = fold_simple (offset);
|
offset = fold_simple (offset);
|
||||||
|
|
||||||
/* The operand as an lvalue. */
|
/* The operand as an lvalue. */
|
||||||
op = cxx_eval_constant_expression (ctx, op, true,
|
op = cxx_eval_constant_expression (ctx, op, vc_glvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
|
|
||||||
/* The operand as an rvalue. */
|
/* The operand as an rvalue. */
|
||||||
tree val
|
tree val
|
||||||
= cxx_eval_constant_expression (ctx, op, false,
|
= cxx_eval_constant_expression (ctx, op, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
/* Don't VERIFY_CONSTANT if this might be dealing with a pointer to
|
/* Don't VERIFY_CONSTANT if this might be dealing with a pointer to
|
||||||
a local array in a constexpr function. */
|
a local array in a constexpr function. */
|
||||||
|
@ -6160,8 +6173,10 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
|
||||||
local_target = NULL_TREE;
|
local_target = NULL_TREE;
|
||||||
jump_target = &local_target;
|
jump_target = &local_target;
|
||||||
}
|
}
|
||||||
for (tree stmt : tsi_range (t))
|
for (tree_stmt_iterator i = tsi_start (t); !tsi_end_p (i); ++i)
|
||||||
{
|
{
|
||||||
|
tree stmt = *i;
|
||||||
|
|
||||||
/* We've found a continue, so skip everything until we reach
|
/* We've found a continue, so skip everything until we reach
|
||||||
the label its jumping to. */
|
the label its jumping to. */
|
||||||
if (continues (jump_target))
|
if (continues (jump_target))
|
||||||
|
@ -6174,7 +6189,13 @@ cxx_eval_statement_list (const constexpr_ctx *ctx, tree t,
|
||||||
}
|
}
|
||||||
if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT)
|
if (TREE_CODE (stmt) == DEBUG_BEGIN_STMT)
|
||||||
continue;
|
continue;
|
||||||
r = cxx_eval_constant_expression (ctx, stmt, false,
|
|
||||||
|
value_cat lval = vc_discard;
|
||||||
|
/* The result of a statement-expression is not wrapped in EXPR_STMT. */
|
||||||
|
if (tsi_one_before_end_p (i) && TREE_CODE (stmt) != EXPR_STMT)
|
||||||
|
lval = vc_prvalue;
|
||||||
|
|
||||||
|
r = cxx_eval_constant_expression (ctx, stmt, lval,
|
||||||
non_constant_p, overflow_p,
|
non_constant_p, overflow_p,
|
||||||
jump_target);
|
jump_target);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
|
@ -6228,7 +6249,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
|
||||||
break;
|
break;
|
||||||
case FOR_STMT:
|
case FOR_STMT:
|
||||||
if (FOR_INIT_STMT (t))
|
if (FOR_INIT_STMT (t))
|
||||||
cxx_eval_constant_expression (ctx, FOR_INIT_STMT (t), /*lval*/false,
|
cxx_eval_constant_expression (ctx, FOR_INIT_STMT (t), vc_discard,
|
||||||
non_constant_p, overflow_p, jump_target);
|
non_constant_p, overflow_p, jump_target);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
@ -6247,7 +6268,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
|
||||||
if (count != -1)
|
if (count != -1)
|
||||||
{
|
{
|
||||||
if (body)
|
if (body)
|
||||||
cxx_eval_constant_expression (&new_ctx, body, /*lval*/false,
|
cxx_eval_constant_expression (&new_ctx, body, vc_discard,
|
||||||
non_constant_p, overflow_p,
|
non_constant_p, overflow_p,
|
||||||
jump_target);
|
jump_target);
|
||||||
if (breaks (jump_target))
|
if (breaks (jump_target))
|
||||||
|
@ -6260,7 +6281,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
|
||||||
*jump_target = NULL_TREE;
|
*jump_target = NULL_TREE;
|
||||||
|
|
||||||
if (expr)
|
if (expr)
|
||||||
cxx_eval_constant_expression (&new_ctx, expr, /*lval*/false,
|
cxx_eval_constant_expression (&new_ctx, expr, vc_prvalue,
|
||||||
non_constant_p, overflow_p,
|
non_constant_p, overflow_p,
|
||||||
jump_target);
|
jump_target);
|
||||||
}
|
}
|
||||||
|
@ -6268,7 +6289,7 @@ cxx_eval_loop_expr (const constexpr_ctx *ctx, tree t,
|
||||||
if (cond)
|
if (cond)
|
||||||
{
|
{
|
||||||
tree res
|
tree res
|
||||||
= cxx_eval_constant_expression (&new_ctx, cond, /*lval*/false,
|
= cxx_eval_constant_expression (&new_ctx, cond, vc_prvalue,
|
||||||
non_constant_p, overflow_p,
|
non_constant_p, overflow_p,
|
||||||
jump_target);
|
jump_target);
|
||||||
if (res)
|
if (res)
|
||||||
|
@ -6322,7 +6343,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t,
|
||||||
{
|
{
|
||||||
tree cond
|
tree cond
|
||||||
= TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_COND (t) : SWITCH_COND (t);
|
= TREE_CODE (t) == SWITCH_STMT ? SWITCH_STMT_COND (t) : SWITCH_COND (t);
|
||||||
cond = cxx_eval_constant_expression (ctx, cond, false,
|
cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (cond);
|
VERIFY_CONSTANT (cond);
|
||||||
*jump_target = cond;
|
*jump_target = cond;
|
||||||
|
@ -6332,7 +6353,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t,
|
||||||
constexpr_ctx new_ctx = *ctx;
|
constexpr_ctx new_ctx = *ctx;
|
||||||
constexpr_switch_state css = css_default_not_seen;
|
constexpr_switch_state css = css_default_not_seen;
|
||||||
new_ctx.css_state = &css;
|
new_ctx.css_state = &css;
|
||||||
cxx_eval_constant_expression (&new_ctx, body, false,
|
cxx_eval_constant_expression (&new_ctx, body, vc_discard,
|
||||||
non_constant_p, overflow_p, jump_target);
|
non_constant_p, overflow_p, jump_target);
|
||||||
if (switches (jump_target) && css == css_default_seen)
|
if (switches (jump_target) && css == css_default_seen)
|
||||||
{
|
{
|
||||||
|
@ -6340,7 +6361,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t,
|
||||||
this time instructing label_matches to return true for default:
|
this time instructing label_matches to return true for default:
|
||||||
label on switches (jump_target). */
|
label on switches (jump_target). */
|
||||||
css = css_default_processing;
|
css = css_default_processing;
|
||||||
cxx_eval_constant_expression (&new_ctx, body, false,
|
cxx_eval_constant_expression (&new_ctx, body, vc_discard,
|
||||||
non_constant_p, overflow_p, jump_target);
|
non_constant_p, overflow_p, jump_target);
|
||||||
}
|
}
|
||||||
if (breaks (jump_target) || switches (jump_target))
|
if (breaks (jump_target) || switches (jump_target))
|
||||||
|
@ -6351,7 +6372,7 @@ cxx_eval_switch_expr (const constexpr_ctx *ctx, tree t,
|
||||||
/* Find the object of TYPE under initialization in CTX. */
|
/* Find the object of TYPE under initialization in CTX. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
lookup_placeholder (const constexpr_ctx *ctx, bool lval, tree type)
|
lookup_placeholder (const constexpr_ctx *ctx, value_cat lval, tree type)
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
@ -6478,12 +6499,12 @@ build_new_constexpr_heap_type (const constexpr_ctx *ctx, tree elt_type,
|
||||||
tree op1 = TREE_OPERAND (arg_size, 1);
|
tree op1 = TREE_OPERAND (arg_size, 1);
|
||||||
if (integer_zerop (op0))
|
if (integer_zerop (op0))
|
||||||
arg_size
|
arg_size
|
||||||
= cxx_eval_constant_expression (ctx, op1, false, non_constant_p,
|
= cxx_eval_constant_expression (ctx, op1, vc_prvalue,
|
||||||
overflow_p);
|
non_constant_p, overflow_p);
|
||||||
else if (integer_zerop (op1))
|
else if (integer_zerop (op1))
|
||||||
arg_size
|
arg_size
|
||||||
= cxx_eval_constant_expression (ctx, op0, false, non_constant_p,
|
= cxx_eval_constant_expression (ctx, op0, vc_prvalue,
|
||||||
overflow_p);
|
non_constant_p, overflow_p);
|
||||||
else
|
else
|
||||||
arg_size = NULL_TREE;
|
arg_size = NULL_TREE;
|
||||||
}
|
}
|
||||||
|
@ -6513,7 +6534,7 @@ build_new_constexpr_heap_type (const constexpr_ctx *ctx, tree elt_type,
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
bool lval,
|
value_cat lval,
|
||||||
bool *non_constant_p, bool *overflow_p,
|
bool *non_constant_p, bool *overflow_p,
|
||||||
tree *jump_target /* = NULL */)
|
tree *jump_target /* = NULL */)
|
||||||
{
|
{
|
||||||
|
@ -6760,8 +6781,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
|
|
||||||
if (tree init = DECL_INITIAL (r))
|
if (tree init = DECL_INITIAL (r))
|
||||||
{
|
{
|
||||||
init = cxx_eval_constant_expression (ctx, init,
|
init = cxx_eval_constant_expression (ctx, init, vc_prvalue,
|
||||||
false,
|
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
/* Don't share a CONSTRUCTOR that might be changed. */
|
/* Don't share a CONSTRUCTOR that might be changed. */
|
||||||
init = unshare_constructor (init);
|
init = unshare_constructor (init);
|
||||||
|
@ -6821,10 +6841,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
ctx->global->values.put (new_ctx.object, new_ctx.ctor);
|
ctx->global->values.put (new_ctx.object, new_ctx.ctor);
|
||||||
ctx = &new_ctx;
|
ctx = &new_ctx;
|
||||||
}
|
}
|
||||||
/* Pass false for 'lval' because this indicates
|
/* Pass vc_prvalue because this indicates
|
||||||
initialization of a temporary. */
|
initialization of a temporary. */
|
||||||
r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1),
|
r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_prvalue,
|
||||||
false,
|
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
break;
|
break;
|
||||||
|
@ -6880,7 +6899,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
r = *p;
|
r = *p;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false,
|
r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
break;
|
break;
|
||||||
|
@ -6922,7 +6941,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
tree cleanup;
|
tree cleanup;
|
||||||
/* Evaluate the cleanups. */
|
/* Evaluate the cleanups. */
|
||||||
FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
|
FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
|
||||||
cxx_eval_constant_expression (ctx, cleanup, false,
|
cxx_eval_constant_expression (ctx, cleanup, vc_discard,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -6933,7 +6952,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
jump_target);
|
jump_target);
|
||||||
if (!*non_constant_p)
|
if (!*non_constant_p)
|
||||||
/* Also evaluate the cleanup. */
|
/* Also evaluate the cleanup. */
|
||||||
cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true,
|
cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_discard,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -6945,7 +6964,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
{
|
{
|
||||||
iloc_sentinel ils (loc);
|
iloc_sentinel ils (loc);
|
||||||
/* Also evaluate the cleanup. */
|
/* Also evaluate the cleanup. */
|
||||||
cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
|
cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), vc_discard,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -6962,8 +6981,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
case ADDR_EXPR:
|
case ADDR_EXPR:
|
||||||
{
|
{
|
||||||
tree oldop = TREE_OPERAND (t, 0);
|
tree oldop = TREE_OPERAND (t, 0);
|
||||||
tree op = cxx_eval_constant_expression (ctx, oldop,
|
tree op = cxx_eval_constant_expression (ctx, oldop, vc_glvalue,
|
||||||
/*lval*/true,
|
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
/* Don't VERIFY_CONSTANT here. */
|
/* Don't VERIFY_CONSTANT here. */
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
|
@ -6987,7 +7005,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
if (r == error_mark_node)
|
if (r == error_mark_node)
|
||||||
;
|
;
|
||||||
else if (r == TREE_OPERAND (t, 0))
|
else if (r == TREE_OPERAND (t, 0) || lval == vc_discard)
|
||||||
r = t;
|
r = t;
|
||||||
else
|
else
|
||||||
r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), r);
|
r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), r);
|
||||||
|
@ -7039,8 +7057,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Check that the LHS is constant and then discard it. */
|
/* Check that the LHS is constant and then discard it. */
|
||||||
cxx_eval_constant_expression (ctx, op0,
|
cxx_eval_constant_expression (ctx, op0, vc_discard,
|
||||||
true, non_constant_p, overflow_p,
|
non_constant_p, overflow_p,
|
||||||
jump_target);
|
jump_target);
|
||||||
if (*non_constant_p)
|
if (*non_constant_p)
|
||||||
return t;
|
return t;
|
||||||
|
@ -7461,7 +7479,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||||
case EXIT_EXPR:
|
case EXIT_EXPR:
|
||||||
{
|
{
|
||||||
tree cond = TREE_OPERAND (t, 0);
|
tree cond = TREE_OPERAND (t, 0);
|
||||||
cond = cxx_eval_constant_expression (ctx, cond, /*lval*/false,
|
cond = cxx_eval_constant_expression (ctx, cond, vc_prvalue,
|
||||||
non_constant_p, overflow_p);
|
non_constant_p, overflow_p);
|
||||||
VERIFY_CONSTANT (cond);
|
VERIFY_CONSTANT (cond);
|
||||||
if (integer_nonzerop (cond))
|
if (integer_nonzerop (cond))
|
||||||
|
@ -7820,8 +7838,8 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
|
||||||
|
|
||||||
if (manifestly_const_eval)
|
if (manifestly_const_eval)
|
||||||
instantiate_constexpr_fns (r);
|
instantiate_constexpr_fns (r);
|
||||||
r = cxx_eval_constant_expression (&ctx, r,
|
r = cxx_eval_constant_expression (&ctx, r, vc_prvalue,
|
||||||
false, &non_constant_p, &overflow_p);
|
&non_constant_p, &overflow_p);
|
||||||
|
|
||||||
if (!constexpr_dtor)
|
if (!constexpr_dtor)
|
||||||
verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
|
verify_constant (r, allow_non_constant, &non_constant_p, &overflow_p);
|
||||||
|
@ -7832,7 +7850,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
|
||||||
tree cleanup;
|
tree cleanup;
|
||||||
/* Evaluate the cleanups. */
|
/* Evaluate the cleanups. */
|
||||||
FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
|
FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
|
||||||
cxx_eval_constant_expression (&ctx, cleanup, false,
|
cxx_eval_constant_expression (&ctx, cleanup, vc_discard,
|
||||||
&non_constant_p, &overflow_p);
|
&non_constant_p, &overflow_p);
|
||||||
|
|
||||||
/* Mutable logic is a bit tricky: we want to allow initialization of
|
/* Mutable logic is a bit tricky: we want to allow initialization of
|
||||||
|
|
Loading…
Reference in New Issue