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