On 12/12/18 5:30 PM, Jakub Jelinek wrote:
Hi!

The following patch fixes __builtin_is_constant_evaluated and
__builtin_constant_p handling during static_assert evaluation.
finish_static_assert calls fold_non_dependent_expr and complains if the
result is not a constant expression, instead of requiring a constant
expression, which causes __builtin_is_constant_evaluated () during the
evaluation to be not considered as constant expression and
__builtin_constant_p calls too if they appear in constexpr functions.

The patch makes sure that manifestly_const_eval is true while evaluating
the expression and also makes sure to fold __builtin_constant_p when that is
true even when in constexpr functions.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2018-12-12  Jakub Jelinek  <ja...@redhat.com>

        PR c++/86524
        PR c++/88446
        * cp-tree.h (fold_non_dependent_expr): Add manifestly_const_eval
        argument.
        * constexpr.c (cxx_eval_builtin_function_call): Evaluate
        __builtin_constant_p if ctx->manifestly_const_eval even in constexpr
        functions.  For arguments to builtins, if ctx->manifestly_const_eval
        try to first evaluate arguments with it, but if that doesn't result
        in a constant expression, retry without it.  Fix comment typo.
        (fold_non_dependent_expr): Add manifestly_const_eval argument, pass
        it through to cxx_eval_outermost_constant_expr and
        maybe_constant_value.
        * semantics.c (finish_static_assert): Call fold_non_dependent_expr
        with true as manifestly_const_eval.

        * g++.dg/cpp1y/constexpr-86524.C: New test.
        * g++.dg/cpp2a/is-constant-evaluated4.C: New test.
        * g++.dg/cpp2a/is-constant-evaluated5.C: New test.
        * g++.dg/cpp2a/is-constant-evaluated6.C: New test.

--- gcc/cp/cp-tree.h.jj 2018-12-12 09:32:27.408535853 +0100
+++ gcc/cp/cp-tree.h    2018-12-12 11:07:24.250459779 +0100
@@ -7665,7 +7665,9 @@ extern tree cxx_constant_value                    (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_init                       (tree, tree = 
NULL_TREE, bool = false);
-extern tree fold_non_dependent_expr            (tree, tsubst_flags_t = 
tf_warning_or_error);
+extern tree fold_non_dependent_expr            (tree,
+                                                tsubst_flags_t = 
tf_warning_or_error,
+                                                bool = false);
  extern tree fold_simple                               (tree);
  extern bool is_sub_constant_expr                (tree);
  extern bool reduced_constant_expression_p       (tree);
--- gcc/cp/constexpr.c.jj       2018-12-12 09:34:17.531736075 +0100
+++ gcc/cp/constexpr.c  2018-12-12 11:30:33.986756914 +0100
@@ -1198,6 +1198,7 @@ cxx_eval_builtin_function_call (const co
       in a constexpr function until we have values for the parameters.  */
    if (bi_const_p
        && ctx->quiet
+      && !ctx->manifestly_const_eval

I think we want to replace the "quiet" check with manifestly_const_eval, rather than adding to it.

@@ -1222,7 +1223,6 @@ cxx_eval_builtin_function_call (const co
       return constant false for a non-constant argument.  */
    constexpr_ctx new_ctx = *ctx;
    new_ctx.quiet = true;
-  bool dummy1 = false, dummy2 = false;
    for (i = 0; i < nargs; ++i)
      {
        args[i] = CALL_EXPR_ARG (t, i);
@@ -1231,10 +1231,23 @@ cxx_eval_builtin_function_call (const co
         of the builtin, verify it here.  */
        if (!builtin_valid_in_constant_expr_p (fun)
          || potential_constant_expression (args[i]))
-       args[i] = cxx_eval_constant_expression (&new_ctx, args[i], false,
-                                               &dummy1, &dummy2);
+       {
+         bool non_cst_p = false, ovf_p = false;
+         tree a = cxx_eval_constant_expression (&new_ctx, args[i], false,
+                                                &non_cst_p, &ovf_p);
+         if ((non_cst_p || ovf_p) && ctx->manifestly_const_eval)
+           {
+             new_ctx.manifestly_const_eval = false;
+             non_cst_p = false;
+             ovf_p = false;
+             a = cxx_eval_constant_expression (&new_ctx, args[i], false,
+                                               &non_cst_p, &ovf_p);
+             new_ctx.manifestly_const_eval = true;
+           }

Why retry without manifestly_const_eval? For static initialization we don't want to try constant evaluation again with __builtin_is_constant_evaluated false if it failed with it true.

Jason

Reply via email to