https://gcc.gnu.org/g:13fd7c971fb573b2f1721c3684b34a65133b7085

commit r14-11469-g13fd7c971fb573b2f1721c3684b34a65133b7085
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Thu Mar 13 00:42:54 2025 +0100

    c++: Evaluate immediate invocation call arguments with mce_true [PR119150]
    
    Since Marek's r14-4140 which moved immediate invocation evaluation
    from build_over_call to cp_fold_r, the following testcase is miscompiled.
    
    The a = foo (bar ()); case is actually handled right, that is handled
    in cp_fold_r and the whole CALL_EXPR is at that point evaluated by
    cp_fold_immediate_r with cxx_constant_value (stmt, tf_none);
    and that uses mce_true for evaluation of the argument as well as the actual
    call.
    
    But in the bool b = foo (bar ()); case we actually try to evaluate this
    as non-manifestly constant-evaluated.  And while
              /* Make sure we fold std::is_constant_evaluated to true in an
                 immediate function.  */
              if (DECL_IMMEDIATE_FUNCTION_P (fun))
                call_ctx.manifestly_const_eval = mce_true;
    ensures that if consteval and __builtin_is_constant_evaluated () is true
    inside of that call, this happens after arguments to the function
    have been already constant evaluated in cxx_bind_parameters_in_call.
    The call_ctx in that case also includes new call_ctx.call, something that
    shouldn't be used for the arguments, so the following patch just arranges
    to call cxx_bind_parameters_in_call with manifestly_constant_evaluated =
    mce_true.
    
    2025-03-13  Jakub Jelinek  <ja...@redhat.com>
    
            PR c++/119150
            * constexpr.cc (cxx_eval_call_expression): For
            DECL_IMMEDIATE_FUNCTION_P (fun) set manifestly_const_eval in new_ctx
            and new_call to mce_true and set ctx to &new_ctx.
    
            * g++.dg/cpp2a/consteval41.C: New test.
    
    (cherry picked from commit ebf6e6241f5658a3cae462b1314f4a8f2bc71760)

Diff:
---
 gcc/cp/constexpr.cc                      |  9 ++++++++
 gcc/testsuite/g++.dg/cpp2a/consteval41.C | 37 ++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index f3b61f5f391a..d3b9fe08e1a5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3030,6 +3030,15 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree 
t,
       ctx->global->put_value (new_ctx.object, ctor);
       ctx = &new_ctx;
     }
+  /* An immediate invocation is manifestly constant evaluated including the
+     arguments of the call, so use mce_true even for the argument
+     evaluation.  */
+  if (DECL_IMMEDIATE_FUNCTION_P (fun))
+    {
+      new_ctx.manifestly_const_eval = mce_true;
+      new_call.manifestly_const_eval = mce_true;
+      ctx = &new_ctx;
+    }
 
   /* We used to shortcut trivial constructor/op= here, but nowadays
      we can only get a trivial function here with -fno-elide-constructors.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/consteval41.C 
b/gcc/testsuite/g++.dg/cpp2a/consteval41.C
new file mode 100644
index 000000000000..76c4a5d2fff7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/consteval41.C
@@ -0,0 +1,37 @@
+// PR c++/119150
+// { dg-do run { target c++20 } }
+
+consteval bool
+foo (bool x)
+{
+  return x;
+}
+
+constexpr bool
+bar ()
+{
+#if __cpp_if_consteval >= 202106L
+  if consteval
+    {
+      return true;
+    }
+  else
+    {
+      return false;
+    }
+#else
+  return __builtin_is_constant_evaluated ();
+#endif
+}
+
+int
+main ()
+{
+  bool a = false;
+  a = foo (bar ());
+  if (!a)
+    __builtin_abort ();
+  bool b = foo (bar ());
+  if (!b)
+    __builtin_abort ();
+}

Reply via email to