I'm a bit confused because I'm not quite sure if this could be a bug in GCC. I tried building bleadperl with a recent gcc-3.4 snapshot (20031217) using ./Configure -des -Dusedevel -Duse64bitint -Dcc=gcc-3.4 -Doptimize='-g -O3' Running 'make test', test 67 of op/sprintf failed: not ok 67 >%hd< >1< >1< >104< # More extensive testing of It's easily reproducible from the command line: mhx@r2d2 perl-current-gcc-3.4 $ ./perl -e 'printf"%hd\n",1' 104 What turns the 1 into a 104 is the (short) cast case 'h': iv = (short)iv; break; in this part of sv.c (at line 9062): else { iv = SvIVx(argsv); switch (intsize) { case 'h': iv = (short)iv; break; default: break; case 'l': iv = (long)iv; break; case 'V': break; #ifdef HAS_QUAD case 'q': iv = (Quad_t)iv; break; #endif } } Adding some debug output else { iv = SvIVx(argsv); DEBUG_c(PerlIO_printf(Perl_debug_log, "+++ %"IVdf" (before)\n", iv)); switch (intsize) { case 'h': iv = (short)iv; break; default: break; case 'l': iv = (long)iv; break; case 'V': break; #ifdef HAS_QUAD case 'q': iv = (Quad_t)iv; break; #endif } DEBUG_c(PerlIO_printf(Perl_debug_log, "+++ %"IVdf" (after)\n", iv)); } gave me: mhx@r2d2 perl-current-gcc-3.4 $ ./perl -Dc -e 'printf"%hd\n",1' EXECUTING... +++ 1 (before) +++ 104 (after) 104 The following plain C program should be equivalent to the above: int main(void) { long long a = 1; printf("%lld\n", a); a = (short) a; printf("%lld\n", a); return 0; } And indeed, when compiled with 'gcc-3.4 -O3' gives me: mhx@r2d2 ~/src/c/test $ gcc-3.4 -O3 -o test test.c && ./test 1 2 Not really 104, but at least 2. But interestingly it doesn't matter which of my various gcc's I'm using. The behaviour is the same for gcc-3.2.3, gcc-3.3.2 and gcc-3.4. It also doesn't matter if I choose -O1, -O2 or -O3. Only if I choose -O0 or -g, I get the correct, expected result. This is interesting, because I don't seem to be able to get perl to fail with e.g. gcc-3.4 -O2 or gcc-3.3.2 -O3. However, the above seems to me like a bug in GCC when trying to cast long longs to shorts (or chars, which I've also checked). BTW, it works when assigning to an int variable before casting to a short: int main(void) { long long a = 1; int b; printf("%lld\n", a); b = a; a = (short) b; printf("%lld\n", a); return 0; } If this is a bug in GCC, should there be a workaround for it in perl? With the attached (very experimental and most probably incomplete) patch, I'm at least getting "All tests successful" with my gcc-3.4 configuration. Is this problem real or am I missing something here? If anyone can confirm that this is a bug, I'll enter a bug report in the GCC bugzilla. -- MarcusThread Next