Let's extend the existing warning to detect more cases, as in http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1938r3.html#compiler-warnings constexpr int f1() { if constexpr (!std::is_constant_evaluated() && sizeof(int) == 4) { // warning: always true return 0; } if (std::is_constant_evaluated()) { return 42; } else { if constexpr (std::is_constant_evaluated()) { // warning: always true return 0; } } return 7; } consteval int f2() { if (std::is_constant_evaluated() && f1()) { // warning: always true return 42; } return 7; } int f3() { if (std::is_constant_evaluated() && f1()) { // warning: always false return 42; } return 7; }
namespace std { constexpr inline bool is_constant_evaluated () noexcept { return __builtin_is_constant_evaluated (); } } int foo () { if (std::is_constant_evaluated ()) return 1; return 0; } constexpr int bar () { if (std::is_constant_evaluated ()) return 1; if constexpr (std::is_constant_evaluated ()) return 2; return 0; } consteval int baz () { if (std::is_constant_evaluated ()) return 1; return 0; } In foo, we know it will always evaluate to false, in baz always to true. In non-constexpr functions it will not evaluate everywhere to false, so one would need to leave out e.g. initializers of static variables and the other spots which are manifestly constant evaluated. But say if conditions except for statement expressions in them and if it is not the init might be always ok and good enough for the warning.
The master branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:26dbe85a3781af913639b17bc966f4a0b8209f3b commit r12-1375-g26dbe85a3781af913639b17bc966f4a0b8209f3b Author: Marek Polacek <polacek@redhat.com> Date: Wed Jun 9 15:18:39 2021 -0400 c++: Extend std::is_constant_evaluated in if warning [PR100995] Jakub pointed me at <http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p1938r3.html#compiler-warnings> which shows that our existing warning could be extended to handle more cases. This patch implements that. A minor annoyance was handling macros, in libstdc++ we have reference operator[](size_type __pos) { __glibcxx_assert(__pos <= size()); ... } wherein __glibcxx_assert expands to if (__builtin_is_constant_evaluated() && !bool(__pos <= size()) ... but I'm of a mind to not warn on that. Once consteval if makes it in, we should tweak this warning one more time. PR c++/100995 gcc/cp/ChangeLog: * constexpr.c (maybe_constexpr_fn): New. * cp-tree.h (maybe_constexpr_fn): Declare. * semantics.c (find_std_constant_evaluated_r): New. (maybe_warn_for_constant_evaluated): New. (finish_if_stmt_cond): Call it. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/is-constant-evaluated9.C: Add dg-warning. * g++.dg/cpp2a/is-constant-evaluated12.C: New test.
Done.