https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103176
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|WAITING |RESOLVED Resolution|--- |WONTFIX --- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> --- Thanks for the test case. The warning is based on the IL below. In basic block 16 the result of operator new is assigned to _134, and in basic block 19 the code stores zero at an negative offset from _134. So the warning is doing its job here: the invalid statement exists in the emitted program, it just may be unreachable and GCC can't prove that. <bb 16> [local count: 19040066]: _82 = len_49 - lastpos.2_4; length_83 = (int) _82; o ={v} {CLOBBER}; _134 = operator new (1); >>> _134 goto <bb 18>; [100.00%] ... <bb 18> [local count: 19040066]: MEM[(char *)_134] = 0; _85 = length_83 + 1; _86 = (unsigned int) _85; if (_86 == 0) goto <bb 19>; [80.71%] else goto <bb 20>; [19.29%] <bb 19> [local count: 25513689]: MEM[(char *)_134 + -1B] = 0; <<< -Wstringop-overflow goto <bb 26>; [100.00%] The cause of the warning is in the subString() function where it can't prove that the length argument won't become negative: string<T> subString(unsigned begin, int length) const { // if start after string // or no proper substring length if ((length <= 0) || (begin>=size())) return string<T>{ "" }; // clamp length to maximal value if ((length+begin) > size()) length = size()-begin; <<< length not proven to become -1 string<T> o; o.reserve(length+1); for (int i=0; i<length; ++i) o.array[i] = array[i+begin]; o.array[length] = 0; <<< store to o.array[-1] emitted o.used = length + 1; return o; } Adding the following just before the definition of the string o prevents the warning. Another alternative is to make both length and the loop control variable unsigned (making variables that represent sizes unsigned and keeping them that is a good practice since it communicates that constraint to the compiler). if (length < 0) __builtin_unreachable (); In general, unless the compiler can prove that some expression won't reach a value that's invalid in some context, it can substitute the value for it in the process of optimizing surrounding code, which can then lead to the invalid code materializing even if it's not actually in the original source and even if the emitted invalid object code isn't reachable. GCC warnings that are designed to look for this invalid code then trigger on it. Resolving these warnings can often help GCC generate better object code (the __builtin_unreachable() trick isn't necessarily always the best way; it's only appropriate if the precondition is in the source and GCC loses track of it). Long story short, there is nothing for us to do to.