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

            Bug ID: 82177
           Summary: Alias analysis too aggressive with integer-to-pointer
                    cast
           Product: gcc
           Version: 7.2.0
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: middle-end
          Assignee: unassigned at gcc dot gnu.org
          Reporter: nunoplopes at sapo dot pt
                CC: gil.hur at sf dot snu.ac.kr, jeehoon.kang at sf dot 
snu.ac.kr,
                    regehr at cs dot utah.edu, sanjoy at playingwithpointers 
dot com
  Target Milestone: ---

The following code gets miscompiled with gcc:

#include <stdio.h>
#include <stdint.h>

void f(int*, int*);

int main()
{
  int a=0, y[1], x = 0;
  uintptr_t pi = (uintptr_t) &x;
  uintptr_t yi = (uintptr_t) (y+1);
  uintptr_t n = pi != yi;

  if (n) {
    a = 100;
    pi = yi;
  }

  if (n) {
    a = 100;
    pi = (uintptr_t) y;
  }

  *(int *)pi = 15;

  printf("a=%d x=%d\n", a, x);

  f(&x,y);

  return 0;
}


$ gcc -O2 c.c b.c -o foo

$ ./foo
a=0 x=0

This result is wrong.  The two possible outcomes are: a=0 x=15, and a=100 x=0.

The bug seems to be in the alias analysis, which is not conservative enough in
handling integer-to-pointer casts. The wrong transformation happens at this
point (dump with -fdump-tree-all):

$ cat c.c.123t.pre
yi_8 = { y }
y = { ESCAPED NONLOCAL }
pi_4 = { y } same as yi_8
pi_9 = { y } same as yi_8
pi.0_10 = { y } same as yi_8

(...)

  pi_7 = (uintptr_t) &x;
  yi_8 = (uintptr_t) &MEM[(void *)&y + 4B];
  if (pi_7 != yi_8)
    goto <bb 4>;
  else
    goto <bb 3>;

  <bb 3>:
  # a_2 = PHI <0(2), 100(4)>
  # pi_4 = PHI <yi_8(2), pi_9(4)>
  pi.0_10 = (int *) pi_4;
  *pi.0_10 = 15;
  printf ("a=%d x=%d\n", a_2, 0);   // <-- constant folded across the *pi store
                                    // because it was incorrectly proven to not
                                    // alias with x

Test case by Gil Hur.

Reply via email to