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

Reply via email to