This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
RT #4682: given() didn't scope $_ correctly
authorDavid Mitchell <davem@iabyn.com>
Tue, 6 Sep 2011 11:16:23 +0000 (12:16 +0100)
committerDavid Mitchell <davem@iabyn.com>
Tue, 6 Sep 2011 11:21:21 +0000 (12:21 +0100)
given(expr) {...} behaves similarly to { my $_ = expr; ...},
except that, prior to this commit, it wasn't doing the SAVECLEARSV()
that pp_padsv would do.  This meant that $_ was still marked as stale
while in scope, and wasn't getting cleared at the end of scope.

pp_ctl.c
t/op/switch.t

index 0d2aae1..238f230 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -4367,6 +4367,7 @@ PP(pp_entergiven)
     ENTER_with_name("given");
     SAVETMPS;
 
+    SAVECLEARSV(PAD_SVl(PL_op->op_targ));
     sv_setsv_mg(PAD_SV(PL_op->op_targ), POPs);
 
     PUSHBLOCK(cx, CXt_GIVEN, SP);
index a286559..420c6ae 100644 (file)
@@ -9,7 +9,7 @@ BEGIN {
 use strict;
 use warnings;
 
-plan tests => 197;
+plan tests => 201;
 
 # The behaviour of the feature pragma should be tested by lib/feature.t
 # using the tests in t/lib/feature/*. This file tests the behaviour of
@@ -1361,6 +1361,35 @@ unreified_check(undef,"");
     is "@res", "1", "break resets the stack";
 }
 
+# RT #94682:
+# must ensure $_ is initialised and cleared at start/end of given block
+
+{
+    sub f1 {
+       given(3) {
+           return sub { $_ } # close over lexical $_
+       }
+    }
+    is(f1()->(), 3, 'closed over $_');
+
+    package RT94682;
+
+    my $d = 0;
+    sub DESTROY { $d++ };
+
+    sub f2 {
+       my $_ = 5;
+       given(bless [7]) {
+           ::is($_->[0], 7, "is [7]");
+       }
+       ::is($_, 5, "is 5");
+       ::is($d, 1, "DESTROY called once");
+    }
+    f2();
+}
+
+
+
 # Okay, that'll do for now. The intricacies of the smartmatch
 # semantics are tested in t/op/smartmatch.t. Taintedness of
 # returned values is checked in t/op/taint.t.