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;
 };
 
 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;
-- 
2.39.1.348.g5dec958dcf

Reply via email to