This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
handy.h, hv.h: fixup hash s suffix macro definitions, move to hv.h
[perl5.git] / doop.c
diff --git a/doop.c b/doop.c
index dbf26d6..79cf4b6 100644 (file)
--- a/doop.c
+++ b/doop.c
@@ -16,7 +16,7 @@
 
 /* This file contains some common functions needed to carry out certain
  * ops. For example, both pp_sprintf() and pp_prtf() call the function
- * do_printf() found in this file.
+ * do_sprintf() found in this file.
  */
 
 #include "EXTERN.h"
@@ -1008,7 +1008,7 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
     PERL_ARGS_ASSERT_DO_VOP;
 
     if (sv != left || (optype != OP_BIT_AND && !SvOK(sv)))
-       sv_setpvs(sv, "");      /* avoid undef warning on |= and ^= */
+        sv_setpvs(sv, "");        /* avoid undef warning on |= and ^= */
     if (sv == left) {
        lsave = lc = SvPV_force_nomg(left, leftlen);
     }
@@ -1093,6 +1093,7 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
            if (sv == left || sv == right)
                (void)sv_usepvn(sv, dcorig, needlen);
            SvCUR_set(sv, dc - dcorig);
+           *SvEND(sv) = 0;
            break;
        case OP_BIT_XOR:
            while (lulen && rulen) {
@@ -1238,11 +1239,15 @@ Perl_do_kv(pTHX)
     HV * const keys = MUTABLE_HV(POPs);
     HE *entry;
     SSize_t extend_size;
-    const I32 gimme = GIMME_V;
+    const U8 gimme = GIMME_V;
     const I32 dokv =     (PL_op->op_type == OP_RV2HV || PL_op->op_type == OP_PADHV);
     /* op_type is OP_RKEYS/OP_RVALUES if pp_rkeys delegated to here */
-    const I32 dokeys =   dokv || (PL_op->op_type == OP_KEYS);
-    const I32 dovalues = dokv || (PL_op->op_type == OP_VALUES);
+    const I32 dokeys =   dokv || (PL_op->op_type == OP_KEYS)
+       || (  PL_op->op_type == OP_AVHVSWITCH
+          && (PL_op->op_private & 3) + OP_EACH == OP_KEYS  );
+    const I32 dovalues = dokv || (PL_op->op_type == OP_VALUES)
+       || (  PL_op->op_type == OP_AVHVSWITCH
+          && (PL_op->op_private & 3) + OP_EACH == OP_VALUES  );
 
     (void)hv_iterinit(keys);   /* always reset iterator regardless */
 
@@ -1273,6 +1278,13 @@ Perl_do_kv(pTHX)
        RETURN;
     }
 
+    if (UNLIKELY(PL_op->op_private & OPpMAYBE_LVSUB)) {
+       const I32 flags = is_lvalue_sub();
+       if (flags && !(flags & OPpENTERSUB_INARGS))
+           /* diag_listed_as: Can't modify %s in %s */
+           Perl_croak(aTHX_ "Can't modify keys in list assignment");
+    }
+
     /* 2*HvUSEDKEYS() should never be big enough to truncate or wrap */
     assert(HvUSEDKEYS(keys) <= (SSize_t_MAX >> 1));
     extend_size = (SSize_t)HvUSEDKEYS(keys) * (dokeys + dovalues);