summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--op.c6
-rw-r--r--op.h3
-rw-r--r--pp_ctl.c17
-rwxr-xr-xt/cmd/while.t19
4 files changed, 33 insertions, 12 deletions
diff --git a/op.c b/op.c
index 04a84b8e6a..6ed38e403e 100644
--- a/op.c
+++ b/op.c
@@ -3764,6 +3764,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
OP *listop;
OP *o;
OP *condop;
+ U8 loopflags = 0;
if (expr && (expr->op_type == OP_READLINE || expr->op_type == OP_GLOB
|| (expr->op_type == OP_NULL && expr->op_targ == OP_GLOB))) {
@@ -3796,8 +3797,10 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
block = scope(block);
}
- if (cont)
+ if (cont) {
next = LINKLIST(cont);
+ loopflags |= OPpLOOP_CONTINUE;
+ }
if (expr) {
cont = append_elem(OP_LINESEQ, cont, newOP(OP_UNSTACK, 0));
if ((line_t)whileline != NOLINE) {
@@ -3840,6 +3843,7 @@ Perl_newWHILEOP(pTHX_ I32 flags, I32 debuggable, LOOP *loop, I32 whileline, OP *
loop->op_redoop = redo;
loop->op_lastop = o;
+ o->op_private |= loopflags;
if (next)
loop->op_nextop = next;
diff --git a/op.h b/op.h
index 6019486701..52b68cb4b8 100644
--- a/op.h
+++ b/op.h
@@ -139,6 +139,9 @@ Deprecated. Use C<GIMME_V> instead.
/* Private for OP_REPEAT */
#define OPpREPEAT_DOLIST 64 /* List replication. */
+/* Private for OP_LEAVELOOP */
+#define OPpLOOP_CONTINUE 64 /* a continue block is present */
+
/* Private for OP_RV2?V, OP_?ELEM */
#define OPpDEREF (32|64) /* Want ref to something: */
#define OPpDEREF_AV 32 /* Want ref to AV. */
diff --git a/pp_ctl.c b/pp_ctl.c
index 308c824b17..552359258b 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1983,17 +1983,14 @@ PP(pp_next)
if (cxix < cxstack_ix)
dounwind(cxix);
- cx = &cxstack[cxstack_ix];
- {
- OP *nextop = cx->blk_loop.next_op;
- /* clean scope, but only if there's no continue block */
- if (nextop == cUNOPx(cx->blk_loop.last_op)->op_first->op_next) {
- TOPBLOCK(cx);
- oldsave = PL_scopestack[PL_scopestack_ix - 1];
- LEAVE_SCOPE(oldsave);
- }
- return nextop;
+ TOPBLOCK(cx);
+
+ /* clean scope, but only if there's no continue block */
+ if (!(cx->blk_loop.last_op->op_private & OPpLOOP_CONTINUE)) {
+ oldsave = PL_scopestack[PL_scopestack_ix - 1];
+ LEAVE_SCOPE(oldsave);
}
+ return cx->blk_loop.next_op;
}
PP(pp_redo)
diff --git a/t/cmd/while.t b/t/cmd/while.t
index 46bbdea15a..ecc15eda53 100755
--- a/t/cmd/while.t
+++ b/t/cmd/while.t
@@ -1,6 +1,6 @@
#!./perl
-print "1..19\n";
+print "1..22\n";
open (tmp,'>Cmd_while.tmp') || die "Can't create Cmd_while.tmp.";
print tmp "tvi925\n";
@@ -160,3 +160,20 @@ print "ok $i\n";
print "ok $l\n"
}
}
+
+$i = 20;
+{
+ while (1) {
+ my $x;
+ print $x if defined $x;
+ $x = "not ";
+ print "ok $i\n"; ++$i;
+ if ($i == 21) {
+ next;
+ }
+ last;
+ }
+ continue {
+ print "ok $i\n"; ++$i;
+ }
+}