Make the literal '@_' illegal in subs with sigs
authorPeter Martini <PeterCMartini@GMail.com>
Thu, 27 Sep 2012 19:39:50 +0000 (15:39 -0400)
committerPeter Martini <PeterCMartini@GMail.com>
Wed, 17 Oct 2012 20:36:11 +0000 (16:36 -0400)
t/comp/namedproto.t
toke.c

index 4887d50..5316395 100644 (file)
@@ -271,6 +271,23 @@ BEGIN {
 no_warnings("invalid slurpy parameters");
 }
 
+# Ban @_ inside the sub if it has a named proto
+{
+    my ($legal, $failed);
+    $legal = eval 'sub not_banned1 { $#_ }; 1';
+    ok($legal, "No changes to \$#_ within traditional subs");
+    $legal = eval 'sub not_banned2 { @_; }; 1';
+    ok($legal, "No changes to \@_ within traditional subs");
+    $failed = !eval 'sub banned1 ($foo){ $#_ }; 1';
+    ok($failed, "Cannot use a literal \$#_ with subroutine signatures");
+    $failed = !eval 'sub banned2 ($foo){ @_ }; 1';
+    ok($failed, "Cannot use a literal \@_ with subroutine signatures");
+    $legal = eval 'sub banned3 ($foo){ sub not_banned3 { $#_ }; }; 1';
+    ok($legal, "\$#_ restriction doesn't apply to nested subs");
+    $legal = eval 'sub banned4 ($foo){ sub not_banned4 { @_ }; }; 1';
+    ok($legal, "\@_ restriction doesn't apply to nested subs");
+}
+
 # Test UTF-8
 
 BEGIN { no_warnings("end of compile time") }
diff --git a/toke.c b/toke.c
index bae1ee2..12dbffd 100644 (file)
--- a/toke.c
+++ b/toke.c
@@ -8742,6 +8742,13 @@ S_pending_ident(pTHX)
         }
     }
 
+    /* Disable access to @_ from within a sub with named parameters,
+       at compile time. This only works for a literal @_ - @main::_ (etc)
+       can still pass through. Aliases must be handled separately */
+    if (tokenbuf_len == 2 && strnEQ(PL_tokenbuf, "@_", 2) && is_sub_with_sig()) {
+       Perl_croak(aTHX_ "Cannot use @_ in a sub with a signature\n");
+    }
+
     /* build ops for a bareword */
     pl_yylval.opval = (OP*)newSVOP(OP_CONST, 0,
                                   newSVpvn_flags(PL_tokenbuf + 1,