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