Promoting of longs to long longs gives incorrect results (i.e. sign extension is not done; upper half of result may in some cases be the upper half of a previous 64-bit computation), and does not give a warning in most cases. I have tried http://cjb.ie/32-64bug.c on the following, on various 32-bit x86 machines: gcc (GCC) 3.3.4 20040623 (Gentoo Linux 3.3.4-r1, ssp-3.3.2-2, pie-8.7.6) gcc-3.3 (GCC) 3.3.5 (Debian 1:3.3.5-8ubuntu2) gcc-3.3 (GCC) 3.3.6 (Ubuntu 1:3.3.6-8ubuntu1) gcc-4.0 (GCC) 4.0.0 20050301 (prerelease) (Debian 4.0-0pre6ubuntu7) gcc-4.0 (GCC) 4.0.2 20050808 (prerelease) (Ubuntu 4.0.1-4ubuntu9) For all of the above, and different values for -O, results seem to be invariant: $ gcc -o 32-64bug 32-64bug.c 32-64bug.c: In function ‘main’: 32-64bug.c:13: warning: left shift count >= width of type 32-64bug.c:14: warning: left shift count >= width of type $ ./32-64bug 550000000000 expected for 85LL<<40, 550000000000 obtained. 10000000000 expected for 1<<40 (const expr as printf arg), 550000000000 obtained. 10000000000 expected for 1<<40 (const expr, precomputed), 0 obtained. 5500000000000 expected for 85LL<<44, 5500000000000 obtained. 10000000000 expected for 1<<40 (variable expr, precomputed), 100 obtained. 10000000000 expected for 1<<40 (variable expr, as printf arg), 100 obtained. 55000000000000 expected for 85LL<<48, 55000000000000 obtained. 1234567800 expected for 0x12345678<<8 (const expr, as printf arg), 55000034567800 obtained. 1234567800 expected for 0x12345678<<8 (const expr, precomputed), 34567800 obtained. $ Note that a warning is only generated for the 1<<40 constant expression, and others are miscomputed with no warning. If it's not easy to get the 'expected' and 'obtained' values to match above, would it be possible to just generate a warning any time a 32-bit value is promoted to 64-bit?
Created attachment 10333 [details] Test case for 32-64 bit promotion bug Most recent version of this file available at http://cjb.ie/32-64bug.c or http://cjb.ie/32-64bug.c.txt
a=1<<b; is done in the type of b and not of type of a so this is invalid as the behavior is undefined.
Well, there's one actual issue here, namely that there is no warning about: int f() { int x = 40; return 1 << x; } even though we could of course detect this, albeit probably only in the middle-end. It might be difficult to get this warning to be emitted reliably and without false positives from there.
(In reply to comment #2) > a=1<<b; > is done in the type of b and not of type of a The type of the right operand of a shift expression has no significance at all. 1 has type int, so has 1<<b.