Re: [Fwd: BUG 20001205.022] Local on Hash elements
Simon Cozens [Mon, 11 Dec 2000 01:21:45 +0000 (01:21 +0000)]
Message-ID: <20001211012144.A23467@deep-dark-truthful-mirror.perlhacker.org>

p4raw-id: //depot/perl@8077

pp.c
pp_hot.c
scope.c
t/op/local.t

diff --git a/pp.c b/pp.c
index f125d56..eaa4d17 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -2833,6 +2833,7 @@ PP(pp_hslice)
        while (++MARK <= SP) {
            SV *keysv = *MARK;
            SV **svp;
+           I32 preeminent = SvRMAGICAL(hv) ? 1 : hv_exists_ent(hv, keysv, 0);
            if (realhv) {
                HE *he = hv_fetch_ent(hv, keysv, lval, 0);
                svp = he ? &HeVAL(he) : 0;
@@ -2845,8 +2846,15 @@ PP(pp_hslice)
                    STRLEN n_a;
                    DIE(aTHX_ PL_no_helem, SvPV(keysv, n_a));
                }
-               if (PL_op->op_private & OPpLVAL_INTRO)
-                   save_helem(hv, keysv, svp);
+               if (PL_op->op_private & OPpLVAL_INTRO) {
+                   if (preeminent) 
+                       save_helem(hv, keysv, svp);
+                   else {
+                       STRLEN keylen;
+                       char *key = SvPV(keysv, keylen);
+                       save_delete(hv, key, keylen);
+                   }
+                }
            }
            *MARK = svp ? *svp : &PL_sv_undef;
        }
index 979d111..2dedcdd 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1532,8 +1532,11 @@ PP(pp_helem)
     U32 defer = PL_op->op_private & OPpLVAL_DEFER;
     SV *sv;
     U32 hash = (SvFAKE(keysv) && SvREADONLY(keysv)) ? SvUVX(keysv) : 0;
+    I32 preeminent;
 
     if (SvTYPE(hv) == SVt_PVHV) {
+       if (PL_op->op_private & OPpLVAL_INTRO)
+           preeminent = SvRMAGICAL(hv) ? 1 : hv_exists_ent(hv, keysv, 0);
        he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
        svp = he ? &HeVAL(he) : 0;
     }
@@ -1566,8 +1569,14 @@ PP(pp_helem)
        if (PL_op->op_private & OPpLVAL_INTRO) {
            if (HvNAME(hv) && isGV(*svp))
                save_gp((GV*)*svp, !(PL_op->op_flags & OPf_SPECIAL));
-           else
-               save_helem(hv, keysv, svp);
+           else {
+               if (!preeminent) {
+                   STRLEN keylen;
+                   char *key = SvPV(keysv, keylen);
+                   save_delete(hv, key, keylen);
+               } else 
+                   save_helem(hv, keysv, svp);
+            }
        }
        else if (PL_op->op_private & OPpDEREF)
            vivify_ref(*svp, PL_op->op_private & OPpDEREF);
diff --git a/scope.c b/scope.c
index 3f41a4e..7c83a41 100644 (file)
--- a/scope.c
+++ b/scope.c
@@ -852,7 +852,6 @@ Perl_leave_scope(pTHX_ I32 base)
            ptr = SSPOPPTR;
            (void)hv_delete(hv, (char*)ptr, (U32)SSPOPINT, G_DISCARD);
            SvREFCNT_dec(hv);
-           Safefree(ptr);
            break;
        case SAVEt_DESTRUCTOR:
            ptr = SSPOPPTR;
index b478e01..781afa5 100755 (executable)
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..69\n";
+print "1..71\n";
 
 # XXX known to leak scalars
 $ENV{PERL_DESTRUCT_LEVEL} = 0 unless $ENV{PERL_DESTRUCT_LEVEL} > 3;
@@ -235,3 +235,14 @@ while (/(o.+?),/gc) {
     untie $_;
 }
 
+{
+    # BUG 20001205.22
+    my %x;
+    $x{a} = 1;
+    { local $x{b} = 1; }
+    print "not " if exists $x{b};
+    print "ok 70\n";
+    { local @x{c,d,e}; }
+    print "not " if exists $x{c};
+    print "ok 71\n"; 
+}