Bug 100995 - Extend std::is_constant_evaluated in if warning
Summary: Extend std::is_constant_evaluated in if warning
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 11.0
: P3 normal
Target Milestone: ---
Assignee: Marek Polacek
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2021-06-09 15:08 UTC by Marek Polacek
Modified: 2021-06-11 02:33 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-06-09 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Marek Polacek 2021-06-09 15:08:43 UTC
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;
}
Comment 1 Jakub Jelinek 2021-06-09 16:09:25 UTC
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.
Comment 2 GCC Commits 2021-06-11 02:32:40 UTC
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.
Comment 3 Marek Polacek 2021-06-11 02:33:31 UTC
Done.