Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Possible precedence problem between ! and numeric eq (==)" failure in automake #22954

Closed
IgorTodorovskiIBM opened this issue Jan 29, 2025 · 24 comments · Fixed by #22965
Closed

Comments

@IgorTodorovskiIBM
Copy link

IgorTodorovskiIBM commented Jan 29, 2025

Module:

Description

When using Perl 5.41.7 or Perl 5.41.8, we are seeing this error message appear when running automake (written in perl).
Perl 5.41.3 did not have this problem.

Possible precedence problem between ! and numeric eq (==) at /data/zopen/usr/local/zopen/automake/automake-1.17.20241029_040611.zos/bin/automake line 6875.

Is this expected? It's preventing us from building autotools based projects.

Here's the reduced snippet of what automake is doing:

# test.pl
use strict;
use warnings;

sub transform_token {
    my ($token, $transform_ref, $key) = @_;
    return exists $transform_ref->{$key} ? $transform_ref->{$key} : '';
}

sub transform {
    my ($token, $transform) = @_;

    if ($token =~ /^%([\w\-]+)%$/) {
        return transform_token($token, $transform, $1);
    }
    elsif ($token =~ /^%\?([\w\-]+)%$/) {
        return transform_token($token, $transform, $1) ? 'TRUE' : 'FALSE';
    }
    elsif ($token =~ /^ \? (!?) ([\w\-]+) \? $/x) {
        my $neg = ($1 eq '!') ? 1 : 0;
        my $val = transform_token($token, $transform, $2);
        return (!!$val == $neg) ? '##%' : '';
    }
    else {
        die "Unknown request format: $token";
    }
}

# Simple test cases
my %transform_data = (
    'KEY1' => 'VALUE1',
    'KEY2' => '',
    'KEY3' => '1',
);

print transform('?KEY3?', \%transform_data) eq '##%' ? "PASS\n" : "FAIL\n";

Steps to Reproduce

perl test.pl

Expected behavior

No "Possible precedence problem between ! and numeric eq (==)" message

Perl configuration

# perl -V output goes here
 perl -V
