sprintf2.t: mark TODO bad denorm values under g++
authorDavid Mitchell <davem@iabyn.com>
Tue, 1 May 2018 14:28:49 +0000 (15:28 +0100)
committerDavid Mitchell <davem@iabyn.com>
Tue, 1 May 2018 14:52:55 +0000 (15:52 +0100)
Some t/op/sprintf2.t tests were failing under g++. This is due the perl
toker interpreting very small literal hex floating pointers as 0 rather
than as a subnormal value.

For example:

    perl -le'print "bad" if 0x1.fffffffffffffp-1022 == 0.0'

This breaks some of the sprintf2.t tests, so mark them TODO them if the
literal value evaluates to zero.

Note that this is a bug in the toker/g++/glibc rather than sprintf.

The issue is due to the use of pow() in scan_num():

under gcc and plain g++, pow(2.0, -1074) returns the smallest denorm
number; however, under 'g++ -ansi', it returns 0.0.

t/op/sprintf2.t

index 5fb7597..3f4c126 100644 (file)
@@ -808,7 +808,17 @@ SKIP: {
     for my $t (@subnormals) {
        # Note that "0x1p+2" is not considered numeric,
        # since neither is "0x12", hence the eval.
-        my $s = sprintf($t->[1], eval $t->[0]);
+        my $f = eval $t->[0];
+        # XXX under g++ -ansi, pow(2.0, -1074) returns 0 rather
+        # than the smallest denorm number. Which means that very small
+        # string literals on a perl compiled under g++ may be seen as 0.
+        # This is either a bug in the g++ math library or scan_num() in
+        # toke.c; but in either case, its not a bug in sprintf(), so
+        # skip the test.
+        local $::TODO = "denorm literals treated as zero"
+            if $f == 0.0 && $t->[2] ne '0x0p+0';
+
+        my $s = sprintf($t->[1], $f);
         is($s, $t->[2], "subnormal @$t got $s");
     }