In perl.git, the branch blead has been updated

<http://perl5.git.perl.org/perl.git/commitdiff/c306e834a2e7e21d20699178dd251b8b8171bc14?hp=18815322461f60e34160149ded6798d9d9304468>

- Log -----------------------------------------------------------------
commit c306e834a2e7e21d20699178dd251b8b8171bc14
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 23:29:21 2011 -0800

    Deparse: detect hh changes properly
    
    The hack to check whether the hint hash has changed doesn’t work.  One
    actually has to iterate through the hash.  Since declare_hinthash does
    that already, just call it.
    
    The change to declare_hinthash to return an empty list instead of ''
    is one of those theoretical speed-ups.  It results in one less state-
    ment and two fewer method calls in its caller.

M       dist/B-Deparse/Deparse.pm
M       dist/B-Deparse/t/deparse.t

commit 70397346423dee021539e9ebb34b4cf1e097ca50
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 23:18:00 2011 -0800

    Adjust docs to match new ver decl behaviour

M       lib/feature.pm
M       pod/perlfunc.pod

commit 035146a3ca31411488f684bee10fdd30d32ba7c3
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 23:07:49 2011 -0800

    Deparse funny keys/values in hh properly
    
    Simply putting '...' or q(...) around a string is not sufficient to
    quote it properly, allowing this sort of ‘fun’:
    
    $ perl -l -MO=Deparse -e'BEGIN{$^H{"'\''.'\''"} = "um);\n    exit("}print'
    BEGIN { $/ = "\n"; $\ = "\n"; }
    sub BEGIN {
        $^H{q['.']} = "um);\n    exit(";
    }
    BEGIN {
        $^H{''.''} = q(um);
        exit();
    }
    print $_;
    -e syntax OK
    
    And B::Deparse already has a facility for quoting strings, so why
    not use it?

M       dist/B-Deparse/Deparse.pm
M       dist/B-Deparse/t/deparse.t

commit 51530e339190db7a300f01c70489f30e1f4a5d01
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 23:01:24 2011 -0800

    Fix up ext/B/t for strict.pm changes

M       ext/B/t/f_map.t
M       ext/B/t/f_sort.t
M       ext/B/t/optree_check.t
M       ext/B/t/optree_constants.t
M       ext/B/t/optree_samples.t
M       ext/B/t/optree_specials.t

commit 04be0204ef928fb968a23b10c5c3bc555389ad14
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 22:58:31 2011 -0800

    Fix deparsing of undefined hint hash values
    
    Undefined values in the hint hash were being deparsed as empty
    strings.  Whenever the hint hash changed, all undefined values, even
    those unmodified, were being printed.

M       dist/B-Deparse/Deparse.pm
M       dist/B-Deparse/t/deparse.t

commit 789fcc52f1a244cfb3e6199774a68c4dc8178682
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 21:33:18 2011 -0800

    use 5.xxx: Don’t load feature.pm unnecessarily
    
    And don’t look in the hint hash unless the LOCALIZE_HH hint is set.

M       op.c

commit 7e294c409ff76fbad8ae5ea35ec2b17915ef8005
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 18:20:19 2011 -0800

    more tests for partial strictures and ver decls

M       t/comp/use.t

commit b50b20584a1bbc1ab57f936301547125d5f4122b
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 18:12:14 2011 -0800

    Implement new ‘use 5.xxx' plan
    
    • Version declarations now unload all features before loading the
      specified feature bundle.
    • Explicit use/no strict overrides any implicit strict-loading done by
      version declarations, whether before or after use of strict.pm.
    • ‘use 5.01’ or earlier disables any implicitly-enabled strictures.

M       lib/strict.pm
M       op.c
M       t/comp/use.t
M       t/lib/feature/implicit

commit 0c9fdf2c6b80bede18dc1c30b17e9c1379e379d8
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 16:54:18 2011 -0800

    Document :default feature bundle

M       lib/feature.pm

commit 4a4443f2c61db10a717416b08e8be299d7100ef1
Author: Father Chrysostomos <[email protected]>
Date:   Tue Dec 6 14:50:16 2011 -0800

    Add :default feature bundle

M       lib/feature.pm
M       t/lib/feature/bundle
-----------------------------------------------------------------------

Summary of changes:
 dist/B-Deparse/Deparse.pm  |   22 +++++++---
 dist/B-Deparse/t/deparse.t |   24 +++++++++++
 ext/B/t/f_map.t            |   52 ++++++++++++------------
 ext/B/t/f_sort.t           |   92 ++++++++++++++++++++++----------------------
 ext/B/t/optree_check.t     |    4 +-
 ext/B/t/optree_constants.t |   24 ++++++------
 ext/B/t/optree_samples.t   |   28 +++++++-------
 ext/B/t/optree_specials.t  |   72 +++++++++++++++++-----------------
 lib/feature.pm             |   13 +++++-
 lib/strict.pm              |   11 +++--
 op.c                       |   33 +++++++++++++++-
 pod/perlfunc.pod           |   12 ++++--
 t/comp/use.t               |   32 +++++++++++++++-
 t/lib/feature/bundle       |   11 +++++
 t/lib/feature/implicit     |   14 +++++++
 15 files changed, 287 insertions(+), 157 deletions(-)

diff --git a/dist/B-Deparse/Deparse.pm b/dist/B-Deparse/Deparse.pm
index f203a53..ed5493b 100644
--- a/dist/B-Deparse/Deparse.pm
+++ b/dist/B-Deparse/Deparse.pm
@@ -1451,11 +1451,12 @@ sub pp_nextstate {
        $self->{'hints'} = $hints;
     }
 
-    # hack to check that the hint hash hasn't changed
     if ($] > 5.009 &&
-       "@{[sort %{$self->{'hinthash'} || {}}]}"
-       ne "@{[sort %{$op->hints_hash->HASH || {}}]}") {
-       push @text, declare_hinthash($self->{'hinthash'}, 
$op->hints_hash->HASH, $self->{indent_size});
+       @text != push @text, declare_hinthash(
+           $self->{'hinthash'}, $op->hints_hash->HASH,
+           $self->{indent_size}
+       )
+    ) {
        $self->{'hinthash'} = $op->hints_hash->HASH;
     }
 
