https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127333

--- Comment #1 from JingYao Zhang <220245569 at seu dot edu.cn> ---
Gentle ping on this issue (and thank you @rguenth for tagging `wrong-code`). To
make this easier to inspect without downloading the attachment, here is a
minimal inline reproducer and the exact root cause in
`gcc/tree-object-size.cc`:

### Minimal Inline Reproducer

```c
struct S {
    long n;
    char a[] __attribute__((counted_by(n)));
};

unsigned long get_size(struct S *p) {
    return __builtin_dynamic_object_size(p->a, 1);
}
```

Compiled with `gcc -O2 -fdump-tree-objsz1=- -S` on `x86_64-linux-gnu` (verified
on GCC 15.2, 16.2, and 17 trunk):
- In the `objsz1` dump, the negative-count clamp is emitted in 32-bit `int`:
  ```c
  _1 = p_2(D)->n;
  _3 = (int) _1;
  _4 = MAX_EXPR <_3, 0>;
  _5 = (sizetype) _4;
  ```
- Consequently, when `p->n` is a valid 64-bit count such as `0x80000000L` (2
GiB), `(int) _1` truncates it to `INT_MIN` (`-2147483648`), which `MAX_EXPR
<_3, 0>` clamps to `0` (or sign-extends depending on folding); when `p->n ==
0x100000000L` (4 GiB), `(int) _1` truncates it to `0`.

### Root Cause & Proposed Fix in `gcc/tree-object-size.cc`

In `access_with_size_object_size` (`gcc/tree-object-size.cc`), when
`TYPE_SIGNED (TREE_TYPE (ref))` is true, the `MAX_EXPR` clamp against zero
converts `ref` and the zero constant to `integer_type_node` (32-bit `int`)
instead of preserving `TREE_TYPE (ref)` (the declared type of the `counted_by`
member, such as `long` or `ssize_t`). Building the `MAX_EXPR` clamp in
`TREE_TYPE (ref)` before converting to `sizetype` preserves the full 64-bit
signed width.

Reply via email to