I found four constant unsigned long (64bit) values which do not agree with bit shifting ~0 by an unsigned long variable holding the value 32 (demo attached): 1) shifting ~0 by 32 2) shifting ~0 by (unsigned long)32 3) shifting ~((unsigned long)0) by (unsigned long) 32 4) shifting ~((unsigned long)0) by 32
One and two are the same(0), and three and four are the same(18446744069414584320). However, letting unsigned long a=32 and mask=~0<<a results in mask being unsigned long ~0 (18446744073709551615). It seems to me at compile time gcc is computing the values 1-4 and storing them(3 and 4 are the values I'd have expected from ~0<<a). However the run time value doesn't make any sense at all to me, as if gcc is mixing 32bit and 64bit register use. I got around the bug in my production code by casting 0 to unsigned long. However, the other value just doesn't make sense with casting I can dream up. The demo computes values 1)-4) and then continuously evaluates mask=~0<<a until mask agrees with any of 1)-4). test.i: # 1 "./test.c" # 1 "/home/alex/malloc/avmalloc/bug//" # 1 "<built-in>" # 1 "<command-line>" # 1 "./test.c" int main(void) { unsigned long mask; unsigned long lower_set_bit=32; unsigned long a; unsigned long b; unsigned long c; unsigned long d; a= ~0 <<(unsigned long)32; b= ~((unsigned long)0) << (unsigned long) 32; c= ~0 << 32; d= ~((unsigned long)0) <<32; do { mask=(~(0) << lower_set_bit); } while(mask!=a && mask!=b && mask!=c && mask!=d); return 0; -- Summary: Bit shifting by a 8 byte variable isn't the same as bit shifting by an 8 or a 4 byte constant on 64bit platform. Product: gcc Version: 4.4.1 Status: UNCONFIRMED Severity: minor Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: mail dot alexhaase at gmail dot com GCC build triplet: x86_64-linux-gnu GCC host triplet: x86_64-linux-gnu GCC target triplet: x86_64-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=43755