RE: mixing FATAL and non-FATAL warnings
Paul Marquess [Thu, 20 Jun 2002 17:14:12 +0000 (18:14 +0100)]
From: "Paul Marquess" <Paul.Marquess@btinternet.com>
Message-ID: <AIEAJICLCBDNAAOLLOKLOEJAEOAA.Paul.Marquess@btinternet.com>

p4raw-id: //depot/perl@17325

lib/warnings.pm
pod/perllexwarn.pod
t/lib/warnings/7fatal
warnings.pl

index 5cb6eff..8aa7748 100644 (file)
@@ -294,17 +294,30 @@ sub Croaker
     croak @_ ;
 }
 
-sub bits {
-    my $mask ;
+sub bits
+{
+    # called from B::Deparse.pm
+
+    push @_, 'all' unless @_;
+
+    my $mask;
     my $catmask ;
     my $fatal = 0 ;
-    foreach my $word (@_) {
-       if  ($word eq 'FATAL') {
+    my $no_fatal = 0 ;
+
+    foreach my $word ( @_ ) {
+       if ($word eq 'FATAL') {
            $fatal = 1;
+           $no_fatal = 0;
+       }
+       elsif ($word eq 'NONFATAL') {
+           $fatal = 0;
+           $no_fatal = 1;
        }
        elsif ($catmask = $Bits{$word}) {
            $mask |= $catmask ;
            $mask |= $DeadBits{$word} if $fatal ;
+           $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
        }
        else
           { Croaker("Unknown warnings category '$word'")}
@@ -313,24 +326,70 @@ sub bits {
     return $mask ;
 }
 
-sub import {
+sub import 
+{
     shift;
+
+    my $catmask ;
+    my $fatal = 0 ;
+    my $no_fatal = 0 ;
+
     my $mask = ${^WARNING_BITS} ;
+
     if (vec($mask, $Offsets{'all'}, 1)) {
         $mask |= $Bits{'all'} ;
         $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
     }
-    ${^WARNING_BITS} = $mask | bits(@_ ? @_ : 'all') ;
+    
+    push @_, 'all' unless @_;
+
+    foreach my $word ( @_ ) {
+       if ($word eq 'FATAL') {
+           $fatal = 1;
+           $no_fatal = 0;
+       }
+       elsif ($word eq 'NONFATAL') {
+           $fatal = 0;
+           $no_fatal = 1;
+       }
+       elsif ($catmask = $Bits{$word}) {
+           $mask |= $catmask ;
+           $mask |= $DeadBits{$word} if $fatal ;
+           $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
+       }
+       else
+          { Croaker("Unknown warnings category '$word'")}
+    }
+
+    ${^WARNING_BITS} = $mask ;
 }
 
-sub unimport {
+sub unimport 
+{
     shift;
+
+    my $catmask ;
     my $mask = ${^WARNING_BITS} ;
+
     if (vec($mask, $Offsets{'all'}, 1)) {
         $mask |= $Bits{'all'} ;
         $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
     }
-    ${^WARNING_BITS} = $mask & ~ (bits('FATAL' => (@_ ? @_ : 'all')) | $All) ;
+
+    push @_, 'all' unless @_;
+
+    foreach my $word ( @_ ) {
+       if ($word eq 'FATAL') {
+           next; 
+       }
+       elsif ($catmask = $Bits{$word}) {
+           $mask &= ~($catmask | $DeadBits{$word} | $All);
+       }
+       else
+          { Croaker("Unknown warnings category '$word'")}
+    }
+
+    ${^WARNING_BITS} = $mask ;
 }
 
 sub __chk
index 7b3ce3c..8ee7fc3 100644 (file)
@@ -351,13 +351,20 @@ The scope where C<length> is used has escalated the C<void> warnings
 category into a fatal error, so the program terminates immediately it
 encounters the warning.
 
-To explicitly disable a "FATAL" warning you just disable the warning it is
-associated with.  So, for example, to disable the "void" warning in the
-example above, either of these will do the trick:
+To explicitly turn off a "FATAL" warning you just disable the warning
+it is associated with.  So, for example, to disable the "void" warning
+in the example above, either of these will do the trick:
 
     no warnings qw(void);
     no warnings FATAL => qw(void);
 
+If you want to downgrade a warning that has been escalated into a fatal
+error back to a normal warning, you can use the "NONFATAL" keyword. For
+example, the code below will promote all warnings into fatal errors,
+except for those in the "syntax" category.
+
+    use warnings FATAL => 'all', NONFATAL => 'syntax';
+
 =head2 Reporting Warnings from a Module
 
 The C<warnings> pragma provides a number of functions that are useful for
index 23c88d8..a3e70f8 100644 (file)
@@ -356,3 +356,71 @@ my $b ; chop $b;
 print STDERR "The End.\n" ;
 EXPECT
 Use of uninitialized value in scalar chop at - line 7.
+########
+
+use warnings FATAL => 'syntax', NONFATAL => 'void' ;
+
+length "abc";
+print STDERR "The End.\n" ;
+EXPECT
+Useless use of length in void context at - line 4.
+The End.
+########
+
+use warnings FATAL => 'all', NONFATAL => 'void' ;
+
+length "abc";
+print STDERR "The End.\n" ;
+EXPECT
+Useless use of length in void context at - line 4.
+The End.
+########
+
+use warnings FATAL => 'all', NONFATAL => 'void' ;
+
+my $a ; chomp $a;
+length "abc";
+print STDERR "The End.\n" ;
+EXPECT
+Useless use of length in void context at - line 5.
+Use of uninitialized value in scalar chomp at - line 4.
+########
+
+use warnings FATAL => 'void', NONFATAL => 'void' ;
+
+length "abc";
+print STDERR "The End.\n" ;
+EXPECT
+Useless use of length in void context at - line 4.
+The End.
+########
+
+use warnings NONFATAL => 'void', FATAL => 'void' ;
+
+length "abc";
+print STDERR "The End.\n" ;
+EXPECT
+Useless use of length in void context at - line 4.
+########
+
+use warnings FATAL => 'all', NONFATAL => 'io';
+no warnings 'once';
+
+open(F, "<true\ncd");
+close "fred" ;
+print STDERR "The End.\n" ;
+EXPECT
+Unsuccessful open on filename containing newline at - line 5.
+close() on unopened filehandle fred at - line 6.
+The End.
+########
+
+use warnings FATAL => 'all', NONFATAL => 'io', FATAL => 'unopened' ;
+no warnings 'once';
+
+open(F, "<true\ncd");
+close "fred" ;
+print STDERR "The End.\n" ;
+EXPECT
+Unsuccessful open on filename containing newline at - line 5.
+close() on unopened filehandle fred at - line 6.
index 75778a1..586e5a7 100644 (file)
@@ -607,17 +607,30 @@ sub Croaker
     croak @_ ;
 }
 
-sub bits {
-    my $mask ;
+sub bits
+{
+    # called from B::Deparse.pm
+
+    push @_, 'all' unless @_;
+
+    my $mask;
     my $catmask ;
     my $fatal = 0 ;
-    foreach my $word (@_) {
-       if  ($word eq 'FATAL') {
+    my $no_fatal = 0 ;
+
+    foreach my $word ( @_ ) {
+       if ($word eq 'FATAL') {
            $fatal = 1;
+           $no_fatal = 0;
+       }
+       elsif ($word eq 'NONFATAL') {
+           $fatal = 0;
+           $no_fatal = 1;
        }
        elsif ($catmask = $Bits{$word}) {
            $mask |= $catmask ;
            $mask |= $DeadBits{$word} if $fatal ;
+           $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
        }
        else
           { Croaker("Unknown warnings category '$word'")}
@@ -626,24 +639,70 @@ sub bits {
     return $mask ;
 }
 
-sub import {
+sub import 
+{
     shift;
+
+    my $catmask ;
+    my $fatal = 0 ;
+    my $no_fatal = 0 ;
+
     my $mask = ${^WARNING_BITS} ;
+
     if (vec($mask, $Offsets{'all'}, 1)) {
         $mask |= $Bits{'all'} ;
         $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
     }
-    ${^WARNING_BITS} = $mask | bits(@_ ? @_ : 'all') ;
+    
+    push @_, 'all' unless @_;
+
+    foreach my $word ( @_ ) {
+       if ($word eq 'FATAL') {
+           $fatal = 1;
+           $no_fatal = 0;
+       }
+       elsif ($word eq 'NONFATAL') {
+           $fatal = 0;
+           $no_fatal = 1;
+       }
+       elsif ($catmask = $Bits{$word}) {
+           $mask |= $catmask ;
+           $mask |= $DeadBits{$word} if $fatal ;
+           $mask &= ~($DeadBits{$word}|$All) if $no_fatal ;
+       }
+       else
+          { Croaker("Unknown warnings category '$word'")}
+    }
+
+    ${^WARNING_BITS} = $mask ;
 }
 
-sub unimport {
+sub unimport 
+{
     shift;
+
+    my $catmask ;
     my $mask = ${^WARNING_BITS} ;
+
     if (vec($mask, $Offsets{'all'}, 1)) {
         $mask |= $Bits{'all'} ;
         $mask |= $DeadBits{'all'} if vec($mask, $Offsets{'all'}+1, 1);
     }
-    ${^WARNING_BITS} = $mask & ~ (bits('FATAL' => (@_ ? @_ : 'all')) | $All) ;
+
+    push @_, 'all' unless @_;
+
+    foreach my $word ( @_ ) {
+       if ($word eq 'FATAL') {
+           next; 
+       }
+       elsif ($catmask = $Bits{$word}) {
+           $mask &= ~($catmask | $DeadBits{$word} | $All);
+       }
+       else
+          { Croaker("Unknown warnings category '$word'")}
+    }
+
+    ${^WARNING_BITS} = $mask ;
 }
 
 sub __chk