@@ -1510,8 +1511,15 @@ sub declare_hinthash {
     my @decls;
     for my $key (keys %$to) {
        next if $ignored_hints{$key};
-       if (!defined $from->{$key} or $from->{$key} ne $to->{$key}) {
-           push @decls, qq(\$^H{'$key'} = q($to->{$key}););
+       if (!exists $from->{$key} or $from->{$key} ne $to->{$key}) {
+           push @decls,
+               qq(\$^H{) . single_delim("q", "'", $key) . qq(} = )
+             . (
+                  defined $to->{$key}
+                       ? single_delim("q", "'", $to->{$key})
+                       : 'undef'
+               )
+             . qq(;);
        }
     }
     for my $key (keys %$from) {
@@ -1520,7 +1528,7 @@ sub declare_hinthash {
            push @decls, qq(delete \$^H{'$key'};);
        }
     }
-    @decls or return '';
+    @decls or return;
     return join("\n" . (" " x $indent), "BEGIN {", @decls) . "\n}\n";
 }
 
diff --git a/dist/B-Deparse/t/deparse.t b/dist/B-Deparse/t/deparse.t
index 84b9925..a4284ef 100644
--- a/dist/B-Deparse/t/deparse.t
+++ b/dist/B-Deparse/t/deparse.t
@@ -793,3 +793,27 @@ print sort(foo('bar'));
 # substr assignment
 substr(my $a, 0, 0) = (foo(), bar());
 $a++;
+####
+# hint hash
+BEGIN { $^H{'foo'} = undef; }
+{
+ BEGIN { $^H{'bar'} = undef; }
+ {
+  BEGIN { $^H{'baz'} = undef; }
+  {
+   print $_;
+  }
+  print $_;
+ }
+ print $_;
+}
+BEGIN { $^H{q[']} = '('; }
+print $_;
+####
+# hint hash changes that serialise the same way with sort %hh
+BEGIN { $^H{'a'} = 'b'; }
+{
+ BEGIN { $^H{'b'} = 'a'; delete $^H{'a'}; }
+ print $_;
+}
+print $_;
diff --git a/ext/B/t/f_map.t b/ext/B/t/f_map.t
index 2fa2ec9..aead90f 100644
--- a/ext/B/t/f_map.t
+++ b/ext/B/t/f_map.t
@@ -46,7 +46,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@chars = map(chr, @nums); },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 475 (eval 10):1) v
+# 1  <;> nextstate(main 475 (eval 10):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*nums] s
@@ -62,7 +62,7 @@ checkOptree(note   => q{},
 # d  <2> aassign[t9] KS/COMMON
 # e  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 559 (eval 15):1) v
+# 1  <;> nextstate(main 559 (eval 15):1) v%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*nums) s
@@ -90,7 +90,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{%hash = map { getkey($_) => $_ } @array; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 476 (eval 10):1) v:{
+# 1  <;> nextstate(main 476 (eval 10):1) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*array] s
@@ -98,7 +98,7 @@ checkOptree(note   => q{},
 # 6  <@> mapstart lK*
 # 7  <|> mapwhile(other->8)[t9] lK
 # 8      <0> enter l
-# 9      <;> nextstate(main 475 (eval 10):1) v:{
+# 9      <;> nextstate(main 475 (eval 10):1) v:%,{
 # a      <0> pushmark s
 # b      <0> pushmark s
 # c      <#> gvsv[*_] s
@@ -114,7 +114,7 @@ checkOptree(note   => q{},
 # l  <2> aassign[t10] KS/COMMON
 # m  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 560 (eval 15):1) v:{
+# 1  <;> nextstate(main 560 (eval 15):1) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*array) s
@@ -122,7 +122,7 @@ EOT_EOT
 # 6  <@> mapstart lK*
 # 7  <|> mapwhile(other->8)[t4] lK
 # 8      <0> enter l
-# 9      <;> nextstate(main 559 (eval 15):1) v:{
+# 9      <;> nextstate(main 559 (eval 15):1) v:%,{
 # a      <0> pushmark s
 # b      <0> pushmark s
 # c      <$> gvsv(*_) s
@@ -155,15 +155,15 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{{ %hash = (); foreach $_ (@array) { $hash{getkey($_)} = 
$_; } } },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 478 (eval 10):1) v:{
+# 1  <;> nextstate(main 478 (eval 10):1) v:%,{
 # 2  <{> enterloop(next->u last->u redo->3) 
-# 3  <;> nextstate(main 475 (eval 10):1) v
+# 3  <;> nextstate(main 475 (eval 10):1) v:%
 # 4  <0> pushmark s
 # 5  <0> pushmark s
 # 6  <#> gv[*hash] s
 # 7  <1> rv2hv[t2] lKRM*/1
 # 8  <2> aassign[t3] vKS
-# 9  <;> nextstate(main 476 (eval 10):1) v:{
+# 9  <;> nextstate(main 476 (eval 10):1) v:%,{
 # a  <0> pushmark sM
 # b  <#> gv[*array] s
 # c  <1> rv2av[t6] sKRM/1
@@ -172,7 +172,7 @@ checkOptree(note   => q{},
 # f  <{> enteriter(next->q last->t redo->g) lKS/8
 # r  <0> iter s
 # s  <|> and(other->g) K/1
-# g      <;> nextstate(main 475 (eval 10):1) v:{
+# g      <;> nextstate(main 475 (eval 10):1) v:%,{
 # h      <#> gvsv[*_] s
 # i      <#> gv[*hash] s
 # j      <1> rv2hv sKR/1
@@ -188,15 +188,15 @@ checkOptree(note   => q{},
 # u  <2> leaveloop K/2
 # v  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 562 (eval 15):1) v:{
+# 1  <;> nextstate(main 562 (eval 15):1) v:%,{
 # 2  <{> enterloop(next->u last->u redo->3) 
-# 3  <;> nextstate(main 559 (eval 15):1) v
+# 3  <;> nextstate(main 559 (eval 15):1) v:%
 # 4  <0> pushmark s
 # 5  <0> pushmark s
 # 6  <$> gv(*hash) s
 # 7  <1> rv2hv[t1] lKRM*/1
 # 8  <2> aassign[t2] vKS
-# 9  <;> nextstate(main 560 (eval 15):1) v:{
+# 9  <;> nextstate(main 560 (eval 15):1) v:%,{
 # a  <0> pushmark sM
 # b  <$> gv(*array) s
 # c  <1> rv2av[t3] sKRM/1
@@ -205,7 +205,7 @@ EOT_EOT
 # f  <{> enteriter(next->q last->t redo->g) lKS/8
 # r  <0> iter s
 # s  <|> and(other->g) K/1
-# g      <;> nextstate(main 559 (eval 15):1) v:{
+# g      <;> nextstate(main 559 (eval 15):1) v:%,{
 # h      <$> gvsv(*_) s
 # i      <$> gv(*hash) s
 # j      <1> rv2hv sKR/1
@@ -234,7 +234,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{%hash = map { +"\L$_", 1 } @array; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 476 (eval 10):1) v
+# 1  <;> nextstate(main 476 (eval 10):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*array] s
@@ -255,7 +255,7 @@ checkOptree(note   => q{},
 # h  <2> aassign[t10] KS/COMMON
 # i  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 560 (eval 15):1) v
+# 1  <;> nextstate(main 560 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*array) s
@@ -288,7 +288,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{%hash = map { ("\L$_", 1) } @array; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 476 (eval 10):1) v
+# 1  <;> nextstate(main 476 (eval 10):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*array] s
@@ -309,7 +309,7 @@ checkOptree(note   => q{},
 # h  <2> aassign[t10] KS/COMMON
 # i  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 560 (eval 15):1) v
+# 1  <;> nextstate(main 560 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*array) s
@@ -342,7 +342,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{%hash = map { lc($_), 1 } @array; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 476 (eval 10):1) v
+# 1  <;> nextstate(main 476 (eval 10):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*array] s
@@ -362,7 +362,7 @@ checkOptree(note   => q{},
 # g  <2> aassign[t9] KS/COMMON
 # h  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 589 (eval 26):1) v
+# 1  <;> nextstate(main 589 (eval 26):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*array) s
@@ -394,7 +394,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{%hash = map +( lc($_), 1 ), @array; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 475 (eval 10):1) v
+# 1  <;> nextstate(main 475 (eval 10):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*array] s
@@ -413,7 +413,7 @@ checkOptree(note   => q{},
 # g  <2> aassign[t8] KS/COMMON
 # h  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 593 (eval 28):1) v
+# 1  <;> nextstate(main 593 (eval 28):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*array) s
@@ -444,7 +444,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{%hash = map ( lc($_), 1 ), @array; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 475 (eval 10):1) v
+# 1  <;> nextstate(main 475 (eval 10):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <0> pushmark s
@@ -463,7 +463,7 @@ checkOptree(note   => q{},
 # g  <@> list K
 # h  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 597 (eval 30):1) v
+# 1  <;> nextstate(main 597 (eval 30):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <0> pushmark s
@@ -494,7 +494,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@hashes = map +{ lc($_), 1 }, @array },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 475 (eval 10):1) v
+# 1  <;> nextstate(main 475 (eval 10):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*array] s
@@ -513,7 +513,7 @@ checkOptree(note   => q{},
 # g  <2> aassign[t8] KS/COMMON
 # h  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 601 (eval 32):1) v
+# 1  <;> nextstate(main 601 (eval 32):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*array) s
diff --git a/ext/B/t/f_sort.t b/ext/B/t/f_sort.t
index 58a8cf2..108f23c 100644
--- a/ext/B/t/f_sort.t
+++ b/ext/B/t/f_sort.t
@@ -51,7 +51,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@articles = sort @files; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 545 (eval 15):1) v
+# 1  <;> nextstate(main 545 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*files] s
@@ -63,7 +63,7 @@ checkOptree(note   => q{},
 # a  <2> aassign[t5] KS/COMMON
 # b  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 545 (eval 15):1) v
+# 1  <;> nextstate(main 545 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*files) s
@@ -88,7 +88,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@articles = sort {$a cmp $b} @files; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*files] s
@@ -100,7 +100,7 @@ checkOptree(note   => q{},
 # a  <2> aassign[t3] KS/COMMON
 # b  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*files) s
@@ -125,7 +125,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@articles = sort {uc($a) cmp uc($b)} @files; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*files] s
@@ -137,7 +137,7 @@ checkOptree(note   => q{},
 # a  <2> aassign[t10] KS/COMMON
 # b  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*files) s
@@ -162,7 +162,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@articles = sort {$b cmp $a} @files; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*files] s
@@ -174,7 +174,7 @@ checkOptree(note   => q{},
 # a  <2> aassign[t3] KS/COMMON
 # b  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*files) s
@@ -199,7 +199,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@articles = sort {$a <=> $b} @files; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*files] s
@@ -211,7 +211,7 @@ checkOptree(note   => q{},
 # a  <2> aassign[t3] KS/COMMON
 # b  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*files) s
@@ -236,7 +236,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@articles = sort {$b <=> $a} @files; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 587 (eval 26):1) v
+# 1  <;> nextstate(main 587 (eval 26):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*files] s
@@ -248,7 +248,7 @@ checkOptree(note   => q{},
 # a  <2> aassign[t3] KS/COMMON
 # b  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*files) s
@@ -274,7 +274,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@eldest = sort { $age{$b} <=> $age{$a} } keys %age; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 592 (eval 28):1) v
+# 1  <;> nextstate(main 592 (eval 28):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*age] s
@@ -287,7 +287,7 @@ checkOptree(note   => q{},
 # b  <2> aassign[t11] KS/COMMON
 # c  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*age) s
@@ -316,7 +316,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{sub byage { $age{$a} <=> $age{$b}; } @sortedclass = 
sort byage @class; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 597 (eval 30):1) v
+# 1  <;> nextstate(main 597 (eval 30):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> const[PV "byage"] s/BARE
@@ -329,7 +329,7 @@ checkOptree(note   => q{},
 # b  <2> aassign[t5] KS/COMMON
 # c  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> const(PV "byage") s/BARE
@@ -366,7 +366,7 @@ checkOptree(name   => q{sort USERSUB LIST },
                        print sort @harry; print sort backwards @harry; 
                        print sort @george, 'to', @harry; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 602 (eval 32):2) v
+# 1  <;> nextstate(main 602 (eval 32):2) v:%
 # 2  <0> pushmark s
 # 3  <$> const[PV "dog"] s
 # 4  <$> const[PV "cat"] s
@@ -377,7 +377,7 @@ checkOptree(name   => q{sort USERSUB LIST },
 # 9  <#> gv[*harry] s
 # a  <1> rv2av[t2] lKRM*/1
 # b  <2> aassign[t3] vKS
-# c  <;> nextstate(main 602 (eval 32):3) v
+# c  <;> nextstate(main 602 (eval 32):3) v:%
 # d  <0> pushmark s
 # e  <$> const[PV "gone"] s
 # f  <$> const[PV "chased"] s
@@ -388,14 +388,14 @@ checkOptree(name   => q{sort USERSUB LIST },
 # k  <#> gv[*george] s
 # l  <1> rv2av[t5] lKRM*/1
 # m  <2> aassign[t6] vKS
-# n  <;> nextstate(main 602 (eval 32):4) v:{
+# n  <;> nextstate(main 602 (eval 32):4) v:%,{
 # o  <0> pushmark s
 # p  <0> pushmark s
 # q  <#> gv[*harry] s
 # r  <1> rv2av[t8] lK/1
 # s  <@> sort lK
 # t  <@> print vK
-# u  <;> nextstate(main 602 (eval 32):4) v:{
+# u  <;> nextstate(main 602 (eval 32):4) v:%,{
 # v  <0> pushmark s
 # w  <0> pushmark s
 # x  <$> const[PV "backwards"] s/BARE
@@ -403,7 +403,7 @@ checkOptree(name   => q{sort USERSUB LIST },
 # z  <1> rv2av[t10] lK/1
 # 10 <@> sort lKS
 # 11 <@> print vK
-# 12 <;> nextstate(main 602 (eval 32):5) v:{
+# 12 <;> nextstate(main 602 (eval 32):5) v:%,{
 # 13 <0> pushmark s
 # 14 <0> pushmark s
 # 15 <#> gv[*george] s
@@ -415,7 +415,7 @@ checkOptree(name   => q{sort USERSUB LIST },
 # 1b <@> print sK
 # 1c <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 602 (eval 32):2) v
+# 1  <;> nextstate(main 602 (eval 32):2) v:%
 # 2  <0> pushmark s
 # 3  <$> const(PV "dog") s
 # 4  <$> const(PV "cat") s
@@ -426,7 +426,7 @@ EOT_EOT
 # 9  <$> gv(*harry) s
 # a  <1> rv2av[t1] lKRM*/1
 # b  <2> aassign[t2] vKS
-# c  <;> nextstate(main 602 (eval 32):3) v
+# c  <;> nextstate(main 602 (eval 32):3) v:%
 # d  <0> pushmark s
 # e  <$> const(PV "gone") s
 # f  <$> const(PV "chased") s
@@ -437,14 +437,14 @@ EOT_EOT
 # k  <$> gv(*george) s
 # l  <1> rv2av[t3] lKRM*/1
 # m  <2> aassign[t4] vKS
-# n  <;> nextstate(main 602 (eval 32):4) v:{
+# n  <;> nextstate(main 602 (eval 32):4) v:%,{
 # o  <0> pushmark s
 # p  <0> pushmark s
 # q  <$> gv(*harry) s
 # r  <1> rv2av[t5] lK/1
 # s  <@> sort lK
 # t  <@> print vK
-# u  <;> nextstate(main 602 (eval 32):4) v:{
+# u  <;> nextstate(main 602 (eval 32):4) v:%,{
 # v  <0> pushmark s
 # w  <0> pushmark s
 # x  <$> const(PV "backwards") s/BARE
@@ -452,7 +452,7 @@ EOT_EOT
 # z  <1> rv2av[t6] lK/1
 # 10 <@> sort lKS
 # 11 <@> print vK
-# 12 <;> nextstate(main 602 (eval 32):5) v:{
+# 12 <;> nextstate(main 602 (eval 32):5) v:%,{
 # 13 <0> pushmark s
 # 14 <0> pushmark s
 # 15 <$> gv(*george) s
@@ -493,7 +493,7 @@ checkOptree(name   => q{Compound sort/map Expression },
                         sort { $b->[1] <=> $a->[1] || $a->[2] cmp $b->[2] }
                         map { [$_, /=(\d+)/, uc($_)] } @old; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 609 (eval 34):3) v:{
+# 1  <;> nextstate(main 609 (eval 34):3) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <0> pushmark s
@@ -503,7 +503,7 @@ checkOptree(name   => q{Compound sort/map Expression },
 # 8  <@> mapstart lK*
 # 9  <|> mapwhile(other->a)[t20] lK
 # a      <0> enter l
-# b      <;> nextstate(main 608 (eval 34):2) v:{
+# b      <;> nextstate(main 608 (eval 34):2) v:%,{
 # c      <0> pushmark s
 # d      <#> gvsv[*_] s
 # e      </> match(/"=(\\d+)"/) l/RTIME
@@ -528,7 +528,7 @@ checkOptree(name   => q{Compound sort/map Expression },
 # u  <2> aassign[t27] KS/COMMON
 # v  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 609 (eval 34):3) v:{
+# 1  <;> nextstate(main 609 (eval 34):3) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <0> pushmark s
@@ -538,7 +538,7 @@ EOT_EOT
 # 8  <@> mapstart lK*
 # 9  <|> mapwhile(other->a)[t11] lK
 # a      <0> enter l
-# b      <;> nextstate(main 608 (eval 34):2) v:{
+# b      <;> nextstate(main 608 (eval 34):2) v:%,{
 # c      <0> pushmark s
 # d      <$> gvsv(*_) s
 # e      </> match(/"=(\\d+)"/) l/RTIME
@@ -581,7 +581,7 @@ checkOptree(name   => q{sort other::sub LIST },
            code   => q{package other; sub backwards ($$) { $_[1] cmp $_[0]; }
                        package main; @new = sort other::backwards @old; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 614 (eval 36):2) v:{
+# 1  <;> nextstate(main 614 (eval 36):2) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> const[PV "other::backwards"] s/BARE
@@ -594,7 +594,7 @@ checkOptree(name   => q{sort other::sub LIST },
 # b  <2> aassign[t5] KS/COMMON
 # c  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 614 (eval 36):2) v:{
+# 1  <;> nextstate(main 614 (eval 36):2) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> const(PV "other::backwards") s/BARE
@@ -621,7 +621,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{sub other::backwards ($$) { $_[1] cmp $_[0]; } @new = 
sort other::backwards @old; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 619 (eval 38):1) v
+# 1  <;> nextstate(main 619 (eval 38):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> const[PV "other::backwards"] s/BARE
@@ -634,7 +634,7 @@ checkOptree(note   => q{},
 # b  <2> aassign[t5] KS/COMMON
 # c  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> const(PV "other::backwards") s/BARE
@@ -742,7 +742,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@articles = sort {$FooPack::b <=> $FooPack::a} @files; 
},
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 667 (eval 44):1) v
+# 1  <;> nextstate(main 667 (eval 44):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*files] s
@@ -754,7 +754,7 @@ checkOptree(note   => q{},
 # a  <2> aassign[t8] KS/COMMON
 # b  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*files) s
@@ -779,7 +779,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{@result = sort { $a <=> $b } grep { $_ == $_ } @input; 
},
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 673 (eval 46):1) v
+# 1  <;> nextstate(main 673 (eval 46):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <0> pushmark s
@@ -799,7 +799,7 @@ checkOptree(note   => q{},
 # g  <2> aassign[t3] KS/COMMON
 # h  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 547 (eval 15):1) v
+# 1  <;> nextstate(main 547 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <0> pushmark s
@@ -832,14 +832,14 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{sort { $a <=> $b } @input; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 678 (eval 48):1) v
+# 1  <;> nextstate(main 678 (eval 48):1) v:%
 # 2  <0> pushmark s
 # 3  <#> gv[*input] s
 # 4  <1> rv2av[t5] lK/1
 # 5  <@> sort K/NUM
 # 6  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v
+# 1  <;> nextstate(main 546 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <$> gv(*input) s
 # 4  <1> rv2av[t2] lK/1
@@ -859,7 +859,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{sort { $a <=> $b } grep { $_ == $_ } @input; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 684 (eval 50):1) v
+# 1  <;> nextstate(main 684 (eval 50):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*input] s
@@ -874,7 +874,7 @@ checkOptree(note   => q{},
 # b  <@> sort K/NUM
 # c  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 547 (eval 15):1) v
+# 1  <;> nextstate(main 547 (eval 15):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*input) s
@@ -902,7 +902,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{$s = sort { $a <=> $b } @input; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 689 (eval 52):1) v:{
+# 1  <;> nextstate(main 689 (eval 52):1) v:%,{
 # 2  <0> pushmark s
 # 3  <#> gv[*input] s
 # 4  <1> rv2av[t6] lK/1
@@ -911,7 +911,7 @@ checkOptree(note   => q{},
 # 7  <2> sassign sKS/2
 # 8  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 546 (eval 15):1) v:{
+# 1  <;> nextstate(main 546 (eval 15):1) v:%,{
 # 2  <0> pushmark s
 # 3  <$> gv(*input) s
 # 4  <1> rv2av[t2] lK/1
@@ -932,7 +932,7 @@ checkOptree(note   => q{},
            bcopts => q{-exec},
            code   => q{$s = sort { $a <=> $b } grep { $_ == $_ } @input; },
            expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 695 (eval 54):1) v:{
+# 1  <;> nextstate(main 695 (eval 54):1) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*input] s
@@ -949,7 +949,7 @@ checkOptree(note   => q{},
 # d  <2> sassign sKS/2
 # e  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 547 (eval 15):1) v:{
+# 1  <;> nextstate(main 547 (eval 15):1) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*input) s
diff --git a/ext/B/t/optree_check.t b/ext/B/t/optree_check.t
index bcbb554..c84e2f9 100644
--- a/ext/B/t/optree_check.t
+++ b/ext/B/t/optree_check.t
@@ -202,7 +202,7 @@ EONT_EONT
 checkOptree ( code     => '$a=$b+42',
              bcopts    => '-exec',
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 837 (eval 24):1) v:{
+# 1  <;> nextstate(main 837 (eval 24):1) v:%,{
 # 2  <#> gvsv[*b] s
 # 3  <$> const[IV 42] s
 # 4  <2> add[t3] sK/2
@@ -210,7 +210,7 @@ checkOptree ( code  => '$a=$b+42',
 # 6  <2> sassign sKS/2
 # 7  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 837 (eval 24):1) v:{
+# 1  <;> nextstate(main 837 (eval 24):1) v:%,{
 # 2  <$> gvsv(*b) s
 # 3  <$> const(IV 42) s
 # 4  <2> add[t1] sK/2
diff --git a/ext/B/t/optree_constants.t b/ext/B/t/optree_constants.t
index 111afa5..c0b6f99 100644
--- a/ext/B/t/optree_constants.t
+++ b/ext/B/t/optree_constants.t
@@ -109,12 +109,12 @@ for $func (sort keys %$want) {
                  expect  => <<EOT_EOT, expect_nt => <<EONT_EONT);
 3  <1> leavesub[2 refs] K/REFC,1 ->(end)
 -     <\@> lineseq KP ->3
-1        <;> dbstate(main 833 (eval 44):1) v ->2
+1        <;> dbstate(main 833 (eval 44):1) v:% ->2
 2        <\$> const[$want->{$func}[0] $want->{$func}[1]] s* ->3
 EOT_EOT
 3  <1> leavesub[2 refs] K/REFC,1 ->(end)
 -     <\@> lineseq KP ->3
-1        <;> dbstate(main 833 (eval 44):1) v ->2
+1        <;> dbstate(main 833 (eval 44):1) v:% ->2
 2        <\$> const($want->{$func}[0] $want->{$func}[1]) s* ->3
 EONT_EONT
 
@@ -181,12 +181,12 @@ EONT_EONT
 my ($expect, $expect_nt) = (<<'EOT_EOT', <<'EONT_EONT');
 # 3  <1> leavesub[2 refs] K/REFC,1 ->(end)
 # -     <@> lineseq K ->3
-# 1        <;> nextstate(constant 61 constant.pm:118) v:*,& ->2
+# 1        <;> nextstate(constant 61 constant.pm:118) v:%,*,& ->2
 # 2        <0> padav[@list:FAKE:m:96] ->3
 EOT_EOT
 # 3  <1> leavesub[2 refs] K/REFC,1 ->(end)
 # -     <@> lineseq K ->3
-# 1        <;> nextstate(constant 61 constant.pm:118) v:*,& ->2
+# 1        <;> nextstate(constant 61 constant.pm:118) v:%,*,& ->2
 # 2        <0> padav[@list:FAKE:m:71] ->3
 EONT_EONT
 
@@ -251,14 +251,14 @@ checkOptree ( name        => 'arithmetic constant folding 
in print',
              expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
 # 5  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->5
-# 1        <;> nextstate(main 937 (eval 53):1) v ->2
+# 1        <;> nextstate(main 937 (eval 53):1) v:% ->2
 # 4        <@> print sK ->5
 # 2           <0> pushmark s ->3
 # 3           <$> const[IV 6] s ->4
 EOT_EOT
 # 5  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->5
-# 1        <;> nextstate(main 937 (eval 53):1) v ->2
+# 1        <;> nextstate(main 937 (eval 53):1) v:% ->2
 # 4        <@> print sK ->5
 # 2           <0> pushmark s ->3
 # 3           <$> const(IV 6) s ->4
@@ -270,14 +270,14 @@ checkOptree ( name        => 'string constant folding in 
print',
              expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
 # 5  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->5
-# 1        <;> nextstate(main 942 (eval 55):1) v ->2
+# 1        <;> nextstate(main 942 (eval 55):1) v:% ->2
 # 4        <@> print sK ->5
 # 2           <0> pushmark s ->3
 # 3           <$> const[PV "foobar"] s ->4
 EOT_EOT
 # 5  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->5
-# 1        <;> nextstate(main 942 (eval 55):1) v ->2
+# 1        <;> nextstate(main 942 (eval 55):1) v:% ->2
 # 4        <@> print sK ->5
 # 2           <0> pushmark s ->3
 # 3           <$> const(PV "foobar") s ->4
@@ -289,14 +289,14 @@ checkOptree ( name        => 'boolean or folding',
              expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
 # 5  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->5
-# 1        <;> nextstate(main 942 (eval 55):1) v ->2
+# 1        <;> nextstate(main 942 (eval 55):1) v:% ->2
 # 4        <@> print sK ->5
 # 2           <0> pushmark s ->3
 # 3           <$> const[PV "foobar"] s ->4
 EOT_EOT
 # 5  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->5
-# 1        <;> nextstate(main 942 (eval 55):1) v ->2
+# 1        <;> nextstate(main 942 (eval 55):1) v:% ->2
 # 4        <@> print sK ->5
 # 2           <0> pushmark s ->3
 # 3           <$> const(PV "foobar") s ->4
@@ -381,14 +381,14 @@ checkOptree ( name        => 'mixed constant folding, 
with explicit braces',
              expect => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
 # 5  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->5
-# 1        <;> nextstate(main 977 (eval 28):1) v ->2
+# 1        <;> nextstate(main 977 (eval 28):1) v:% ->2
 # 4        <@> print sK ->5
 # 2           <0> pushmark s ->3
 # 3           <$> const[PV "foobar5"] s ->4
 EOT_EOT
 # 5  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->5
-# 1        <;> nextstate(main 977 (eval 28):1) v ->2
+# 1        <;> nextstate(main 977 (eval 28):1) v:% ->2
 # 4        <@> print sK ->5
 # 2           <0> pushmark s ->3
 # 3           <$> const(PV "foobar5") s ->4
diff --git a/ext/B/t/optree_samples.t b/ext/B/t/optree_samples.t
index 3e0b7f8..a8f608f 100644
--- a/ext/B/t/optree_samples.t
+++ b/ext/B/t/optree_samples.t
@@ -424,7 +424,7 @@ checkOptree ( name  => '@foo = grep(!/^\#/, @bar)',
              code      => '@foo = grep(!/^\#/, @bar)',
              bcopts    => '-exec',
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 496 (eval 20):1) v:{
+# 1  <;> nextstate(main 496 (eval 20):1) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*bar] s
@@ -440,7 +440,7 @@ checkOptree ( name  => '@foo = grep(!/^\#/, @bar)',
 # d  <2> aassign[t6] KS/COMMON
 # e  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 496 (eval 20):1) v:{
+# 1  <;> nextstate(main 496 (eval 20):1) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*bar) s
@@ -464,7 +464,7 @@ checkOptree ( name  => '%h = map { getkey($_) => $_ } @a',
              code      => '%h = map { getkey($_) => $_ } @a',
              bcopts    => '-exec',
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 501 (eval 22):1) v:{
+# 1  <;> nextstate(main 501 (eval 22):1) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*a] s
@@ -472,7 +472,7 @@ checkOptree ( name  => '%h = map { getkey($_) => $_ } @a',
 # 6  <@> mapstart lK*
 # 7  <|> mapwhile(other->8)[t9] lK
 # 8      <0> enter l
-# 9      <;> nextstate(main 500 (eval 22):1) v:{
+# 9      <;> nextstate(main 500 (eval 22):1) v:%,{
 # a      <0> pushmark s
 # b      <0> pushmark s
 # c      <#> gvsv[*_] s
@@ -488,7 +488,7 @@ checkOptree ( name  => '%h = map { getkey($_) => $_ } @a',
 # l  <2> aassign[t10] KS/COMMON
 # m  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 501 (eval 22):1) v:{
+# 1  <;> nextstate(main 501 (eval 22):1) v:%,{
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*a) s
@@ -496,7 +496,7 @@ EOT_EOT
 # 6  <@> mapstart lK*
 # 7  <|> mapwhile(other->8)[t4] lK
 # 8      <0> enter l
-# 9      <;> nextstate(main 500 (eval 22):1) v:{
+# 9      <;> nextstate(main 500 (eval 22):1) v:%,{
 # a      <0> pushmark s
 # b      <0> pushmark s
 # c      <$> gvsv(*_) s
@@ -517,13 +517,13 @@ checkOptree ( name        => '%h=(); for 
$_(@a){$h{getkey($_)} = $_}',
              code      => '%h=(); for $_(@a){$h{getkey($_)} = $_}',
              bcopts    => '-exec',
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 505 (eval 24):1) v
+# 1  <;> nextstate(main 505 (eval 24):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <#> gv[*h] s
 # 5  <1> rv2hv[t2] lKRM*/1
 # 6  <2> aassign[t3] vKS
-# 7  <;> nextstate(main 506 (eval 24):1) v:{
+# 7  <;> nextstate(main 506 (eval 24):1) v:%,{
 # 8  <0> pushmark sM
 # 9  <#> gv[*a] s
 # a  <1> rv2av[t6] sKRM/1
@@ -532,7 +532,7 @@ checkOptree ( name  => '%h=(); for $_(@a){$h{getkey($_)} = 
$_}',
 # d  <{> enteriter(next->o last->r redo->e) lKS/8
 # p  <0> iter s
 # q  <|> and(other->e) K/1
-# e      <;> nextstate(main 505 (eval 24):1) v:{
+# e      <;> nextstate(main 505 (eval 24):1) v:%,{
 # f      <#> gvsv[*_] s
 # g      <#> gv[*h] s
 # h      <1> rv2hv sKR/1
@@ -547,13 +547,13 @@ checkOptree ( name        => '%h=(); for 
$_(@a){$h{getkey($_)} = $_}',
 # r  <2> leaveloop KP/2
 # s  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 505 (eval 24):1) v
+# 1  <;> nextstate(main 505 (eval 24):1) v:%
 # 2  <0> pushmark s
 # 3  <0> pushmark s
 # 4  <$> gv(*h) s
 # 5  <1> rv2hv[t1] lKRM*/1
 # 6  <2> aassign[t2] vKS
-# 7  <;> nextstate(main 506 (eval 24):1) v:{
+# 7  <;> nextstate(main 506 (eval 24):1) v:%,{
 # 8  <0> pushmark sM
 # 9  <$> gv(*a) s
 # a  <1> rv2av[t3] sKRM/1
@@ -562,7 +562,7 @@ EOT_EOT
 # d  <{> enteriter(next->o last->r redo->e) lKS/8
 # p  <0> iter s
 # q  <|> and(other->e) K/1
-# e      <;> nextstate(main 505 (eval 24):1) v:{
+# e      <;> nextstate(main 505 (eval 24):1) v:%,{
 # f      <$> gvsv(*_) s
 # g      <$> gv(*h) s
 # h      <1> rv2hv sKR/1
@@ -582,7 +582,7 @@ checkOptree ( name  => 'map $_+42, 10..20',
              code      => 'map $_+42, 10..20',
              bcopts    => '-exec',
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
-# 1  <;> nextstate(main 497 (eval 20):1) v
+# 1  <;> nextstate(main 497 (eval 20):1) v:%
 # 2  <0> pushmark s
 # 3  <$> const[AV ] s
 # 4  <1> rv2av lKPM/1
@@ -594,7 +594,7 @@ checkOptree ( name  => 'map $_+42, 10..20',
 #            goto 6
 # a  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
-# 1  <;> nextstate(main 511 (eval 26):1) v
+# 1  <;> nextstate(main 511 (eval 26):1) v:%
 # 2  <0> pushmark s
 # 3  <$> const(AV ) s
 # 4  <1> rv2av lKPM/1
diff --git a/ext/B/t/optree_specials.t b/ext/B/t/optree_specials.t
index b8b9078..c6e4199 100644
--- a/ext/B/t/optree_specials.t
+++ b/ext/B/t/optree_specials.t
@@ -49,10 +49,10 @@ checkOptree ( name  => 'BEGIN',
 # BEGIN 1:
 # a  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->a
-# 1        <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->2
+# 1        <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$ ->2
 # 3        <1> require sK/1 ->4
 # 2           <$> const[PV "strict.pm"] s/BARE ->3
-# 4        <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->5
+# 4        <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$ ->5
 # -        <@> lineseq K ->-
 # -           <0> null ->5
 # 9           <1> entersub[t1] KS*/TARG,2 ->a
@@ -63,10 +63,10 @@ checkOptree ( name  => 'BEGIN',
 # BEGIN 2:
 # k  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq K ->k
-# b        <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->c
+# b        <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$ ->c
 # d        <1> require sK/1 ->e
 # c           <$> const[PV "strict.pm"] s/BARE ->d
-# e        <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->f
+# e        <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$ ->f
 # -        <@> lineseq K ->-
 # -           <0> null ->f
 # j           <1> entersub[t1] KS*/TARG,2 ->k
@@ -77,10 +77,10 @@ checkOptree ( name  => 'BEGIN',
 # BEGIN 3:
 # u  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->u
-# l        <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->m
+# l        <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$ ->m
 # n        <1> require sK/1 ->o
 # m           <$> const[PV "warnings.pm"] s/BARE ->n
-# o        <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->p
+# o        <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$ ->p
 # -        <@> lineseq K ->-
 # -           <0> null ->p
 # t           <1> entersub[t1] KS*/TARG,2 ->u
@@ -99,10 +99,10 @@ EOT_EOT
 # BEGIN 1:
 # a  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->a
-# 1        <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->2
+# 1        <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$ ->2
 # 3        <1> require sK/1 ->4
 # 2           <$> const(PV "strict.pm") s/BARE ->3
-# 4        <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$ ->5
+# 4        <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$ ->5
 # -        <@> lineseq K ->-
 # -           <0> null ->5
 # 9           <1> entersub[t1] KS*/TARG,2 ->a
@@ -113,10 +113,10 @@ EOT_EOT
 # BEGIN 2:
 # k  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq K ->k
-# b        <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->c
+# b        <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$ ->c
 # d        <1> require sK/1 ->e
 # c           <$> const(PV "strict.pm") s/BARE ->d
-# e        <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$ ->f
+# e        <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$ ->f
 # -        <@> lineseq K ->-
 # -           <0> null ->f
 # j           <1> entersub[t1] KS*/TARG,2 ->k
@@ -127,10 +127,10 @@ EOT_EOT
 # BEGIN 3:
 # u  <1> leavesub[1 ref] K/REFC,1 ->(end)
 # -     <@> lineseq KP ->u
-# l        <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->m
+# l        <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$ ->m
 # n        <1> require sK/1 ->o
 # m           <$> const(PV "warnings.pm") s/BARE ->n
-# o        <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$ ->p
+# o        <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$ ->p
 # -        <@> lineseq K ->-
 # -           <0> null ->p
 # t           <1> entersub[t1] KS*/TARG,2 ->u
@@ -248,10 +248,10 @@ checkOptree ( name        => 'all of BEGIN END INIT CHECK 
UNITCHECK -exec',
              strip_open_hints => 1,
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
 # BEGIN 1:
-# 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
+# 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$
 # 2  <$> const[PV "strict.pm"] s/BARE
 # 3  <1> require sK/1
-# 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
+# 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$
 # 5  <0> pushmark s
 # 6  <$> const[PV "strict"] sM
 # 7  <$> const[PV "refs"] sM
@@ -259,10 +259,10 @@ checkOptree ( name        => 'all of BEGIN END INIT CHECK 
UNITCHECK -exec',
 # 9  <1> entersub[t1] KS*/TARG,2
 # a  <1> leavesub[1 ref] K/REFC,1
 # BEGIN 2:
-# b  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
+# b  <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$
 # c  <$> const[PV "strict.pm"] s/BARE
 # d  <1> require sK/1
-# e  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
+# e  <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$
 # f  <0> pushmark s
 # g  <$> const[PV "strict"] sM
 # h  <$> const[PV "refs"] sM
@@ -270,10 +270,10 @@ checkOptree ( name        => 'all of BEGIN END INIT CHECK 
UNITCHECK -exec',
 # j  <1> entersub[t1] KS*/TARG,2
 # k  <1> leavesub[1 ref] K/REFC,1
 # BEGIN 3:
-# l  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
+# l  <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$
 # m  <$> const[PV "warnings.pm"] s/BARE
 # n  <1> require sK/1
-# o  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
+# o  <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$
 # p  <0> pushmark s
 # q  <$> const[PV "warnings"] sM
 # r  <$> const[PV "qw"] sM
@@ -307,10 +307,10 @@ checkOptree ( name        => 'all of BEGIN END INIT CHECK 
UNITCHECK -exec',
 # 1e <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
 # BEGIN 1:
-# 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
+# 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$
 # 2  <$> const(PV "strict.pm") s/BARE
 # 3  <1> require sK/1
-# 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
+# 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$
 # 5  <0> pushmark s
 # 6  <$> const(PV "strict") sM
 # 7  <$> const(PV "refs") sM
@@ -318,10 +318,10 @@ EOT_EOT
 # 9  <1> entersub[t1] KS*/TARG,2
 # a  <1> leavesub[1 ref] K/REFC,1
 # BEGIN 2:
-# b  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
+# b  <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$
 # c  <$> const(PV "strict.pm") s/BARE
 # d  <1> require sK/1
-# e  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
+# e  <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$
 # f  <0> pushmark s
 # g  <$> const(PV "strict") sM
 # h  <$> const(PV "refs") sM
@@ -329,10 +329,10 @@ EOT_EOT
 # j  <1> entersub[t1] KS*/TARG,2
 # k  <1> leavesub[1 ref] K/REFC,1
 # BEGIN 3:
-# l  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
+# l  <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$
 # m  <$> const(PV "warnings.pm") s/BARE
 # n  <1> require sK/1
-# o  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
+# o  <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$
 # p  <0> pushmark s
 # q  <$> const(PV "warnings") sM
 # r  <$> const(PV "qw") sM
@@ -377,10 +377,10 @@ checkOptree ( name        => 'regression test for patch 
25352',
              @warnings_todo,
              expect    => <<'EOT_EOT', expect_nt => <<'EONT_EONT');
 # BEGIN 1:
-# 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
+# 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$
 # 2  <$> const[PV "strict.pm"] s/BARE
 # 3  <1> require sK/1
-# 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
+# 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$
 # 5  <0> pushmark s
 # 6  <$> const[PV "strict"] sM
 # 7  <$> const[PV "refs"] sM
@@ -388,10 +388,10 @@ checkOptree ( name        => 'regression test for patch 
25352',
 # 9  <1> entersub[t1] KS*/TARG,2
 # a  <1> leavesub[1 ref] K/REFC,1
 # BEGIN 2:
-# b  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
+# b  <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$
 # c  <$> const[PV "strict.pm"] s/BARE
 # d  <1> require sK/1
-# e  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
+# e  <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$
 # f  <0> pushmark s
 # g  <$> const[PV "strict"] sM
 # h  <$> const[PV "refs"] sM
@@ -399,10 +399,10 @@ checkOptree ( name        => 'regression test for patch 
25352',
 # j  <1> entersub[t1] KS*/TARG,2
 # k  <1> leavesub[1 ref] K/REFC,1
 # BEGIN 3:
-# l  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
+# l  <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$
 # m  <$> const[PV "warnings.pm"] s/BARE
 # n  <1> require sK/1
-# o  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
+# o  <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$
 # p  <0> pushmark s
 # q  <$> const[PV "warnings"] sM
 # r  <$> const[PV "qw"] sM
@@ -411,10 +411,10 @@ checkOptree ( name        => 'regression test for patch 
25352',
 # u  <1> leavesub[1 ref] K/REFC,1
 EOT_EOT
 # BEGIN 1:
-# 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
+# 1  <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$
 # 2  <$> const(PV "strict.pm") s/BARE
 # 3  <1> require sK/1
-# 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:*,&,{,$
+# 4  <;> nextstate(B::Concise -275 Concise.pm:356) v:%,*,&,{,$
 # 5  <0> pushmark s
 # 6  <$> const(PV "strict") sM
 # 7  <$> const(PV "refs") sM
@@ -422,10 +422,10 @@ EOT_EOT
 # 9  <1> entersub[t1] KS*/TARG,2
 # a  <1> leavesub[1 ref] K/REFC,1
 # BEGIN 2:
-# b  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
+# b  <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$
 # c  <$> const(PV "strict.pm") s/BARE
 # d  <1> require sK/1
-# e  <;> nextstate(B::Concise -265 Concise.pm:367) v:*,&,$
+# e  <;> nextstate(B::Concise -265 Concise.pm:367) v:%,*,&,$
 # f  <0> pushmark s
 # g  <$> const(PV "strict") sM
 # h  <$> const(PV "refs") sM
@@ -433,10 +433,10 @@ EOT_EOT
 # j  <1> entersub[t1] KS*/TARG,2
 # k  <1> leavesub[1 ref] K/REFC,1
 # BEGIN 3:
-# l  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
+# l  <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$
 # m  <$> const(PV "warnings.pm") s/BARE
 # n  <1> require sK/1
-# o  <;> nextstate(B::Concise -254 Concise.pm:386) v:*,&,{,$
+# o  <;> nextstate(B::Concise -254 Concise.pm:386) v:%,*,&,{,$
 # p  <0> pushmark s
 # q  <$> const(PV "warnings") sM
 # r  <$> const(PV "qw") sM
diff --git a/lib/feature.pm b/lib/feature.pm
index c48b4e3..ac7a23c 100644
--- a/lib/feature.pm
+++ b/lib/feature.pm
@@ -21,6 +21,7 @@ our $hint_uni8bit = 0x00000800;
 # NB. the latest bundle must be loaded by the -E switch (see toke.c)
 
 our %feature_bundle = (
+    "default" => [],
     "5.10" => [qw(say state switch)],
     "5.11" => [qw(say state switch unicode_strings)],
     "5.15" => [qw(say state switch unicode_strings unicode_eval
@@ -190,9 +191,11 @@ This feature is available starting with Perl 5.16.
 
 It's possible to load a whole slew of features in one go, using
 a I<feature bundle>. The name of a feature bundle is prefixed with
-a colon, to distinguish it from an actual feature. At present, the
-only feature bundles correspond to Perl releases, e.g. C<use feature
-":5.10"> which is equivalent to C<use feature qw(switch say state)>.
+a colon, to distinguish it from an actual feature. At present, most
+feature bundles correspond to Perl releases, e.g. C<use feature
+":5.10"> which is equivalent to C<use feature qw(switch say state)>. The
+only bundle that does not follow this convention is ":default", which is
+currently empty.
 
 By convention, the feature bundle for any given Perl release includes
 the features of previous releases, down to and including 5.10, the
@@ -228,6 +231,7 @@ the C<use VERSION> construct, and when the version is 
higher than or equal to
 
 will do an implicit
 
+    no feature;
     use feature ':5.10';
 
 and so on. Note how the trailing sub-version is automatically stripped from the
@@ -239,6 +243,9 @@ But to avoid portability warnings (see L<perlfunc/use>), 
you may prefer:
 
 with the same effect.
 
+For versions below 5.010, the ":default" feature bundle is automatically
+loaded, but it is currently empty and has no effect.
+
 =back
 
 =cut
diff --git a/lib/strict.pm b/lib/strict.pm
index c1544f5..e9fc4ff 100644
--- a/lib/strict.pm
+++ b/lib/strict.pm
@@ -19,7 +19,10 @@ sub bits {
     my $bits = 0;
     my @wrong;
     foreach my $s (@_) {
-       push @wrong, $s unless exists $bitmask{$s};
+       if (exists $bitmask{$s}) {
+           $^H{"strict/$s"} = undef;
+       }
+       else { push @wrong, $s };
         $bits |= $bitmask{$s} || 0;
     }
     if (@wrong) {
@@ -29,16 +32,16 @@ sub bits {
     $bits;
 }
 
-my $default_bits = bits(qw(refs subs vars));
+my @default_bits = qw(refs subs vars);
 
 sub import {
     shift;
-    $^H |= @_ ? bits(@_) : $default_bits;
+    $^H |= bits(@_ ? @_ : @default_bits);
 }
 
 sub unimport {
     shift;
-    $^H &= ~ (@_ ? bits(@_) : $default_bits);
+    $^H &= ~ bits(@_ ? @_ : @default_bits);
 }
 
 1;
diff --git a/op.c b/op.c
index e353015..718f0e6 100644
--- a/op.c
+++ b/op.c
@@ -4669,6 +4669,20 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP 
*idop, OP *arg)
            newSTATEOP(0, NULL, imop) ));
 
     if (use_version) {
+       HV * const hinthv = GvHV(PL_hintgv);
+       const bool hhoff = !hinthv || !(PL_hints & HINT_LOCALIZE_HH);
+
+       /* Turn features off */
+       if (hhoff)
+           /* avoid loading feature.pm */
+           PL_hints &= ~HINT_UNI_8_BIT;
+       else {
+           ENTER_with_name("load_feature");
+           Perl_load_module(aTHX_
+               PERL_LOADMOD_DENY, newSVpvs("feature"), NULL, NULL
+           );
+       }
+
        /* If we request a version >= 5.9.5, load feature.pm with the
         * feature bundle that corresponds to the required version. */
        use_version = sv_2mortal(new_version(use_version));
@@ -4676,15 +4690,30 @@ Perl_utilize(pTHX_ int aver, I32 floor, OP *version, OP 
*idop, OP *arg)
        if (vcmp(use_version,
                 sv_2mortal(upg_version(newSVnv(5.009005), FALSE))) >= 0) {
            SV *const importsv = vnormal(use_version);
+           if (hhoff) ENTER_with_name("load_feature");
            *SvPVX_mutable(importsv) = ':';
-           ENTER_with_name("load_feature");
            Perl_load_module(aTHX_ 0, newSVpvs("feature"), NULL, importsv, 
NULL);
            LEAVE_with_name("load_feature");
        }
+       else if (!hhoff) LEAVE_with_name("load_feature");
        /* If a version >= 5.11.0 is requested, strictures are on by default! */
        if (vcmp(use_version,
                 sv_2mortal(upg_version(newSVnv(5.011000), FALSE))) >= 0) {
-           PL_hints |= (HINT_STRICT_REFS | HINT_STRICT_SUBS | 
HINT_STRICT_VARS);
+           if (hhoff || !hv_exists(hinthv, "strict/refs", 11))
+               PL_hints |= HINT_STRICT_REFS;
+           if (hhoff || !hv_exists(hinthv, "strict/subs", 11))
+               PL_hints |= HINT_STRICT_SUBS;
+           if (hhoff || !hv_exists(hinthv, "strict/vars", 11))
+               PL_hints |= HINT_STRICT_VARS;
+       }
+       /* otherwise they are off */
+       else {
+           if (hhoff || !hv_exists(hinthv, "strict/refs", 11))
+               PL_hints &= ~HINT_STRICT_REFS;
+           if (hhoff || !hv_exists(hinthv, "strict/subs", 11))
+               PL_hints &= ~HINT_STRICT_SUBS;
+           if (hhoff || !hv_exists(hinthv, "strict/vars", 11))
+               PL_hints &= ~HINT_STRICT_VARS;
        }
     }
 
diff --git a/pod/perlfunc.pod b/pod/perlfunc.pod
index bb9c355..809cc67 100644
--- a/pod/perlfunc.pod
+++ b/pod/perlfunc.pod
@@ -7709,12 +7709,16 @@ This is often useful if you need to check the current 
Perl version before
 C<use>ing library modules that won't work with older versions of Perl.
 (We try not to do this more than we have to.)
 
-Also, if the specified Perl version is greater than or equal to 5.9.5,
-C<use VERSION> will also load the C<feature> pragma and enable all
-features available in the requested version.  See L<feature>.
+C<use VERSION> also loads the C<feature> pragma and enables all features
+available in the requested version, disabling any features not in
+the current version's feature bundle.  See L<feature>.  (Whether
+it actually loads the F<feature.pm> module is subject to
+change.  In some cases it is skipped for efficiency reasons.)
 Similarly, if the specified Perl version is greater than or equal to
 5.11.0, strictures are enabled lexically as with C<use strict> (except
-that the F<strict.pm> file is not actually loaded).
+that the F<strict.pm> file is not actually loaded).  Any explicit use of
+C<use strict> or C<no strict> overrides C<use VERSION>, even if it comes
+before it.
 
 The C<BEGIN> forces the C<require> and C<import> to happen at compile time.  
The
 C<require> makes sure the module is loaded into memory if it hasn't been
diff --git a/t/comp/use.t b/t/comp/use.t
index c9b76d7..25e2a96 100644
--- a/t/comp/use.t
+++ b/t/comp/use.t
@@ -6,7 +6,7 @@ BEGIN {
     $INC{"feature.pm"} = 1; # so we don't attempt to load feature.pm
 }
 
-print "1..73\n";
+print "1..83\n";
 
 # Can't require test.pl, as we're testing the use/require mechanism here.
 
@@ -22,6 +22,8 @@ sub _ok {
        $result = $got ne $expected;
     } elsif ($type eq 'like') {
        $result = $got =~ $expected;
+    } elsif ($type eq 'ok') {
+       $result = not not $got;
     } else {
        die "Unexpected type '$type'$name";
     }
@@ -46,6 +48,8 @@ sub _ok {
            print "# Expected not '$expected'\n";
        } elsif ($type eq 'like') {
            print "# Expected $expected\n";
+       } elsif ($type eq 'ok') {
+           print "# Expected a true value\n";
        }
     }
     $test = $test + 1;
@@ -61,6 +65,9 @@ sub is ($$;$) {
 sub isnt ($$;$) {
     _ok ('isnt', @_);
 }
+sub ok($;$) {
+    _ok ('ok', shift, undef, @_);
+}
 
 eval "use 5";           # implicit semicolon
 is ($@, '');
@@ -134,6 +141,29 @@ is ($@, "");
 # and they are properly scoped
 eval '{use 5.11.0;} ${"foo"} = "bar";';
 is ($@, "");
+eval 'no strict; use 5.012; ${"foo"} = "bar"';
+is $@, "", 'explicit "no strict" overrides later ver decl';
+eval 'use strict; use 5.01; ${"foo"} = "bar"';
+like $@, qr/^Can't use string/,
+    'explicit use strict overrides later use 5.01';
+eval 'use strict "subs"; use 5.012; ${"foo"} = "bar"';
+like $@, qr/^Can't use string/,
+    'explicit use strict "subs" does not stop ver decl from enabling refs';
+eval 'use 5.012; use 5.01; ${"foo"} = "bar"';
+is $@, "", 'use 5.01 overrides implicit strict from prev ver decl';
+eval 'no strict "subs"; use 5.012; ${"foo"} = "bar"';
+ok $@, 'no strict subs allows ver decl to enable refs';
+eval 'no strict "subs"; use 5.012; $nonexistent_pack_var';
+ok $@, 'no strict subs allows ver decl to enable vars';
+eval 'no strict "refs"; use 5.012; fancy_bareword';
+ok $@, 'no strict refs allows ver decl to enable subs';
+eval 'no strict "refs"; use 5.012; $nonexistent_pack_var';
+ok $@, 'no strict refs allows ver decl to enable subs';
+eval 'no strict "vars"; use 5.012; ${"foo"} = "bar"';
+ok $@, 'no strict vars allows ver decl to enable refs';
+eval 'no strict "vars"; use 5.012; ursine_word';
+ok $@, 'no strict vars allows ver decl to enable subs';
+
 
 { use test_use }       # check that subparse saves pending tokens
 
diff --git a/t/lib/feature/bundle b/t/lib/feature/bundle
index 11fde32..05708e5 100644
--- a/t/lib/feature/bundle
+++ b/t/lib/feature/bundle
@@ -67,3 +67,14 @@ use feature ":5.8.8";
 EXPECT
 OPTIONS regex
 ^Feature bundle "5.8.8" is not supported by Perl \d+\.\d+\.\d+ at - line \d+
+########
+# :default
+BEGIN { *say = *state = *given = sub { print "custom sub\n" }; }
+use feature ":default";
+say "yes";
+state my $foo;
+given a => chance;
+EXPECT
+custom sub
+custom sub
+custom sub
diff --git a/t/lib/feature/implicit b/t/lib/feature/implicit
index a6c3bea..3a82f01 100644
--- a/t/lib/feature/implicit
+++ b/t/lib/feature/implicit
@@ -64,3 +64,17 @@ Helloworld
 # no implicit features with 'no'
 eval "no " . ($]+1); print $@;
 EXPECT
+########
+# lower version after higher version
+sub evalbytes { print "evalbytes sub\n" }
+sub say { print "say sub\n" }
+use 5.015;
+evalbytes "say 'yes'";
+use 5.014;
+evalbytes;
+use 5;
+say "no"
+EXPECT
+yes
+evalbytes sub
+say sub

--
Perl5 Master Repository

Reply via email to