[proposed PATCH] correctly unlocalise exists on tied/%ENV
[p5sagit/p5-mst-13.2.git] / pp_hot.c
index 3ff6dc6..f2387b4 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -734,7 +734,7 @@ PP(pp_rv2av)
        EXTEND(SP, maxarg);
        if (SvRMAGICAL(av)) {
            U32 i;
-           for (i=0; i < maxarg; i++) {
+           for (i=0; i < (U32)maxarg; i++) {
                SV **svp = av_fetch(av, i, FALSE);
                SP[i+1] = (svp) ? *svp : &PL_sv_undef;
            }
@@ -1232,7 +1232,7 @@ PP(pp_match)
        rx = PM_GETRE(pm);
     }
 
-    if (rx->minlen > len)
+    if (rx->minlen > (I32)len)
        goto failure;
 
     truebase = t = s;
@@ -1644,7 +1644,12 @@ PP(pp_helem)
 
     if (SvTYPE(hv) == SVt_PVHV) {
        if (PL_op->op_private & OPpLVAL_INTRO)
-           preeminent = SvRMAGICAL(hv) ? 1 : hv_exists_ent(hv, keysv, 0);
+           preeminent =  
+               ( SvRMAGICAL(hv)
+                 && !mg_find((SV*)hv, PERL_MAGIC_tied)
+                 && !mg_find((SV*)hv, PERL_MAGIC_env)
+               ) ? 1 : hv_exists_ent(hv, keysv, 0);
+
        he = hv_fetch_ent(hv, keysv, lval && !defer, hash);
        svp = he ? &HeVAL(he) : 0;
     }
@@ -1682,8 +1687,17 @@ PP(pp_helem)
                    STRLEN keylen;
                    char *key = SvPV(keysv, keylen);
                    SAVEDELETE(hv, savepvn(key,keylen), keylen);
-               } else
+               } else {
+                   SV *sv;
                    save_helem(hv, keysv, svp);
+                   sv = *svp;
+                   /* If we're localizing a tied hash element, this new
+                    * sv won't actually be stored in the hash - so it
+                    * won't get reaped when the localize ends. Ensure it
+                    * gets reaped by mortifying it instead. DAPM */
+                   if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
+                       sv_2mortal(sv);
+               }
             }
        }
        else if (PL_op->op_private & OPpDEREF)
@@ -1975,7 +1989,7 @@ PP(pp_subst)
     }
     
     /* can do inplace substitution? */
-    if (c && clen <= rx->minlen && (once || !(r_flags & REXEC_COPY_STR))
+    if (c && (I32)clen <= rx->minlen && (once || !(r_flags & REXEC_COPY_STR))
        && !(rx->reganch & ROPT_LOOKBEHIND_SEEN)) {
        if (!CALLREGEXEC(aTHX_ rx, s, strend, orig, 0, TARG, NULL,
                         r_flags | REXEC_CHECKED))
@@ -2117,7 +2131,14 @@ PP(pp_subst)
                break;
        } while (CALLREGEXEC(aTHX_ rx, s, strend, orig, s == m,
                             TARG, NULL, r_flags));
-       sv_catpvn(dstr, s, strend - s);
+       if (doutf8 && !DO_UTF8(dstr)) {
+           SV* nsv = sv_2mortal(newSVpvn(s, strend - s));
+           
+           sv_utf8_upgrade(nsv);
+           sv_catpvn(dstr, SvPVX(nsv), SvCUR(nsv));
+       }
+       else
+           sv_catpvn(dstr, s, strend - s);
 
        (void)SvOOK_off(TARG);
        Safefree(SvPVX(TARG));
@@ -2931,8 +2952,17 @@ PP(pp_aelem)
            PUSHs(lv);
            RETURN;
        }
-       if (PL_op->op_private & OPpLVAL_INTRO)
+       if (PL_op->op_private & OPpLVAL_INTRO) {
+           SV *sv;
            save_aelem(av, elem, svp);
+           sv = *svp;
+           /* If we're localizing a tied array element, this new sv
+            * won't actually be stored in the array - so it won't get
+            * reaped when the localize ends. Ensure it gets reaped by
+            * mortifying it instead. DAPM */
+           if (SvTIED_mg(sv, PERL_MAGIC_tiedelem))
+               sv_2mortal(sv);
+       }
        else if (PL_op->op_private & OPpDEREF)
            vivify_ref(*svp, PL_op->op_private & OPpDEREF);
     }