[PATCH] adjust object size computation for union accesses and PHIs (PR 92765)

Jakub Jelinek jakub@redhat.com
Thu Jan 16 13:26:00 GMT 2020


On Wed, Jan 15, 2020 at 09:52:57PM +0100, Jakub Jelinek wrote:
> This looks wrong.  For one, this function is used for two purposes now and
> you tweak it for one, but more importantly, whether he initial stmt
> you see is a PHI or not can't make a difference, how is that case e.g.
> different from _1 = PHI <_3, _4>; _2 = _1 + 1; and asking about _2?
> For _1, you'd use (correctly) the maximum, but if called on _2, you'd ask
> (wrongly) for minimum instead of maximum.

And now with testcases.  strlenopt-95.c shows the above.

> This also looks like a hack to shut up the particular testcases instead of
> really playing with what the IL provides.  Instead of the unions, consider
> e.g. C++ placement new, have a pointer to a buffer into which you placement
> new one structure, take address of some member in it, pass it to something,
> if it doesn't have a destructor do a C++ placement new into the same buffer
> but with different structure, take address of a different member with the
> same address as the first member, do the str*cmp on it that invokes this
> stuff.  SCCVN will (likely) find out that the values of those two pointers
> are the same and just use the former pointer in the latter case.

And strlenopt-93.C shows the latter.  strlenopt-94.C is similar, just to
show that it breaks equally badly with non-PODs that will be constructed by
placement new and destructed later.

	Jakub
-------------- next part --------------
__attribute__((noipa)) int
barrier_copy (char *x, int y)
{
  asm volatile ("" : : "g" (x), "g" (y) : "memory");
  if (y == 0)
    __builtin_strcpy (x, "abcd");
  return y;
}

__attribute__((noipa)) char *
test_2 (int x)
{
  char *p;
  if (x)
    p = __builtin_malloc (4);
  else
    p = __builtin_calloc (16, 1);
  char *q = p + 2;
  if (barrier_copy (q, x))
    return p;
  if (__builtin_strcmp (q, "abcd") != 0)
    __builtin_abort ();
  return p;
}

int
main ()
{
  __builtin_free (test_2 (0));
  __builtin_free (test_2 (1));
  return 0;
}
-------------- next part --------------
#include <new>

struct S1 { char a[2]; char b[2]; char c[2]; };
struct S2 { char d[6]; };

__attribute__((noipa)) void
foo (char *b)
{
  b[0] = 1;
  b[1] = 2;
  asm volatile ("" : : "g" (b) : "memory");
}

__attribute__((noipa)) void
bar (char *d)
{
  __builtin_memcpy (d, "cde", 4);
  asm volatile ("" : : "g" (d) : "memory");
}

__attribute__((noipa)) void
baz (char *buf)
{
  S1 *s1 = new (buf) S1;
  char *p = (char *) &s1->b;
  foo (p);
  S2 *s2 = new (buf) S2;
  char *q = (char *) &s2->d[2];
  bar (q);
  if (__builtin_strcmp (q, "cde"))
    __builtin_abort ();
}

int
main ()
{
  union U { S1 s1; S2 s2; char buf[sizeof (S1) > sizeof (S2) ? sizeof (S1) : sizeof (S2)]; } u;
  baz (u.buf);
  return 0;
}
-------------- next part --------------
#include <new>

struct S1 { char a[2]; char b[2]; char c[2]; S1 () { a[0] = 0; b[0] = 0; c[0] = 0; }; ~S1 () {} };
struct S2 { char d[6]; S2 () { d[0] = 0; d[2] = 0; } ~S2 () {} };

__attribute__((noipa)) void
foo (char *b)
{
  b[0] = 1;
  b[1] = 2;
  asm volatile ("" : : "g" (b) : "memory");
}

__attribute__((noipa)) void
bar (char *d)
{
  __builtin_memcpy (d, "cde", 4);
  asm volatile ("" : : "g" (d) : "memory");
}

__attribute__((noipa)) void
baz (char *buf)
{
  S1 *s1 = new (buf) S1 ();
  char *p = (char *) &s1->b;
  foo (p);
  s1->~S1 ();
  S2 *s2 = new (buf) S2 ();
  char *q = (char *) &s2->d[2];
  bar (q);
  if (__builtin_strcmp (q, "cde"))
    __builtin_abort ();
  s2->~S2 ();
}

int
main ()
{
  char buf[sizeof (S1) > sizeof (S2) ? sizeof (S1) : sizeof (S2)];
  baz (buf);
  return 0;
}


More information about the Gcc-patches mailing list