This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Amelioration of the error message "Unrecognized character %s in column %d"
[perl5.git] / pp.c
diff --git a/pp.c b/pp.c
index 0fbc6e4..9cedc3f 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -3912,7 +3912,17 @@ PP(pp_aslice)
 
     if (SvTYPE(av) == SVt_PVAV) {
        const I32 arybase = CopARYBASE_get(PL_curcop);
-       if (lval && PL_op->op_private & OPpLVAL_INTRO) {
+       const bool localizing = PL_op->op_private & OPpLVAL_INTRO;
+       bool can_preserve = FALSE;
+
+       if (localizing) {
+           MAGIC *mg;
+           HV *stash;
+
+           can_preserve = SvCANEXISTDELETE(av);
+       }
+
+       if (lval && localizing) {
            register SV **svp;
            I32 max = -1;
            for (svp = MARK + 1; svp <= SP; svp++) {
@@ -3923,18 +3933,32 @@ PP(pp_aslice)
            if (max > AvMAX(av))
                av_extend(av, max);
        }
+
        while (++MARK <= SP) {
            register SV **svp;
            I32 elem = SvIV(*MARK);
+           bool preeminent = TRUE;
 
            if (elem > 0)
                elem -= arybase;
+           if (localizing && can_preserve) {
+               /* If we can determine whether the element exist,
+                * Try to preserve the existenceness of a tied array
+                * element by using EXISTS and DELETE if possible.
+                * Fallback to FETCH and STORE otherwise. */
+               preeminent = av_exists(av, elem);
+           }
+
            svp = av_fetch(av, elem, lval);
            if (lval) {
                if (!svp || *svp == &PL_sv_undef)
                    DIE(aTHX_ PL_no_aelem, elem);
-               if (PL_op->op_private & OPpLVAL_INTRO)
-                   save_aelem(av, elem, svp);
+               if (localizing) {
+                   if (preeminent)
+                       save_aelem(av, elem, svp);
+                   else
+                       SAVEADELETE(av, elem);
+               }
            }
            *MARK = svp ? *svp : &PL_sv_undef;
        }
@@ -4143,31 +4167,28 @@ PP(pp_hslice)
     register HV * const hv = MUTABLE_HV(POPs);
     register const I32 lval = (PL_op->op_flags & OPf_MOD || LVRET);
     const bool localizing = PL_op->op_private & OPpLVAL_INTRO;
-    bool other_magic = FALSE;
+    bool can_preserve = FALSE;
 
     if (localizing) {
         MAGIC *mg;
         HV *stash;
 
-        other_magic = mg_find((const SV *)hv, PERL_MAGIC_env) ||
-            ((mg = mg_find((const SV *)hv, PERL_MAGIC_tied))
-             /* Try to preserve the existenceness of a tied hash
-              * element by using EXISTS and DELETE if possible.
-              * Fallback to FETCH and STORE otherwise */
-             && (stash = SvSTASH(SvRV(SvTIED_obj(MUTABLE_SV(hv), mg))))
-             && gv_fetchmethod_autoload(stash, "EXISTS", TRUE)
-             && gv_fetchmethod_autoload(stash, "DELETE", TRUE));
+       if (SvCANEXISTDELETE(hv) || mg_find((const SV *)hv, PERL_MAGIC_env))
+           can_preserve = TRUE;
     }
 
     while (++MARK <= SP) {
         SV * const keysv = *MARK;
         SV **svp;
         HE *he;
-        bool preeminent = FALSE;
-
-        if (localizing) {
-            preeminent = SvRMAGICAL(hv) && !other_magic ? 1 :
-                hv_exists_ent(hv, keysv, 0);
+        bool preeminent = TRUE;
+
+        if (localizing && can_preserve) {
+           /* If we can determine whether the element exist,
+             * try to preserve the existenceness of a tied hash
+             * element by using EXISTS and DELETE if possible.
+             * Fallback to FETCH and STORE otherwise. */
+            preeminent = hv_exists_ent(hv, keysv, 0);
         }
 
         he = hv_fetch_ent(hv, keysv, lval, 0);
@@ -5041,9 +5062,9 @@ PP(pp_lock)
     dSP;
     dTOPss;
     SV *retsv = sv;
+    assert(SvTYPE(retsv) != SVt_PVCV);
     SvLOCK(sv);
-    if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV
-       || SvTYPE(retsv) == SVt_PVCV) {
+    if (SvTYPE(retsv) == SVt_PVAV || SvTYPE(retsv) == SVt_PVHV) {
        retsv = refto(retsv);
     }
     SETs(retsv);