Summary of my perl5 (revision 5 version 41 subversion 7) configuration:
  Derived from: 3a3761b09845d0d6d68f91eb45c52ae70de89489
  Platform:
    osname=os390
    osvers=27.00
    archname=os390
    uname='os390 vs01 27.00 04 8562 '
    config_args='-Dprefix=/home/itodoro/zopen/usr/local/zopen/perl5/perl5 -Duserelocatableinc -Dusedevel -des -Duse64bitall -Dusedl -D ccflags=-fzos-le-char-mode=ascii -std=gnu11 -mnocsect -fno-short-enums -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -m64 -mzos-target=zosv2r4 -O3  -I/home/itodoro/zopen/usr/local/zopen/curl/curl/include -I/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/include -I/home/itodoro/zopen/usr/local/zopen/zlib/zlib/include -isystem /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include -include /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include/zos-v2r5-symbolfixes.h  -DNSIG=42 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE -D_OPEN_SYS_FILE_EXT=1 -D_AE_BIMODAL=1 -D_ENHANCED_ASCII_EXT=0xFFFFFFFF  -DZOSLIB_OVERRIDE_CLIB=1 -DZOSLIB_OVERRIDE_CLIB_GETENV=1 -DOS390 -DZOS -DNO_LOCALE_MESSAGES -DOEMVS -DMAXSIG=39 -D_EXT=1 -fvisibility=default -D ldflags=-Wl,-bedit=no -m64  -L/home/itodoro/zopen/usr/local/zopen/curl/curl/lib -L/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/lib -L/home/itodoro/zopen/usr/local/zopen/zlib/zlib/lib -L/home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib -D libs=  -lcurl -lncurses -lz -lzoslib /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib/celquopt.s.o -lzoslib-supp /jenkins/workspace/Port-Build/perl/perl5/.zoslib_hooks/zoslib_env_hook.c.o CC=clang CPPFLAGS=-DNSIG=42 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE -D_OPEN_SYS_FILE_EXT=1 -D_AE_BIMODAL=1 -D_ENHANCED_ASCII_EXT=0xFFFFFFFF  -DZOSLIB_OVERRIDE_CLIB=1 -DZOSLIB_OVERRIDE_CLIB_GETENV=1 CFLAGS=-fzos-le-char-mode=ascii -std=gnu11 -mnocsect -fno-short-enums -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -m64 -mzos-target=zosv2r4 -O3  -I/home/itodoro/zopen/usr/local/zopen/curl/curl/include -I/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/include -I/home/itodoro/zopen/usr/local/zopen/zlib/zlib/include -isystem /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include -include /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include/zos-v2r5-symbolfixes.h  CXX=clang++ CXXFLAGS=-fzos-le-char-mode=ascii -mnocsect -fno-short-enums -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -m64 -mzos-target=zosv2r4 -O3     -I/home/itodoro/zopen/usr/local/zopen/curl/curl/include -I/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/include -I/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/include/ncurses -I/home/itodoro/zopen/usr/local/zopen/zlib/zlib/include -isystem /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include -include /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include/zos-v2r5-symbolfixes.h  LDFLAGS=-Wl,-bedit=no -m64  -L/home/itodoro/zopen/usr/local/zopen/curl/curl/lib -L/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/lib -L/home/itodoro/zopen/usr/local/zopen/zlib/zlib/lib -L/home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib LIBS=  -lcurl -lncurses -lz -lzoslib /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib/celquopt.s.o -lzoslib-supp /jenkins/workspace/Port-Build/perl/perl5/.zoslib_hooks/zoslib_env_hook.c.o LDLIBS=  -lcurl -lncurses -lz -lzoslib /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib/celquopt.s.o -lzoslib-supp /jenkins/workspace/Port-Build/perl/perl5/.zoslib_hooks/zoslib_env_hook.c.o'
    hint=recommended
    useposix=true
    d_sigaction=define
    useithreads=undef
    usemultiplicity=undef
    use64bitint=define
    use64bitall=define
    uselongdouble=undef
    usemymalloc=n
    default_inc_excludes_dot=define
  Compiler:
    cc='clang'
    ccflags ='-fzos-le-char-mode=ascii -std=gnu11 -mnocsect -fno-short-enums -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -m64 -mzos-target=zosv2r4 -O3 -I/home/itodoro/zopen/usr/local/zopen/curl/curl/include -I/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/include -I/home/itodoro/zopen/usr/local/zopen/zlib/zlib/include -isystem /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include -include /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include/zos-v2r5-symbolfixes.h -DNSIG=42 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE -D_OPEN_SYS_FILE_EXT=1 -D_AE_BIMODAL=1 -D_ENHANCED_ASCII_EXT=0xFFFFFFFF -DZOSLIB_OVERRIDE_CLIB=1 -DZOSLIB_OVERRIDE_CLIB_GETENV=1 -DOS390 -DZOS -DNO_LOCALE_MESSAGES -DOEMVS -DMAXSIG=39 -D_EXT=1 -fvisibility=default'
    optimize=' '
    cppflags='-fzos-le-char-mode=ascii -std=gnu11 -mnocsect -fno-short-enums -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -m64 -mzos-target=zosv2r4 -O3 -I/home/itodoro/zopen/usr/local/zopen/curl/curl/include -I/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/include -I/home/itodoro/zopen/usr/local/zopen/zlib/zlib/include -isystem /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include -include /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/include/zos-v2r5-symbolfixes.h -DNSIG=42 -D_XOPEN_SOURCE=600 -D_ALL_SOURCE -D_OPEN_SYS_FILE_EXT=1 -D_AE_BIMODAL=1 -D_ENHANCED_ASCII_EXT=0xFFFFFFFF -DZOSLIB_OVERRIDE_CLIB=1 -DZOSLIB_OVERRIDE_CLIB_GETENV=1 -DOS390 -DZOS -DNO_LOCALE_MESSAGES -DOEMVS -DMAXSIG=39 -D_EXT=1 -fvisibility=default'
    ccversion=''
    gccversion=''
    gccosandvers=''
    intsize=4
    longsize=8
    ptrsize=8
    doublesize=8
    byteorder=87654321
    doublekind=4
    d_longlong=define
    longlongsize=8
    d_longdbl=define
    longdblsize=16
    longdblkind=2
    ivtype='long'
    ivsize=8
    nvtype='double'
    nvsize=8
    Off_t='off_t'
    lseeksize=8
    alignbytes=8
    prototype=define
  Linker and Libraries:
    ld='clang'
    ldflags ='-Wl,-bedit=no -m64 -L/home/itodoro/zopen/usr/local/zopen/curl/curl/lib -L/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/lib -L/home/itodoro/zopen/usr/local/zopen/zlib/zlib/lib -L/home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib'
    libpth=/lib /usr/lib
    libs= -lcurl -lncurses -lz -lzoslib /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib/celquopt.s.o -lzoslib-supp /jenkins/workspace/Port-Build/perl/perl5/.zoslib_hooks/zoslib_env_hook.c.o
    perllibs=-lcurl -lncurses -lz -lzoslib /home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib/celquopt.s.o -lzoslib-supp /jenkins/workspace/Port-Build/perl/perl5/.zoslib_hooks/zoslib_env_hook.c.o
    libc=
    so=so
    useshrplib=true
    libperl=libperl.so
    gnulibc_version=''
  Dynamic Linking:
    dlsrc=dl_dllload.xs
    dlext=so
    d_dlsymun=undef
    ccdlflags='  /jenkins/workspace/Port-Build/perl/perl5/libperl.x'
    cccdlflags='-c -m64'
    lddlflags='-m64 -L/home/itodoro/zopen/usr/local/zopen/curl/curl/lib -L/home/itodoro/zopen/usr/local/zopen/ncurses/ncurses/lib -L/home/itodoro/zopen/usr/local/zopen/zlib/zlib/lib -L/home/itodoro/zopen/usr/local/zopen/zoslib/zoslib/lib /jenkins/workspace/Port-Build/perl/perl5/libperl.x'


