Deparse: handle warnings NOFATAL
authorDavid Mitchell <davem@iabyn.com>
Wed, 22 Nov 2017 17:01:04 +0000 (17:01 +0000)
committerDavid Mitchell <davem@iabyn.com>
Thu, 23 Nov 2017 08:52:16 +0000 (08:52 +0000)
In general, Deparse currently outputs 'use warnings foo' as

BEGIN {${^WARNING_BITS} =
    "\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55"}

or similar, except that it special-cases all bits being set or unset as

    use warnings;
and
    no warnings;

This failed for something like

    use warnings FATAL => all;
    {
        use warnings NOFATAL => all;
    }

since was deparing the NOFATAL line as a simple

    use warnings;

which is wrong.

So don't just see whehter the final bit pattern matches 'use/no warnings';
also see whether there are any other bits which need turning off.

lib/B/Deparse.pm

index 69379ce..552798d 100644 (file)
@@ -2145,12 +2145,18 @@ sub pp_nextstate {
 
 sub declare_warnings {
     my ($self, $from, $to) = @_;
-    if (($to & WARN_MASK) eq (warnings::bits("all") & WARN_MASK)) {
-       return $self->keyword("use") . " warnings;\n";
-    }
-    elsif (($to & WARN_MASK) eq ("\0"x length($to) & WARN_MASK)) {
-       return $self->keyword("no") . " warnings;\n";
+    $from //= '';
+    my $all = (warnings::bits("all") & WARN_MASK);
+    unless ((($from & WARN_MASK) & ~$all) =~ /[^\0]/) {
+        # no FATAL bits need turning off
+        if (   ($to & WARN_MASK) eq $all) {
+            return $self->keyword("use") . " warnings;\n";
+        }
+        elsif (($to & WARN_MASK) eq ("\0"x length($to) & WARN_MASK)) {
+            return $self->keyword("no") . " warnings;\n";
+        }
     }
+
     return "BEGIN {\${^WARNING_BITS} = \""
            . join("", map { sprintf("\\x%02x", ord $_) } split "", $to)
            . "\"}\n\cK";