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

Martin Sebor <msebor at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2021-07-12
                 CC|                            |jwakely.gcc at gmail dot com,
                   |                            |msebor at gcc dot gnu.org
     Ever confirmed|0                           |1
             Blocks|                            |97048
             Status|UNCONFIRMED                 |NEW
          Component|c++                         |libstdc++

--- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> ---
The warning triggers for the memcmp_eq() call in the IL below, so it's working
as designed, and the problem is that optimization exposes invalid but likely
unreachable code:

  _77 = __builtin_memcmp_eq (_27, _86, 18446744073709551615);

The test case in attachment 51130 has the same issue:

  <bb 3> [local count: 1013569139]:
  # i_141 = PHI <i_16(12), _23(2)>
  # prephitmp_26 = PHI <pretmp_32(12), _11(2)>
  D.47043 ={v} {CLOBBER};
  MEM[(struct _Alloc_hider *)&D.47043] ={v} {CLOBBER};
  MEM[(struct _Alloc_hider *)&D.47043]._M_p = &MEM <char[16]> [(void *)&D.47043
+ 16B];
  _46 = MEM[(const struct basic_string *)s2_10(D)]._M_dataplus._M_p;
  _50 = MIN_EXPR <prephitmp_26, i_141>;
  _51 = _46 + _50;
  std::__cxx11::basic_string<char>::_M_construct.isra (&D.47043, _46, _51);
  _21 = D.47043._M_string_length;
  _22 = D.47043._M_dataplus._M_p;
  _18 = MEM[(const struct basic_string *)s1_7(D)]._M_string_length;
  _19 = MEM[(const struct basic_string *)s1_7(D)]._M_dataplus._M_p;
  if (_18 >= _21)
    goto <bb 4>; [33.00%]
  ...

   <bb 4> [local count: 334477814]:
  _130 = .SUB_OVERFLOW (_18, _21);
  _40 = REALPART_EXPR <_130>;
  _2 = IMAGPART_EXPR <_130>;
  if (_2 != 0)
    goto <bb 5>; [0.04%]
  else
    goto <bb 6>; [99.96%]

  ...
  <bb 6> [local count: 334344023]:
  if (_21 != 18446744073709551615)
    goto <bb 17>; [34.00%]
  else
    goto <bb 20>; [66.00%]
  ...
  <bb 20> [local count: 220667054]:
  _125 = _19 + _40;
  _107 = __builtin_memcmp_eq (_125, _22, 18446744073709551615);

The IL is the result of the string ends_with function passing npos to compare
as a shorthand for "the rest of the string:"

      bool
      ends_with(basic_string_view __x) const noexcept
      {
        return this->size() >= __x.size()
          && this->compare(this->size() - __x.size(), npos, __x) == 0;          
      }

Getting rid of npos also avoid the warning.  I think the following should be
equivalent:

      bool
      ends_with(basic_string_view __x) const noexcept
      {
        return this->size() >= __x.size()
          && this->compare(this->size() - __x.size(), __x.size(), __x) == 0;    
      }

Jonathan, would this (or something like it) work?


Referenced Bugs:

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97048
[Bug 97048] [meta-bug] bogus/missing -Wstringop-overread warnings

Reply via email to