Running gcc-4.3 -O2 on PR1386.c I get different results than with -O1. $ gcc-4.3 -O2 PR1386.c && ./a.out PR1386.c: In function ‘main’: PR1386.c:15: warning: large integer implicitly truncated to unsigned type PR1386.c:17: warning: large integer implicitly truncated to unsigned type bad bits: fffffffffffffff0 $ gcc-4.3 -O2 PR1386.c && ./a.out PR1386.c: In function ‘main’: PR1386.c:15: warning: large integer implicitly truncated to unsigned type PR1386.c:17: warning: large integer implicitly truncated to unsigned type bad bits: fffffffffffffff0 gcc-4.2 is fine: $ gcc-4.2 -O2 PR1386.c && ./a.out PR1386.c: In function ‘main’: PR1386.c:15: warning: large integer implicitly truncated to unsigned type PR1386.c:17: warning: large integer implicitly truncated to unsigned type bad bits: 0 $ gcc-4.2 -O3 PR1386.c && ./a.out PR1386.c: In function ‘main’: PR1386.c:15: warning: large integer implicitly truncated to unsigned type PR1386.c:17: warning: large integer implicitly truncated to unsigned type bad bits: 0 The file is from an LLVM testcase http://llvm.org/bugs/show_bug.cgi?id=1386 #include <stdio.h> #include <stdint.h> struct X { unsigned char pad : 4; uint64_t a : 64; uint64_t b : 60; } __attribute__((packed)); int main (void) { struct X x; uint64_t bad_bits; x.pad = 255; x.a = -1ULL; x.b = -1ULL; bad_bits = ((uint64_t)-1ULL) ^ *(1+(uint64_t *) &x); printf("bad bits: %llx\n", bad_bits); return bad_bits != 0; }
(In reply to comment #0) > Running gcc-4.3 -O2 on PR1386.c I get different results than with -O1. > > $ gcc-4.3 -O2 PR1386.c && ./a.out > PR1386.c: In function ‘main’: > PR1386.c:15: warning: large integer implicitly truncated to unsigned type > PR1386.c:17: warning: large integer implicitly truncated to unsigned type > bad bits: fffffffffffffff0 $ gcc-4.3 -O1 PR1386.c && ./a.out PR1386.c: In function ‘main’: PR1386.c:15: warning: large integer implicitly truncated to unsigned type PR1386.c:17: warning: large integer implicitly truncated to unsigned type bad bits: 0
You invoke undefined behavior by accessing parts of a and b via *(1+(uint64_t *) &x). This access is not valid because of C aliasing rules.
Does it work with -fno-strict-aliasing?
(In reply to comment #3) > Does it work with -fno-strict-aliasing? > It doesn't. edwin@debian:~$ g++ -O2 -fno-strict-aliasing x.c x.c: In function ‘int main()’: x.c:15: warning: large integer implicitly truncated to unsigned type x.c:17: warning: large integer implicitly truncated to unsigned type edwin@debian:~$ ./a.out bad bits: fffffffffffffff0
Please clone/reopen this bug, it should work with -fno-strict-aliasing.