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.

Reply via email to