The stuff below applies to the CVS head revision as well as 3.4.*. Maybe there is a bug w.r.t. sign promotion of the results of signed/unsigned mixed multiplication from 32 to 64 bits. IMHO the result should be signed (shouldn't it?).
I'm a little bit confused w.r.t. to signed/unsigned multiplication on x86_64: Assume multiplying (signed <some integer type)-1 by (unsigned <same integer type)20 and cast that value to a larger integer. With gcc-3.4.3 as well as the CVS head revision I get the following: 1. (signed long) = (signed int) = (signed short) = (signed char) x (unsigned char) This yields proper (?) sign extension to every integer type. In hex notation: if (signed long)a = (signed char)-1 * (unsigned char)20, then a = 0xffff ffff ffff ffec 2. (signed long) = (signed int) = (signed short) x (unsigned short) Dito (with char replaced by short): if a = -1 * 20, then a = 0xffff ffff ffff ffec 3. (signed long) = (signed int) x (unsigned int) Surprisingly the sign is not promoted in this case: a = -1 * 20, then a = 0x0000 0000 ffff ffec IMHO, this is a bug. Below is a short test program which tries to execute the three scenarios. But maybe there is some thinko on my side. The output from the test program below (on my host) is: ################################################ Char : 0xffffffffffffffec | 0xffffffec | 0xffec Short: 0xffffffffffffffec | 0xffffffec Int : 0x00000000ffffffec ################################################ Best regards Claus ############################ snip #################################### #include <stdio.h> short char_mix(signed char sign, unsigned char val) { return sign * val; } int short_mix(signed short sign, unsigned short val) { return sign * val; } long int int_mix(int sign, unsigned int val) { return sign * val; } int main(int argc, const char *argv[]) { short short_res; int int_res; long int long_int_res; short_res = char_mix(-1, 20); int_res = short_mix(-1, 20); long_int_res = int_mix(-1, 20); printf("Char : 0x%016lx | 0x%08x | 0x%04x\n", (unsigned long)short_res, (unsigned int)short_res, (unsigned short)short_res); printf("Short: 0x%016lx | 0x%08x\n", (unsigned long)int_res, (unsigned int)int_res); printf("Int : 0x%016lx\n", (unsigned long)long_int_res); } ############################ snap #################################### -- Summary: signed/unsigned multiplication + sign extension broken 32->64 bit sign promotion? Product: gcc Version: 4.0.0 Status: UNCONFIRMED Severity: critical Priority: P2 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: ch at dot-heine dot de CC: gcc-bugs at gcc dot gnu dot org GCC build triplet: x86_64-unknown-linux-gnu GCC host triplet: x86_64-unknown-linux-gnu GCC target triplet: x86_64-unknown-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=20238