aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-03-13 00:42:54 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2025-03-13 00:42:54 +0100
commitebf6e6241f5658a3cae462b1314f4a8f2bc71760 (patch)
tree94057660d5a3e4d1b184b74cca3bac9e7bc2e8b7
parent2eb3d7454ee578335b7719aadfb9e37a8456f1f1 (diff)
downloadgcc-ebf6e6241f5658a3cae462b1314f4a8f2bc71760.zip
gcc-ebf6e6241f5658a3cae462b1314f4a8f2bc71760.tar.gz
gcc-ebf6e6241f5658a3cae462b1314f4a8f2bc71760.tar.bz2
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 <jakub@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.
-rw-r--r--gcc/cp/constexpr.cc9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/consteval41.C37
2 files changed, 46 insertions, 0 deletions
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 76a9176..4820bcc 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -3077,6 +3077,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 0000000..76c4a5d
--- /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 ();
+}