https://gcc.gnu.org/bugzilla/show_bug.cgi?id=100516
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Blocks| |97048 Status|UNCONFIRMED |NEW Ever confirmed|0 |1 Last reconfirmed| |2021-05-11 Known to work| |10.3.0 Summary|Unexpected |[11 Regression] Unexpected |-Wstringop-overread in |-Wstringop-overread in |deque<char> initialization |deque<char> initialization |from empty initializer_list |from empty initializer_list Known to fail| |11.1.0, 12.0 --- Comment #3 from Martin Sebor <msebor at gcc dot gnu.org> --- Confirmed. Strictly speaking it's a GCC 11 regression introduced by a) the warning becoming stricter and considering constant addresses to be invalid (as they usually result from invalid arithmetic involving null pointers), and b) GCC 11 exposing the null pointer arithmetic. The warning in the original test case in comment #0 triggers for the IL below where _19 is set to the address 512 plus some offset: <bb 5> [local count: 955247968]: _18 = (unsigned long) _58; _67 = (unsigned long) __cur_node_17; _13 = _18 + 18446744073709551615; _40 = _13 - _67; _25 = _40 >> 3; _3 = _25 * 512; _19 = 512B + _3; <<< 512 (invalid address) _26 = D.17216.D.17192._M_impl.D.16554._M_finish._M_first; _39 = (long int) _19; _Num_28 = -_39; _Num.7_29 = (long unsigned int) _Num_28; <<< nonzero __builtin_memcpy (_26, _19, _Num.7_29); <<< -Wstringop-overread Since there can be no object at address 512 its size is determined to be zero. The warning triggers because the third argument to memcpy is determined to be nonzero (also 512 plus some offset). The bad address results from SCCP: final value replacement: _19 = PHI <_37(4)> with expr: 512B + ((((unsigned long) _58 - (unsigned long) __cur_node_17) + 18446744073709551615) / 8) * 512 final stmt: _19 = 512B + _3; based on: <bb 4> [local count: 8684072504]: # __first_2 = PHI <_37(10), 0B(9)> # __cur_node_42 = PHI <__cur_node_24(10), __cur_node_17(9)> _37 = __first_2 + 512; The underlying problem is that the loop in deque::_M_range_initialize() iterates over both the deque's nodes and the initializer list's elements, and the number of iterations has no apparent relationship to the latter. As far as GCC sees, the loop increments the null pointer to the empty initializer list by the deque's buffer size of 512. The warning could be avoided by _M_range_initialize() returning early, before entering the loop, when the range is empty. Alternatively, it could be suppressed by #pragma GCC diagnostic (that might need a patch like the one mentioned in pr98465 comment 32). Referenced Bugs: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97048 [Bug 97048] [meta-bug] bogus/missing -Wstringop-overread warnings