This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Add support for new warning categories outside of "all"
authorÆvar Arnfjörð Bjarmason <avar@cpan.org>
Mon, 29 Dec 2014 20:04:01 +0000 (21:04 +0100)
committerÆvar Arnfjörð Bjarmason <avar@cpan.org>
Mon, 29 Dec 2014 20:13:53 +0000 (21:13 +0100)
When someone suggests a new warning on p5p it always often up being
argued about on the basis that it'll break existing code, and that we
shouldn't add warnings for possibly legitimate code just because it's
unusual or odd.

As I pointed out in a discussion about RT #121025 (see [1]) we only keep
having this discussion because until now we've had no facility to add
new warnings outside of the default set that'll be retroactively enabled
for everything that does 'use warnings'. This patch introduces such a
facility.

As a proof of concept I'm adding a warning for something that was added
as a warning in the past, but pulled out because it was deemed too
controversial at the time: warning about the use of grep in void
context.

That warning was added back in v5.10.0-218-g74295f0 but quickly pulled
out in v5.10.0-230-gf5df478. See [2] for the discussion about it at the
time.

Now if you do:

    use warnings;
    grep /42/, (1,2);

You'll get no warnings as before, but if you do:

    use warnings qw(extra); # Or its sole subcategory: void_unusual
    grep /42/, (1,2);

You'll get a warning about "Unusual use of grep in void context". To
turn off this warning once you've turned it on it's *not* sufficient to
do:

    no warnings;

You need to do:

    no warnings qw(pedantic);

Or:

    no warnings qw(everything);

I'm willing to change that, but first we should ask ourselves whether
this should continue to remain a symmetric operation:

    {use,no} warnings ['all'];

There's more elaboration on how this works in the changes I'm making to
the perldelta and the warnings documentation. But briefly this should be
100% backwards compatible, but allow us to have our cake and eat it too
in the future by adding new warnings without imposing them on existing
code written against older perl versions (unless that code explicitly
requested to get new warnings as they upgrade perl).

The patch to the warnings.pm documentation lays out a backwards
compatibility policy for warnings, we promise that we'll continue the
status quo with the "all" category, but for other categories (including
future additions) we'll make such promises on a per-category basis.

TODO: I wanted to come up with some more general facility for being able
to add these new warnings without altering the behavior of the -w and -W
switches. I.e. now we'll emit this, as intended:

    $ ./perl -Ilib -w -e 'grep /42/, (1,2)'
    $ ./perl -Ilib -W -e 'grep /42/, (1,2)'
    $ ./perl -Ilib -e 'use warnings; grep /42/, (1,2)'
    $ ./perl -Ilib -e 'use warnings "extra"; grep /42/, (1,2)'
    Unusual use of grep in void context at -e line 1.

I.e. we don't want -w and -W to mean "use warnings 'everything'", it
should continue to mean "use warnings 'all'". But due to how they're
implemented I couldn't find an easy way to generalize this. Right now
I'm just hardcoding an exception to the new warning category I've added
outside "all" for these warnings.

That should be followed-up with a more general solution, but for now if
we only have a few of these catogeries we should be fine.

This patch incorporates work from Andreas Guðmundsson
<andreasg@nasarde.org> who picked up an earlier version of mine and
figured out the change being made to mg.c here. That change removes an
optimization in the ${^WARNING_BITS} magic which might make things a tad
slower.

1. https://rt.perl.org/Ticket/Display.html?id=121025#txn-1276663
2. http://www.nntp.perl.org/group/perl.perl5.porters/2007/12/msg131922.html

13 files changed:
AUTHORS
lib/B/Deparse.t
lib/warnings.pm
mg.c
op.c
pod/perldelta.pod
pod/perldiag.pod
pod/perlrun.pod
regen/warnings.pl
t/lib/warnings/op
t/op/caller.t
util.c
warnings.h

diff --git a/AUTHORS b/AUTHORS
index 7990955..68da811 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -75,6 +75,7 @@ Ambrose Kofi Laing
 Ammon Riley                    <ammon@rhythm.com>
 Ananth Kesari                  <HYanantha@novell.com>
 Anders Johnson                 <ajohnson@nvidia.com>
+Andreas Guðmundsson           <andreasg@nasarde.org>
 Andreas Karrer                 <karrer@ife.ee.ethz.ch>
 Andreas Klussmann              <andreas@infosys.heitec.de>
 Andreas König                 <a.koenig@mind.de>
index c7bf611..74f37a7 100644 (file)
@@ -1857,12 +1857,12 @@ my sub f {}
 print f();
 >>>>
 use feature 'lexical_subs';
-BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUUU\005"}
+BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUT\005U\001"}
 my sub f {
-    BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUU\005"}
+    BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUT\005\001"}
     
 }
-BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUU\005"}
+BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUT\005\001"}
 print f();
 ####
 # SKIP ?$] < 5.017004 && "lexical subs not implemented on this Perl version"
@@ -1873,13 +1873,13 @@ state sub f {}
 print f();
 >>>>
 use feature 'lexical_subs';
-BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUUU\005"}
+BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUT\005U\001"}
 CORE::state sub f {
-    BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUU\005"}
+    BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUT\005\001"}
     use feature 'state';
     
 }
-BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUU\005"}
+BEGIN {${^WARNING_BITS} = "TUUUUUUUUUUUUTUT\005\001"}
 use feature 'state';
 print f();
 ####
index c86909c..5f18b40 100644 (file)
@@ -5,7 +5,7 @@
 
 package warnings;
 
-our $VERSION = '1.29';
+our $VERSION = '1.30';
 
 # Verify that we're called correctly so that warnings will work.
 # see also strict.pm.
