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