diff mbox series

[1/2] c++: make manifestly_const_eval tri-state

Message ID 20230127220250.1896137-1-ppalka@redhat.com
State New
Headers show
Series [1/2] c++: make manifestly_const_eval tri-state | expand

Commit Message

Patrick Palka Jan. 27, 2023, 10:02 p.m. UTC
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

Jason Merrill Jan. 30, 2023, 8:02 p.m. UTC | #1
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;
Patrick Palka Feb. 3, 2023, 9:21 p.m. UTC | #2
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;
diff mbox series

Patch

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;
 };
 
 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.  */
+
+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,
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;