https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77301
Bug ID: 77301 Summary: __builtin_object_size incorrect for an array in a struct referenced by a pointer Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: msebor at gcc dot gnu.org Target Milestone: --- The Object Size Checking page of the manual describes the type argument to the __builtin_object_size intrinsic like so: type is an integer constant from 0 to 3. If the least significant bit is clear, objects are whole variables, if it is set, a closest surrounding subobject is considered the object a pointer points to. Based on this I would expect the output of the program below to be 4 8 4 8 4 8 4 8 The first line of the expected output above is for a known single object of struct A, so in __builtin_object_size (a.a, 0), the object referenced by a.a is a "whole variable" whose size is 4. In __builtin_object_size (a.a, 1), the "closest surrounding subobject" of a.a is , whose size is 8. The actual results on this line are exactly the opposite. The second line of the expected output above is for an "unknown" object of struct A (or an element of an array of such objects). As above, in __builtin_object_size (p->a, 0), p->a also refers to the "whole" member a of the struct, and a's size is 4. Similarly, in __builtin_object_size (p->a, 1) the result should be the size of the "closest surrounding subobject" of p->a, or the object that p points to. That's clearly an object of struct A whose size is 8. Instead, the results are even more confounding than in the first case. Even if the object pointed to by p were considered to be an array of some unknown number of structs A, the expected result would then be 4 -1 4 0, but certainly not -1 4 0 4. $ cat z.c && /build/gcc-trunk-svn/gcc/xgcc -B /build/gcc-trunk-svn/gcc -O2 -Wall -Wextra z.c && ./a.out struct A { char a [4]; int i; } a; void __attribute__ ((noclone, noinline)) f (struct A *p) { __builtin_printf ("%zi %zi %zi %zi\n", __builtin_object_size (a.a, 0), __builtin_object_size (a.a, 1), __builtin_object_size (a.a, 2), __builtin_object_size (a.a, 3)); __builtin_printf ("%zi %zi %zi %zi\n", __builtin_object_size (p->a, 0), __builtin_object_size (p->a, 1), __builtin_object_size (p->a, 2), __builtin_object_size (p->a, 3)); } int main (void) { f (&a); } 8 4 8 4 -1 4 0 4