summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/warnings.pm62
-rw-r--r--regen/warnings.pl62
-rw-r--r--t/lib/warnings/2use51
3 files changed, 159 insertions, 16 deletions
diff --git a/lib/warnings.pm b/lib/warnings.pm
index 595792cd8e..6f3420b8dd 100644
--- a/lib/warnings.pm
+++ b/lib/warnings.pm
@@ -5,7 +5,7 @@
package warnings;
-our $VERSION = "1.48";
+our $VERSION = "1.49";
# Verify that we're called correctly so that warnings will work.
# Can't use Carp, since Carp uses us!
@@ -335,16 +335,24 @@ sub bits
sub import
{
- shift;
-
- my $mask = ${^WARNING_BITS} // ($^W ? $Bits{all} : $DEFAULT) ;
+ my $invocant = shift;
# append 'all' when implied (empty import list or after a lone
# "FATAL" or "NONFATAL")
push @_, 'all'
- if !@_ || (@_==1 && ($_[0] eq 'FATAL' || $_[0] eq 'NONFATAL'));
-
- ${^WARNING_BITS} = _bits($mask, @_);
+ if !@_ || (@_==1 && ($_[0] eq 'FATAL' || $_[0] eq 'NONFATAL'));
+
+ my @fatal = ();
+ foreach my $warning (@_) {
+ if($warning =~ /^(NON)?FATAL$/) {
+ @fatal = ($warning);
+ } elsif(substr($warning, 0, 1) ne '-') {
+ my $mask = ${^WARNING_BITS} // ($^W ? $Bits{all} : $DEFAULT) ;
+ ${^WARNING_BITS} = _bits($mask, @fatal, $warning);
+ } else {
+ $invocant->unimport(substr($warning, 1));
+ }
+ }
}
sub unimport
@@ -571,7 +579,10 @@ warnings - Perl pragma to control optional warnings
no warnings;
use warnings "all";
- no warnings "all";
+ no warnings "uninitialized";
+
+ # or equivalent to those last two ...
+ use warnings qw(all -uninitialized);
use warnings::register;
if (warnings::enabled()) {
@@ -658,6 +669,41 @@ be reported for the C<$x> variable.
Note that neither the B<-w> flag or the C<$^W> can be used to
disable/enable default warnings. They are still mandatory in this case.
+=head2 "Negative warnings"
+
+As a convenience, you can (as of Perl 5.34) pass arguments to the
+C<import()> method both positively and negatively. Negative warnings
+are those with a C<-> sign prepended to their names; positive warnings
+are anything else. This lets you turn on some warnings and turn off
+others in one command. So, assuming that you've already turned on a
+bunch of warnings but want to tweak them a bit in some block, you can
+do this:
+
+ {
+ use warnings qw(uninitialized -redefine);
+ ...
+ }
+
+which is equivalent to:
+
+ {
+ use warnings qw(uninitialized);
+ no warnings qw(redefine);
+ ...
+ }
+
+The argument list is processed in the order you specify. So, for example, if you
+don't want to be warned about use of experimental features, except for C<somefeature>
+that you really dislike, you can say this:
+
+ use warnings qw(all -experimental experimental::somefeature);
+
+which is equivalent to:
+
+ use warnings 'all';
+ no warnings 'experimental';
+ use warnings 'experimental::somefeature';
+
=head2 What's wrong with B<-w> and C<$^W>
Although very useful, the big problem with using B<-w> on the command
diff --git a/regen/warnings.pl b/regen/warnings.pl
index cf07974693..498b93e285 100644
--- a/regen/warnings.pl
+++ b/regen/warnings.pl
@@ -16,7 +16,7 @@
#
# This script is normally invoked from regen.pl.
-$VERSION = '1.48';
+$VERSION = '1.49';
BEGIN {
require './regen/regen_lib.pl';
@@ -639,16 +639,24 @@ sub bits
sub import
{
- shift;
-
- my $mask = ${^WARNING_BITS} // ($^W ? $Bits{all} : $DEFAULT) ;
+ my $invocant = shift;
# append 'all' when implied (empty import list or after a lone
# "FATAL" or "NONFATAL")
push @_, 'all'
- if !@_ || (@_==1 && ($_[0] eq 'FATAL' || $_[0] eq 'NONFATAL'));
-
- ${^WARNING_BITS} = _bits($mask, @_);
+ if !@_ || (@_==1 && ($_[0] eq 'FATAL' || $_[0] eq 'NONFATAL'));
+
+ my @fatal = ();
+ foreach my $warning (@_) {
+ if($warning =~ /^(NON)?FATAL$/) {
+ @fatal = ($warning);
+ } elsif(substr($warning, 0, 1) ne '-') {
+ my $mask = ${^WARNING_BITS} // ($^W ? $Bits{all} : $DEFAULT) ;
+ ${^WARNING_BITS} = _bits($mask, @fatal, $warning);
+ } else {
+ $invocant->unimport(substr($warning, 1));
+ }
+ }
}
sub unimport
@@ -875,7 +883,10 @@ warnings - Perl pragma to control optional warnings
no warnings;
use warnings "all";
- no warnings "all";
+ no warnings "uninitialized";
+
+ # or equivalent to those last two ...
+ use warnings qw(all -uninitialized);
use warnings::register;
if (warnings::enabled()) {
@@ -962,6 +973,41 @@ be reported for the C<$x> variable.
Note that neither the B<-w> flag or the C<$^W> can be used to
disable/enable default warnings. They are still mandatory in this case.
+=head2 "Negative warnings"
+
+As a convenience, you can (as of Perl 5.34) pass arguments to the
+C<import()> method both positively and negatively. Negative warnings
+are those with a C<-> sign prepended to their names; positive warnings
+are anything else. This lets you turn on some warnings and turn off
+others in one command. So, assuming that you've already turned on a
+bunch of warnings but want to tweak them a bit in some block, you can
+do this:
+
+ {
+ use warnings qw(uninitialized -redefine);
+ ...
+ }
+
+which is equivalent to:
+
+ {
+ use warnings qw(uninitialized);
+ no warnings qw(redefine);
+ ...
+ }
+
+The argument list is processed in the order you specify. So, for example, if you
+don't want to be warned about use of experimental features, except for C<somefeature>
+that you really dislike, you can say this:
+
+ use warnings qw(all -experimental experimental::somefeature);
+
+which is equivalent to:
+
+ use warnings 'all';
+ no warnings 'experimental';
+ use warnings 'experimental::somefeature';
+
=head2 What's wrong with B<-w> and C<$^W>
Although very useful, the big problem with using B<-w> on the command
diff --git a/t/lib/warnings/2use b/t/lib/warnings/2use
index 4df98e2baa..f66b758a58 100644
--- a/t/lib/warnings/2use
+++ b/t/lib/warnings/2use
@@ -79,6 +79,57 @@ EXPECT
Useless use of a constant ("foobar") in void context at - line 3.
########
+# Check -negative import with no other args
+use warnings qw(-syntax);
+sub foo { 'foo' }
+my $a =+ 1 ; # syntax: shouldn't warn, it was never turned on
+*foo = sub { 'bar' }; # redefine: shouldn't warn, it was never turned on
+$a = 'foo' . undef; # uninitialized: shouldn't warn, it was never turned on
+EXPECT
+########
+
+# Check -negative import after turning all warnings on
+use warnings qw(all -syntax);
+sub foo { 'foo' }
+my $a =+ 1 ; # syntax: shouldn't warn, we've turned that off
+*foo = sub { 'bar' }; # redefine: should warn, as there was an explicit 'all'
+$a = 'foo' . undef; # uninitialized: should warn, as there was an explicit 'all'
+EXPECT
+Subroutine main::foo redefined at - line 6.
+Use of uninitialized value in concatenation (.) or string at - line 7.
+########
+
+# Check -negative import with an explicit import
+use warnings qw(redefine -syntax);
+sub foo { 'foo' }
+my $a =+ 1 ; # syntax: shouldn't warn, it was never turned on
+*foo = sub { 'bar' }; # redefine: should warn, as there was an explicit 'redefine'
+$a = 'foo' . undef; # uninitialized: shouldn't warn, as explicit 'redefine' means no implicit 'all'
+EXPECT
+Subroutine main::foo redefined at - line 6.
+########
+
+# Check multiple -negative imports
+use warnings qw(all -syntax -uninitialized);
+sub foo { 'foo' }
+my $a =+ 1 ; # syntax: shouldn't warn, we've turned that off
+*foo = sub { 'bar' }; # redefine: should warn, as there was an explicit 'all'
+$a = 'foo' . undef; # uninitialized: shouldn't warn, we've turned it off
+EXPECT
+Subroutine main::foo redefined at - line 6.
+########
+
+# Check mixed list of +ve and -ve imports
+use warnings qw(all -once -syntax parenthesis);
+sub foo { 'foo' }
+*foo = sub { 'bar' }; # redefined: should warn, as it was turned on by 'all'
+my $a =+ 1 ; # syntax: shouldn't warn, we've turned that off
+my $foo, $bar = @_; # parenthesis: should warn, as we turned that back on after disabling 'syntax'
+EXPECT
+Parentheses missing around "my" list at - line 7.
+Subroutine main::foo redefined at - line 5.
+########
+
--FILE-- abc
my $a =+ 1 ;
1;