summaryrefslogtreecommitdiff
path: root/pad.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2014-09-22 21:48:48 -0700
committerFather Chrysostomos <sprout@cpan.org>2014-09-22 21:56:36 -0700
commit14d91147b4bfd5289f2548af3eb0d745d241b9f8 (patch)
treec0a9c91dc617c129c50f17e9d8e3819c27cb73e3 /pad.c
parent39ff6c37b02dc106ce36a529c4fdd80ac93c7ada (diff)
downloadperl-14d91147b4bfd5289f2548af3eb0d745d241b9f8.tar.gz
Stop flip from returning the same scalar each time
sub f { for my $n (1..5) { my $x = \scalar($n == 2 .. $n == 4); $_ = $x if $n == 1; print "$n: $$_\n"; } print("-----\n"), f() if @_ } f(1); Output: 1: 2: 1 3: 2 4: 3E0 5: ----- 1: 2: 3: 4: 5: When f() is called, it evaluates a flipflop five times. It takes a reference to the return value the first time, and prints that same scalar for each iteration. Notice how the very same scalar is returned each time in the outer sub call, but the recursive call hides that implementation detail. .. should not be returning the same scalar each time, or at least that implementation detail should not leak through. (Most operators do reuse the same scalar, but the scalar is flagged such that \ will copy it, hiding that fact.) This was happening because of the eccentric way that the flipflop targets are allocated in the pad. They are allocated as PADMY (i.e., like ‘my’ variables), but without a name. pad_push (which creates a new pad for recursion) assumes that anything without a name is PADTMP instead (copy on reference). So the recursive call behaves correctly. I am not sure why the targets were allocated with PADMY to begin with. (This goes back to perl 5.000.) But now the PADMY prevents the tar- gets from being shared with other ops under USE_PAD_RESET builds. The better way to allocate these targets is to use PADMY as before, but actually give those slots names. The target that gets returned needs to be marked PADTMP, so we also need to copy that flag in pad_push.
Diffstat (limited to 'pad.c')
-rw-r--r--pad.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/pad.c b/pad.c
index fafb946dab..1306a0a1e4 100644
--- a/pad.c
+++ b/pad.c
@@ -2375,7 +2375,11 @@ Perl_pad_push(pTHX_ PADLIST *padlist, int depth)
else if (sigil == '%')
sv = MUTABLE_SV(newHV());
else
+ {
sv = newSV(0);
+ /* For flip-flop targets: */
+ if (SvPADTMP(oldpad[ix])) SvPADTMP_on(sv);
+ }
av_store(newpad, ix, sv);
SvPADMY_on(sv);
}