diff options
author | Marty Pauley <marty@martian.org> | 2010-10-24 18:02:40 +0900 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-11-04 00:33:47 -0700 |
commit | 91e34d82e7dd2f0ba610299faa1af2efc8b404dc (patch) | |
tree | 6a53af64d2795a2a4ac46420bcc80b85fa1bdc39 | |
parent | 8897dcaad14089c32e969309beb16112ec768eaf (diff) | |
download | perl-91e34d82e7dd2f0ba610299faa1af2efc8b404dc.tar.gz |
fix for #23790.
padav is leaving an arrayref on the stack when producing the return value for an
lvalue sub. But when this is in an argument list it really should be a array,
not a ref. So, in leavesublv I check for this case and expand the arrayref to
an array.
-rw-r--r-- | pp_hot.c | 23 | ||||
-rw-r--r-- | t/op/sub_lval.t | 12 |
2 files changed, 32 insertions, 3 deletions
@@ -2595,6 +2595,29 @@ PP(pp_leavesublv) if (gimme == G_SCALAR) goto temporise; if (gimme == G_ARRAY) { + mark = newsp + 1; + /* We want an array here, but padav will have left us an arrayref for an lvalue, + * so we need to expand it */ + if(SvTYPE(*mark) == SVt_PVAV) { + AV *const av = MUTABLE_AV(*mark); + const I32 maxarg = AvFILL(av) + 1; + (void)POPs; /* get rid of the array ref */ + EXTEND(SP, maxarg); + if (SvRMAGICAL(av)) { + U32 i; + for (i=0; i < (U32)maxarg; i++) { + SV ** const svp = av_fetch(av, i, FALSE); + SP[i+1] = svp + ? SvGMAGICAL(*svp) ? (mg_get(*svp), *svp) : *svp + : &PL_sv_undef; + } + } + else { + Copy(AvARRAY(av), SP+1, maxarg, SV*); + } + SP += maxarg; + PUTBACK; + } if (!CvLVALUE(cx->blk_sub.cv)) goto temporise_array; EXTEND_MORTAL(SP - newsp); diff --git a/t/op/sub_lval.t b/t/op/sub_lval.t index aedaba05d1..d0ba84a043 100644 --- a/t/op/sub_lval.t +++ b/t/op/sub_lval.t @@ -3,7 +3,7 @@ BEGIN { @INC = '../lib'; require './test.pl'; } -plan tests=>74; +plan tests=>76; sub a : lvalue { my $a = 34; ${\(bless \$a)} } # Return a temporary sub b : lvalue { ${\shift} } @@ -527,8 +527,7 @@ TODO: { is($blah, 8, "yada"); } -TODO: { - local $TODO = "bug #23790"; +{ # bug #23790 my @arr = qw /one two three/; my $line = "zero"; sub lval_array () : lvalue {@arr} @@ -538,6 +537,13 @@ TODO: { } is($line, "zeroonetwothree"); + + sub trythislval { scalar(@_)."x".join "", @_ } + is(trythislval(lval_array()), "3xonetwothree"); + + sub changeme { $_[2] = "free" } + changeme(lval_array); + is("@arr", "one two free"); } { |