@@ -93,15 +93,18 @@ our %Offsets = (
 
     # Warnings Categories added in Perl 5.021
 
-    'experimental::refaliasing'=> 120,
-    'experimental::win32_perlio'=> 122,
-    'locale'           => 124,
-    'missing'          => 126,
-    'redundant'                => 128,
+    'everything'       => 120,
+    'experimental::refaliasing'=> 122,
+    'experimental::win32_perlio'=> 124,
+    'locale'           => 126,
+    'missing'          => 128,
+    'redundant'                => 130,
+    'extra'            => 132,
+    'void_unusual'     => 134,
   );
 
 our %Bits = (
-    'all'              => "\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x01", # [0..64]
+    'all'              => "\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x54\x05", # [0..59,61..65]
     'ambiguous'                => "\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [29]
     'bareword'         => "\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [30]
     'closed'           => "\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [6]
@@ -109,18 +112,20 @@ our %Bits = (
     'debugging'                => "\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [22]
     'deprecated'       => "\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [2]
     'digit'            => "\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [31]
+    'everything'       => "\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55\x55", # [0..67]
     'exec'             => "\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [7]
     'exiting'          => "\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [3]
-    'experimental'     => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x55\x15\x05\x00", # [51..58,60,61]
+    'experimental'     => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x55\x15\x14\x00", # [51..58,61,62]
     'experimental::autoderef'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00", # [56]
     'experimental::lexical_subs'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00", # [52]
     'experimental::lexical_topic'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00", # [53]
     'experimental::postderef'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00", # [57]
-    'experimental::refaliasing'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00", # [60]
+    'experimental::refaliasing'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00", # [61]
     'experimental::regex_sets'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00", # [54]
     'experimental::signatures'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00", # [58]
     'experimental::smartmatch'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00", # [55]
-    'experimental::win32_perlio'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00", # [61]
+    'experimental::win32_perlio'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00", # [62]
+    'extra'            => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x50", # [66,67]
     'glob'             => "\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [4]
     'illegalproto'     => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00", # [47]
     'imprecision'      => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00", # [46]
@@ -128,10 +133,10 @@ our %Bits = (
     'internal'         => "\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [24]
     'io'               => "\x00\x54\x55\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00", # [5..11,59]
     'layer'            => "\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [8]
-    'locale'           => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00", # [62]
+    'locale'           => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00", # [63]
     'malloc'           => "\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [25]
     'misc'             => "\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [12]
-    'missing'          => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00", # [63]
+    'missing'          => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", # [64]
     'newline'          => "\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [9]
     'non_unicode'      => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00", # [48]
     'nonchar'          => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00", # [49]
@@ -148,7 +153,7 @@ our %Bits = (
     'qw'               => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00", # [36]
     'recursion'                => "\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [18]
     'redefine'         => "\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [19]
-    'redundant'                => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01", # [64]
+    'redundant'                => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04", # [65]
     'regexp'           => "\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [20]
     'reserved'         => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00", # [37]
     'semicolon'                => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00", # [38]
@@ -166,10 +171,11 @@ our %Bits = (
     'untie'            => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40\x00\x00\x00\x00\x00\x00", # [43]
     'utf8'             => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x15\x00\x00\x00\x00", # [44,48..50]
     'void'             => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00", # [45]
+    'void_unusual'     => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x40", # [67]
   );
 
 our %DeadBits = (
-    'all'              => "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\x02", # [0..64]
+    'all'              => "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xa8\x0a", # [0..59,61..65]
     'ambiguous'                => "\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [29]
     'bareword'         => "\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [30]
     'closed'           => "\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [6]
@@ -177,18 +183,20 @@ our %DeadBits = (
     'debugging'                => "\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [22]
     'deprecated'       => "\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [2]
     'digit'            => "\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [31]
+    'everything'       => "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", # [0..67]
     'exec'             => "\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [7]
     'exiting'          => "\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [3]
-    'experimental'     => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xaa\x2a\x0a\x00", # [51..58,60,61]
+    'experimental'     => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\xaa\x2a\x28\x00", # [51..58,61,62]
     'experimental::autoderef'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00", # [56]
     'experimental::lexical_subs'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00", # [52]
     'experimental::lexical_topic'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00", # [53]
     'experimental::postderef'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00", # [57]
-    'experimental::refaliasing'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00", # [60]
+    'experimental::refaliasing'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00", # [61]
     'experimental::regex_sets'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00", # [54]
     'experimental::signatures'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00", # [58]
     'experimental::smartmatch'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00", # [55]
-    'experimental::win32_perlio'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00", # [61]
+    'experimental::win32_perlio'=> "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00", # [62]
+    'extra'            => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa0", # [66,67]
     'glob'             => "\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [4]
     'illegalproto'     => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00", # [47]
     'imprecision'      => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00", # [46]
@@ -196,10 +204,10 @@ our %DeadBits = (
     'internal'         => "\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [24]
     'io'               => "\x00\xa8\xaa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00", # [5..11,59]
     'layer'            => "\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [8]
-    'locale'           => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00", # [62]
+    'locale'           => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00", # [63]
     'malloc'           => "\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [25]
     'misc'             => "\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [12]
-    'missing'          => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00", # [63]
+    'missing'          => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", # [64]
     'newline'          => "\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [9]
     'non_unicode'      => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00", # [48]
     'nonchar'          => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00", # [49]
@@ -216,7 +224,7 @@ our %DeadBits = (
     'qw'               => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00", # [36]
     'recursion'                => "\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [18]
     'redefine'         => "\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [19]
-    'redundant'                => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02", # [64]
+    'redundant'                => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08", # [65]
     'regexp'           => "\x00\x00\x00\x00\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", # [20]
     'reserved'         => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00\x00\x00", # [37]
     'semicolon'                => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00", # [38]
@@ -234,11 +242,12 @@ our %DeadBits = (
     'untie'            => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00", # [43]
     'utf8'             => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x2a\x00\x00\x00\x00", # [44,48..50]
     'void'             => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x08\x00\x00\x00\x00\x00", # [45]
+    'void_unusual'     => "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80", # [67]
   );
 
 $NONE     = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-$DEFAULT  = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x00\x55\x15\x15\x00", # [2,56,52,53,57,60,54,58,55,61,4,62,22,23,25]
-$LAST_BIT = 130 ;
+$DEFAULT  = "\x10\x01\x00\x00\x00\x50\x04\x00\x00\x00\x00\x00\x00\x55\x15\x54\x00", # [2,56,52,53,57,61,54,58,55,62,4,63,22,23,25]
+$LAST_BIT = 136 ;
 $BYTES    = 17 ;
 
 $All = "" ; vec($All, $Offsets{'all'}, 2) = 3 ;
@@ -520,12 +529,17 @@ be applied to their module.
 By default, optional warnings are disabled, so any legacy code that
 doesn't attempt to control the warnings will work unchanged.
 
-All warnings are enabled in a block by either of these:
+When we talk about "all" warnings we don't actually mean "all the
+warnings we support". See L</Top-level warning categories & associated
+confusion> for details. The "all" category should really be called the
+"default" category, if not for backwards-compatibility concerns.
+
+"All" warnings are enabled in a block by either of these:
 
     use warnings;
     use warnings 'all';
 
-Similarly all warnings are disabled in a block by either of these:
+Similarly "all" warnings are disabled in a block by either of these:
 
     no warnings;
     no warnings 'all';
@@ -643,7 +657,7 @@ details of how this flag interacts with lexical warnings.
 =item B<-W>
 X<-W>
 
-If the B<-W> flag is used on the command line, it will enable all warnings
+If the B<-W> flag is used on the command line, it will enable "all" warnings
 throughout the program regardless of whether warnings were disabled
 locally using C<no warnings> or C<$^W =0>.
 This includes all files that get
@@ -653,10 +667,80 @@ Think of it as the Perl equivalent of the "lint" command.
 =item B<-X>
 X<-X>
 
-Does the exact opposite to the B<-W> flag, i.e. it disables all warnings.
+Does the exact opposite to the B<-W> flag, i.e. it disables "all" warnings.
+
+=back
+
+=head2 Top-level warning categories & associated confusion
+
+The lexical warning pragma was introduced in v5.6.0 of perl, and from
+the very beginning doing C<use warnings> would enable the "all"
+category of warnings, which were all the warnings we support.
+
+This led to arguments whenever someone suggested a new warning be
+added to perl, since that implicitly meant that existing programs that
+used the warnings pragma would be retroactively subjected to them when
+perl was upgraded.
+
+So similarly to how most C compilers support C<-Wall> to mean "not
+quite all warnings" along with extra options like C<-Wextra>, we
+support warnings outside of the "all" category. Think of the "all"
+category as "default", that's what we'd call it we were starting out
+today and didn't have a bunch of programs doing C<use warnings "all">
+in the wild already.
+
+The categories we support are:
+
+=over
+
+=item * all
+
+This is the "default" category for warnings that we've supported ever
+since v5.6.0. We have and might occasionally add new warnings here if
+they're deemed to be similar in nature to our existing warnings, but
+mostly these are things we're pretty sure are a logic error, but
+aren't irrecoverable, so they're not a runtime error.
+
+When you upgrade perl you might find that we've added some new
+warnings here, but they won't be anything wildly different from the
+current set of warnings, so the burden of going through your existing
+code and auditing the new parts that are warning should be fairly
+light.
+
+=item * everything
+
+This is what "all" would be if the world made any sense, but since we
+started out with "all" you need to enable "everything" to really
+enable "all the warnings".
+
+You almost definitely don't want to enable "everything", unless you're
+willing to potentially get a flood of new warnings with every perl
+upgrade, and those warnings may be entirely different in spirit to
+existing warnings shipped with previous releases.
+
+Maybe we'll start introducing really pedantic warnings that aren't
+useful for most cases, maybe we'll start warning about inconsistent
+indentation, who knows? If you really want ALL the warnings perl has
+to offer enable these, otherwise stick with some more sane category.
+
+=item * extra
+
+These are warnings that we might have put into "all"
+(a.k.a. "default") if we had a time machine and were starting out with
+perl today, but they'd probably cause too much of a disruption today
+so we're not doing that.
+
+As of writing this the sole warning in this category is a warning
+about useless use of grep in void context, but unlike for the "all"
+category we reserve the right to freely add things to this category in
+the future.
 
 =back
 
+In the future we might add any number of other top-level
+categories. The backwards-compatibility promises of those categories
+(if any) will be documented here.
+
 =head2 Backward Compatibility
 
 If you are used to working with a version of Perl prior to the
@@ -713,135 +797,141 @@ to be enabled/disabled in isolation.
 
 The current hierarchy is:
 
-    all -+
-         |
-         +- closure
-         |
-         +- deprecated
-         |
-         +- exiting
-         |
-         +- experimental --+
-         |                 |
-         |                 +- experimental::autoderef
-         |                 |
-         |                 +- experimental::lexical_subs
-         |                 |
-         |                 +- experimental::lexical_topic
-         |                 |
-         |                 +- experimental::postderef
-         |                 |
-         |                 +- experimental::refaliasing
-         |                 |
-         |                 +- experimental::regex_sets
-         |                 |
-         |                 +- experimental::signatures
-         |                 |
-         |                 +- experimental::smartmatch
-         |                 |
-         |                 +- experimental::win32_perlio
-         |
-         +- glob
-         |
-         +- imprecision
-         |
-         +- io ------------+
-         |                 |
-         |                 +- closed
-         |                 |
-         |                 +- exec
-         |                 |
-         |                 +- layer
-         |                 |
-         |                 +- newline
-         |                 |
-         |                 +- pipe
-         |                 |
-         |                 +- syscalls
-         |                 |
-         |                 +- unopened
-         |
-         +- locale
-         |
-         +- misc
-         |
-         +- missing
-         |
-         +- numeric
-         |
-         +- once
-         |
-         +- overflow
-         |
-         +- pack
-         |
-         +- portable
-         |
-         +- recursion
-         |
-         +- redefine
-         |
-         +- redundant
-         |
-         +- regexp
-         |
-         +- severe --------+
-         |                 |
-         |                 +- debugging
-         |                 |
-         |                 +- inplace
-         |                 |
-         |                 +- internal
-         |                 |
-         |                 +- malloc
-         |
-         +- signal
-         |
-         +- substr
-         |
-         +- syntax --------+
-         |                 |
-         |                 +- ambiguous
-         |                 |
-         |                 +- bareword
-         |                 |
-         |                 +- digit
-         |                 |
-         |                 +- illegalproto
-         |                 |
-         |                 +- parenthesis
-         |                 |
-         |                 +- precedence
-         |                 |
-         |                 +- printf
-         |                 |
-         |                 +- prototype
-         |                 |
-         |                 +- qw
-         |                 |
-         |                 +- reserved
-         |                 |
-         |                 +- semicolon
-         |
-         +- taint
-         |
-         +- threads
-         |
-         +- uninitialized
-         |
-         +- unpack
-         |
-         +- untie
-         |
-         +- utf8 ----------+
-         |                 |
-         |                 +- non_unicode
-         |                 |
-         |                 +- nonchar
-         |                 |
-         |                 +- surrogate
-         |
-         +- void
+    everything -+
+                |
+                +- all ---+
+                |         |
+                |         +- closure
+                |         |
+                |         +- deprecated
+                |         |
+                |         +- exiting
+                |         |
+                |         +- experimental --+
+                |         |                 |
+                |         |                 +- experimental::autoderef
+                |         |                 |
+                |         |                 +- experimental::lexical_subs
+                |         |                 |
+                |         |                 +- experimental::lexical_topic
+                |         |                 |
+                |         |                 +- experimental::postderef
+                |         |                 |
+                |         |                 +- experimental::refaliasing
+                |         |                 |
+                |         |                 +- experimental::regex_sets
+                |         |                 |
+                |         |                 +- experimental::signatures
+                |         |                 |
+                |         |                 +- experimental::smartmatch
+                |         |                 |
+                |         |                 +- experimental::win32_perlio
+                |         |
+                |         +- glob
+                |         |
+                |         +- imprecision
+                |         |
+                |         +- io ------------+
+                |         |                 |
+                |         |                 +- closed
+                |         |                 |
+                |         |                 +- exec
+                |         |                 |
+                |         |                 +- layer
+                |         |                 |
+                |         |                 +- newline
+                |         |                 |
+                |         |                 +- pipe
+                |         |                 |
+                |         |                 +- syscalls
+                |         |                 |
+                |         |                 +- unopened
+                |         |
+                |         +- locale
+                |         |
+                |         +- misc
+                |         |
+                |         +- missing
+                |         |
+                |         +- numeric
+                |         |
+                |         +- once
+                |         |
+                |         +- overflow
+                |         |
+                |         +- pack
+                |         |
+                |         +- portable
+                |         |
+                |         +- recursion
+                |         |
+                |         +- redefine
+                |         |
+                |         +- redundant
+                |         |
+                |         +- regexp
+                |         |
+                |         +- severe --------+
+                |         |                 |
+                |         |                 +- debugging
+                |         |                 |
+                |         |                 +- inplace
+                |         |                 |
+                |         |                 +- internal
+                |         |                 |
+                |         |                 +- malloc
+                |         |
+                |         +- signal
+                |         |
+                |         +- substr
+                |         |
+                |         +- syntax --------+
+                |         |                 |
+                |         |                 +- ambiguous
+                |         |                 |
+                |         |                 +- bareword
+                |         |                 |
+                |         |                 +- digit
+                |         |                 |
+                |         |                 +- illegalproto
+                |         |                 |
+                |         |                 +- parenthesis
+                |         |                 |
+                |         |                 +- precedence
+                |         |                 |
+                |         |                 +- printf
+                |         |                 |
+                |         |                 +- prototype
+                |         |                 |
+                |         |                 +- qw
+                |         |                 |
+                |         |                 +- reserved
+                |         |                 |
+                |         |                 +- semicolon
+                |         |
+                |         +- taint
+                |         |
+                |         +- threads
+                |         |
+                |         +- uninitialized
+                |         |
+                |         +- unpack
+                |         |
+                |         +- untie
+                |         |
+                |         +- utf8 ----------+
+                |         |                 |
+                |         |                 +- non_unicode
+                |         |                 |
+                |         |                 +- nonchar
+                |         |                 |
+                |         |                 +- surrogate
+                |         |
+                |         +- void
+                |
+                +- extra -+
+                          |
+                          +- void_unusual
 
 Just like the "strict" pragma any of these categories can be combined
 
diff --git a/mg.c b/mg.c
index 4e6dcaf..a64801e 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -2774,17 +2774,6 @@ Perl_magic_set(pTHX_ SV *sv, MAGIC *mg)
                            PerlMemShared_free(PL_compiling.cop_warnings);
                        PL_compiling.cop_warnings = pWARN_NONE;
                    }
-                   /* Yuck. I can't see how to abstract this:  */
-                   else if (isWARN_on(
-                                ((STRLEN *)SvPV_nolen_const(sv)) - 1,
-                                WARN_ALL)
-                            && !any_fatals)
-                    {
-                       if (!specialWARN(PL_compiling.cop_warnings))
-                           PerlMemShared_free(PL_compiling.cop_warnings);
-                       PL_compiling.cop_warnings = pWARN_ALL;
-                       PL_dowarn |= G_WARN_ONCE ;
-                   }
                     else {
                        STRLEN len;
                        const char *const p = SvPV_const(sv, len);
diff --git a/op.c b/op.c
index 5a6e896..51b0bf0 100644 (file)
--- a/op.c
+++ b/op.c
@@ -1765,6 +1765,7 @@ Perl_scalarvoid(pTHX_ OP *arg)
     do {
         SV *useless_sv = NULL;
         const char* useless = NULL;
+        bool useless_is_grep = FALSE;
 
         if (o->op_type == OP_NEXTSTATE
             || o->op_type == OP_DBSTATE
@@ -1884,9 +1885,15 @@ Perl_scalarvoid(pTHX_ OP *arg)
         case OP_HELEM:
         case OP_HSLICE:
             if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO)))
-                /* Otherwise it's "Useless use of grep iterator" */
                 useless = OP_DESC(o);
             break;
+        case OP_GREPWHILE:
+            if (!(o->op_private & (OPpLVAL_INTRO|OPpOUR_INTRO))) {
+                /* Otherwise it's "Useless use of grep iterator" */
+                useless = "grep";
+                useless_is_grep = TRUE;
+            }
+            break;
 
         case OP_SPLIT:
             kid = cLISTOPo->op_first;
@@ -2116,9 +2123,15 @@ Perl_scalarvoid(pTHX_ OP *arg)
                            SVfARG(sv_2mortal(useless_sv)));
         }
         else if (useless) {
-            Perl_ck_warner(aTHX_ packWARN(WARN_VOID),
-                           "Useless use of %s in void context",
-                           useless);
+           if (useless_is_grep) {
+                Perl_ck_warner(aTHX_ packWARN(WARN_VOID_UNUSUAL),
+                               "Unusual use of %s in void context",
+                               useless);
+           } else {
+                Perl_ck_warner(aTHX_ packWARN(WARN_VOID),
+                               "Useless use of %s in void context",
+                               useless);
+           }
         }
     } while ( (o = POP_DEFERRED_OP()) );
 
index 4a9ac5a..6eecc00 100644 (file)
@@ -27,6 +27,21 @@ here, but most should go in the L</Performance Enhancements> section.
 
 [ List each enhancement as a =head2 entry ]
 
+=head2 The warnings pragma now supports warnings outside of "all"
+
+Ever since perl v5.6.0 we've had no way of adding new warnings without
+retroactively adding them to all existing programs that used C<-w>,
+C<-W> or C<use warnings>.
+
+This caused us to not add new useful warnings out of fear that they
+might unduly burden users who just wanted to upgrade perl and didn't
+want to deal with a bunch of warnings from their existing code.
+
+We now support a way to have our cake and eat it too, and can add new
+warnings to the core going forward through other top-level warning
+categories. See L<the warnings documentation|warnings/Top-level
+warning categories & associated confusion> for details.
+
 =head1 Security
 
 XXX Any security-related notices go here.  In particular, any security
index 0457474..1c845dd 100644 (file)
@@ -6473,6 +6473,17 @@ since they are often used in statements like
 String constants that would normally evaluate to 0 or 1 are warned
 about.
 
+=item Unusual use of %s in void context
+
+(W void_unusual) Similar to the "Useless use of %s in void context"
+warning, but only turned on by the top-level "pedantic" warning
+category, used for e.g. C<grep> in void context, which may indicate a
+bug, but could also just be someone using C<grep> for its side-effects
+as a loop.
+
+Enabled as part of "extra" warnings, not in the "all" category. See
+L<warnings> for details
+
 =item Useless use of (?-p) in regex; marked by S<<-- HERE> in m/%s/
 
 (W regexp) The C<p> modifier cannot be turned off once set.  Trying to do
index acf2702..0964a42 100644 (file)
@@ -925,13 +925,13 @@ of warnings; see L<warnings>.
 =item B<-W>
 X<-W>
 
-Enables all warnings regardless of C<no warnings> or C<$^W>.
+Enables "all" warnings regardless of C<no warnings> or C<$^W>.
 See L<warnings>.
 
 =item B<-X>
 X<-X>
 
-Disables all warnings regardless of C<use warnings> or C<$^W>.
+Disables "all" warnings regardless of C<use warnings> or C<$^W>.
 See L<warnings>.
 
 =item B<-x>
index 96e6d06..949617f 100644 (file)
@@ -28,91 +28,99 @@ sub DEFAULT_ON  () { 1 }
 sub DEFAULT_OFF () { 2 }
 
 my $tree = {
-
-'all' => [ 5.008, {
-       'io'            => [ 5.008, {
-                               'pipe'          => [ 5.008, DEFAULT_OFF],
-                                       'unopened'      => [ 5.008, DEFAULT_OFF],
-                                       'closed'        => [ 5.008, DEFAULT_OFF],
-                                       'newline'       => [ 5.008, DEFAULT_OFF],
-                                       'exec'          => [ 5.008, DEFAULT_OFF],
-                                       'layer'         => [ 5.008, DEFAULT_OFF],
-                               'syscalls'      => [ 5.019, DEFAULT_OFF],
-                          }],
-       'syntax'        => [ 5.008, {
-                               'ambiguous'     => [ 5.008, DEFAULT_OFF],
-                               'semicolon'     => [ 5.008, DEFAULT_OFF],
-                               'precedence'    => [ 5.008, DEFAULT_OFF],
-                               'bareword'      => [ 5.008, DEFAULT_OFF],
-                               'reserved'      => [ 5.008, DEFAULT_OFF],
-                               'digit'         => [ 5.008, DEFAULT_OFF],
-                               'parenthesis'   => [ 5.008, DEFAULT_OFF],
-                                       'printf'        => [ 5.008, DEFAULT_OFF],
-                                       'prototype'     => [ 5.008, DEFAULT_OFF],
-                                       'qw'            => [ 5.008, DEFAULT_OFF],
-                                'illegalproto'  => [ 5.011, DEFAULT_OFF],
-                          }],
-               'severe'        => [ 5.008, {
-                               'inplace'       => [ 5.008, DEFAULT_ON],
-                               'internal'      => [ 5.008, DEFAULT_OFF],
-                               'debugging'     => [ 5.008, DEFAULT_ON],
-                               'malloc'        => [ 5.008, DEFAULT_ON],
-                          }],
-        'deprecated'   => [ 5.008, DEFAULT_ON],
-               'void'          => [ 5.008, DEFAULT_OFF],
-               'recursion'     => [ 5.008, DEFAULT_OFF],
-               'redefine'      => [ 5.008, DEFAULT_OFF],
-               'numeric'       => [ 5.008, DEFAULT_OFF],
-        'uninitialized'        => [ 5.008, DEFAULT_OFF],
-               'once'          => [ 5.008, DEFAULT_OFF],
-               'misc'          => [ 5.008, DEFAULT_OFF],
-               'regexp'        => [ 5.008, DEFAULT_OFF],
-               'glob'          => [ 5.008, DEFAULT_ON],
-               'untie'         => [ 5.008, DEFAULT_OFF],
-       'substr'        => [ 5.008, DEFAULT_OFF],
-       'taint'         => [ 5.008, DEFAULT_OFF],
-       'signal'        => [ 5.008, DEFAULT_OFF],
-       'closure'       => [ 5.008, DEFAULT_OFF],
-       'overflow'      => [ 5.008, DEFAULT_OFF],
-       'portable'      => [ 5.008, DEFAULT_OFF],
-       'utf8'          => [ 5.008, {
-                                'surrogate' => [ 5.013, DEFAULT_OFF],
-                                'nonchar' => [ 5.013, DEFAULT_OFF],
-                                'non_unicode' => [ 5.013, DEFAULT_OFF],
-                        }],
-               'exiting'       => [ 5.008, DEFAULT_OFF],
-               'pack'          => [ 5.008, DEFAULT_OFF],
-               'unpack'        => [ 5.008, DEFAULT_OFF],
-               'threads'       => [ 5.008, DEFAULT_OFF],
-               'imprecision'   => [ 5.011, DEFAULT_OFF],
-               'experimental'  => [ 5.017, {
-                                'experimental::lexical_subs' =>
-                                    [ 5.017, DEFAULT_ON ],
-                                'experimental::regex_sets' =>
-                                    [ 5.017, DEFAULT_ON ],
-                                'experimental::lexical_topic' =>
-                                    [ 5.017, DEFAULT_ON ],
-                                'experimental::smartmatch' =>
-                                    [ 5.017, DEFAULT_ON ],
-                                'experimental::postderef' =>
-                                    [ 5.019, DEFAULT_ON ],
-                                'experimental::autoderef' =>
-                                    [ 5.019, DEFAULT_ON ],
-                                'experimental::signatures' =>
-                                    [ 5.019, DEFAULT_ON ],
-                                'experimental::win32_perlio' =>
-                                    [ 5.021, DEFAULT_ON ],
-                                'experimental::refaliasing' =>
-                                    [ 5.021, DEFAULT_ON ],
-                        }],
-
-               'missing'       => [ 5.021, DEFAULT_OFF],
-               'redundant'     => [ 5.021, DEFAULT_OFF],
-        'locale'       => [ 5.021, DEFAULT_ON],
-
-                #'default'     => [ 5.008, DEFAULT_ON ],
-       }],
-} ;
+'everything' => [ 5.021, {
+        'all' => [ 5.008, {
+                'io'            => [ 5.008, {
+                                        'pipe'          => [ 5.008, DEFAULT_OFF],
+                                        'unopened'      => [ 5.008, DEFAULT_OFF],
+                                        'closed'        => [ 5.008, DEFAULT_OFF],
+                                        'newline'       => [ 5.008, DEFAULT_OFF],
+                                        'exec'          => [ 5.008, DEFAULT_OFF],
+                                        'layer'         => [ 5.008, DEFAULT_OFF],
+                                        'syscalls'      => [ 5.019, DEFAULT_OFF],
+                                   }],
+                'syntax'        => [ 5.008, {
+                                        'ambiguous'     => [ 5.008, DEFAULT_OFF],
+                                        'semicolon'     => [ 5.008, DEFAULT_OFF],
+                                        'precedence'    => [ 5.008, DEFAULT_OFF],
+                                        'bareword'      => [ 5.008, DEFAULT_OFF],
+                                        'reserved'      => [ 5.008, DEFAULT_OFF],
+                                        'digit'         => [ 5.008, DEFAULT_OFF],
+                                        'parenthesis'   => [ 5.008, DEFAULT_OFF],
+                                        'printf'        => [ 5.008, DEFAULT_OFF],
+                                        'prototype'     => [ 5.008, DEFAULT_OFF],
+                                        'qw'            => [ 5.008, DEFAULT_OFF],
+                                        'illegalproto'  => [ 5.011, DEFAULT_OFF],
+                                   }],
+                'severe'        => [ 5.008, {
+                                        'inplace'       => [ 5.008, DEFAULT_ON],
+                                        'internal'      => [ 5.008, DEFAULT_OFF],
+                                        'debugging'     => [ 5.008, DEFAULT_ON],
+                                        'malloc'        => [ 5.008, DEFAULT_ON],
+                                   }],
+                'deprecated'    => [ 5.008, DEFAULT_ON],
+                'void'          => [ 5.008, DEFAULT_OFF],
+                'recursion'     => [ 5.008, DEFAULT_OFF],
+                'redefine'      => [ 5.008, DEFAULT_OFF],
+                'numeric'       => [ 5.008, DEFAULT_OFF],
+                'uninitialized' => [ 5.008, DEFAULT_OFF],
+                'once'          => [ 5.008, DEFAULT_OFF],
+                'misc'          => [ 5.008, DEFAULT_OFF],
+                'regexp'        => [ 5.008, DEFAULT_OFF],
+                'glob'          => [ 5.008, DEFAULT_ON],
+                'untie'         => [ 5.008, DEFAULT_OFF],
+                'substr'        => [ 5.008, DEFAULT_OFF],
+                'taint'         => [ 5.008, DEFAULT_OFF],
+                'signal'        => [ 5.008, DEFAULT_OFF],
+                'closure'       => [ 5.008, DEFAULT_OFF],
+                'overflow'      => [ 5.008, DEFAULT_OFF],
+                'portable'      => [ 5.008, DEFAULT_OFF],
+                'utf8'          => [ 5.008, {
+                                        'surrogate' => [ 5.013, DEFAULT_OFF],
+                                        'nonchar' => [ 5.013, DEFAULT_OFF],
+                                        'non_unicode' => [ 5.013, DEFAULT_OFF],
+                                }],
+                'exiting'       => [ 5.008, DEFAULT_OFF],
+                'pack'          => [ 5.008, DEFAULT_OFF],
+                'unpack'        => [ 5.008, DEFAULT_OFF],
+                'threads'       => [ 5.008, DEFAULT_OFF],
+                'imprecision'   => [ 5.011, DEFAULT_OFF],
+                'experimental'  => [ 5.017, {
+                                        'experimental::lexical_subs' =>
+                                            [ 5.017, DEFAULT_ON ],
+                                        'experimental::regex_sets' =>
+                                            [ 5.017, DEFAULT_ON ],
+                                        'experimental::lexical_topic' =>
+                                            [ 5.017, DEFAULT_ON ],
+                                        'experimental::smartmatch' =>
+                                            [ 5.017, DEFAULT_ON ],
+                                        'experimental::postderef' =>
+                                            [ 5.019, DEFAULT_ON ],
+                                        'experimental::autoderef' =>
+                                            [ 5.019, DEFAULT_ON ],
+                                        'experimental::signatures' =>
+                                            [ 5.019, DEFAULT_ON ],
+                                        'experimental::win32_perlio' =>
+                                            [ 5.021, DEFAULT_ON ],
+                                        'experimental::refaliasing' =>
+                                            [ 5.021, DEFAULT_ON ],
+                                }],
+
+                'missing'       => [ 5.021, DEFAULT_OFF],
+                'redundant'     => [ 5.021, DEFAULT_OFF],
+                'locale'        => [ 5.021, DEFAULT_ON],
+
+                 #'default'     => [ 5.008, DEFAULT_ON ],
+        }],
+
+        # When adding new warnings outside of "all" make sure to
+        # either patch util.c to ignore them under -w and -W, or to
+        # generalize the facility for adding them so that it knows
+        # about warnings outside of "all".
+        'extra' => [ 5.021, {
+                'void_unusual'     => [ 5.021, DEFAULT_OFF],
+        }],
+}]};
 
 my @def ;
 my %list ;
@@ -478,7 +486,7 @@ read_only_bottom_close_and_rename($pm);
 __END__
 package warnings;
 
-our $VERSION = '1.29';
+our $VERSION = '1.30';
 
 # Verify that we're called correctly so that warnings will work.
 # see also strict.pm.
@@ -768,12 +776,17 @@ be applied to their module.
 By default, optional warnings are disabled, so any legacy code that
 doesn't attempt to control the warnings will work unchanged.
 
-All warnings are enabled in a block by either of these:
+When we talk about "all" warnings we don't actually mean "all the
+warnings we support". See L</Top-level warning categories & associated
+confusion> for details. The "all" category should really be called the
+"default" category, if not for backwards-compatibility concerns.
+
+"All" warnings are enabled in a block by either of these:
 
     use warnings;
     use warnings 'all';
 
-Similarly all warnings are disabled in a block by either of these:
+Similarly "all" warnings are disabled in a block by either of these:
 
     no warnings;
     no warnings 'all';
@@ -891,7 +904,7 @@ details of how this flag interacts with lexical warnings.
 =item B<-W>
 X<-W>
 
-If the B<-W> flag is used on the command line, it will enable all warnings
+If the B<-W> flag is used on the command line, it will enable "all" warnings
 throughout the program regardless of whether warnings were disabled
 locally using C<no warnings> or C<$^W =0>.
 This includes all files that get
@@ -901,10 +914,80 @@ Think of it as the Perl equivalent of the "lint" command.
 =item B<-X>
 X<-X>
 
-Does the exact opposite to the B<-W> flag, i.e. it disables all warnings.
+Does the exact opposite to the B<-W> flag, i.e. it disables "all" warnings.
 
 =back
 
+=head2 Top-level warning categories & associated confusion
+
+The lexical warning pragma was introduced in v5.6.0 of perl, and from
+the very beginning doing C<use warnings> would enable the "all"
+category of warnings, which were all the warnings we support.
+
+This led to arguments whenever someone suggested a new warning be
+added to perl, since that implicitly meant that existing programs that
+used the warnings pragma would be retroactively subjected to them when
+perl was upgraded.
+
+So similarly to how most C compilers support C<-Wall> to mean "not
+quite all warnings" along with extra options like C<-Wextra>, we
+support warnings outside of the "all" category. Think of the "all"
+category as "default", that's what we'd call it we were starting out
+today and didn't have a bunch of programs doing C<use warnings "all">
+in the wild already.
+
+The categories we support are:
+
+=over
+
+=item * all
+
+This is the "default" category for warnings that we've supported ever
+since v5.6.0. We have and might occasionally add new warnings here if
+they're deemed to be similar in nature to our existing warnings, but
+mostly these are things we're pretty sure are a logic error, but
+aren't irrecoverable, so they're not a runtime error.
+
+When you upgrade perl you might find that we've added some new
+warnings here, but they won't be anything wildly different from the
+current set of warnings, so the burden of going through your existing
+code and auditing the new parts that are warning should be fairly
+light.
+
+=item * everything
+
+This is what "all" would be if the world made any sense, but since we
+started out with "all" you need to enable "everything" to really
+enable "all the warnings".
+
+You almost definitely don't want to enable "everything", unless you're
+willing to potentially get a flood of new warnings with every perl
+upgrade, and those warnings may be entirely different in spirit to
+existing warnings shipped with previous releases.
+
+Maybe we'll start introducing really pedantic warnings that aren't
+useful for most cases, maybe we'll start warning about inconsistent
+indentation, who knows? If you really want ALL the warnings perl has
+to offer enable these, otherwise stick with some more sane category.
+
+=item * extra
+
+These are warnings that we might have put into "all"
+(a.k.a. "default") if we had a time machine and were starting out with
+perl today, but they'd probably cause too much of a disruption today
+so we're not doing that.
+
+As of writing this the sole warning in this category is a warning
+about useless use of grep in void context, but unlike for the "all"
+category we reserve the right to freely add things to this category in
+the future.
+
+=back
+
+In the future we might add any number of other top-level
+categories. The backwards-compatibility promises of those categories
+(if any) will be documented here.
+
 =head2 Backward Compatibility
 
 If you are used to working with a version of Perl prior to the
index 4290bcb..a468ebe 100644 (file)
@@ -417,6 +417,7 @@ $a <=> $b;          # OP_NCMP
 use 5.015;
 __SUB__        ;               # OP_RUNCV
 [];                    # OP_ANONLIST
+grep /42/, (1,2);      # OP_GREP, not warned about, in the "everything" & "void_unusual" category
 EXPECT
 Useless use of a constant ("111") in void context at - line 2.
 Useless use of repeat (x) in void context at - line 3.
@@ -466,6 +467,17 @@ Useless use of __SUB__ in void context at - line 61.
 Useless use of anonymous array ([]) in void context at - line 62.
 ########
 # op.c
+use warnings 'void_unusual' ; close STDIN ;
+grep /42/, (1,2);      # OP_GREP
+no warnings 'void_unusual';
+grep /42/, (1,2);      # OP_GREP
+use warnings 'everything';
+grep /42/, (1,2);      # OP_GREP
+EXPECT
+Unusual use of grep in void context at - line 3.
+Unusual use of grep in void context at - line 7.
+########
+# op.c
 use warnings 'void' ; close STDIN ;
 my $x = sort (2,1,3);
 no warnings 'void' ;
index 6e56d67..760c412 100644 (file)
@@ -106,15 +106,14 @@ sub testwarn {
            vec($default, $i, 2) = 1;
        }
        $registered = $default;
-       vec($registered, $warnings::LAST_BIT/2, 2) = 1;
     }
 
     BEGIN { check_bits( ${^WARNING_BITS}, "\0" x $warnings::BYTES, 'all bits off via "no warnings"' ) }
     testwarn("\0" x $warnings::BYTES, 'no bits');
 
-    use warnings;
+    use warnings qw(everything);
     BEGIN { check_bits( ${^WARNING_BITS}, $default,
-                       'default bits on via "use warnings"' ); }
+                       'all bits on via "use warnings qw(everything)"' ); }
     BEGIN { testwarn($default, 'all'); }
     # run-time :
     # the warning mask has been extended by warnings::register