Characteristics of this binary (from libperl):
  Compile-time options:
    HAS_LONG_DOUBLE
    HAS_STRTOLD
    HAS_TIMES
    PERLIO_LAYERS
    PERL_COPY_ON_WRITE
    PERL_DONT_CREATE_GVSV
    PERL_HASH_FUNC_SIPHASH13
    PERL_HASH_USE_SBOX32
    PERL_MALLOC_WRAP
    PERL_OP_PARENT
    PERL_PRESERVE_IVUV
    PERL_USE_DEVEL
    PERL_USE_SAFE_PUTENV
    USE_64_BIT_ALL
    USE_64_BIT_INT
    USE_LARGE_FILES
    USE_LOCALE
    USE_LOCALE_COLLATE
    USE_LOCALE_CTYPE
    USE_LOCALE_NUMERIC
    USE_LOCALE_TIME
    USE_PERLIO
    USE_PERL_ATOF
  Locally applied patches:
    uncommitted-changes
  Built under os390
  Compiled at Jan 23 2025 11:25:38
  %ENV:
    PERL5LIB="/home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7/:/home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7/os390/:/home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/perl5/5.41.7/:/home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/perl5/5.41.7/os390/:/home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7/:/home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7/os390/:/home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/perl5/5.41.7/:/home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/perl5/5.41.7/os390/:"
  @INC:
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7//os390
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7/
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7/os390/
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/perl5/5.41.7/
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/perl5/5.41.7/os390/
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7//os390
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7/
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/5.41.7/os390/
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/perl5/5.41.7/
    /home/itodoro/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/lib/perl5/5.41.7/os390/
    ../lib/site_perl/5.41.7/os390
    ../lib/site_perl/5.41.7
    ../lib/5.41.7/os390
    ../lib/5.41.7

@IgorTodorovskiIBM
Copy link
Author

You can also reproduce this by pulling the latest automake code, building it and running automake.

curl -O https://ftp.gnu.org/gnu/automake/automake-1.17.tar.gz
cd automake*
./configure
make -j10
make install
automake

@Grinnz
Copy link
Contributor

Grinnz commented Jan 29, 2025

If it is intended for !!$val to be used as the integer 0 or 1 to be compared to $neg, this warning could be avoided by making that explicit: 0+!!$val == $neg

The purpose of the warning is to call out a common mistake where !$x == $y is written instead of !($x == $y) - but warnings just produce STDERR output, is it causing some other issue?

@IgorTodorovskiIBM
Copy link
Author

IgorTodorovskiIBM commented Jan 29, 2025

