summaryrefslogtreecommitdiff
path: root/perly.y
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2014-11-25 18:08:13 -0800
committerFather Chrysostomos <sprout@cpan.org>2014-11-25 20:11:05 -0800
commit0f602692adc580e73d2236976e9da7fec968ca93 (patch)
tree9d6e87ddf1e27273dd168fce9b165a582f1626c8 /perly.y
parent205681b5d1e56b5ec94a53a7a80c51b866099763 (diff)
downloadperl-0f602692adc580e73d2236976e9da7fec968ca93.tar.gz
[perl #123286] Lone C-style for in a block
A block in perl usually consists of an enter/leave pair plus the con- tents of the block: leave enter nextstate whatever But if the contents of the block are simple enough to forego the full block structure, a simple scope op is used, which is not even executed: scope ex-nextstate whatever If there is a real nextstate op anywhere in the block, it resets the stack to whatever it was at block entry, based on the value on the context stack placed there by the enter op. That’s why we can never have scope+nextstate (we have ex-nextstate, or a former nextstate op that is not executed). A for-loop (for(init; cond; cont) { ... }) executes the init section first, and then an unstack op, which is like nextstate in that it resets the stack based on what the context stack says is the base off- set for this block. If we have an unstack op, we can’t use scope, just as we can’t use it with nextstate. But we *were* nonetheless using scope in this case. Hence, map { for(...;...;...) {...} } ... caused the for-loop to reset the stack to the beginning of map’s own arguments. So the for-loop would stomp on them. We can see the same bug with ‘for’ clobbering an outer list: $ perl5.20.1 -le 'print 1..3, do{for(0;0;){}}, 4..6;' 0456
Diffstat (limited to 'perly.y')
-rw-r--r--perly.y1
1 files changed, 1 insertions, 0 deletions
diff --git a/perly.y b/perly.y
index ece2904e6c..6ba61aebba 100644
--- a/perly.y
+++ b/perly.y
@@ -370,6 +370,7 @@ barestmt: PLUGSTMT
newOP(OP_UNSTACK, OPf_SPECIAL),
forop));
}
+ PL_hints |= HINT_BLOCK_SCOPE;
$$ = block_end($3, forop);
parser->copline = (line_t)$1;
}