develooper Front page | perl.perl5.porters | Postings from March 2001

PATCH for [ID 20010305.003]

Thread Next
From:
Robin Houston
Date:
March 13, 2001 18:45
Subject:
PATCH for [ID 20010305.003]
Message ID:
20010314024551.A16207@puffinry.freeserve.co.uk
This was the situation where code like:

  eval { goto foo; }; die "OK\n";
  foreach $i(1,2,3) { foo: die "Inconclusive\n"; }

would die, and the death not be caught by the eval.
Some people seemed to think it wasn't a bug, but it
looks like one to me...

And since I was already working on the right bit of
code, a patch is below. It applies over the two
patches I've already posted tonight.

 .robin.


--- perl-robin2/pp_ctl.c.before	Wed Mar 14 02:14:39 2001
+++ perl-robin2/pp_ctl.c	Wed Mar 14 02:34:36 2001
@@ -2454,6 +2454,7 @@
 
     if (label && *label) {
 	OP *gotoprobe = 0;
+	bool leaving_eval = FALSE;
 
 	/* find label */
 
@@ -2463,6 +2464,7 @@
 	    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;
@@ -2504,6 +2506,17 @@
 	}
 	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 */
 
--- perl-robin/t/op/eval.t	Tue Mar 13 16:02:38 2001
+++ perl-robin2/t/op/eval.t	Wed Mar 14 02:42:44 2001
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..40\n";
+print "1..41\n";
 
 eval 'print "ok 1\n";';
 
@@ -205,4 +205,19 @@
     print "not " if $@;
     print "ok $x\n";
     $x++;
+}
+
+# Check that eval catches bad goto calls
+#   (BUG ID 20010305.003)
+{
+    eval {
+	eval { goto foo; };
+	print ($@ ? "ok 41\n" : "not ok 41\n");
+	last;
+	foreach my $i (1) {
+	    foo: print "not ok 41\n";
+	    print "# jumped into foreach\n";
+	}
+    };
+    print "not ok 41\n" if $@;
 }

Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About