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.