https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122083

            Bug ID: 122083
           Summary: [Regression 15/16] Bogus -Wnonnull for call to memcmp
                    with length determined using <=> operator
           Product: gcc
           Version: 15.2.1
            Status: UNCONFIRMED
          Keywords: diagnostic
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: redi at gcc dot gnu.org
            Blocks: 95507
  Target Milestone: ---

Reduced from 25_algorithms/lexicographical_compare_three_way/1.cc in the
libstdc++ testsuite, compile with -std=gnu++20 -O2 -Wall

#include <compare>

  template<typename Tp>
    constexpr auto
    min_cmp(Tp x, Tp y)
    {
      struct Res {
        Tp M_min;
        decltype(x <=> y) M_cmp;
      };
      auto c = x <=> y;
      if (c > 0)
        return Res{y, c};
      return Res{x, c};
    }


  template<typename InputIter1, typename InputIter2>
    auto
    lexicographical_compare_three_way(InputIter1 first1,
                                      InputIter1 last1,
                                      InputIter2 first2,
                                      InputIter2 last2)
    -> decltype(*first1 <=> *first2)
    {
      const auto [len, lencmp] =
        min_cmp(last1 - first1, last2 - first2);
      if (len)
      {
        const auto blen = len * sizeof(*first1);
        const auto c
          = __builtin_memcmp(&*first1, &*first2, blen) <=> 0;
        if (c != 0)
          return c;
      }
      return lencmp;
    }

auto
test03()
{
  unsigned char a[2] = { 1, 2 };
  unsigned char* p = nullptr;
  return lexicographical_compare_three_way(p, p, a, a+2);
}



In function ‘decltype (((* first1) <=> (* first2)))
lexicographical_compare_three_way(InputIter1, InputIter1, InputIter2,
InputIter2) [with InputIter1 = unsigned char*; InputIter2 = unsigned char*]’,
    inlined from ‘auto test03()’ at lexcmp.cc:44:43:
lexcmp.cc:32:29: warning: argument 1 null where non-null expected because
argument 3 is nonzero [-Wnonnull]
   32 |           = __builtin_memcmp(&*first1, &*first2, blen) <=> 0;
      |             ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
lexcmp.cc:32:29: note: in a call to built-in function ‘int
__builtin_memcmp(const void*, const void*, long unsigned int)’


The call to __builtin_memcmp only happens if min(last1 - first1, last2 -
first2) != 0 so there is no call with a null argument.


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95507
[Bug 95507] [meta-bug] bogus/missing -Wnonnull

Reply via email to