diff options
author | Jakub Jelinek <jakub@redhat.com> | 2025-03-13 00:42:54 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2025-03-13 00:42:54 +0100 |
commit | ebf6e6241f5658a3cae462b1314f4a8f2bc71760 (patch) | |
tree | 94057660d5a3e4d1b184b74cca3bac9e7bc2e8b7 | |
parent | 2eb3d7454ee578335b7719aadfb9e37a8456f1f1 (diff) | |
download | gcc-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.cc | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/consteval41.C | 37 |
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 (); +} |