https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106074
Bug ID: 106074 Summary: Spurious Wstringop-overflow for int-to-string with SSE4 Product: gcc Version: 13.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: ed at catmur dot uk Target Milestone: --- Code adapted from https://github.com/capnproto/capnproto/blob/be7a80b4add706ddaeb41689221146b86c3e0f5f/c%2B%2B/src/kj/string.c%2B%2B#L157-L203 : auto f(short i) { struct R { char data[6]; } result; bool negative = i < 0; unsigned u = i; if (negative) u = -u; unsigned char reverse[5]; unsigned char* p = reverse; if (u == 0) *p++ = 0; else for (; u > 0; u /= 10) *p++ = u % 10; char* p2 = result.data; if (negative) *p2++ = '-'; while (p > reverse) { #ifdef ASSUME if (p2 >= (&result.data)[1]) __builtin_unreachable(); #endif *p2++ = '0' + *--p; } if (p2 < (&result.data)[1]) *p2 = '\0'; return result; } When compiled with -O3 -msse4, from 12.1.0 through 13.0.0 20220619: <source>: In function 'auto f(short int)': <source>:21:11: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 21 | *p2++ = '0' + *--p; | ~~~~~~^~~~~~~~~~~~ <source>:2:19: note: at offset 6 into destination object 'f(short int)::R::data' of size 6 2 | struct R { char data[6]; } result; | ^~~~ <source>:2:30: note: at offset 7 into destination object 'result' of size 6 2 | struct R { char data[6]; } result; | ^~~~~~ <source>:2:19: note: at offset 6 into destination object 'f(short int)::R::data' of size 6 2 | struct R { char data[6]; } result; | ^~~~ <source>:2:19: note: at offset 6 into destination object 'f(short int)::R::data' of size 6 <source>:2:30: note: at offset 7 into destination object 'result' of size 6 2 | struct R { char data[6]; } result; | ^~~~~~ <source>:2:19: note: at offset 6 into destination object 'f(short int)::R::data' of size 6 2 | struct R { char data[6]; } result; | ^~~~ <source>:2:19: note: at offset 6 into destination object 'f(short int)::R::data' of size 6 <source>:2:30: note: at offset 7 into destination object 'result' of size 6 2 | struct R { char data[6]; } result; | ^~~~~~ <source>:2:19: note: at offset 6 into destination object 'f(short int)::R::data' of size 6 2 | struct R { char data[6]; } result; | ^~~~ <source>:2:19: note: at offset 6 into destination object 'f(short int)::R::data' of size 6 <source>:2:30: note: at offset 7 into destination object 'result' of size 6 2 | struct R { char data[6]; } result; | ^~~~~~ <source>:2:19: note: at offset 6 into destination object 'f(short int)::R::data' of size 6 2 | struct R { char data[6]; } result; | ^~~~ Adding the assumption at line 19 (-DASSUME) works around this.