Skip to content

Commit

Permalink
Restore ‘Can’t localize through ref’ to lv subs
Browse files Browse the repository at this point in the history
In commit 40c94d1, I put an if statement inside an if statement,
skipping the else that followed if the outer if was true:

  if (...) {

  }
  else if {

became

  if (...) {
     ...
     if (...) {
        ...
     }
  }
  else if {

The result was that ‘Can’t localize through a reference’ no longer
happened if the operator (%{} or @{}) was the last thing in an lvalue
sub, if the lvalue sub was not called in lvalue context.

$ perl5.14.0 -e 'sub foo :lvalue { local %{\%foo} } foo(); print "ok\n"'
Can't localize through a reference at -e line 1.
$ perl5.16.0 -e 'sub foo :lvalue { local %{\%foo} } foo(); print "ok\n"'
ok

If the sub is called in lvalue context, the bug exists there, too, but
is much older (probably 82d0398):

$ perl5.6.2 -e 'sub f :lvalue { local %{\%foo} } (f()) =3; print "ok\n"'
Can't localize through a reference at -e line 1.
$ perl5.8.1 -e 'sub f :lvalue { local %{\%foo} } (f()) =3; print "ok\n"'
ok

The simplest solution is to change the order of the conditions.  If
the rv2hv or rv2av op is passed a reference, and has ‘local’ in front
of it (OPf_MOD && OPpLVAL_INTRO), that should die, regardless of
whether it is the last thing in an lvalue sub.
  • Loading branch information
Father Chrysostomos committed Aug 26, 2012
1 parent 83d881f commit 858e07c
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 3 deletions.
6 changes: 3 additions & 3 deletions pp_hot.c
Expand Up @@ -781,6 +781,9 @@ PP(pp_rv2av)
SETs(sv);
RETURN;
}
else if (PL_op->op_flags & OPf_MOD
&& PL_op->op_private & OPpLVAL_INTRO)
Perl_croak(aTHX_ "%s", PL_no_localize_ref);
else if (PL_op->op_private & OPpMAYBE_LVSUB) {
const I32 flags = is_lvalue_sub();
if (flags && !(flags & OPpENTERSUB_INARGS)) {
Expand All @@ -790,9 +793,6 @@ PP(pp_rv2av)
RETURN;
}
}
else if (PL_op->op_flags & OPf_MOD
&& PL_op->op_private & OPpLVAL_INTRO)
Perl_croak(aTHX_ "%s", PL_no_localize_ref);
}
else {
if (SvTYPE(sv) == type) {
Expand Down
24 changes: 24 additions & 0 deletions t/lib/croak/pp_hot
@@ -1,4 +1,28 @@
__END__
# NAME local %$ref on last line of lvalue sub in lv cx
sub foo :lvalue { local %{\%foo} }
(foo) = 3;
EXPECT
Can't localize through a reference at - line 1.
########
# NAME local @$ref on last line of lvalue sub in lv cx
sub foo :lvalue { local @{\@foo} }
(foo) = 3;
EXPECT
Can't localize through a reference at - line 1.
########
# NAME local %$ref on last line of lvalue sub in non-lv cx
sub foo :lvalue { local %{\%foo} }
foo;
EXPECT
Can't localize through a reference at - line 1.
########
# NAME local @$ref on last line of lvalue sub in non-lv cx
sub foo :lvalue { local @{\@foo} }
foo;
EXPECT
Can't localize through a reference at - line 1.
########
# NAME calling undef sub belonging to undef GV
my $foosub = \&foo;
undef *foo;
Expand Down

0 comments on commit 858e07c

Please sign in to comment.