https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61502
--- Comment #18 from Alexander Cherepanov <ch3root at openwall dot com> --- A bit simplified variant: #include <stdio.h> int main() { int x, y = 1; int *volatile v; int *p; v = &y; p = v; if (p == &x + 1) { *p = 2; printf("y = %d\n", y); } } 077t.alias dump shows such "Points-to sets" (among others): v = { y } p_5 = { y } same as v and then the code: <bb 3>: *p_5 = 2; y.0_7 = y; printf ("y = %d\n", y.0_7); Seems right. 081t.vrp1 dump shows such "Value ranges after VRP": p_11: [&MEM[(void *)&x + 4B], &MEM[(void *)&x + 4B]] EQUIVALENCES: { p_5 } (1 elements) and the code: <bb 3>: MEM[(int *)&x + 4B] = 2; y.0_7 = y; printf ("y = %d\n", y.0_7); Seems wrong. gcc 5.2.0 On 2015-11-16 01:30, ch3root at openwall dot com wrote: > I guess it depends on the transitivity of the == operator. After this bug is > fixed it will be possible to constuct a third pointer r from two pointer p and > q such that r == p and r == q but p != q. For p and q take &x + 1 and &y as > above, obtain r by stripping provenance info from p or q (e.g. by printf/scanf > with %p). This bug turned out to be not that tricky after all. The program: #include <stdio.h> int main() { int x, y; void *p = &x + 1, *q = &y, *r; /* Strip p of provenance info */ /* To simplify testing: */ char s[100]; sprintf(s, "%p", p); sscanf(s, "%p", &r); /* Instead, imagine this: printf("%p or %p? ", p, q); scanf("%p", &r); */ char *eq[] = {"!=", "=="}; printf("r %s p, r %s q, p %s q\n", eq[r == p], eq[r == q], eq[p == q]); } prints "r == p, r == q, p != q" and the first two equalities are essentially mandated by C11 (unless you patch it by making one of them UB).