The attached patch adds a context parameter to
cxx_eval_constant_expression and its subprograms. This way, we do not
have to thread all context parameters manually. This will simplify the
introduction of additional location information, as suggested by Jason
in <http://gcc.gnu.org/ml/gcc-patches/2012-06/msg01596.html>.
Bootstrapped and tested on x86_64-redhat-linux-gnu.
--
Florian Weimer / Red Hat Product Security Team
2012-07-31 Florian Weimer <fwei...@redhat.com>
* semantics.c (cxx_eval_builtin_function_call): Introduce
const cxx_eval_constant_ctx * parameter.
(cxx_bind_parameters_in_call): Likewise.
(cxx_eval_call_expression): Likewise.
(VERIFY_CONSTANT): Likewise.
(cxx_eval_unary_expression): Likewise.
(cxx_eval_binary_expression): Likewise.
(cxx_eval_conditional_expression): Likewise.
(cxx_eval_array_reference): Likewise.
(cxx_eval_component_reference): Likewise.
(cxx_eval_bit_field_ref): Likewise.
(cxx_eval_logical_expression): Likewise.
(cxx_eval_bare_aggregate): Likewise.
(cxx_eval_vec_init_1): Likewise.
(cxx_eval_vec_init): Likewise.
(cxx_eval_indirect_ref): Likewise.
(cxx_eval_vec_perm_expr): Likewise.
(cxx_eval_constant_expression): Likewise.
(cxx_eval_outermost_constant_expr): Pass cxx_eval_constant_ctx
object as parameter.
(is_sub_constant_expr): Pass cxx_eval_constant_ctx object as
parameter.
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index b27e8ab..94a0633 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -6222,10 +6222,19 @@ typedef struct GTY(()) constexpr_call {
static GTY ((param_is (constexpr_call))) htab_t constexpr_call_table;
+/* Context passsed down from cxx_eval_constant_expression.
+ Called functions can copy this data structure, so if changes need
+ to be passed upwards, pointers must be used. */
+typedef struct {
+ bool allow_non_constant;
+ bool addr;
+ bool *non_constant_p;
+} cxx_eval_constant_ctx;
+
static tree cxx_eval_constant_expression (const constexpr_call *, tree,
- bool, bool, bool *);
-static tree cxx_eval_vec_perm_expr (const constexpr_call *, tree, bool, bool,
- bool *);
+ const cxx_eval_constant_ctx *);
+static tree cxx_eval_vec_perm_expr (const constexpr_call *, tree,
+ const cxx_eval_constant_ctx *ctx);
/* Compute a hash value for a constexpr call representation. */
@@ -6351,8 +6360,7 @@ lookup_parameter_binding (const constexpr_call *call, tree t)
static tree
cxx_eval_builtin_function_call (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
const int nargs = call_expr_nargs (t);
tree *args = (tree *) alloca (nargs * sizeof (tree));
@@ -6360,13 +6368,11 @@ cxx_eval_builtin_function_call (const constexpr_call *call, tree t,
int i;
for (i = 0; i < nargs; ++i)
{
- args[i] = cxx_eval_constant_expression (call, CALL_EXPR_ARG (t, i),
- allow_non_constant, addr,
- non_constant_p);
- if (allow_non_constant && *non_constant_p)
+ args[i] = cxx_eval_constant_expression (call, CALL_EXPR_ARG (t, i), ctx);
+ if (ctx->allow_non_constant && *ctx->non_constant_p)
return t;
}
- if (*non_constant_p)
+ if (*ctx->non_constant_p)
return t;
new_call = build_call_array_loc (EXPR_LOCATION (t), TREE_TYPE (t),
CALL_EXPR_FN (t), nargs, args);
@@ -6397,8 +6403,7 @@ adjust_temp_type (tree type, tree temp)
static void
cxx_bind_parameters_in_call (const constexpr_call *old_call, tree t,
constexpr_call *new_call,
- bool allow_non_constant,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
const int nargs = call_expr_nargs (t);
tree fun = new_call->fundef->decl;
@@ -6408,22 +6413,23 @@ cxx_bind_parameters_in_call (const constexpr_call *old_call, tree t,
{
tree x, arg;
tree type = parms ? TREE_TYPE (parms) : void_type_node;
+ cxx_eval_constant_ctx ctx1;
/* For member function, the first argument is a pointer to the implied
object. And for an object contruction, don't bind `this' before
it is fully constructed. */
if (i == 0 && DECL_CONSTRUCTOR_P (fun))
goto next;
x = get_nth_callarg (t, i);
- arg = cxx_eval_constant_expression (old_call, x, allow_non_constant,
- TREE_CODE (type) == REFERENCE_TYPE,
- non_constant_p);
+ ctx1 = *ctx;
+ ctx1.addr = TREE_CODE (type) == REFERENCE_TYPE;
+ arg = cxx_eval_constant_expression (old_call, x, &ctx1);
/* Don't VERIFY_CONSTANT here. */
- if (*non_constant_p && allow_non_constant)
+ if (*ctx->non_constant_p && ctx->allow_non_constant)
return;
/* Just discard ellipsis args after checking their constantitude. */
if (!parms)
continue;
- if (*non_constant_p)
+ if (*ctx->non_constant_p)
/* Don't try to adjust the type of non-constant args. */
goto next;
@@ -6480,8 +6486,7 @@ cx_error_context (void)
static tree
cxx_eval_call_expression (const constexpr_call *old_call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
location_t loc = EXPR_LOC_OR_HERE (t);
tree fun = get_function_named_in_call (t);
@@ -6490,36 +6495,37 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
constexpr_call **slot;
constexpr_call *entry;
bool depth_ok;
+ cxx_eval_constant_ctx ctx1;
if (TREE_CODE (fun) != FUNCTION_DECL)
{
/* Might be a constexpr function pointer. */
- fun = cxx_eval_constant_expression (old_call, fun, allow_non_constant,
- /*addr*/false, non_constant_p);
+ ctx1 = *ctx;
+ ctx1.addr = false;
+ fun = cxx_eval_constant_expression (old_call, fun, &ctx1);
if (TREE_CODE (fun) == ADDR_EXPR)
fun = TREE_OPERAND (fun, 0);
}
if (TREE_CODE (fun) != FUNCTION_DECL)
{
- if (!allow_non_constant && !*non_constant_p)
+ if (!ctx->allow_non_constant && !*ctx->non_constant_p)
error_at (loc, "expression %qE does not designate a constexpr "
"function", fun);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
return t;
}
if (DECL_CLONED_FUNCTION_P (fun))
fun = DECL_CLONED_FUNCTION (fun);
if (is_builtin_fn (fun))
- return cxx_eval_builtin_function_call (old_call, t, allow_non_constant,
- addr, non_constant_p);
+ return cxx_eval_builtin_function_call (old_call, t, ctx);
if (!DECL_DECLARED_CONSTEXPR_P (fun))
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
{
error_at (loc, "call to non-constexpr function %qD", fun);
explain_invalid_constexpr_fn (fun);
}
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
return t;
}
@@ -6527,8 +6533,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
if (call_expr_nargs (t) == 2 && trivial_fn_p (fun))
{
tree arg = convert_from_reference (get_nth_callarg (t, 1));
- return cxx_eval_constant_expression (old_call, arg, allow_non_constant,
- addr, non_constant_p);
+ return cxx_eval_constant_expression (old_call, arg, ctx);
}
/* If in direct recursive call, optimize definition search. */
@@ -6539,7 +6544,7 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
new_call.fundef = retrieve_constexpr_fundef (fun);
if (new_call.fundef == NULL || new_call.fundef->body == NULL)
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
{
if (DECL_INITIAL (fun))
{
@@ -6550,13 +6555,12 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
else
error_at (loc, "%qD used before its definition", fun);
}
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
return t;
}
}
- cxx_bind_parameters_in_call (old_call, t, &new_call,
- allow_non_constant, non_constant_p);
- if (*non_constant_p)
+ cxx_bind_parameters_in_call (old_call, t, &new_call, ctx);
+ if (*ctx->non_constant_p)
return t;
depth_ok = push_cx_call_context (t);
@@ -6581,19 +6585,19 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
so that we can detect circular dependencies. */
else if (entry->result == NULL)
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("call has circular dependency");
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
entry->result = result = error_mark_node;
}
if (!depth_ok)
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("constexpr evaluation depth exceeds maximum of %d (use "
"-fconstexpr-depth= to increase the maximum)",
max_constexpr_depth);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
entry->result = result = error_mark_node;
}
else
@@ -6601,12 +6605,10 @@ cxx_eval_call_expression (const constexpr_call *old_call, tree t,
result = entry->result;
if (!result || result == error_mark_node)
result = (cxx_eval_constant_expression
- (&new_call, new_call.fundef->body,
- allow_non_constant, addr,
- non_constant_p));
+ (&new_call, new_call.fundef->body, ctx));
if (result == error_mark_node)
- *non_constant_p = true;
- if (*non_constant_p)
+ *ctx->non_constant_p = true;
+ if (*ctx->non_constant_p)
entry->result = result = error_mark_node;
else
{
@@ -6676,7 +6678,8 @@ verify_constant (tree t, bool allow_non_constant, bool *non_constant_p)
}
#define VERIFY_CONSTANT(X) \
do { \
- if (verify_constant ((X), allow_non_constant, non_constant_p)) \
+ if (verify_constant ((X), (ctx)->allow_non_constant, \
+ (ctx)->non_constant_p)) \
return t; \
} while (0)
@@ -6687,13 +6690,11 @@ do { \
static tree
cxx_eval_unary_expression (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
tree r;
tree orig_arg = TREE_OPERAND (t, 0);
- tree arg = cxx_eval_constant_expression (call, orig_arg, allow_non_constant,
- addr, non_constant_p);
+ tree arg = cxx_eval_constant_expression (call, orig_arg, ctx);
VERIFY_CONSTANT (arg);
if (arg == orig_arg)
return t;
@@ -6707,20 +6708,15 @@ cxx_eval_unary_expression (const constexpr_call *call, tree t,
static tree
cxx_eval_binary_expression (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
tree r;
tree orig_lhs = TREE_OPERAND (t, 0);
tree orig_rhs = TREE_OPERAND (t, 1);
tree lhs, rhs;
- lhs = cxx_eval_constant_expression (call, orig_lhs,
- allow_non_constant, addr,
- non_constant_p);
+ lhs = cxx_eval_constant_expression (call, orig_lhs, ctx);
VERIFY_CONSTANT (lhs);
- rhs = cxx_eval_constant_expression (call, orig_rhs,
- allow_non_constant, addr,
- non_constant_p);
+ rhs = cxx_eval_constant_expression (call, orig_rhs, ctx);
VERIFY_CONSTANT (rhs);
if (lhs == orig_lhs && rhs == orig_rhs)
return t;
@@ -6735,21 +6731,14 @@ cxx_eval_binary_expression (const constexpr_call *call, tree t,
static tree
cxx_eval_conditional_expression (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
- tree val = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0),
- allow_non_constant, addr,
- non_constant_p);
+ tree val = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0), ctx);
VERIFY_CONSTANT (val);
/* Don't VERIFY_CONSTANT the other operands. */
if (integer_zerop (val))
- return cxx_eval_constant_expression (call, TREE_OPERAND (t, 2),
- allow_non_constant, addr,
- non_constant_p);
- return cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
- allow_non_constant, addr,
- non_constant_p);
+ return cxx_eval_constant_expression (call, TREE_OPERAND (t, 2), ctx);
+ return cxx_eval_constant_expression (call, TREE_OPERAND (t, 1), ctx);
}
/* Subroutine of cxx_eval_constant_expression.
@@ -6757,27 +6746,24 @@ cxx_eval_conditional_expression (const constexpr_call *call, tree t,
static tree
cxx_eval_array_reference (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
tree oldary = TREE_OPERAND (t, 0);
- tree ary = cxx_eval_constant_expression (call, oldary,
- allow_non_constant, addr,
- non_constant_p);
+ tree ary = cxx_eval_constant_expression (call, oldary, ctx);
tree index, oldidx;
HOST_WIDE_INT i;
tree elem_type;
unsigned len, elem_nchars = 1;
- if (*non_constant_p)
+ cxx_eval_constant_ctx ctx1 = *ctx;
+ if (*ctx->non_constant_p)
return t;
oldidx = TREE_OPERAND (t, 1);
- index = cxx_eval_constant_expression (call, oldidx,
- allow_non_constant, false,
- non_constant_p);
+ ctx1.addr = false;
+ index = cxx_eval_constant_expression (call, oldidx, &ctx1);
VERIFY_CONSTANT (index);
- if (addr && ary == oldary && index == oldidx)
+ if (ctx->addr && ary == oldary && index == oldidx)
return t;
- else if (addr)
+ else if (ctx->addr)
return build4 (ARRAY_REF, TREE_TYPE (t), ary, index, NULL, NULL);
elem_type = TREE_TYPE (TREE_TYPE (ary));
if (TREE_CODE (ary) == CONSTRUCTOR)
@@ -6802,14 +6788,12 @@ cxx_eval_array_reference (const constexpr_call *call, tree t,
/* If it's within the array bounds but doesn't have an explicit
initializer, it's value-initialized. */
tree val = build_value_init (elem_type, tf_warning_or_error);
- return cxx_eval_constant_expression (call, val,
- allow_non_constant, addr,
- non_constant_p);
+ return cxx_eval_constant_expression (call, val, ctx);
}
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("array subscript out of bound");
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
return t;
}
i = tree_low_cst (index, 0);
@@ -6833,37 +6817,34 @@ cxx_eval_array_reference (const constexpr_call *call, tree t,
static tree
cxx_eval_component_reference (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
unsigned HOST_WIDE_INT i;
tree field;
tree value;
tree part = TREE_OPERAND (t, 1);
tree orig_whole = TREE_OPERAND (t, 0);
- tree whole = cxx_eval_constant_expression (call, orig_whole,
- allow_non_constant, addr,
- non_constant_p);
+ tree whole = cxx_eval_constant_expression (call, orig_whole, ctx);
if (whole == orig_whole)
return t;
- if (addr)
+ if (ctx->addr)
return fold_build3 (COMPONENT_REF, TREE_TYPE (t),
whole, part, NULL_TREE);
/* Don't VERIFY_CONSTANT here; we only want to check that we got a
CONSTRUCTOR. */
- if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
+ if (!*ctx->non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("%qE is not a constant expression", orig_whole);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
}
if (DECL_MUTABLE_P (part))
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("mutable %qD is not usable in a constant expression", part);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
}
- if (*non_constant_p)
+ if (*ctx->non_constant_p)
return t;
FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (whole), i, field, value)
{
@@ -6874,18 +6855,16 @@ cxx_eval_component_reference (const constexpr_call *call, tree t,
&& CONSTRUCTOR_NELTS (whole) > 0)
{
/* DR 1188 says we don't have to deal with this. */
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("accessing %qD member instead of initialized %qD member in "
"constant expression", part, CONSTRUCTOR_ELT (whole, 0)->index);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
return t;
}
/* If there's no explicit init for this field, it's value-initialized. */
value = build_value_init (TREE_TYPE (t), tf_warning_or_error);
- return cxx_eval_constant_expression (call, value,
- allow_non_constant, addr,
- non_constant_p);
+ return cxx_eval_constant_expression (call, value, ctx);
}
/* Subroutine of cxx_eval_constant_expression.
@@ -6894,16 +6873,13 @@ cxx_eval_component_reference (const constexpr_call *call, tree t,
static tree
cxx_eval_bit_field_ref (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
tree orig_whole = TREE_OPERAND (t, 0);
tree retval, fldval, utype, mask;
bool fld_seen = false;
HOST_WIDE_INT istart, isize;
- tree whole = cxx_eval_constant_expression (call, orig_whole,
- allow_non_constant, addr,
- non_constant_p);
+ tree whole = cxx_eval_constant_expression (call, orig_whole, ctx);
tree start, field, value;
unsigned HOST_WIDE_INT i;
@@ -6911,13 +6887,13 @@ cxx_eval_bit_field_ref (const constexpr_call *call, tree t,
return t;
/* Don't VERIFY_CONSTANT here; we only want to check that we got a
CONSTRUCTOR. */
- if (!*non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
+ if (!*ctx->non_constant_p && TREE_CODE (whole) != CONSTRUCTOR)
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("%qE is not a constant expression", orig_whole);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
}
- if (*non_constant_p)
+ if (*ctx->non_constant_p)
return t;
start = TREE_OPERAND (t, 2);
@@ -6974,19 +6950,15 @@ cxx_eval_bit_field_ref (const constexpr_call *call, tree t,
static tree
cxx_eval_logical_expression (const constexpr_call *call, tree t,
tree bailout_value, tree continue_value,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
tree r;
- tree lhs = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0),
- allow_non_constant, addr,
- non_constant_p);
+ tree lhs = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0), ctx);
VERIFY_CONSTANT (lhs);
if (tree_int_cst_equal (lhs, bailout_value))
return lhs;
gcc_assert (tree_int_cst_equal (lhs, continue_value));
- r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
- allow_non_constant, addr, non_constant_p);
+ r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1), ctx);
VERIFY_CONSTANT (r);
return r;
}
@@ -7027,8 +6999,7 @@ base_field_constructor_elt (VEC(constructor_elt,gc) *v, tree ref)
static tree
cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (t);
VEC(constructor_elt,gc) *n = VEC_alloc (constructor_elt, gc,
@@ -7039,11 +7010,9 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
gcc_assert (!BRACE_ENCLOSED_INITIALIZER_P (t));
for (i = 0; VEC_iterate (constructor_elt, v, i, ce); ++i)
{
- tree elt = cxx_eval_constant_expression (call, ce->value,
- allow_non_constant, addr,
- non_constant_p);
+ tree elt = cxx_eval_constant_expression (call, ce->value, ctx);
/* Don't VERIFY_CONSTANT here. */
- if (allow_non_constant && *non_constant_p)
+ if (ctx->allow_non_constant && *ctx->non_constant_p)
goto fail;
if (elt != ce->value)
changed = true;
@@ -7064,7 +7033,7 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
else
CONSTRUCTOR_APPEND_ELT (n, ce->index, elt);
}
- if (*non_constant_p || !changed)
+ if (*ctx->non_constant_p || !changed)
{
fail:
VEC_free (constructor_elt, gc, n);
@@ -7089,8 +7058,7 @@ cxx_eval_bare_aggregate (const constexpr_call *call, tree t,
static tree
cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
- bool value_init, bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ bool value_init, const cxx_eval_constant_ctx *ctx)
{
tree elttype = TREE_TYPE (atype);
int max = tree_low_cst (array_type_nelts (atype), 0);
@@ -7108,8 +7076,7 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
else if (value_init)
{
init = build_value_init (elttype, tf_warning_or_error);
- init = cxx_eval_constant_expression
- (call, init, allow_non_constant, addr, non_constant_p);
+ init = cxx_eval_constant_expression (call, init, ctx);
pre_init = true;
}
else if (!init)
@@ -7119,12 +7086,11 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
&argvec, elttype, LOOKUP_NORMAL,
tf_warning_or_error);
release_tree_vector (argvec);
- init = cxx_eval_constant_expression (call, init, allow_non_constant,
- addr, non_constant_p);
+ init = cxx_eval_constant_expression (call, init, ctx);
pre_init = true;
}
- if (*non_constant_p && !allow_non_constant)
+ if (*ctx->non_constant_p && !ctx->allow_non_constant)
goto fail;
for (i = 0; i <= max; ++i)
@@ -7140,8 +7106,7 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
eltinit = cp_build_array_ref (input_location, init, idx,
tf_warning_or_error);
eltinit = cxx_eval_vec_init_1 (call, elttype, eltinit, value_init,
- allow_non_constant, addr,
- non_constant_p);
+ ctx);
}
else if (pre_init)
{
@@ -7168,15 +7133,14 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
(NULL_TREE, complete_ctor_identifier, &argvec,
elttype, LOOKUP_NORMAL, tf_warning_or_error));
release_tree_vector (argvec);
- eltinit = cxx_eval_constant_expression
- (call, eltinit, allow_non_constant, addr, non_constant_p);
+ eltinit = cxx_eval_constant_expression (call, eltinit, ctx);
}
- if (*non_constant_p && !allow_non_constant)
+ if (*ctx->non_constant_p && !ctx->allow_non_constant)
goto fail;
CONSTRUCTOR_APPEND_ELT (n, idx, eltinit);
}
- if (!*non_constant_p)
+ if (!*ctx->non_constant_p)
{
init = build_constructor (atype, n);
TREE_CONSTANT (init) = true;
@@ -7190,15 +7154,13 @@ cxx_eval_vec_init_1 (const constexpr_call *call, tree atype, tree init,
static tree
cxx_eval_vec_init (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
tree atype = TREE_TYPE (t);
tree init = VEC_INIT_EXPR_INIT (t);
tree r = cxx_eval_vec_init_1 (call, atype, init,
- VEC_INIT_EXPR_VALUE_INIT (t),
- allow_non_constant, addr, non_constant_p);
- if (*non_constant_p)
+ VEC_INIT_EXPR_VALUE_INIT (t), ctx);
+ if (*ctx->non_constant_p)
return t;
else
return r;
@@ -7386,25 +7348,26 @@ cxx_fold_indirect_ref (location_t loc, tree type, tree op0, bool *empty_base)
static tree
cxx_eval_indirect_ref (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
tree orig_op0 = TREE_OPERAND (t, 0);
- tree op0 = cxx_eval_constant_expression (call, orig_op0, allow_non_constant,
- /*addr*/false, non_constant_p);
+ tree op0;
bool empty_base = false;
tree r;
+ cxx_eval_constant_ctx ctx1 = *ctx;
+
+ ctx1.addr = false;
+ op0 = cxx_eval_constant_expression (call, orig_op0, &ctx1);
/* Don't VERIFY_CONSTANT here. */
- if (*non_constant_p)
+ if (*ctx->non_constant_p)
return t;
r = cxx_fold_indirect_ref (EXPR_LOCATION (t), TREE_TYPE (t), op0,
&empty_base);
if (r)
- r = cxx_eval_constant_expression (call, r, allow_non_constant,
- addr, non_constant_p);
+ r = cxx_eval_constant_expression (call, r, ctx);
else
{
tree sub = op0;
@@ -7421,11 +7384,11 @@ cxx_eval_indirect_ref (const constexpr_call *call, tree t,
gcc_assert (!same_type_ignoring_top_level_qualifiers_p
(TREE_TYPE (TREE_TYPE (sub)), TREE_TYPE (t)));
/* DR 1188 says we don't have to deal with this. */
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("accessing value of %qE through a %qT glvalue in a "
"constant expression", build_fold_indirect_ref (sub),
TREE_TYPE (t));
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
return t;
}
}
@@ -7491,9 +7454,8 @@ non_const_var_error (tree r)
/* Evaluate VEC_PERM_EXPR (v1, v2, mask). */
static tree
-cxx_eval_vec_perm_expr (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool * non_constant_p)
+cxx_eval_vec_perm_expr (const constexpr_call *call, tree t,
+ const cxx_eval_constant_ctx *ctx)
{
int i;
tree args[3];
@@ -7502,10 +7464,8 @@ cxx_eval_vec_perm_expr (const constexpr_call *call, tree t,
for (i = 0; i < 3; i++)
{
- args[i] = cxx_eval_constant_expression (call, TREE_OPERAND (t, i),
- allow_non_constant, addr,
- non_constant_p);
- if (*non_constant_p)
+ args[i] = cxx_eval_constant_expression (call, TREE_OPERAND (t, i), ctx);
+ if (*ctx->non_constant_p)
goto fail;
}
@@ -7528,14 +7488,13 @@ cxx_eval_vec_perm_expr (const constexpr_call *call, tree t,
static tree
cxx_eval_constant_expression (const constexpr_call *call, tree t,
- bool allow_non_constant, bool addr,
- bool *non_constant_p)
+ const cxx_eval_constant_ctx *ctx)
{
tree r = t;
if (t == error_mark_node)
{
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
return t;
}
if (CONSTANT_CLASS_P (t))
@@ -7551,7 +7510,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
switch (TREE_CODE (t))
{
case VAR_DECL:
- if (addr)
+ if (ctx->addr)
return t;
/* else fall through. */
case CONST_DECL:
@@ -7561,9 +7520,9 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
r = TARGET_EXPR_INITIAL (r);
if (DECL_P (r))
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
non_const_var_error (r);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
}
break;
@@ -7577,58 +7536,57 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
{
if (DECL_ARTIFICIAL (t) && DECL_CONSTRUCTOR_P (DECL_CONTEXT (t)))
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
sorry ("use of the value of the object being constructed "
"in a constant expression");
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
}
else
r = lookup_parameter_binding (call, t);
}
- else if (addr)
+ else if (ctx->addr)
/* Defer in case this is only used for its type. */;
else
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error ("%qE is not a constant expression", t);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
}
break;
case CALL_EXPR:
case AGGR_INIT_EXPR:
- r = cxx_eval_call_expression (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_call_expression (call, t, ctx);
break;
case TARGET_EXPR:
if (!literal_type_p (TREE_TYPE (t)))
{
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
{
error ("temporary of non-literal type %qT in a "
"constant expression", TREE_TYPE (t));
explain_non_literal_class (TREE_TYPE (t));
}
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
break;
}
/* else fall through. */
case INIT_EXPR:
/* Pass false for 'addr' because these codes indicate
initialization of a temporary. */
- r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
- allow_non_constant, false,
- non_constant_p);
- if (!*non_constant_p)
+ {
+ cxx_eval_constant_ctx ctx1 = *ctx;
+ ctx1.addr = false;
+ r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1), &ctx1);
+ }
+ if (!*ctx->non_constant_p)
/* Adjust the type of the result to the type of the temporary. */
r = adjust_temp_type (TREE_TYPE (t), r);
break;
case SCOPE_REF:
- r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1),
- allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 1), ctx);
break;
case RETURN_EXPR:
@@ -7637,28 +7595,25 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
case CLEANUP_POINT_EXPR:
case MUST_NOT_THROW_EXPR:
case SAVE_EXPR:
- r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0),
- allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_constant_expression (call, TREE_OPERAND (t, 0), ctx);
break;
/* These differ from cxx_eval_unary_expression in that this doesn't
check for a constant operand or result; an address can be
constant without its operand being, and vice versa. */
case INDIRECT_REF:
- r = cxx_eval_indirect_ref (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_indirect_ref (call, t, ctx);
break;
case ADDR_EXPR:
{
tree oldop = TREE_OPERAND (t, 0);
- tree op = cxx_eval_constant_expression (call, oldop,
- allow_non_constant,
- /*addr*/true,
- non_constant_p);
+ tree op;
+ cxx_eval_constant_ctx ctx1 = *ctx;
+ ctx1.addr= true;
+ op = cxx_eval_constant_expression (call, oldop, &ctx1);
/* Don't VERIFY_CONSTANT here. */
- if (*non_constant_p)
+ if (*ctx->non_constant_p)
return t;
/* This function does more aggressive folding than fold itself. */
r = build_fold_addr_expr_with_type (op, TREE_TYPE (t));
@@ -7677,8 +7632,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
case BIT_NOT_EXPR:
case TRUTH_NOT_EXPR:
case FIXED_CONVERT_EXPR:
- r = cxx_eval_unary_expression (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_unary_expression (call, t, ctx);
break;
case COMPOUND_EXPR:
@@ -7691,15 +7645,14 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
STRIP_NOPS (op1);
if ((TREE_CODE (op0) == TARGET_EXPR && op1 == TARGET_EXPR_SLOT (op0))
|| TREE_CODE (op1) == EMPTY_CLASS_EXPR)
- r = cxx_eval_constant_expression (call, op0, allow_non_constant,
- addr, non_constant_p);
+ r = cxx_eval_constant_expression (call, op0, ctx);
else
{
/* Check that the LHS is constant and then discard it. */
- cxx_eval_constant_expression (call, op0, allow_non_constant,
- false, non_constant_p);
- r = cxx_eval_constant_expression (call, op1, allow_non_constant,
- addr, non_constant_p);
+ cxx_eval_constant_ctx ctx1 = *ctx;
+ ctx1.addr = false;
+ cxx_eval_constant_expression (call, op0, &ctx1);
+ r = cxx_eval_constant_expression (call, op1, ctx);
}
}
break;
@@ -7742,8 +7695,7 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
case UNEQ_EXPR:
case RANGE_EXPR:
case COMPLEX_EXPR:
- r = cxx_eval_binary_expression (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_binary_expression (call, t, ctx);
break;
/* fold can introduce non-IF versions of these; still treat them as
@@ -7751,43 +7703,34 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
case TRUTH_AND_EXPR:
case TRUTH_ANDIF_EXPR:
r = cxx_eval_logical_expression (call, t, boolean_false_node,
- boolean_true_node,
- allow_non_constant, addr,
- non_constant_p);
+ boolean_true_node, ctx);
break;
case TRUTH_OR_EXPR:
case TRUTH_ORIF_EXPR:
r = cxx_eval_logical_expression (call, t, boolean_true_node,
- boolean_false_node,
- allow_non_constant, addr,
- non_constant_p);
+ boolean_false_node, ctx);
break;
case ARRAY_REF:
- r = cxx_eval_array_reference (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_array_reference (call, t, ctx);
break;
case COMPONENT_REF:
- r = cxx_eval_component_reference (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_component_reference (call, t, ctx);
break;
case BIT_FIELD_REF:
- r = cxx_eval_bit_field_ref (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_bit_field_ref (call, t, ctx);
break;
case COND_EXPR:
case VEC_COND_EXPR:
- r = cxx_eval_conditional_expression (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_conditional_expression (call, t, ctx);
break;
case CONSTRUCTOR:
- r = cxx_eval_bare_aggregate (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_bare_aggregate (call, t, ctx);
break;
case VEC_INIT_EXPR:
@@ -7796,13 +7739,11 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
be NULL, meaning default-initialization, or it will be an lvalue
or xvalue of the same type, meaning direct-initialization from the
corresponding member. */
- r = cxx_eval_vec_init (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_vec_init (call, t, ctx);
break;
case VEC_PERM_EXPR:
- r = cxx_eval_vec_perm_expr (call, t, allow_non_constant, addr,
- non_constant_p);
+ r = cxx_eval_vec_perm_expr (call, t, ctx);
break;
case CONVERT_EXPR:
@@ -7810,10 +7751,8 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
case NOP_EXPR:
{
tree oldop = TREE_OPERAND (t, 0);
- tree op = cxx_eval_constant_expression (call, oldop,
- allow_non_constant, addr,
- non_constant_p);
- if (*non_constant_p)
+ tree op = cxx_eval_constant_expression (call, oldop, ctx);
+ if (*ctx->non_constant_p)
return t;
if (op == oldop)
/* We didn't fold at the top so we could check for ptr-int
@@ -7855,23 +7794,23 @@ cxx_eval_constant_expression (const constexpr_call *call, tree t,
case BASELINK:
case EXPR_STMT:
case OFFSET_REF:
- if (!allow_non_constant)
+ if (!ctx->allow_non_constant)
error_at (EXPR_LOC_OR_HERE (t),
"expression %qE is not a constant-expression", t);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
break;
default:
internal_error ("unexpected expression %qE of kind %s", t,
tree_code_name[TREE_CODE (t)]);
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
break;
}
if (r == error_mark_node)
- *non_constant_p = true;
+ *ctx->non_constant_p = true;
- if (*non_constant_p)
+ if (*ctx->non_constant_p)
return t;
else
return r;
@@ -7881,8 +7820,12 @@ static tree
cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant)
{
bool non_constant_p = false;
- tree r = cxx_eval_constant_expression (NULL, t, allow_non_constant,
- false, &non_constant_p);
+ tree r;
+ cxx_eval_constant_ctx ctx;
+ ctx.allow_non_constant = allow_non_constant;
+ ctx.addr = false;
+ ctx.non_constant_p = &non_constant_p;
+ r = cxx_eval_constant_expression (NULL, t, &ctx);
verify_constant (r, allow_non_constant, &non_constant_p);
@@ -7949,7 +7892,11 @@ bool
is_sub_constant_expr (tree t)
{
bool non_constant_p = false;
- cxx_eval_constant_expression (NULL, t, true, false, &non_constant_p);
+ cxx_eval_constant_ctx ctx;
+ ctx.allow_non_constant = true;
+ ctx.addr = false;
+ ctx.non_constant_p = &non_constant_p;
+ cxx_eval_constant_expression (NULL, t, &ctx);
return !non_constant_p;
}