Why does the compiler assume that these seemingly equal pointers differ?

Viewed 954

Looks like GCC with some optimization thinks two pointers from different translation units can never be same even if they are actually the same.

Code:

main.c

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

int a __attribute__((section("test")));
extern int b;

void check(int cond) { puts(cond ? "TRUE" : "FALSE"); }

int main() {
    int * p = &a + 1;
    check(
        (p == &b)
        ==
        ((uintptr_t)p == (uintptr_t)&b)
    );
    check(p == &b);
    check((uintptr_t)p == (uintptr_t)&b);
    return 0;
}

b.c

int b __attribute__((section("test")));

If I compile it with -O0, it prints

TRUE
TRUE
TRUE

But with -O1

FALSE
FALSE
TRUE

So p and &b are actually the same value, but the compiler optimized out their comparison assuming they can never be equal.

I can't figure out, which optimization made this.

It doesn't look like strict aliasing, because pointers are of one type, and -fstrict-aliasing option doesn't make this effect.

Is this the documented behavour? Or is this a bug?

5 Answers
Related