Skip to content

Commit

Permalink
builtin: make inf/nan conditional depending on float support
Browse files Browse the repository at this point in the history
On some machines (VAX), the double type doesn't support Infinity/NaN
values. Handle this case by making builtin::inf/builtin::nan throw a
runtime error.

Fixes Perl#22882.
  • Loading branch information
mauke committed Jan 6, 2025
1 parent 6c4c496 commit aead16f
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 10 deletions.
16 changes: 16 additions & 0 deletions builtin.c
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,12 @@ XS(XS_builtin_inf)
dXSARGS;
if(items)
croak_xs_usage(cv, "");
#ifdef DOUBLE_HAS_INF
EXTEND(SP, 1);
XSRETURN_NV(NV_INF);
#else
Perl_croak_nocontext("builtin::inf not implemented");
#endif
}

XS(XS_builtin_nan);
Expand All @@ -106,8 +110,12 @@ XS(XS_builtin_nan)
dXSARGS;
if(items)
croak_xs_usage(cv, "");
#ifdef DOUBLE_HAS_NAN
EXTEND(SP, 1);
XSRETURN_NV(NV_NAN);
#else
Perl_croak_nocontext("builtin::nan not implemented");
#endif
}

enum {
Expand Down Expand Up @@ -135,8 +143,16 @@ static OP *ck_builtin_const(pTHX_ OP *entersubop, GV *namegv, SV *ckobj)
switch(builtin->ckval) {
case BUILTIN_CONST_FALSE: constval = &PL_sv_no; break;
case BUILTIN_CONST_TRUE: constval = &PL_sv_yes; break;
#ifdef DOUBLE_HAS_INF
case BUILTIN_CONST_INF: constval = newSVnv(NV_INF); break;
#else
case BUILTIN_CONST_INF: return entersubop;
#endif
#ifdef DOUBLE_HAS_NAN
case BUILTIN_CONST_NAN: constval = newSVnv(NV_NAN); break;
#else
case BUILTIN_CONST_NAN: return entersubop;
#endif
default:
DIE(aTHX_ "panic: unrecognised builtin_const value %" IVdf,
builtin->ckval);
Expand Down
33 changes: 23 additions & 10 deletions lib/builtin.t
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ BEGIN {

use v5.36;
no warnings 'experimental::builtin';
use Config;

package FetchStoreCounter {
sub TIESCALAR($class, @args) { bless \@args, $class }
Expand Down Expand Up @@ -55,19 +56,31 @@ package FetchStoreCounter {
{
use builtin qw( inf nan );

ok(inf, 'inf is true');
ok(inf > 1E10, 'inf is bigger than 1E10');
ok(inf == inf, 'inf is equal to inf');
ok(inf == inf + 1, 'inf is equal to inf + 1');
if ($Config{d_double_has_inf}) {
ok(inf, 'inf is true');
ok(inf > 1E10, 'inf is bigger than 1E10');
ok(inf == inf, 'inf is equal to inf');
ok(inf == inf + 1, 'inf is equal to inf + 1');

# Invoke the real XSUB
my $inf = ( \&builtin::inf )->();
ok($inf == $inf + 1, 'inf returned by real xsub');
# Invoke the real XSUB
my $inf = ( \&builtin::inf )->();
ok($inf == $inf + 1, 'inf returned by real xsub');
} else {
is(eval { inf }, undef, 'inf throws');
my $e = $@;
like($e, qr/^builtin::inf not implemented at/, 'inf fails with correct error');
}

ok(nan != nan, 'NaN is not equal to NaN');
if ($Config{d_double_has_nan}) {
ok(nan != nan, 'NaN is not equal to NaN');

my $nan = ( \&builtin::nan )->();
ok($nan != $nan, 'NaN returned by real xsub');
my $nan = ( \&builtin::nan )->();
ok($nan != $nan, 'NaN returned by real xsub');
} else {
is(eval { nan }, undef, 'nan throws');
my $e = $@;
like($e, qr/^builtin::nan not implemented at/, 'nan fails with correct error');
}
}

# weakrefs
Expand Down
10 changes: 10 additions & 0 deletions pod/perldiag.pod
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,16 @@ is currently being compiled. Since this method is used to introduce new
lexical subroutines into the scope currently being compiled, this is not
going to have any effect.

=item builtin::inf not implemented

(F) Your machine doesn't support infinity as a numeric value (probably because
it's a VAX).

=item builtin::nan not implemented

(F) Your machine doesn't support NaN ("not a number") as a numeric value
(probably because it's a VAX).

=item Builtin version bundle "%s" is not supported by Perl

(F) You attempted to C<use builtin :ver> for a version number that is either
Expand Down

0 comments on commit aead16f

Please sign in to comment.