https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92955
Martin Sebor <msebor at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |missed-optimization Status|WAITING |NEW Component|testsuite |tree-optimization --- Comment #4 from Martin Sebor <msebor at gcc dot gnu.org> --- That does look like the same problem. I was also able to tweak the test case so that it reproduces the spurious warning even with an x86_64-linux native compiler: $ cat pr92955.c && gcc -O3 -S -Wall pr92955.c typedef struct S { unsigned char n, a[4]; } S; void f (S *s, const unsigned char *p, const unsigned char *q) { long n; for (n = 0; n < (s->n & 7); ++n); if (p + (4 - n) > q) while (p < q) s->a[n++] = *p++; } pr92955.c: In function âfâ: pr92955.c:11:17: warning: writing 1 byte into a region of size 0 [-Wstringop-overflow=] 11 | s->a[n++] = *p++; | ~~~~~~~~~~^~~~~~ pr92955.c:1:37: note: at offset [4, 11] to object âaâ with size 4 declared here 1 | typedef struct S { unsigned char n, a[4]; } S; | ^ The loop is only unrolled at -O3. The dump below shows that the last unrolled iteration accesses the member array at index 4, so it should be avoided Compiling with -fno-unroll-loops doesn't show the warning. This is very close to the problem in bug 60505 where the warning was -Warray-bounds. The two warnings detect many of the same problems but -Wstringop-overflow only detects out-of-bounds char stores and runs just a little before -Warray-bounds so it gets first dibs on diagnosing those. With the former suppressed via -Wno-stringop-overflow I would expect -Warray-bounds to trigger for this test case but it doesn't, even though the IL is the same. The false negative seems like a separate bug. ;; basic block 10, loop depth 0, count 27487790 (estimated locally), maybe hot ;; prev block 9, next block 11, flags: (NEW, REACHABLE, VISITED) ;; pred: 9 [80.0% (guessed)] count:27487790 (estimated locally) (TRUE_ VALUE,EXECUTABLE) # PT = nonlocal p_46 = p_39 + 1; # RANGE [4, 11] NONZERO 15 n_47 = n_40 + 1; <<< n_47 is out of bounds here # VUSE <.MEM_42> _48 = *p_39; # .MEM_49 = VDEF <.MEM_42> s_15(D)->aD.2902[n_40] = _48; if (q_17(D) > p_46) goto <bb 11>; [80.00%] else goto <bb 5>; [20.00%] ;; succ: 11 [80.0% (guessed)] count:21990232 (estimated locally) (TRUE _VALUE,EXECUTABLE) ;; 5 [20.0% (guessed)] count:5497558 (estimated locally) (FALSE_ VALUE,EXECUTABLE) ;; basic block 11, loop depth 0, count 21990232 (estimated locally), maybe hot ;; prev block 10, next block 12, flags: (NEW, REACHABLE, VISITED) ;; pred: 10 [80.0% (guessed)] count:21990232 (estimated locally) (TRUE _VALUE,EXECUTABLE) # PT = nonlocal p_53 = p_46 + 1; # RANGE [5, 12] NONZERO 15 n_54 = n_47 + 1; # VUSE <.MEM_49> _55 = *p_46; # .MEM_56 = VDEF <.MEM_49> s_15(D)->aD.2902[n_47] = _55; <<< n_47 is used here