Hi,

the attached proposed patch against blead hopefully fixes a problem when
a lvalue-sub has an element of a tied hash or array as its last
statement. It should be a solution for buglet #30582 "Conflicts between
the :shared attribute and lvalue subroutines" which boiled down to

$ perl -MTie::Hash -we'tie %x,"Tie::StdHash"; sub foo:lvalue {$x{foo}} foo=1'
Can't return a temporary from lvalue subroutine at -e line 1.

The patch also contains a couple of new tests in t/op/sub_lval.t for
these constructs.

Tassilo
-- 
use bigint;
$n=71423350343770280161397026330337371139054411854220053437565440;
$m=-8,;;$_=$n&(0xff)<<$m,,$_>>=$m,,print+chr,,while(($m+=8)<=200);
--- [EMAIL PROTECTED]/pp_hot.c  2005-07-20 09:33:46.000000000 +0200
+++ [EMAIL PROTECTED]/pp_hot.c  2005-07-20 10:32:23.000000000 +0200
@@ -2441,7 +2441,10 @@ PP(pp_leavesublv)
            MARK = newsp + 1;
            EXTEND_MORTAL(1);
            if (MARK == SP) {
-               if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY)) {
+               /* Temporaries are bad unless they happen to be elements
+                * of a tied hash or array */
+               if (SvFLAGS(TOPs) & (SVs_TEMP | SVs_PADTMP | SVf_READONLY) &&
+                   !(SvRMAGICAL(TOPs) && mg_find(TOPs, PERL_MAGIC_tiedelem))) {
                    LEAVE;
                    cxstack_ix--;
                    POPSUB(cx,sv);
--- [EMAIL PROTECTED]/t/op/sub_lval.t   2005-07-20 09:33:49.000000000 +0200
+++ [EMAIL PROTECTED]/t/op/sub_lval.t   2005-07-20 10:30:41.000000000 +0200
@@ -1,4 +1,4 @@
-print "1..68\n";
+print "1..72\n";
 
 BEGIN {
     chdir 't' if -d 't';
@@ -530,8 +530,51 @@ sub lval2 : lvalue { $ary[1]; }
 print "not " unless join(':', @ary) eq "1:2:6";
 print "ok 64\n";
 
+# check that an element of a tied hash/array can be assigned to via lvalueness
+
+package Tie_Hash;
+
+our ($key, $val);
+sub TIEHASH { bless \my $v => __PACKAGE__ }
+sub STORE   { ($key, $val) = @_[1,2] }
+
+package main;
+sub lval_tie_hash : lvalue {
+    tie my %t => 'Tie_Hash';
+    $t{key};
+}
+
+eval { lval_tie_hash() = "value"; };
+
+print "# element of tied hash: [EMAIL PROTECTED] " if $@;
+print "ok 65\n";
+
+print "not " if "$Tie_Hash::key-$Tie_Hash::val" ne "key-value";
+print "ok 66\n";
+
+
+package Tie_Array;
+
+our @val;
+sub TIEARRAY { bless \my $v => __PACKAGE__ }
+sub STORE   { $val[ $_[1] ] = $_[2] }
+
+package main;
+sub lval_tie_array : lvalue {
+    tie my @t => 'Tie_Array';
+    $t[0];
+}
+
+eval { lval_tie_array() = "value"; };
+
+print "# element of tied array: [EMAIL PROTECTED] " if $@;
+print "ok 67\n";
+
+print "not " if $Tie_Array::val[0] ne "value";
+print "ok 68\n";
+
 require './test.pl';
-curr_test(65);
+curr_test(69);
 
 TODO: {
     local $TODO = 'test explicit return of lval expr';

Reply via email to