diff --git a/util.c b/util.c
index 3737a01..7efc986 100644 (file)
--- a/util.c
+++ b/util.c
@@ -1944,8 +1944,13 @@ bool
 Perl_ckwarn(pTHX_ U32 w)
 {
     /* If lexical warnings have not been set, use $^W.  */
-    if (isLEXWARN_off)
-       return PL_dowarn & G_WARN_ON;
+    if (isLEXWARN_off) {
+       /* TODO: Hardcoding this here sucks, see the commit that added this */
+       if (w == WARN_VOID_UNUSUAL)
+           return FALSE;
+       else
+           return PL_dowarn & G_WARN_ON;
+    }
 
     return ckwarn_common(w);
 }
@@ -1956,8 +1961,13 @@ bool
 Perl_ckwarn_d(pTHX_ U32 w)
 {
     /* If lexical warnings have not been set then default classes warn.  */
-    if (isLEXWARN_off)
-       return TRUE;
+    if (isLEXWARN_off) {
+       /* TODO: Hardcoding this here sucks, see the commit that added this */
+       if (w == WARN_VOID_UNUSUAL)
+           return FALSE;
+       else
+           return TRUE;
+    }
 
     return ckwarn_common(w);
 }
@@ -1965,8 +1975,13 @@ Perl_ckwarn_d(pTHX_ U32 w)
 static bool
 S_ckwarn_common(pTHX_ U32 w)
 {
-    if (PL_curcop->cop_warnings == pWARN_ALL)
-       return TRUE;
+    if (PL_curcop->cop_warnings == pWARN_ALL) {
+       /* TODO: Hardcoding this here sucks, see the commit that added this */
+       if (w == WARN_VOID_UNUSUAL)
+           return FALSE;
+       else
+           return TRUE;
+    }
 
     if (PL_curcop->cop_warnings == pWARN_NONE)
        return FALSE;
index 7495f82..323e5c8 100644 (file)
 
 /* Warnings Categories added in Perl 5.021 */
 
-#define WARN_EXPERIMENTAL__REFALIASING 60
-#define WARN_EXPERIMENTAL__WIN32_PERLIO 61
-#define WARN_LOCALE             62
-#define WARN_MISSING            63
-#define WARN_REDUNDANT          64
+#define WARN_EVERYTHING                 60
+#define WARN_EXPERIMENTAL__REFALIASING 61
+#define WARN_EXPERIMENTAL__WIN32_PERLIO 62
+#define WARN_LOCALE             63
+#define WARN_MISSING            64
+#define WARN_REDUNDANT          65
+#define WARN_EXTRA              66
+#define WARN_VOID_UNUSUAL       67
 
 #define WARNsize               17
 #define WARN_ALLstring         "\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125\125"