develooper Front page | perl.perl5.porters | Postings from December 2003

GCC bug breaking Perl_sv_catpvfn()?

Thread Next
From:
Marcus Holland-Moritz
Date:
December 24, 2003 19:56
Subject:
GCC bug breaking Perl_sv_catpvfn()?
Message ID:
02b801c3ca9a$ff6661e0$5700a8c0@R2D2
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.

-- Marcus

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About