[Bug c/105689] New: Bogus `-Wstringop-overflow=` after accessing field, then containing struct (wrong "region size")
sagebar at web dot de
gcc-bugzilla@gcc.gnu.org
Sun May 22 11:30:51 GMT 2022
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105689
Bug ID: 105689
Summary: Bogus `-Wstringop-overflow=` after accessing field,
then containing struct (wrong "region size")
Product: gcc
Version: 12.1.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: sagebar at web dot de
Target Milestone: ---
The following code wrongly produces a warning `[-Wstringop-overflow=`:
Compile (using `gcc -c -O2 infile.c`)
```
struct subobject {
int field1;
int field2;
};
struct myobject {
struct subobject sub;
};
extern void access_1(int *a);
extern __attribute__((access(read_write, 1))) void access_2(struct subobject
*);
void myfunc(struct myobject *me) {
// { void *p __attribute__((unused)) = &me->sub; }
access_1(&me->sub.field1);
access_2(&me->sub);
}
```
======= Output (gcc-12) =======
>infile.c: In function 'myfunc':
>infile.c:16:9: warning: 'access_2' accessing 8 bytes in a region of size 4 [-Wstringop-overflow=]
> 16 | access_2(&me->sub);
> | ^~~~~~~~~~~~~~~~~~
>infile.c:11:52: note: in a call to function 'access_2' declared with attribute 'access (read_write, 1)'
> 11 | extern __attribute__((access(read_write, 1))) void access_2(struct subobject *);
> | ^~~~~~~~
======= Output (expected) =======
><No warning>
======= Notes =======
- By uncommenting the line `{ void *p __attribute__((unused)) = &me->sub; }`,
the warning goes away, even though that line literally does nothing. (see
Theory below)
- I was able to observe this bug in gcc-12.1.0 and gcc-11.2.0
======= Theory =======
It seems that this has got something to do with some internal, hidden attribute
(relating to the "region size") attached to some field-expression the first
time that field is accessed, only that when accessing `me->sub.field1` (where
`offsetof(field1) == 0`) before `me->sub`, that "region size" attribute
wrongfully also gets attached to `me->sub`. Then, when an access to `me->sub`
actually happens, gcc seems to think that the "region size" of `me->sub` as a
whole matches the size of the previously accessed field (`me->sub.field1`).
This seems further compounded by the fact that this only happens when `field1`
is the first field of `subobject` (i.e. has offset 0). If we insert another
field `int field0;` before it, the warning also disappears (so something in
gcc's logic appears to make it think that `region_size_of(<field-at-offset-0>)
== region_size_of(<containing-struct>)`)
More information about the Gcc-bugs
mailing list