https://gcc.gnu.org/bugzilla/show_bug.cgi?id=89689
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |diagnostic Status|UNCONFIRMED |NEW Last reconfirmed| |2019-03-12 CC| |msebor at gcc dot gnu.org Component|c |tree-optimization Ever confirmed|0 |1 Known to fail| |8.3.0, 9.0 --- Comment #1 from Martin Sebor <msebor at gcc dot gnu.org> --- Confirmed. The warning is an unfortunate side-effect of an optimization triggered by the 'if (c->data != __sb_slop)' test in the set0 function. It introduces a call to memcpy with __sb_slop as the destination. The intermediate representation of the code can be seen in the VRP dump with the smaller test case below. We're discussing ways to prevent this in the future but the only way to avoid it for now that I can think of other than the #pragma(*) is to either assert(**) h.data != __sb_slop just before calling memcpy, or "hide" the conditional so it's not visible when compiling the function that calls memcpy (e.g., by preventing set0 from being inlined via attribute noinline), disable the warning for this code, or disable _FORTIFY_SOURCE for this function by calling __builtin_memcpy directly. [*] It's worth mentioning that #pragma GCC diagnostic doesn't work very well for these late warnings when inlining is involved. [**] An assert that would work without any cost is "if (h.data == __sb_slop) __builtin_unreachable ();" $ cat a.c && gcc -O2 -S -Wall -fdump-tree-vrp1=/dev/stdout a.c char __sb_slop[1], buf[5]; void f (char *p) { if (p != __sb_slop) p[0] = 0; __builtin___memcpy_chk (p, "abcd", 4, __builtin_object_size (p, 0)); if (p != __sb_slop) p[0] = 0; } ... f (char * p) { long unsigned int _15; long unsigned int _18; <bb 2> [local count: 1073741824]: if (p_4(D) != &__sb_slop) goto <bb 3>; [70.00%] else goto <bb 5>; [30.00%] ;; p_4(D) == &__sb_slop <bb 3> [local count: 751619278]: *p_4(D) = 0; _15 = __builtin_object_size (p_4(D), 0); __builtin_memcpy (p_4(D), "abcd", 4); *p_4(D) = 0; <bb 4> [local count: 1073741824]: return; <bb 5> [local count: 322122544]: _18 = __builtin_object_size (p_4(D), 0); __builtin_memcpy (p_4(D), "abcd", 4); ;; p_4(D) == &__sb_slop goto <bb 4>; [100.00%] } a.c: In function ‘f’: a.c:8:3: warning: ‘__builtin_memcpy’ forming offset [2, 4] is out of the bounds [0, 1] of object ‘__sb_slop’ with type ‘char[1]’ [-Warray-bounds] 8 | __builtin___memcpy_chk (p, "abcd", 4, __builtin_object_size (p, 0)); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ a.c:1:6: note: ‘__sb_slop’ declared here 1 | char __sb_slop[1], buf[5]; | ^~~~~~~~~