summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2010-04-17 20:11:49 +0100
committerJesse Vincent <jesse@bestpractical.com>2010-05-08 17:39:53 -0400
commit6daa92fd3bab897011f098c559e29da4d873978a (patch)
tree011c1aecdb9221cf95abb54de166edf1da65eb40
parent379b40dc8dcedf4e3d5b0883fd2734423b2a076d (diff)
downloadperl-6daa92fd3bab897011f098c559e29da4d873978a.tar.gz
Fix RT #74290 - regression for labels immediately before string evals.
Fix location identified by Father Chrysostomos, who also offered a patch, but this patch is more efficient, as it avoids any allocation. Test code based on his test example.
-rw-r--r--hv.c2
-rw-r--r--pp_ctl.c13
-rw-r--r--t/op/goto.t11
3 files changed, 24 insertions, 2 deletions
diff --git a/hv.c b/hv.c
index 477b11ef4b..89c6456185 100644
--- a/hv.c
+++ b/hv.c
@@ -2972,6 +2972,8 @@ Perl_refcounted_he_free(pTHX_ struct refcounted_he *he) {
}
}
+/* pp_entereval is aware that labels are stored with a key ':' at the top of
+ the linked list. */
const char *
Perl_fetch_cop_label(pTHX_ struct refcounted_he *const chain, STRLEN *len,
U32 *flags) {
diff --git a/pp_ctl.c b/pp_ctl.c
index de3487998f..72fe93d86a 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -3758,7 +3758,18 @@ PP(pp_entereval)
if (PL_compiling.cop_hints_hash) {
Perl_refcounted_he_free(aTHX_ PL_compiling.cop_hints_hash);
}
- PL_compiling.cop_hints_hash = PL_curcop->cop_hints_hash;
+ if (Perl_fetch_cop_label(aTHX_ PL_curcop->cop_hints_hash, NULL, NULL)) {
+ /* The label, if present, is the first entry on the chain. So rather
+ than writing a blank label in front of it (which involves an
+ allocation), just use the next entry in the chain. */
+ PL_compiling.cop_hints_hash
+ = PL_curcop->cop_hints_hash->refcounted_he_next;
+ /* Check the assumption that this removed the label. */
+ assert(Perl_fetch_cop_label(aTHX_ PL_compiling.cop_hints_hash, NULL,
+ NULL) == NULL);
+ }
+ else
+ PL_compiling.cop_hints_hash = PL_curcop->cop_hints_hash;
if (PL_compiling.cop_hints_hash) {
HINTS_REFCNT_LOCK;
PL_compiling.cop_hints_hash->refcounted_he_refcnt++;
diff --git a/t/op/goto.t b/t/op/goto.t
index 5aaf630bb9..0a8aeeecbb 100644
--- a/t/op/goto.t
+++ b/t/op/goto.t
@@ -10,7 +10,7 @@ BEGIN {
use warnings;
use strict;
-plan tests => 66;
+plan tests => 67;
our $TODO;
my $deprecated = 0;
@@ -474,3 +474,12 @@ TODO: {
}
is($deprecated, 0);
+
+#74290
+{
+ my $x;
+ my $y;
+ F1:++$x and eval 'return if ++$y == 10; goto F1;';
+ is($x, 10,
+ 'labels outside evals can be distinguished from the start of the eval');
+}