[1/2] c++: make manifestly_const_eval tri-state
Checks
Commit Message
This patch turns the manifestly_const_eval flag used by the constexpr
machinery into a tri-state enum so that we're able to express wanting
to fold __builtin_is_constant_evaluated to false via late speculative
constexpr evaluation. Of all the entry points to constexpr evaluation
only maybe_constant_value is changed to take a tri-state value; the
others continue to take bool. The subsequent patch will use this to fold
the builtin to false when called from cp_fold_function.
gcc/cp/ChangeLog:
* constexpr.cc (constexpr_call::manifestly_const_eval): Give
it type int instead of bool.
(constexpr_ctx::manifestly_const_eval): Give it type mce_value
instead of bool.
(cxx_eval_builtin_function_call): Adjust after making
manifestly_const_eval tri-state.
(cxx_eval_call_expression): Likewise.
(cxx_eval_binary_expression): Likewise.
(cxx_eval_conditional_expression): Likewise.
(cxx_eval_constant_expression): Likewise.
(cxx_eval_outermost_constant_expr): Likewise.
(cxx_constant_value): Likewise.
(cxx_constant_dtor): Likewise.
(maybe_constant_value): Give manifestly_const_eval parameter
type mce_value instead of bool and adjust accordingly.
(fold_non_dependent_expr_template): Adjust call
to cxx_eval_outermost_constant_expr.
(fold_non_dependent_expr): Likewise.
(maybe_constant_init_1): Likewise.
* constraint.cc (satisfy_atom): Adjust call to
maybe_constant_value.
* cp-tree.h (enum class mce_value): Define.
(maybe_constant_value): Adjust manifestly_const_eval parameter
type and default argument.
* decl.cc (compute_array_index_type_loc): Adjust call to
maybe_constant_value.
* pt.cc (convert_nontype_argument): Likewise.
---
gcc/cp/constexpr.cc | 61 ++++++++++++++++++++++++--------------------
gcc/cp/constraint.cc | 3 +--
gcc/cp/cp-tree.h | 18 ++++++++++++-
gcc/cp/decl.cc | 2 +-
gcc/cp/pt.cc | 6 ++---
5 files changed, 54 insertions(+), 36 deletions(-)
Comments
On 1/27/23 17:02, Patrick Palka wrote:
> This patch turns the manifestly_const_eval flag used by the constexpr
> machinery into a tri-state enum so that we're able to express wanting
> to fold __builtin_is_constant_evaluated to false via late speculative
> constexpr evaluation. Of all the entry points to constexpr evaluation
> only maybe_constant_value is changed to take a tri-state value; the
> others continue to take bool. The subsequent patch will use this to fold
> the builtin to false when called from cp_fold_function.
>
> gcc/cp/ChangeLog:
>
> * constexpr.cc (constexpr_call::manifestly_const_eval): Give
> it type int instead of bool.
> (constexpr_ctx::manifestly_const_eval): Give it type mce_value
> instead of bool.
> (cxx_eval_builtin_function_call): Adjust after making
> manifestly_const_eval tri-state.
> (cxx_eval_call_expression): Likewise.
> (cxx_eval_binary_expression): Likewise.
> (cxx_eval_conditional_expression): Likewise.
> (cxx_eval_constant_expression): Likewise.
> (cxx_eval_outermost_constant_expr): Likewise.
> (cxx_constant_value): Likewise.
> (cxx_constant_dtor): Likewise.
> (maybe_constant_value): Give manifestly_const_eval parameter
> type mce_value instead of bool and adjust accordingly.
> (fold_non_dependent_expr_template): Adjust call
> to cxx_eval_outermost_constant_expr.
> (fold_non_dependent_expr): Likewise.
> (maybe_constant_init_1): Likewise.
> * constraint.cc (satisfy_atom): Adjust call to
> maybe_constant_value.
> * cp-tree.h (enum class mce_value): Define.
> (maybe_constant_value): Adjust manifestly_const_eval parameter
> type and default argument.
> * decl.cc (compute_array_index_type_loc): Adjust call to
> maybe_constant_value.
> * pt.cc (convert_nontype_argument): Likewise.
> ---
> gcc/cp/constexpr.cc | 61 ++++++++++++++++++++++++--------------------
> gcc/cp/constraint.cc | 3 +--
> gcc/cp/cp-tree.h | 18 ++++++++++++-
> gcc/cp/decl.cc | 2 +-
`> gcc/cp/pt.cc | 6 ++---
> 5 files changed, 54 insertions(+), 36 deletions(-)
>
> diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> index be99bec17e7..34662198903 100644
> --- a/gcc/cp/constexpr.cc
> +++ b/gcc/cp/constexpr.cc
> @@ -1119,8 +1119,8 @@ struct GTY((for_user)) constexpr_call {
> /* The hash of this call; we remember it here to avoid having to
> recalculate it when expanding the hash table. */
> hashval_t hash;
> - /* Whether __builtin_is_constant_evaluated() should evaluate to true. */
> - bool manifestly_const_eval;
> + /* The raw value of constexpr_ctx::manifestly_const_eval. */
> + int manifestly_const_eval;
Why not mce_value?
> };
>
> struct constexpr_call_hasher : ggc_ptr_hash<constexpr_call>
> @@ -1248,7 +1248,7 @@ struct constexpr_ctx {
> trying harder to get a constant value. */
> bool strict;
> /* Whether __builtin_is_constant_evaluated () should be true. */
> - bool manifestly_const_eval;
> + mce_value manifestly_const_eval;
> };
>
> /* This internal flag controls whether we should avoid doing anything during
> @@ -1463,7 +1463,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
> /* If we aren't requiring a constant expression, defer __builtin_constant_p
> in a constexpr function until we have values for the parameters. */
> if (bi_const_p
> - && !ctx->manifestly_const_eval
> + && ctx->manifestly_const_eval == mce_unknown
> && current_function_decl
> && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
> {
> @@ -1479,12 +1479,13 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
> if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
> BUILT_IN_FRONTEND))
> {
> - if (!ctx->manifestly_const_eval)
> + if (ctx->manifestly_const_eval == mce_unknown)
> {
> *non_constant_p = true;
> return t;
> }
> - return boolean_true_node;
> + return constant_boolean_node (ctx->manifestly_const_eval == mce_true,
> + boolean_type_node);
> }
>
> if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
> @@ -1591,7 +1592,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
> }
>
> bool save_ffbcp = force_folding_builtin_constant_p;
> - force_folding_builtin_constant_p |= ctx->manifestly_const_eval;
> + force_folding_builtin_constant_p |= ctx->manifestly_const_eval != mce_unknown;
> tree save_cur_fn = current_function_decl;
> /* Return name of ctx->call->fundef->decl for __builtin_FUNCTION (). */
> if (fndecl_built_in_p (fun, BUILT_IN_FUNCTION)
> @@ -2644,7 +2645,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
> location_t loc = cp_expr_loc_or_input_loc (t);
> tree fun = get_function_named_in_call (t);
> constexpr_call new_call
> - = { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
> + = { NULL, NULL, NULL, 0, (int)ctx->manifestly_const_eval };
> int depth_ok;
>
> if (fun == NULL_TREE)
> @@ -2916,7 +2917,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
> location_t save_loc = input_location;
> input_location = loc;
> ++function_depth;
> - if (ctx->manifestly_const_eval)
> + if (ctx->manifestly_const_eval == mce_true)
> FNDECL_MANIFESTLY_CONST_EVALUATED (fun) = true;
> instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false);
> --function_depth;
> @@ -3676,7 +3677,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
>
> if (r == NULL_TREE)
> {
> - if (ctx->manifestly_const_eval
> + if (ctx->manifestly_const_eval == mce_true
> && (flag_constexpr_fp_except
> || TREE_CODE (type) != REAL_TYPE))
> {
> @@ -3741,13 +3742,13 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t,
> without manifestly_const_eval even expressions or parts thereof which
> will later be manifestly const_eval evaluated), otherwise fold it to
> true. */
> - if (ctx->manifestly_const_eval)
> - val = boolean_true_node;
> - else
> + if (ctx->manifestly_const_eval == mce_unknown)
> {
> *non_constant_p = true;
> return t;
> }
> + val = constant_boolean_node (ctx->manifestly_const_eval == mce_true,
> + boolean_type_node);
> }
> /* Don't VERIFY_CONSTANT the other operands. */
> if (integer_zerop (val))
> @@ -7055,7 +7056,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
> r = v;
> break;
> }
> - if (ctx->manifestly_const_eval)
> + if (ctx->manifestly_const_eval == mce_true)
> maybe_warn_about_constant_value (loc, t);
> if (COMPLETE_TYPE_P (TREE_TYPE (t))
> && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
> @@ -7644,7 +7645,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
> if (TREE_CODE (t) == CONVERT_EXPR
> && ARITHMETIC_TYPE_P (type)
> && INDIRECT_TYPE_P (TREE_TYPE (op))
> - && ctx->manifestly_const_eval)
> + && ctx->manifestly_const_eval == mce_true)
> {
> if (!ctx->quiet)
> error_at (loc,
> @@ -8137,7 +8138,7 @@ mark_non_constant (tree t)
> static tree
> cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
> bool strict = true,
> - bool manifestly_const_eval = false,
> + mce_value manifestly_const_eval = mce_unknown,
> bool constexpr_dtor = false,
> tree object = NULL_TREE)
> {
> @@ -8155,10 +8156,11 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
> constexpr_global_ctx global_ctx;
> constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
> allow_non_constant, strict,
> - manifestly_const_eval || !allow_non_constant };
> + !allow_non_constant ? mce_true : manifestly_const_eval };
>
> /* Turn off -frounding-math for manifestly constant evaluation. */
> - warning_sentinel rm (flag_rounding_math, ctx.manifestly_const_eval);
> + warning_sentinel rm (flag_rounding_math,
> + ctx.manifestly_const_eval == mce_true);
> tree type = initialized_type (t);
> tree r = t;
> bool is_consteval = false;
> @@ -8247,7 +8249,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
> auto_vec<tree, 16> cleanups;
> global_ctx.cleanups = &cleanups;
>
> - if (manifestly_const_eval)
> + if (manifestly_const_eval == mce_true)
> instantiate_constexpr_fns (r);
> r = cxx_eval_constant_expression (&ctx, r, vc_prvalue,
> &non_constant_p, &overflow_p);
> @@ -8386,7 +8388,7 @@ cxx_constant_value (tree t, tree decl /* = NULL_TREE */,
> tsubst_flags_t complain /* = tf_error */)
> {
> bool sfinae = !(complain & tf_error);
> - tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, true, false, decl);
> + tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, mce_true, false, decl);
> if (sfinae && !TREE_CONSTANT (r))
> r = error_mark_node;
> return r;
> @@ -8398,7 +8400,7 @@ cxx_constant_value (tree t, tree decl /* = NULL_TREE */,
> void
> cxx_constant_dtor (tree t, tree decl)
> {
> - cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
> + cxx_eval_outermost_constant_expr (t, false, true, mce_true, true, decl);
> }
>
> /* Helper routine for fold_simple function. Either return simplified
> @@ -8484,7 +8486,7 @@ static GTY((deletable)) hash_map<tree, tree> *cv_cache;
>
> tree
> maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
> - bool manifestly_const_eval /* = false */)
> + mce_value manifestly_const_eval /* = mce_unknown */)
> {
> tree r;
>
> @@ -8499,8 +8501,9 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
> /* No caching or evaluation needed. */
> return t;
>
> - if (manifestly_const_eval)
> - return cxx_eval_outermost_constant_expr (t, true, true, true, false, decl);
> + if (manifestly_const_eval != mce_unknown)
> + return cxx_eval_outermost_constant_expr (t, true, true,
> + manifestly_const_eval, false, decl);
>
> if (cv_cache == NULL)
> cv_cache = hash_map<tree, tree>::create_ggc (101);
> @@ -8524,7 +8527,8 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
> return t;
>
> uid_sensitive_constexpr_evaluation_checker c;
> - r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
> + r = cxx_eval_outermost_constant_expr (t, true, true,
> + manifestly_const_eval, false, decl);
> gcc_checking_assert (r == t
> || CONVERT_EXPR_P (t)
> || TREE_CODE (t) == VIEW_CONVERT_EXPR
> @@ -8590,7 +8594,7 @@ fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
> return t;
>
> tree r = cxx_eval_outermost_constant_expr (t, true, true,
> - manifestly_const_eval,
> + mce_value (manifestly_const_eval),
> false, object);
> /* cp_tree_equal looks through NOPs, so allow them. */
> gcc_checking_assert (r == t
> @@ -8637,7 +8641,7 @@ fold_non_dependent_expr (tree t,
> return fold_non_dependent_expr_template (t, complain,
> manifestly_const_eval, object);
>
> - return maybe_constant_value (t, object, manifestly_const_eval);
> + return maybe_constant_value (t, object, (mce_value)manifestly_const_eval);
> }
>
> /* Like fold_non_dependent_expr, but if EXPR couldn't be folded to a constant,
> @@ -8715,7 +8719,8 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
> bool is_static = (decl && DECL_P (decl)
> && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
> t = cxx_eval_outermost_constant_expr (t, allow_non_constant, !is_static,
> - manifestly_const_eval, false, decl);
> + mce_value (manifestly_const_eval),
> + false, decl);
> }
> if (TREE_CODE (t) == TARGET_EXPR)
> {
> diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> index 2e5acdf8fcb..9374327008b 100644
> --- a/gcc/cp/constraint.cc
> +++ b/gcc/cp/constraint.cc
> @@ -3068,8 +3068,7 @@ satisfy_atom (tree t, tree args, sat_info info)
> }
> else
> {
> - result = maybe_constant_value (result, NULL_TREE,
> - /*manifestly_const_eval=*/true);
> + result = maybe_constant_value (result, NULL_TREE, mce_true);
> if (!TREE_CONSTANT (result))
> result = error_mark_node;
> }
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 74b7ab71ca5..2d39185b182 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -8456,6 +8456,22 @@ struct GTY((for_user)) constexpr_fundef {
> tree result;
> };
>
> +/* Used by the constexpr machinery to control folding of
> + __builtin_is_constant_evaluated. */
Add "Whether the current context is manifestly constant-evaluated." at
the start.
> +enum class mce_value
> +{ > + /* Treat __builtin_is_constant_evaluated as non-constant. */
"Unknown, so..."
> + mce_unknown = 0,
> + /* Fold it to true. */
> + mce_true = 1,
> + /* Fold it to false. */
"Primarily used during cp_fold_function."
OK with these tweaks.
> + mce_false = -1,
> +};
> +constexpr mce_value mce_unknown = mce_value::mce_unknown;
> +constexpr mce_value mce_true = mce_value::mce_true;
> +constexpr mce_value mce_false = mce_value::mce_false;
> +
> extern void fini_constexpr (void);
> extern bool literal_type_p (tree);
> extern void maybe_save_constexpr_fundef (tree);
> @@ -8484,7 +8500,7 @@ inline tree cxx_constant_value (tree t, tsubst_flags_t complain)
> { return cxx_constant_value (t, NULL_TREE, complain); }
> extern void cxx_constant_dtor (tree, tree);
> extern tree cxx_constant_init (tree, tree = NULL_TREE);
> -extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
> +extern tree maybe_constant_value (tree, tree = NULL_TREE, mce_value = mce_unknown);
> extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
> extern tree fold_non_dependent_expr (tree,
> tsubst_flags_t = tf_warning_or_error,
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index d606b31d7a7..a023c38c59d 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -11372,7 +11372,7 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
> cp_convert (ssizetype, integer_one_node,
> complain),
> complain);
> - itype = maybe_constant_value (itype, NULL_TREE, true);
> + itype = maybe_constant_value (itype, NULL_TREE, mce_true);
> }
>
> if (!TREE_CONSTANT (itype))
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index 64e9128a5f1..4d82666891c 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -7390,16 +7390,14 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
> IMPLICIT_CONV_EXPR_NONTYPE_ARG (expr) = true;
> return expr;
> }
> - expr = maybe_constant_value (expr, NULL_TREE,
> - /*manifestly_const_eval=*/true);
> + expr = maybe_constant_value (expr, NULL_TREE, mce_true);
> expr = convert_from_reference (expr);
> /* EXPR may have become value-dependent. */
> val_dep_p = value_dependent_expression_p (expr);
> }
> else if (TYPE_PTR_OR_PTRMEM_P (type))
> {
> - tree folded = maybe_constant_value (expr, NULL_TREE,
> - /*manifestly_const_eval=*/true);
> + tree folded = maybe_constant_value (expr, NULL_TREE, mce_true);
> if (TYPE_PTR_P (type) ? integer_zerop (folded)
> : null_member_pointer_value_p (folded))
> expr = folded;
On Mon, 30 Jan 2023, Jason Merrill wrote:
> On 1/27/23 17:02, Patrick Palka wrote:
> > This patch turns the manifestly_const_eval flag used by the constexpr
> > machinery into a tri-state enum so that we're able to express wanting
> > to fold __builtin_is_constant_evaluated to false via late speculative
> > constexpr evaluation. Of all the entry points to constexpr evaluation
> > only maybe_constant_value is changed to take a tri-state value; the
> > others continue to take bool. The subsequent patch will use this to fold
> > the builtin to false when called from cp_fold_function.
> >
> > gcc/cp/ChangeLog:
> >
> > * constexpr.cc (constexpr_call::manifestly_const_eval): Give
> > it type int instead of bool.
> > (constexpr_ctx::manifestly_const_eval): Give it type mce_value
> > instead of bool.
> > (cxx_eval_builtin_function_call): Adjust after making
> > manifestly_const_eval tri-state.
> > (cxx_eval_call_expression): Likewise.
> > (cxx_eval_binary_expression): Likewise.
> > (cxx_eval_conditional_expression): Likewise.
> > (cxx_eval_constant_expression): Likewise.
> > (cxx_eval_outermost_constant_expr): Likewise.
> > (cxx_constant_value): Likewise.
> > (cxx_constant_dtor): Likewise.
> > (maybe_constant_value): Give manifestly_const_eval parameter
> > type mce_value instead of bool and adjust accordingly.
> > (fold_non_dependent_expr_template): Adjust call
> > to cxx_eval_outermost_constant_expr.
> > (fold_non_dependent_expr): Likewise.
> > (maybe_constant_init_1): Likewise.
> > * constraint.cc (satisfy_atom): Adjust call to
> > maybe_constant_value.
> > * cp-tree.h (enum class mce_value): Define.
> > (maybe_constant_value): Adjust manifestly_const_eval parameter
> > type and default argument.
> > * decl.cc (compute_array_index_type_loc): Adjust call to
> > maybe_constant_value.
> > * pt.cc (convert_nontype_argument): Likewise.
> > ---
> > gcc/cp/constexpr.cc | 61 ++++++++++++++++++++++++--------------------
> > gcc/cp/constraint.cc | 3 +--
> > gcc/cp/cp-tree.h | 18 ++++++++++++-
> > gcc/cp/decl.cc | 2 +-
> `> gcc/cp/pt.cc | 6 ++---
> > 5 files changed, 54 insertions(+), 36 deletions(-)
> >
> > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
> > index be99bec17e7..34662198903 100644
> > --- a/gcc/cp/constexpr.cc
> > +++ b/gcc/cp/constexpr.cc
> > @@ -1119,8 +1119,8 @@ struct GTY((for_user)) constexpr_call {
> > /* The hash of this call; we remember it here to avoid having to
> > recalculate it when expanding the hash table. */
> > hashval_t hash;
> > - /* Whether __builtin_is_constant_evaluated() should evaluate to true. */
> > - bool manifestly_const_eval;
> > + /* The raw value of constexpr_ctx::manifestly_const_eval. */
> > + int manifestly_const_eval;
>
> Why not mce_value?
gengtype complained about 'mce_value' being an unknown type here
(constexpr_call is gengtype-enabled). Ah, but it looks like using
'enum mce_value' makes gengtype happy.
>
> > };
> > struct constexpr_call_hasher : ggc_ptr_hash<constexpr_call>
> > @@ -1248,7 +1248,7 @@ struct constexpr_ctx {
> > trying harder to get a constant value. */
> > bool strict;
> > /* Whether __builtin_is_constant_evaluated () should be true. */
> > - bool manifestly_const_eval;
> > + mce_value manifestly_const_eval;
> > };
> > /* This internal flag controls whether we should avoid doing anything
> > during
> > @@ -1463,7 +1463,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx
> > *ctx, tree t, tree fun,
> > /* If we aren't requiring a constant expression, defer
> > __builtin_constant_p
> > in a constexpr function until we have values for the parameters. */
> > if (bi_const_p
> > - && !ctx->manifestly_const_eval
> > + && ctx->manifestly_const_eval == mce_unknown
> > && current_function_decl
> > && DECL_DECLARED_CONSTEXPR_P (current_function_decl))
> > {
> > @@ -1479,12 +1479,13 @@ cxx_eval_builtin_function_call (const constexpr_ctx
> > *ctx, tree t, tree fun,
> > if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
> > BUILT_IN_FRONTEND))
> > {
> > - if (!ctx->manifestly_const_eval)
> > + if (ctx->manifestly_const_eval == mce_unknown)
> > {
> > *non_constant_p = true;
> > return t;
> > }
> > - return boolean_true_node;
> > + return constant_boolean_node (ctx->manifestly_const_eval == mce_true,
> > + boolean_type_node);
> > }
> > if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION,
> > BUILT_IN_FRONTEND))
> > @@ -1591,7 +1592,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx
> > *ctx, tree t, tree fun,
> > }
> > bool save_ffbcp = force_folding_builtin_constant_p;
> > - force_folding_builtin_constant_p |= ctx->manifestly_const_eval;
> > + force_folding_builtin_constant_p |= ctx->manifestly_const_eval !=
> > mce_unknown;
> > tree save_cur_fn = current_function_decl;
> > /* Return name of ctx->call->fundef->decl for __builtin_FUNCTION (). */
> > if (fndecl_built_in_p (fun, BUILT_IN_FUNCTION)
> > @@ -2644,7 +2645,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx,
> > tree t,
> > location_t loc = cp_expr_loc_or_input_loc (t);
> > tree fun = get_function_named_in_call (t);
> > constexpr_call new_call
> > - = { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
> > + = { NULL, NULL, NULL, 0, (int)ctx->manifestly_const_eval };
> > int depth_ok;
> > if (fun == NULL_TREE)
> > @@ -2916,7 +2917,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx,
> > tree t,
> > location_t save_loc = input_location;
> > input_location = loc;
> > ++function_depth;
> > - if (ctx->manifestly_const_eval)
> > + if (ctx->manifestly_const_eval == mce_true)
> > FNDECL_MANIFESTLY_CONST_EVALUATED (fun) = true;
> > instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false);
> > --function_depth;
> > @@ -3676,7 +3677,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx,
> > tree t,
> > if (r == NULL_TREE)
> > {
> > - if (ctx->manifestly_const_eval
> > + if (ctx->manifestly_const_eval == mce_true
> > && (flag_constexpr_fp_except
> > || TREE_CODE (type) != REAL_TYPE))
> > {
> > @@ -3741,13 +3742,13 @@ cxx_eval_conditional_expression (const constexpr_ctx
> > *ctx, tree t,
> > without manifestly_const_eval even expressions or parts thereof which
> > will later be manifestly const_eval evaluated), otherwise fold it to
> > true. */
> > - if (ctx->manifestly_const_eval)
> > - val = boolean_true_node;
> > - else
> > + if (ctx->manifestly_const_eval == mce_unknown)
> > {
> > *non_constant_p = true;
> > return t;
> > }
> > + val = constant_boolean_node (ctx->manifestly_const_eval == mce_true,
> > + boolean_type_node);
> > }
> > /* Don't VERIFY_CONSTANT the other operands. */
> > if (integer_zerop (val))
> > @@ -7055,7 +7056,7 @@ cxx_eval_constant_expression (const constexpr_ctx
> > *ctx, tree t,
> > r = v;
> > break;
> > }
> > - if (ctx->manifestly_const_eval)
> > + if (ctx->manifestly_const_eval == mce_true)
> > maybe_warn_about_constant_value (loc, t);
> > if (COMPLETE_TYPE_P (TREE_TYPE (t))
> > && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
> > @@ -7644,7 +7645,7 @@ cxx_eval_constant_expression (const constexpr_ctx
> > *ctx, tree t,
> > if (TREE_CODE (t) == CONVERT_EXPR
> > && ARITHMETIC_TYPE_P (type)
> > && INDIRECT_TYPE_P (TREE_TYPE (op))
> > - && ctx->manifestly_const_eval)
> > + && ctx->manifestly_const_eval == mce_true)
> > {
> > if (!ctx->quiet)
> > error_at (loc,
> > @@ -8137,7 +8138,7 @@ mark_non_constant (tree t)
> > static tree
> > cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
> > bool strict = true,
> > - bool manifestly_const_eval = false,
> > + mce_value manifestly_const_eval =
> > mce_unknown,
> > bool constexpr_dtor = false,
> > tree object = NULL_TREE)
> > {
> > @@ -8155,10 +8156,11 @@ cxx_eval_outermost_constant_expr (tree t, bool
> > allow_non_constant,
> > constexpr_global_ctx global_ctx;
> > constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
> > allow_non_constant, strict,
> > - manifestly_const_eval || !allow_non_constant };
> > + !allow_non_constant ? mce_true : manifestly_const_eval
> > };
> > /* Turn off -frounding-math for manifestly constant evaluation. */
> > - warning_sentinel rm (flag_rounding_math, ctx.manifestly_const_eval);
> > + warning_sentinel rm (flag_rounding_math,
> > + ctx.manifestly_const_eval == mce_true);
> > tree type = initialized_type (t);
> > tree r = t;
> > bool is_consteval = false;
> > @@ -8247,7 +8249,7 @@ cxx_eval_outermost_constant_expr (tree t, bool
> > allow_non_constant,
> > auto_vec<tree, 16> cleanups;
> > global_ctx.cleanups = &cleanups;
> > - if (manifestly_const_eval)
> > + if (manifestly_const_eval == mce_true)
> > instantiate_constexpr_fns (r);
> > r = cxx_eval_constant_expression (&ctx, r, vc_prvalue,
> > &non_constant_p, &overflow_p);
> > @@ -8386,7 +8388,7 @@ cxx_constant_value (tree t, tree decl /* = NULL_TREE
> > */,
> > tsubst_flags_t complain /* = tf_error */)
> > {
> > bool sfinae = !(complain & tf_error);
> > - tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, true, false,
> > decl);
> > + tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, mce_true,
> > false, decl);
> > if (sfinae && !TREE_CONSTANT (r))
> > r = error_mark_node;
> > return r;
> > @@ -8398,7 +8400,7 @@ cxx_constant_value (tree t, tree decl /* = NULL_TREE
> > */,
> > void
> > cxx_constant_dtor (tree t, tree decl)
> > {
> > - cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
> > + cxx_eval_outermost_constant_expr (t, false, true, mce_true, true, decl);
> > }
> > /* Helper routine for fold_simple function. Either return simplified
> > @@ -8484,7 +8486,7 @@ static GTY((deletable)) hash_map<tree, tree>
> > *cv_cache;
> > tree
> > maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
> > - bool manifestly_const_eval /* = false */)
> > + mce_value manifestly_const_eval /* = mce_unknown */)
> > {
> > tree r;
> > @@ -8499,8 +8501,9 @@ maybe_constant_value (tree t, tree decl /* =
> > NULL_TREE */,
> > /* No caching or evaluation needed. */
> > return t;
> > - if (manifestly_const_eval)
> > - return cxx_eval_outermost_constant_expr (t, true, true, true, false,
> > decl);
> > + if (manifestly_const_eval != mce_unknown)
> > + return cxx_eval_outermost_constant_expr (t, true, true,
> > + manifestly_const_eval, false,
> > decl);
> > if (cv_cache == NULL)
> > cv_cache = hash_map<tree, tree>::create_ggc (101);
> > @@ -8524,7 +8527,8 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE
> > */,
> > return t;
> > uid_sensitive_constexpr_evaluation_checker c;
> > - r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
> > + r = cxx_eval_outermost_constant_expr (t, true, true,
> > + manifestly_const_eval, false, decl);
> > gcc_checking_assert (r == t
> > || CONVERT_EXPR_P (t)
> > || TREE_CODE (t) == VIEW_CONVERT_EXPR
> > @@ -8590,7 +8594,7 @@ fold_non_dependent_expr_template (tree t,
> > tsubst_flags_t complain,
> > return t;
> > tree r = cxx_eval_outermost_constant_expr (t, true, true,
> > - manifestly_const_eval,
> > + mce_value
> > (manifestly_const_eval),
> > false, object);
> > /* cp_tree_equal looks through NOPs, so allow them. */
> > gcc_checking_assert (r == t
> > @@ -8637,7 +8641,7 @@ fold_non_dependent_expr (tree t,
> > return fold_non_dependent_expr_template (t, complain,
> > manifestly_const_eval, object);
> > - return maybe_constant_value (t, object, manifestly_const_eval);
> > + return maybe_constant_value (t, object,
> > (mce_value)manifestly_const_eval);
> > }
> > /* Like fold_non_dependent_expr, but if EXPR couldn't be folded to a
> > constant,
> > @@ -8715,7 +8719,8 @@ maybe_constant_init_1 (tree t, tree decl, bool
> > allow_non_constant,
> > bool is_static = (decl && DECL_P (decl)
> > && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
> > t = cxx_eval_outermost_constant_expr (t, allow_non_constant,
> > !is_static,
> > - manifestly_const_eval, false,
> > decl);
> > + mce_value (manifestly_const_eval),
> > + false, decl);
> > }
> > if (TREE_CODE (t) == TARGET_EXPR)
> > {
> > diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
> > index 2e5acdf8fcb..9374327008b 100644
> > --- a/gcc/cp/constraint.cc
> > +++ b/gcc/cp/constraint.cc
> > @@ -3068,8 +3068,7 @@ satisfy_atom (tree t, tree args, sat_info info)
> > }
> > else
> > {
> > - result = maybe_constant_value (result, NULL_TREE,
> > - /*manifestly_const_eval=*/true);
> > + result = maybe_constant_value (result, NULL_TREE, mce_true);
> > if (!TREE_CONSTANT (result))
> > result = error_mark_node;
> > }
> > diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> > index 74b7ab71ca5..2d39185b182 100644
> > --- a/gcc/cp/cp-tree.h
> > +++ b/gcc/cp/cp-tree.h
> > @@ -8456,6 +8456,22 @@ struct GTY((for_user)) constexpr_fundef {
> > tree result;
> > };
> > +/* Used by the constexpr machinery to control folding of
> > + __builtin_is_constant_evaluated. */
>
> Add "Whether the current context is manifestly constant-evaluated." at the
> start.
>
> > +enum class mce_value
> > +{ > + /* Treat __builtin_is_constant_evaluated as non-constant. */
>
> "Unknown, so..."
>
> > + mce_unknown = 0,
> > + /* Fold it to true. */
> > + mce_true = 1,
> > + /* Fold it to false. */
>
> "Primarily used during cp_fold_function."
>
> OK with these tweaks.
Thanks, here's v2 with the above changes, pending approval of the
second patch of the series. I'll make sure to adjust the comment
for mce_value::mce_false to say
"Primarily used during cp_fold_function and cp_fully_fold_init"
if we do end up using it from cp_fully_fold_init as well.
-- >8 --
Subject: [PATCH 1/2] c++: make manifestly_const_eval tri-state
This patch turns the manifestly_const_eval flag used by the constexpr
machinery into a tri-state enum so that we're able to express wanting
to fold __builtin_is_constant_evaluated to false via late speculative
constexpr evaluation. Of all the entry points to constexpr evaluation
only maybe_constant_value is changed to take a tri-state value; the
others continue to take bool. The subsequent patch will use this to fold
the builtin to false when called from cp_fold_function.
gcc/cp/ChangeLog:
* constexpr.cc (constexpr_call::manifestly_const_eval): Give
it type int instead of bool.
(constexpr_ctx::manifestly_const_eval): Give it type mce_value
instead of bool.
(cxx_eval_builtin_function_call): Adjust after making
manifestly_const_eval tri-state.
(cxx_eval_call_expression): Likewise.
(cxx_eval_binary_expression): Likewise.
(cxx_eval_conditional_expression): Likewise.
(cxx_eval_constant_expression): Likewise.
(cxx_eval_outermost_constant_expr): Likewise.
(cxx_constant_value): Likewise.
(cxx_constant_dtor): Likewise.
(maybe_constant_value): Give manifestly_const_eval parameter
type mce_value instead of bool and adjust accordingly.
(fold_non_dependent_expr_template): Adjust call
to cxx_eval_outermost_constant_expr.
(fold_non_dependent_expr): Likewise.
(maybe_constant_init_1): Likewise.
* constraint.cc (satisfy_atom): Adjust call to
maybe_constant_value.
* cp-tree.h (enum class mce_value): Define.
(maybe_constant_value): Adjust manifestly_const_eval parameter
type and default argument.
* decl.cc (compute_array_index_type_loc): Adjust call to
maybe_constant_value.
* pt.cc (convert_nontype_argument): Likewise.
---
gcc/cp/constexpr.cc | 59 ++++++++++++++++++++++++--------------------
gcc/cp/constraint.cc | 3 +--
gcc/cp/cp-tree.h | 19 +++++++++++++-
gcc/cp/decl.cc | 2 +-
gcc/cp/pt.cc | 6 ++---
5 files changed, 54 insertions(+), 35 deletions(-)
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 5b31f9c27d1..4576aebd8d2 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1119,8 +1119,8 @@ struct GTY((for_user)) constexpr_call {
/* The hash of this call; we remember it here to avoid having to
recalculate it when expanding the hash table. */
hashval_t hash;
- /* Whether __builtin_is_constant_evaluated() should evaluate to true. */
- bool manifestly_const_eval;
+ /* The value of constexpr_ctx::manifestly_const_eval. */
+ enum mce_value manifestly_const_eval;
};
struct constexpr_call_hasher : ggc_ptr_hash<constexpr_call>
@@ -1248,7 +1248,7 @@ struct constexpr_ctx {
trying harder to get a constant value. */
bool strict;
/* Whether __builtin_is_constant_evaluated () should be true. */
- bool manifestly_const_eval;
+ mce_value manifestly_const_eval;
};
/* This internal flag controls whether we should avoid doing anything during
@@ -1463,7 +1463,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
/* If we aren't requiring a constant expression, defer __builtin_constant_p
in a constexpr function until we have values for the parameters. */
if (bi_const_p
- && !ctx->manifestly_const_eval
+ && ctx->manifestly_const_eval == mce_unknown
&& current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
{
@@ -1479,12 +1479,13 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
BUILT_IN_FRONTEND))
{
- if (!ctx->manifestly_const_eval)
+ if (ctx->manifestly_const_eval == mce_unknown)
{
*non_constant_p = true;
return t;
}
- return boolean_true_node;
+ return constant_boolean_node (ctx->manifestly_const_eval == mce_true,
+ boolean_type_node);
}
if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
@@ -1591,7 +1592,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
}
bool save_ffbcp = force_folding_builtin_constant_p;
- force_folding_builtin_constant_p |= ctx->manifestly_const_eval;
+ force_folding_builtin_constant_p |= ctx->manifestly_const_eval != mce_unknown;
tree save_cur_fn = current_function_decl;
/* Return name of ctx->call->fundef->decl for __builtin_FUNCTION (). */
if (fndecl_built_in_p (fun, BUILT_IN_FUNCTION)
@@ -2916,7 +2917,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
location_t save_loc = input_location;
input_location = loc;
++function_depth;
- if (ctx->manifestly_const_eval)
+ if (ctx->manifestly_const_eval == mce_true)
FNDECL_MANIFESTLY_CONST_EVALUATED (fun) = true;
instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false);
--function_depth;
@@ -3676,7 +3677,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
if (r == NULL_TREE)
{
- if (ctx->manifestly_const_eval
+ if (ctx->manifestly_const_eval == mce_true
&& (flag_constexpr_fp_except
|| TREE_CODE (type) != REAL_TYPE))
{
@@ -3741,13 +3742,13 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t,
without manifestly_const_eval even expressions or parts thereof which
will later be manifestly const_eval evaluated), otherwise fold it to
true. */
- if (ctx->manifestly_const_eval)
- val = boolean_true_node;
- else
+ if (ctx->manifestly_const_eval == mce_unknown)
{
*non_constant_p = true;
return t;
}
+ val = constant_boolean_node (ctx->manifestly_const_eval == mce_true,
+ boolean_type_node);
}
/* Don't VERIFY_CONSTANT the other operands. */
if (integer_zerop (val))
@@ -7055,7 +7056,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = v;
break;
}
- if (ctx->manifestly_const_eval)
+ if (ctx->manifestly_const_eval == mce_true)
maybe_warn_about_constant_value (loc, t);
if (COMPLETE_TYPE_P (TREE_TYPE (t))
&& is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
@@ -7644,7 +7645,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (TREE_CODE (t) == CONVERT_EXPR
&& ARITHMETIC_TYPE_P (type)
&& INDIRECT_TYPE_P (TREE_TYPE (op))
- && ctx->manifestly_const_eval)
+ && ctx->manifestly_const_eval == mce_true)
{
if (!ctx->quiet)
error_at (loc,
@@ -8182,7 +8183,7 @@ mark_non_constant (tree t)
static tree
cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
bool strict = true,
- bool manifestly_const_eval = false,
+ mce_value manifestly_const_eval = mce_unknown,
bool constexpr_dtor = false,
tree object = NULL_TREE)
{
@@ -8200,10 +8201,11 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
constexpr_global_ctx global_ctx;
constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
allow_non_constant, strict,
- manifestly_const_eval || !allow_non_constant };
+ !allow_non_constant ? mce_true : manifestly_const_eval };
/* Turn off -frounding-math for manifestly constant evaluation. */
- warning_sentinel rm (flag_rounding_math, ctx.manifestly_const_eval);
+ warning_sentinel rm (flag_rounding_math,
+ ctx.manifestly_const_eval == mce_true);
tree type = initialized_type (t);
tree r = t;
bool is_consteval = false;
@@ -8292,7 +8294,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
auto_vec<tree, 16> cleanups;
global_ctx.cleanups = &cleanups;
- if (manifestly_const_eval)
+ if (manifestly_const_eval == mce_true)
instantiate_constexpr_fns (r);
r = cxx_eval_constant_expression (&ctx, r, vc_prvalue,
&non_constant_p, &overflow_p);
@@ -8431,7 +8433,7 @@ cxx_constant_value (tree t, tree decl /* = NULL_TREE */,
tsubst_flags_t complain /* = tf_error */)
{
bool sfinae = !(complain & tf_error);
- tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, true, false, decl);
+ tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, mce_true, false, decl);
if (sfinae && !TREE_CONSTANT (r))
r = error_mark_node;
return r;
@@ -8443,7 +8445,7 @@ cxx_constant_value (tree t, tree decl /* = NULL_TREE */,
void
cxx_constant_dtor (tree t, tree decl)
{
- cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
+ cxx_eval_outermost_constant_expr (t, false, true, mce_true, true, decl);
}
/* Helper routine for fold_simple function. Either return simplified
@@ -8529,7 +8531,7 @@ static GTY((deletable)) hash_map<tree, tree> *cv_cache;
tree
maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
- bool manifestly_const_eval /* = false */)
+ mce_value manifestly_const_eval /* = mce_unknown */)
{
tree r;
@@ -8544,8 +8546,9 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
/* No caching or evaluation needed. */
return t;
- if (manifestly_const_eval)
- return cxx_eval_outermost_constant_expr (t, true, true, true, false, decl);
+ if (manifestly_const_eval != mce_unknown)
+ return cxx_eval_outermost_constant_expr (t, true, true,
+ manifestly_const_eval, false, decl);
if (cv_cache == NULL)
cv_cache = hash_map<tree, tree>::create_ggc (101);
@@ -8569,7 +8572,8 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
return t;
uid_sensitive_constexpr_evaluation_checker c;
- r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
+ r = cxx_eval_outermost_constant_expr (t, true, true,
+ manifestly_const_eval, false, decl);
gcc_checking_assert (r == t
|| CONVERT_EXPR_P (t)
|| TREE_CODE (t) == VIEW_CONVERT_EXPR
@@ -8635,7 +8639,7 @@ fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
return t;
tree r = cxx_eval_outermost_constant_expr (t, true, true,
- manifestly_const_eval,
+ mce_value (manifestly_const_eval),
false, object);
/* cp_tree_equal looks through NOPs, so allow them. */
gcc_checking_assert (r == t
@@ -8682,7 +8686,7 @@ fold_non_dependent_expr (tree t,
return fold_non_dependent_expr_template (t, complain,
manifestly_const_eval, object);
- return maybe_constant_value (t, object, manifestly_const_eval);
+ return maybe_constant_value (t, object, mce_value (manifestly_const_eval));
}
/* Like fold_non_dependent_expr, but if EXPR couldn't be folded to a constant,
@@ -8760,7 +8764,8 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
bool is_static = (decl && DECL_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
t = cxx_eval_outermost_constant_expr (t, allow_non_constant, !is_static,
- manifestly_const_eval, false, decl);
+ mce_value (manifestly_const_eval),
+ false, decl);
}
if (TREE_CODE (t) == TARGET_EXPR)
{
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 2e5acdf8fcb..9374327008b 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -3068,8 +3068,7 @@ satisfy_atom (tree t, tree args, sat_info info)
}
else
{
- result = maybe_constant_value (result, NULL_TREE,
- /*manifestly_const_eval=*/true);
+ result = maybe_constant_value (result, NULL_TREE, mce_true);
if (!TREE_CONSTANT (result))
result = error_mark_node;
}
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 31fd8af4f21..00b2bffc85c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8455,6 +8455,23 @@ struct GTY((for_user)) constexpr_fundef {
tree result;
};
+/* Whether the current context is manifestly constant-evaluated.
+ Used by the constexpr machinery to control folding of
+ __builtin_is_constant_evaluated. */
+
+enum class mce_value
+{
+ /* Unknown, so treat __builtin_is_constant_evaluated as non-constant. */
+ mce_unknown = 0,
+ /* Fold it to true. */
+ mce_true = 1,
+ /* Fold it to false. Primarily used during cp_fold_function. */
+ mce_false = -1,
+};
+constexpr mce_value mce_unknown = mce_value::mce_unknown;
+constexpr mce_value mce_true = mce_value::mce_true;
+constexpr mce_value mce_false = mce_value::mce_false;
+
extern void fini_constexpr (void);
extern bool literal_type_p (tree);
extern void maybe_save_constexpr_fundef (tree);
@@ -8483,7 +8500,7 @@ inline tree cxx_constant_value (tree t, tsubst_flags_t complain)
{ return cxx_constant_value (t, NULL_TREE, complain); }
extern void cxx_constant_dtor (tree, tree);
extern tree cxx_constant_init (tree, tree = NULL_TREE);
-extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
+extern tree maybe_constant_value (tree, tree = NULL_TREE, mce_value = mce_unknown);
extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
extern tree fold_non_dependent_expr (tree,
tsubst_flags_t = tf_warning_or_error,
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index d606b31d7a7..a023c38c59d 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -11372,7 +11372,7 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
cp_convert (ssizetype, integer_one_node,
complain),
complain);
- itype = maybe_constant_value (itype, NULL_TREE, true);
+ itype = maybe_constant_value (itype, NULL_TREE, mce_true);
}
if (!TREE_CONSTANT (itype))
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 51fc246ed71..255332dc0c1 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -7390,16 +7390,14 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
IMPLICIT_CONV_EXPR_NONTYPE_ARG (expr) = true;
return expr;
}
- expr = maybe_constant_value (expr, NULL_TREE,
- /*manifestly_const_eval=*/true);
+ expr = maybe_constant_value (expr, NULL_TREE, mce_true);
expr = convert_from_reference (expr);
/* EXPR may have become value-dependent. */
val_dep_p = value_dependent_expression_p (expr);
}
else if (TYPE_PTR_OR_PTRMEM_P (type))
{
- tree folded = maybe_constant_value (expr, NULL_TREE,
- /*manifestly_const_eval=*/true);
+ tree folded = maybe_constant_value (expr, NULL_TREE, mce_true);
if (TYPE_PTR_P (type) ? integer_zerop (folded)
: null_member_pointer_value_p (folded))
expr = folded;
@@ -1119,8 +1119,8 @@ struct GTY((for_user)) constexpr_call {
/* The hash of this call; we remember it here to avoid having to
recalculate it when expanding the hash table. */
hashval_t hash;
- /* Whether __builtin_is_constant_evaluated() should evaluate to true. */
- bool manifestly_const_eval;
+ /* The raw value of constexpr_ctx::manifestly_const_eval. */
+ int manifestly_const_eval;
};
struct constexpr_call_hasher : ggc_ptr_hash<constexpr_call>
@@ -1248,7 +1248,7 @@ struct constexpr_ctx {
trying harder to get a constant value. */
bool strict;
/* Whether __builtin_is_constant_evaluated () should be true. */
- bool manifestly_const_eval;
+ mce_value manifestly_const_eval;
};
/* This internal flag controls whether we should avoid doing anything during
@@ -1463,7 +1463,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
/* If we aren't requiring a constant expression, defer __builtin_constant_p
in a constexpr function until we have values for the parameters. */
if (bi_const_p
- && !ctx->manifestly_const_eval
+ && ctx->manifestly_const_eval == mce_unknown
&& current_function_decl
&& DECL_DECLARED_CONSTEXPR_P (current_function_decl))
{
@@ -1479,12 +1479,13 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
if (fndecl_built_in_p (fun, CP_BUILT_IN_IS_CONSTANT_EVALUATED,
BUILT_IN_FRONTEND))
{
- if (!ctx->manifestly_const_eval)
+ if (ctx->manifestly_const_eval == mce_unknown)
{
*non_constant_p = true;
return t;
}
- return boolean_true_node;
+ return constant_boolean_node (ctx->manifestly_const_eval == mce_true,
+ boolean_type_node);
}
if (fndecl_built_in_p (fun, CP_BUILT_IN_SOURCE_LOCATION, BUILT_IN_FRONTEND))
@@ -1591,7 +1592,7 @@ cxx_eval_builtin_function_call (const constexpr_ctx *ctx, tree t, tree fun,
}
bool save_ffbcp = force_folding_builtin_constant_p;
- force_folding_builtin_constant_p |= ctx->manifestly_const_eval;
+ force_folding_builtin_constant_p |= ctx->manifestly_const_eval != mce_unknown;
tree save_cur_fn = current_function_decl;
/* Return name of ctx->call->fundef->decl for __builtin_FUNCTION (). */
if (fndecl_built_in_p (fun, BUILT_IN_FUNCTION)
@@ -2644,7 +2645,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
location_t loc = cp_expr_loc_or_input_loc (t);
tree fun = get_function_named_in_call (t);
constexpr_call new_call
- = { NULL, NULL, NULL, 0, ctx->manifestly_const_eval };
+ = { NULL, NULL, NULL, 0, (int)ctx->manifestly_const_eval };
int depth_ok;
if (fun == NULL_TREE)
@@ -2916,7 +2917,7 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
location_t save_loc = input_location;
input_location = loc;
++function_depth;
- if (ctx->manifestly_const_eval)
+ if (ctx->manifestly_const_eval == mce_true)
FNDECL_MANIFESTLY_CONST_EVALUATED (fun) = true;
instantiate_decl (fun, /*defer_ok*/false, /*expl_inst*/false);
--function_depth;
@@ -3676,7 +3677,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
if (r == NULL_TREE)
{
- if (ctx->manifestly_const_eval
+ if (ctx->manifestly_const_eval == mce_true
&& (flag_constexpr_fp_except
|| TREE_CODE (type) != REAL_TYPE))
{
@@ -3741,13 +3742,13 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t,
without manifestly_const_eval even expressions or parts thereof which
will later be manifestly const_eval evaluated), otherwise fold it to
true. */
- if (ctx->manifestly_const_eval)
- val = boolean_true_node;
- else
+ if (ctx->manifestly_const_eval == mce_unknown)
{
*non_constant_p = true;
return t;
}
+ val = constant_boolean_node (ctx->manifestly_const_eval == mce_true,
+ boolean_type_node);
}
/* Don't VERIFY_CONSTANT the other operands. */
if (integer_zerop (val))
@@ -7055,7 +7056,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
r = v;
break;
}
- if (ctx->manifestly_const_eval)
+ if (ctx->manifestly_const_eval == mce_true)
maybe_warn_about_constant_value (loc, t);
if (COMPLETE_TYPE_P (TREE_TYPE (t))
&& is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
@@ -7644,7 +7645,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (TREE_CODE (t) == CONVERT_EXPR
&& ARITHMETIC_TYPE_P (type)
&& INDIRECT_TYPE_P (TREE_TYPE (op))
- && ctx->manifestly_const_eval)
+ && ctx->manifestly_const_eval == mce_true)
{
if (!ctx->quiet)
error_at (loc,
@@ -8137,7 +8138,7 @@ mark_non_constant (tree t)
static tree
cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
bool strict = true,
- bool manifestly_const_eval = false,
+ mce_value manifestly_const_eval = mce_unknown,
bool constexpr_dtor = false,
tree object = NULL_TREE)
{
@@ -8155,10 +8156,11 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
constexpr_global_ctx global_ctx;
constexpr_ctx ctx = { &global_ctx, NULL, NULL, NULL, NULL, NULL, NULL,
allow_non_constant, strict,
- manifestly_const_eval || !allow_non_constant };
+ !allow_non_constant ? mce_true : manifestly_const_eval };
/* Turn off -frounding-math for manifestly constant evaluation. */
- warning_sentinel rm (flag_rounding_math, ctx.manifestly_const_eval);
+ warning_sentinel rm (flag_rounding_math,
+ ctx.manifestly_const_eval == mce_true);
tree type = initialized_type (t);
tree r = t;
bool is_consteval = false;
@@ -8247,7 +8249,7 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
auto_vec<tree, 16> cleanups;
global_ctx.cleanups = &cleanups;
- if (manifestly_const_eval)
+ if (manifestly_const_eval == mce_true)
instantiate_constexpr_fns (r);
r = cxx_eval_constant_expression (&ctx, r, vc_prvalue,
&non_constant_p, &overflow_p);
@@ -8386,7 +8388,7 @@ cxx_constant_value (tree t, tree decl /* = NULL_TREE */,
tsubst_flags_t complain /* = tf_error */)
{
bool sfinae = !(complain & tf_error);
- tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, true, false, decl);
+ tree r = cxx_eval_outermost_constant_expr (t, sfinae, true, mce_true, false, decl);
if (sfinae && !TREE_CONSTANT (r))
r = error_mark_node;
return r;
@@ -8398,7 +8400,7 @@ cxx_constant_value (tree t, tree decl /* = NULL_TREE */,
void
cxx_constant_dtor (tree t, tree decl)
{
- cxx_eval_outermost_constant_expr (t, false, true, true, true, decl);
+ cxx_eval_outermost_constant_expr (t, false, true, mce_true, true, decl);
}
/* Helper routine for fold_simple function. Either return simplified
@@ -8484,7 +8486,7 @@ static GTY((deletable)) hash_map<tree, tree> *cv_cache;
tree
maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
- bool manifestly_const_eval /* = false */)
+ mce_value manifestly_const_eval /* = mce_unknown */)
{
tree r;
@@ -8499,8 +8501,9 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
/* No caching or evaluation needed. */
return t;
- if (manifestly_const_eval)
- return cxx_eval_outermost_constant_expr (t, true, true, true, false, decl);
+ if (manifestly_const_eval != mce_unknown)
+ return cxx_eval_outermost_constant_expr (t, true, true,
+ manifestly_const_eval, false, decl);
if (cv_cache == NULL)
cv_cache = hash_map<tree, tree>::create_ggc (101);
@@ -8524,7 +8527,8 @@ maybe_constant_value (tree t, tree decl /* = NULL_TREE */,
return t;
uid_sensitive_constexpr_evaluation_checker c;
- r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
+ r = cxx_eval_outermost_constant_expr (t, true, true,
+ manifestly_const_eval, false, decl);
gcc_checking_assert (r == t
|| CONVERT_EXPR_P (t)
|| TREE_CODE (t) == VIEW_CONVERT_EXPR
@@ -8590,7 +8594,7 @@ fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
return t;
tree r = cxx_eval_outermost_constant_expr (t, true, true,
- manifestly_const_eval,
+ mce_value (manifestly_const_eval),
false, object);
/* cp_tree_equal looks through NOPs, so allow them. */
gcc_checking_assert (r == t
@@ -8637,7 +8641,7 @@ fold_non_dependent_expr (tree t,
return fold_non_dependent_expr_template (t, complain,
manifestly_const_eval, object);
- return maybe_constant_value (t, object, manifestly_const_eval);
+ return maybe_constant_value (t, object, (mce_value)manifestly_const_eval);
}
/* Like fold_non_dependent_expr, but if EXPR couldn't be folded to a constant,
@@ -8715,7 +8719,8 @@ maybe_constant_init_1 (tree t, tree decl, bool allow_non_constant,
bool is_static = (decl && DECL_P (decl)
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl)));
t = cxx_eval_outermost_constant_expr (t, allow_non_constant, !is_static,
- manifestly_const_eval, false, decl);
+ mce_value (manifestly_const_eval),
+ false, decl);
}
if (TREE_CODE (t) == TARGET_EXPR)
{
@@ -3068,8 +3068,7 @@ satisfy_atom (tree t, tree args, sat_info info)
}
else
{
- result = maybe_constant_value (result, NULL_TREE,
- /*manifestly_const_eval=*/true);
+ result = maybe_constant_value (result, NULL_TREE, mce_true);
if (!TREE_CONSTANT (result))
result = error_mark_node;
}
@@ -8456,6 +8456,22 @@ struct GTY((for_user)) constexpr_fundef {
tree result;
};
+/* Used by the constexpr machinery to control folding of
+ __builtin_is_constant_evaluated. */
+
+enum class mce_value
+{
+ /* Treat __builtin_is_constant_evaluated as non-constant. */
+ mce_unknown = 0,
+ /* Fold it to true. */
+ mce_true = 1,
+ /* Fold it to false. */
+ mce_false = -1,
+};
+constexpr mce_value mce_unknown = mce_value::mce_unknown;
+constexpr mce_value mce_true = mce_value::mce_true;
+constexpr mce_value mce_false = mce_value::mce_false;
+
extern void fini_constexpr (void);
extern bool literal_type_p (tree);
extern void maybe_save_constexpr_fundef (tree);
@@ -8484,7 +8500,7 @@ inline tree cxx_constant_value (tree t, tsubst_flags_t complain)
{ return cxx_constant_value (t, NULL_TREE, complain); }
extern void cxx_constant_dtor (tree, tree);
extern tree cxx_constant_init (tree, tree = NULL_TREE);
-extern tree maybe_constant_value (tree, tree = NULL_TREE, bool = false);
+extern tree maybe_constant_value (tree, tree = NULL_TREE, mce_value = mce_unknown);
extern tree maybe_constant_init (tree, tree = NULL_TREE, bool = false);
extern tree fold_non_dependent_expr (tree,
tsubst_flags_t = tf_warning_or_error,
@@ -11372,7 +11372,7 @@ compute_array_index_type_loc (location_t name_loc, tree name, tree size,
cp_convert (ssizetype, integer_one_node,
complain),
complain);
- itype = maybe_constant_value (itype, NULL_TREE, true);
+ itype = maybe_constant_value (itype, NULL_TREE, mce_true);
}
if (!TREE_CONSTANT (itype))
@@ -7390,16 +7390,14 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
IMPLICIT_CONV_EXPR_NONTYPE_ARG (expr) = true;
return expr;
}
- expr = maybe_constant_value (expr, NULL_TREE,
- /*manifestly_const_eval=*/true);
+ expr = maybe_constant_value (expr, NULL_TREE, mce_true);
expr = convert_from_reference (expr);
/* EXPR may have become value-dependent. */
val_dep_p = value_dependent_expression_p (expr);
}
else if (TYPE_PTR_OR_PTRMEM_P (type))
{
- tree folded = maybe_constant_value (expr, NULL_TREE,
- /*manifestly_const_eval=*/true);
+ tree folded = maybe_constant_value (expr, NULL_TREE, mce_true);
if (TYPE_PTR_P (type) ? integer_zerop (folded)
: null_member_pointer_value_p (folded))
expr = folded;