Restore ‘Can’t localize through ref’ to lv subs
authorFather Chrysostomos <sprout@cpan.org>
Sun, 26 Aug 2012 18:06:39 +0000 (11:06 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 26 Aug 2012 20:16:54 +0000 (13:16 -0700)
commit858e07c416232a7bc145c8c4da21220a4f0a2cbd
tree433fb796087071c7ba4d37ac61e8072ff6d6763f
parent83d881f0f43224b94b0ea14e09e51156a3c8c28f
Restore ‘Can’t localize through ref’ to lv subs

In commit 40c94d11, 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 82d039840b9):

$ 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.
pp_hot.c
t/lib/croak/pp_hot