https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127377
liu zhenyu <lzy20000419 at outlook dot com> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |lzy20000419 at outlook dot com
--- Comment #10 from liu zhenyu <lzy20000419 at outlook dot com> ---
The r17-4215 fix looks incomplete. This still fails on trunk (17.0.0 20261029)
at -O1 and -O2. 14.2, 15.2 and 16.2 are fine.
```c
struct A { unsigned long long lo : 32, y : 19, rest : 13; };
struct BF { unsigned long long x0:4, x1:8, x2:31, x3:3, x4:4, x5:14; };
union U { unsigned char b[8]; struct A a; struct BF bf; };
__attribute__((noipa)) unsigned f(union U *p, unsigned v) {
p->b[6] = 209;
p->a.y = v;
p->b[5] = 39;
return p->bf.x4;
}
int main(void) {
static union U x;
unsigned r = f(&x, 0x30000);
if (r != 12) __builtin_abort();
return 0;
}
```
$ gcc -O1 t.c && ./a.out
Aborted (f is folded to "return 4")
-O0 and -fno-tree-fre are fine.
In push_partial_def, the start is rounded down to a byte, which leaves head
padding h = offseti - pd.offset. The new size, maxsizei + (tail % 8), does not
include h. Here the load is bits 46..49 and the store to a.y is 32..50 (h = 6,
tail = 1), so it is pruned to [40,45) instead of [40,51) and dropped as
shadowed by b[5]. Maybe something like pd.size = (offseti + maxsizei -
pd.offset) + tail % 8 (not tested). The gcc-16 backport (r16-9671) has the same
code.
Disclaimer: This test case was generated by a fuzzer, and the report was
written with LLM assistance.