summaryrefslogtreecommitdiff
path: root/pp_ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'pp_ctl.c')
-rw-r--r--pp_ctl.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index 46e7ef02ef..99e3ff415c 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2454,6 +2454,7 @@ PP(pp_goto)
if (label && *label) {
OP *gotoprobe = 0;
+ bool leaving_eval = FALSE;
/* find label */
@@ -2463,6 +2464,7 @@ PP(pp_goto)
cx = &cxstack[ix];
switch (CxTYPE(cx)) {
case CXt_EVAL:
+ leaving_eval = TRUE;
if (CxREALEVAL(cx)) {
gotoprobe = PL_eval_root; /* XXX not good for nested eval */
break;
@@ -2505,6 +2507,17 @@ PP(pp_goto)
if (!retop)
DIE(aTHX_ "Can't find label %s", label);
+ /* if we're leaving an eval, check before we pop any frames
+ that we're not going to punt, otherwise the error
+ won't be caught */
+
+ if (leaving_eval && *enterops && enterops[1]) {
+ I32 i;
+ for (i = 1; enterops[i]; i++)
+ if (enterops[i]->op_type == OP_ENTERITER)
+ DIE(aTHX_ "Can't \"goto\" into the middle of a foreach loop");
+ }
+
/* pop unwanted frames */
if (ix < cxstack_ix) {