If it is intended for !!$val to be used as the integer 0 or 1 to be compared to $neg, this warning could be avoided by making that explicit: 0+!!$val == $neg

The purpose of the warning is to call out a common mistake where !$x == $y is written instead of !($x == $y) - but warnings just produce STDERR output, is it causing some other issue?

Yes, in automake case it's causing automake to exit with rc of 255

 ./bin/automake-1.17 ; echo $?
Possible precedence problem between ! and numeric eq (==) at ./bin/automake-1.17 line 6875.
255

@IgorTodorovskiIBM
Copy link
Author

Ah they have: use warnings FATAL => 'all';

@Grinnz
Copy link
Contributor

Grinnz commented Jan 29, 2025

Using fatal warnings is an assumption of risk of breakage: https://perldoc.perl.org/warnings#Fatal-Warnings

@mauke
Copy link
Contributor

mauke commented Jan 29, 2025

my $neg = ($1 eq '!') ? 1 : 0;
my $val = transform_token($token, $transform, $2);
return (!!$val == $neg) ? '##%' : '';

This code is bizarre. It uses ? 1 : 0 in the initialization of $neg where it is unnecessary (since eq already returns a boolean), but does not use it for $val where it would make sense (since transform_token returns a string).

That is,

my $neg = $1 eq '!';
my $val = transform_token($token, $transform, $2) ? 1 : 0;
return ($val == $neg) ? '##%' : '';

would do the right thing and not trigger a warning.

(Alternatively, parenthesizing the last expression as return (!!$val) == $neg ? '##%' : '' would also avoid the warning.)


That said, the warning already has a list of exceptions where it doesn't trigger:

  • (!...) == ... (LHS parenthesized) does not warn
  • !... == !... (negation on both LHS and RHS) does not warn

It would be fairly easy to add !!... == ... (double negation on LHS) to the list of exceptions. Is this something we want?

@Grinnz
Copy link
Contributor

Grinnz commented Jan 29, 2025

I think that would risk failing to catch instances where !!($x == $y) was accidentally written without the parentheses, as that is rather similar to the original case it is meant to catch, and that exception should only be added if automake isn't reasonably able to work around the warning; and if that is the case, they should be strongly recommended not to use fatal warnings as this issue will occur again.

@IgorTodorovskiIBM
Copy link
Author

IgorTodorovskiIBM commented Jan 30, 2025

I'm also seeing a similar case in texinfo (another GNU package):

makeinfo
Possible precedence problem between ! and string eq at /home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Converter.pm line 1092.
Possible precedence problem between ! and string eq at /home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Info.pm line 92.
makeinfo: missing file argument.
Try `makeinfo --help' for more information.

/home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Converter.pm line 1092.

1091   my $fh;
1092   if (! $self->{'output_file'} eq '') {
1093     $fh = $self->Texinfo::Common::open_out($self->{'output_file'});
1094     if (!$fh) {
1095       $self->document_error(sprintf(__("could not open %s for writing: %s"),
1096                                     $self->{'output_file'}, $!));
1097       return undef;
1098     }
1099   }

/home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Info.pm line 92.

 90
 91   my $fh;
 92   if (! $self->{'output_file'} eq '') {
 93     if ($self->get_conf('VERBOSE')) {
 94       print STDERR "Output file $self->{'output_file'}\n";
 95     }
 96     $fh = _open_info_file($self, $self->{'output_file'});
 97     if (!$fh) {
 98       return undef;
 99     }
100   }

@IgorTodorovskiIBM
Copy link
Author

IgorTodorovskiIBM commented Jan 30, 2025

Curl fails at make check with Perl 5.41.7 due to this as well:

make[2]: Leaving directory '/jenkins/workspace/Port-Build/curl/curl-8.11.1/tests'
srcdir=. /jenkins/zopen/usr/local/zopen/perl/perl5-heads.v5.41.7.20250123_102326.zos/bin/perl -I. ./runtests.pl   -a -s 
Possible precedence problem between ! and string eq at ./runtests.pl line 1691.
make[1]: *** [Makefile:898: quiet-test] Error 129
make[1]: Leaving directory '/jenkins/workspace/Port-Build/curl/curl-8.11.1/tests'

@IgorTodorovskiIBM
Copy link
Author

I have sent an email to [email protected] <[email protected]> to report the problem.

@Grinnz
Copy link
Contributor

Grinnz commented Jan 30, 2025

I'm also seeing a similar case in texinfo (another GNU package):

makeinfo
Possible precedence problem between ! and string eq at /home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Converter.pm line 1092.
Possible precedence problem between ! and string eq at /home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Info.pm line 92.
makeinfo: missing file argument.
Try `makeinfo --help' for more information.

