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

            Bug ID: 79352
           Summary: [6 Regression] -fprintf-return-value doesn't handle
                    flexible-like array members properly
           Product: gcc
           Version: 7.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jakub at gcc dot gnu.org
  Target Milestone: ---

Most of the optimization passes handle flexible array members and trailing
arrays in structures that could be poor man's flexible array members
conservatively, but apparently gimple-ssa-sprintf.c does not.

char buf[64];
struct S { int i; char j[1]; };

__attribute__((noinline, noclone)) void
foo (struct S *p)
{
  int a = __builtin_sprintf (buf, "a%sf", p->j);
  if (a != 6)
    __builtin_abort ();
}

int
main ()
{
  struct S *s = __builtin_malloc (sizeof (struct S) + 4);
  if (s)
    {
      s->i = 5;
      __builtin_strcpy (s->j, "bcde");
      foo (s);
      __builtin_free (s);
    }
  return 0;
}

ICEs because of that, the pass thinks that p->j must be "", while in foo it can
be arbitrary length.  If you try to print __builtin_object_size (s->j, {0,1})
before the call to foo, it prints 8 (that is sizeof (struct S) + 4 - offsetof
(struct S, s->j[0])), if you try to print __builtin_object_size (p->j, {0,1})
inside of foo, it will correctly print -1, don't know length.

Reply via email to