Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses

Re: Why does $Config{ccflags} include "-fwrapv" on many gcc builds of perl ?

by dave_the_m (Monsignor)
on Apr 19, 2021 at 06:31 UTC ( [id://11131458] : note . print w/replies, xml ) Need Help??

in reply to Why does $Config{ccflags} include "-fwrapv" on many gcc builds of perl ?

It was to fix this issue. I haven't read the ticket closely so can't otherwise comment.


Replies are listed 'Best First'.
Re^2: Why does $Config{ccflags} include "-fwrapv" on many gcc builds of perl ?
by syphilis (Archbishop) on Apr 19, 2021 at 12:52 UTC
    It was to fix this issue.

    Thanks Dave.
    I haven't managed to prove that the inclusion of -fwrapv achieves anything wrt perl, but there are some well credentialed perl developers saying that it does (or, at least, that it once did).
    I'm not about to start arguing the point with them.
    I guess, that if its inclusion does something useful then that's well and good. And if it doesn't do anything useful then it's harmless, anyway.

    Interesting that the -SvIVX(sv) is still present in sv.c, because I think it's still undefined behaviour when SvIVX(sv) is IV_MIN (aka LONG_MIN), even if -fwrapv is somehow masking it when perl is involved.
    UPDATE: The above sentence was incorrect. On reading the code properly (which involved minimal widening of my field of vision), I realize that -SvIVX(sv) is never reached if SvIVX(sv) is IV_MIN.

    I haven't yet found any evidence that, in C, that switch ever alters anything.
    $ cat LONG_MIN.c #include <stdio.h> #include <limits.h> int main(void) { printf("%ld %ld\n", LONG_MIN, -LONG_MIN); return 0; } $ gcc -o LONG_MIN LONG_MIN.c LONG_MIN.c: In function ‘main’: LONG_MIN.c:6:33: warning: integer overflow in expression ‘-92233720368 +54775808’ of type ‘long int’ results in ‘-9223372036854775808’ [-Wove +rflow] 6 | printf("%ld %ld\n", LONG_MIN, -LONG_MIN); | ^ $ ./LONG_MIN -9223372036854775808 -9223372036854775808
    The compilation warning relates only to "-LONG_MIN".
    It's exactly the same (in every respect) when I compile using the -fwrapv switch, and -ftrapv catches nothing.


      -fwrapv gives implementation defined behaviour for wrapping variables but not constants.

      #include <limits.h> #include <stdio.h> int main() { printf(" LONG_MIN %ld\n", LONG_MIN); printf(" LONG_MAX %ld\n", LONG_MAX); printf("-LONG_MAX %ld\n", -LONG_MIN); // line 9 long lval = LONG_MIN; lval = lval * -1; // this is okay with -fwrapv printf("wrap lval %ld\n", lval); }
      $ gcc -Wall -Wextra -Woverflow -fwrapv -fsanitize=undefined t.c -o t & +& ./t t.c: In function ‘main’: t.c:9:31: warning: integer overflow in expression ‘-922337203685477580 +8’ of type ‘long int’ results in ‘-9223372036854775808’ [-Woverflow] 9 | printf("-LONG_MAX %ld\n", -LONG_MIN); // line 9 | ^ LONG_MIN -9223372036854775808 LONG_MAX 9223372036854775807 -LONG_MAX -9223372036854775808 wrap lval 9223372036854775807

      I see that the patch fixes it by changing to unsigned int so it seems the wrapping is irrelevant there.

        I've since noticed that -fwrapv is omitted from CCFLAGS when I build perl on Windows using gcc-10.2.0. So I created an issue about that, wherein I again queried the need for the -fwrapv switch. In that thread, Tomasz Konojacki (@xenu) explains it clearly:

        -fwrapv basically means "signed integer overflow won't cause undefined behavior".
        In practice, gcc with this flag disabled will still wrap signed integers on overflow, because that's how virtually all CPUs implement signed integer arithmetic.
        However, what does change is the behavior of the optimizer: it will assume that all signed integers will never overflow.
        Because of that, the breakage caused by omission of this flag is very subtle and unpredictable, and there's no reasonable way to test for it.

        That makes good sense to me, and I also provided a patch to win32/GNUmakefile that fixes that issue with gcc-10.x.x and (presumably) later.

      In the past I've noted a lot of change for the sake of change. Not to say it is the case here, but that is the case nonetheless in bleed.
        In the past I've noted a lot of change for the sake of change. Not to say it is the case here, ...

        Yes, I don't think it's the case here.
        There's good evidence that this change was deemed necessary.

        However, I've just built perl-5.33.8 on Windows, without -fwrapv, and all tests passed.
        This was using gcc-10.3.0. Maybe Windows was never affected, or maybe something has changed with gcc-10.3.0.
        I'll test more extensively with perl-5.33.9 when it comes out (either later today or tomorrow), and add a report to if I can't find any need for -fwrapv
        C:\comp-1020\perl-5.33.9\win32>..\perl -I..\lib -V:archname archname='MSWin32-x64-multi-thread'; C:\comp-1020\perl-5.33.9\win32>..\perl -I..\lib -V:d_nv_preserves_uv d_nv_preserves_uv='undef'; C:\comp-1020\perl-5.33.9\win32>..\perl -I..\lib -V:nv_preserves_uv_bit +s nv_preserves_uv_bits='53'; C:\comp-1020\perl-5.33.9\win32>..\perl -I..\lib -V:ccflags ccflags=' -DWIN32 -DWIN64 -fdiagnostics-color=never -DPERL_TEXTMODE_SC +RIPTS -DPERL_IMPLICIT_CONTEXT -DPERL_IMPLICIT_SYS -DUSE_PERLIO -D__USE_MINGW_ANSI_STDIO -fno-strict +-aliasing -mms-bitfields'; C:\comp-1020\perl-5.33.9\win32>..\perl -I..\lib -le "print $];" 5.033008