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

--- Comment #4 from Harald van Dijk <harald at gigawatt dot nl> ---
That's an interesting argument. You may well be right that the original code,
strictly speaking, does not prove that GCC has a bug, but I do think GCC has a
bug nonetheless, and have come up with a different example.

#include <stdio.h>
#include <string.h>

int x, y;

char buf[sizeof (int *)];

int main()
{
  int *p = &y;
  memcpy (buf, &p, sizeof p);
  memcpy (&p, buf, sizeof p);
  x = 2, y = 1;
  if (p == &x + 1)
    *p = 2;
  else
    y = 2;
  printf ("x = %d, y = %d\n", x, y);
  return 0;
}

Compiling with -O2, I see "x = 2, y = 1". p has been assigned &y. Whether it
compares equal to &x + 1 is unspecified, but it doesn't change its origins: p
points to y. Therefore, either the assignment to *p should change y, or in the
else branch, the plain assignment to y should change y. Either way, the correct
result is "x = 2, y = 2".

It seems like GCC is assuming that if p == &x + 1, and &x + 1 != &y, then p !=
&y, so the assignment to *p cannot change y. The flaw in that logic is again
the optimisation of &x + 1 != &y to a constant.

I see the behaviour I describe in versions 4.9.0 and 4.8.2. This program does
print "x = 2, y = 2" in my testing on GCC 4.7.3, but that is because p == &x +
1 happens to not compare as true in that version. Slightly tweaked versions of
this fail with versions 4.7.3, 4.6.4, 4.5.4 and 4.4.7, but not 4.3.6.

Reply via email to