/home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Converter.pm line 1092.

1091   my $fh;
1092   if (! $self->{'output_file'} eq '') {
1093     $fh = $self->Texinfo::Common::open_out($self->{'output_file'});
1094     if (!$fh) {
1095       $self->document_error(sprintf(__("could not open %s for writing: %s"),
1096                                     $self->{'output_file'}, $!));
1097       return undef;
1098     }
1099   }

/home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Info.pm line 92.

 90
 91   my $fh;
 92   if (! $self->{'output_file'} eq '') {
 93     if ($self->get_conf('VERBOSE')) {
 94       print STDERR "Output file $self->{'output_file'}\n";
 95     }
 96     $fh = _open_info_file($self, $self->{'output_file'});
 97     if (!$fh) {
 98       return undef;
 99     }
100   }

These are actual logical errors which the warning has pointed out; the code is attempting to check whether $self->{output_file} is non-empty, but instead checks whether $self->{output_file} is true (via checking whether its boolean negation is equal to the empty string).

@IgorTodorovskiIBM
Copy link
Author

IgorTodorovskiIBM commented Jan 30, 2025

I'm also seeing a similar case in texinfo (another GNU package):

makeinfo
Possible precedence problem between ! and string eq at /home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Converter.pm line 1092.
Possible precedence problem between ! and string eq at /home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Info.pm line 92.
makeinfo: missing file argument.
Try `makeinfo --help' for more information.

/home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Converter.pm line 1092.

1091   my $fh;
1092   if (! $self->{'output_file'} eq '') {
1093     $fh = $self->Texinfo::Common::open_out($self->{'output_file'});
1094     if (!$fh) {
1095       $self->document_error(sprintf(__("could not open %s for writing: %s"),
1096                                     $self->{'output_file'}, $!));
1097       return undef;
1098     }
1099   }

/home/itodoro/zopen/usr/local/zopen/texinfo/texinfo/share/texinfo/Texinfo/Convert/Info.pm line 92.

 90
 91   my $fh;
 92   if (! $self->{'output_file'} eq '') {
 93     if ($self->get_conf('VERBOSE')) {
 94       print STDERR "Output file $self->{'output_file'}\n";
 95     }
 96     $fh = _open_info_file($self, $self->{'output_file'});
 97     if (!$fh) {
 98       return undef;
 99     }
100   }

These are actual logical errors which the warning has pointed out; the code is attempting to check whether $self->{output_file} is non-empty, but instead checks whether $self->{output_file} is true (via checking whether its boolean negation is equal to the empty string).

Should these warnings have been introduced in a minor or major release rather than a patch release? 5.41.3 did not emit these warnings. I've seen 3 popular open source tools break as a result of these changes.

@Grinnz
Copy link
Contributor

Grinnz commented Jan 30, 2025

As mentioned, these warnings emit only STDERR in supported operation. If these utilities are using fatal warnings, they have accepted the contract that they must update their code whenever new warnings are introduced. This allows new warnings to be introduced, as otherwise Perl's devotion to backwards compatibility would make it near impossible to do so, major version or not.

In addition, this is not a patch release, this is a development release. These warnings will not be introduced to a stable version of Perl until 5.42.0.

@IgorTodorovskiIBM
Copy link
Author

Ok, thanks I have reported the issue to the curl community: curl/curl#16128

@demerphq
Copy link
Collaborator

demerphq commented Jan 30, 2025 via email

@Grinnz
Copy link
Contributor

Grinnz commented Jan 30, 2025

On Thu, 30 Jan 2025, 07:13 mauke, @.***> wrote:
my $neg = ($1 eq '!') ? 1 : 0;my $val = transform_token($token, $transform, $2);return (!!$val == $neg) ? '##%' : '';

This code is bizarre.
I dont agree it's bizarre. The ternary is superluous, but it's not that
weird or unusual for people to write code like this in the interest of
clarity.

It would be fairly easy to add !!... == ... (double negation on LHS) to the
list of exceptions. Is this something we want?
Imo yes. !!$x is a standard "operator" to booleanify a var. (Book published
a huge list of such "operators" years ago.) Using it with == should not be
a warning.

So is !, and adding that exception would make this warning do nothing, so I don't agree with this logic.

@mauke
Copy link
Contributor

mauke commented Jan 30, 2025

I dont agree it's bizarre. The ternary is superluous, but it's not that
weird or unusual for people to write code like this in the interest of
clarity.

My issue is not that the ternary is superfluous. It's that they go out of their way to manually convert a boolean to an integer in one case ($1 eq '!') ? 1 : 0, but in the other case they simply slap a !! on the variable and call it a day.

If they had used ? 1 : 0 consistently on both sides (using == to compare two integers), they wouldn't get a warning. If they had used !! consistently on both sides (using == to implicitly numify the booleans), they wouldn't get a warning.

To put it another way, one side of the equation is natively a boolean ($1 eq '!'), the other a string (transform_token(...)). Those are different types and some people like to be explicit about type conversions, sure. But here the first value is explicitly converted from a boolean to an integer, and the second value from a string to a boolean. In the end, we still have different types and must rely on == to perform an implicit conversion. This feels bizarre to me and I don't see how doing things this way makes anything clearer.

(Also, I'm not familiar with the context of the code, but boolifying a string treats '0' and '' as the same value. I'm not sure if this is intentional.)

@demerphq
Copy link
Collaborator

demerphq commented Jan 30, 2025 via email

@demerphq
Copy link
Collaborator

demerphq commented Jan 30, 2025 via email

@guest20
Copy link

guest20 commented Jan 30, 2025

Content Warning: Light hearted pedantry

The word "regression" in the title of this ticket is not appropriate to the situation. This is a new (fatal) warning from a new version of perl. So, gression-wise, I'd say it's progression, not regression.

jollaitbot pushed a commit to sailfishos-mirror/texinfo that referenced this issue Jan 31, 2025
tp/Texinfo/Convert/LaTeX.pm (output), tp/Texinfo/Convert/IXIN.pm: fix
precedence problem between ! and string eq, which leads to a warning
with Perl 5.41.7.  Report from Igor Todorovski, details on:
Perl/perl5#22954 (comment)
@Leont
Copy link
Contributor

Leont commented Jan 31, 2025

I'd agree the pure idiomatic form is clearer. But that isn't really
relevant, the code is still functionally correct , false is silently
equivalent to 0 in numeric context.

I agree. Generally speaking false positives we really want to avoid in warnings. It doesn't take that many for people to turn that warning off, and then we're in an even worse position.

@mauke
Copy link
Contributor

mauke commented Jan 31, 2025

I have some thoughts.

  • Fatalizing all warnings is a bad idea; doing so in production code is just asking for trouble. That's automake's problem.

  • However, there is a more general issue here. I agree that false positives are bad in general and should be avoided where reasonably possible.

  • Only the automake case is a false positive. The texinfo and curl cases are true positives: The warning has found real bugs.

  • I tried to search CPAN for instances of !! being used in suspicious ways. I only found two results:

    • Alien::Build::Plugin::Fetch::Git:
      $can_minus_c = !! $? == 0 && -d $tmp->child('.git');
      I'm not sure what's going on here. You could call this a false positive because the code produces correct results, but !! $? == 0 leaves me scratching my head. I can't tell what the author's intent was and I think the !! should just be removed.
    • Device::BusPirate::Mode::SPI:
      if( any { defined $args{$_} and !!$args{$_} != $self->$_ } qw( open_drain ckp cke sample ) ) {
      This is a genuine false positive. Avoiding the warning would be simple (by writing $args{$_} ^^ $self->$_ or !!$args{$_} != !!$self->$_ or (!!$args{$_}) != $self->$_), but I count it as a point towards making !! exempt from the warning.

    If you have more examples, please let me know.

  • As for the automake code not being bizarre: I don't follow Yves' reasoning. Sure, I can see how code might end up in this shape due to inattention or multiple developers of different experience levels working on it, but that wasn't the point. The point is that the end result is incoherent code.

  • As for treating '0' and '' as the same value being intentional because otherwise people wouldn't write !! in their code: I don't buy it. People write sloppy code all the time. That doesn't mean they fully understand the ramifications of writing a check a particular way. (For example, the texinfo case above doesn't use !!, but it is a bug that doesn't let you use 0 as the output filename.)

  • This kind of "change your code because we don't approve of your coding
    style" is something we long avoided, I dont see why that should change
    now.

    That ... is not something I would agree with. Consider this warning from perl 4.0.33:

    $ perl -wE 'say (":-)");'
    say (...) interpreted as function at -e line 1.
    :-)
    

    Or this one from perl 5.000:

    $ perl -we 'use Carp qw(croak); exec "echo ok"; croak "Could not exec: $!"'
    Statement unlikely to be reached at -e line 1.
            (Maybe you meant system() when you said exec()?)
    ok
    

    Or these from perl 5.003_08:

    $ perl -we 'my @c = qw( ! ? . , ; # );'
    Possible attempt to separate words with commas at -e line 1.
    Possible attempt to put comments in qw() list at -e line 1.
    

    These are all false positives, enforcing a particular "coding style". (In particular, the qw ones have always annoyed me. They've never identified a single bug in my code. Can we patch them out?)

On the whole, I'll err on the side of caution and prepare a patch that exempts !! from the warning because of code like the one in Device::BusPirate. (More examples welcome.)

The warning itself should stay, I think. It has identified real bugs in high-profile projects such as perl's Test2 suite, texinfo, and curl.

@mauke mauke changed the title "Possible precedence problem between ! and numeric eq (==)" regression in automake "Possible precedence problem between ! and numeric eq (==)" failure in automake Jan 31, 2025
mauke added a commit to mauke/perl5 that referenced this issue Jan 31, 2025
Exempt `!!` from the "Possible precedence problem between ! and <cmp>"
warning.

Fixes Perl#22954.
@leonerd
Copy link
Contributor

leonerd commented Jan 31, 2025

+1 to what @mauke said (and not just because he used one of my modules as a counterexample ;) )

The new warning is providing valuable feedback on genuinely suspect code. The false positives are an annoying distraction to it, which the PR fixes (and I have reviewed and given it a thumbs up).

Also agree that anyone running fatalized warnings in a production system is skating on very thin ice. They have asked for their code to randomly start crashing out on warnings from future versions of Perl, so that is what they shall receive.

@demerphq
Copy link
Collaborator

demerphq commented Jan 31, 2025 via email

jollaitbot pushed a commit to sailfishos-mirror/automake that referenced this issue Jan 31, 2025
Per Perl recommendation:
  https://perldoc.perl.org/warnings#Fatal-Warnings
Suggested by Collin Funk:
  https://lists.gnu.org/archive/html/automake/2025-01/msg00003.html
And in the Perl discussion:
  Perl/perl5#22954 (comment)

* bin/aclocal.in: just use warnings, not making them fatal.
* bin/automake.in:
* contrib/tap-driver.pl:
* gen-testsuite-part:
* lib/Automake/ChannelDefs.pm:
* lib/Automake/Channels.pm:
* lib/Automake/Condition.pm:
* lib/Automake/Config.in:
* lib/Automake/Configure_ac.pm:
* lib/Automake/DisjConditions.pm:
* lib/Automake/FileUtils.pm:
* lib/Automake/General.pm:
* lib/Automake/Getopt.pm:
* lib/Automake/Item.pm:
* lib/Automake/ItemDef.pm:
* lib/Automake/Language.pm:
* lib/Automake/Location.pm:
* lib/Automake/Options.pm:
* lib/Automake/Rule.pm:
* lib/Automake/RuleDef.pm:
* lib/Automake/VarDef.pm:
* lib/Automake/Variable.pm:
* lib/Automake/Version.pm:
* lib/Automake/Wrap.pm:
* lib/Automake/XFile.pm:
* t/ax/deltree.pl:
* t/ax/extract-testsuite-summary.pl:
* t/check-fd-redirect.sh:
* t/tap-signal.tap:
* t/tests-environment-fd-redirect.sh:
* t/testsuite-summary-count-many.sh:
@mauke mauke closed this as completed in 65e079e Jan 31, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants