Apd |int |mg_clear |NN SV* sv
Apd |int |mg_copy |NN SV *sv|NN SV *nsv|NULLOK const char *key \
|I32 klen
-pd |void |mg_localize |NN SV* sv|NN SV* nsv
+pd |void |mg_localize |NN SV* sv|NN SV* nsv|I32 empty
ApdR |MAGIC* |mg_find |NULLOK const SV* sv|int type
Apd |int |mg_free |NN SV* sv
Apd |int |mg_get |NN SV* sv
Ap |void |save_shared_pvref|NN char** str
Ap |void |save_gp |NN GV* gv|I32 empty
Ap |HV* |save_hash |NN GV* gv
-Ap |void |save_helem |NN HV *hv|NN SV *key|NN SV **sptr
+Ap |void |save_helem |NN HV *hv|NN SV *key|NN SV **sptr|I32 empty
Ap |void |save_hptr |NN HV** hptr
Ap |void |save_I16 |NN I16* intp
Ap |void |save_I32 |NN I32* intp
#endif
#if defined(PERL_IN_SCOPE_C) || defined(PERL_DECL_PROT)
-s |SV* |save_scalar_at |NN SV **sptr
+s |SV* |save_scalar_at |NN SV **sptr|I32 empty
#endif
#if defined(PERL_IN_GV_C) || defined(PERL_IN_SV_C) || defined(PERL_IN_PAD_C) || defined(PERL_DECL_PROT)
#define mg_clear(a) Perl_mg_clear(aTHX_ a)
#define mg_copy(a,b,c,d) Perl_mg_copy(aTHX_ a,b,c,d)
#ifdef PERL_CORE
-#define mg_localize(a,b) Perl_mg_localize(aTHX_ a,b)
+#define mg_localize(a,b,c) Perl_mg_localize(aTHX_ a,b,c)
#endif
#define mg_find(a,b) Perl_mg_find(aTHX_ a,b)
#define mg_free(a) Perl_mg_free(aTHX_ a)
#define save_shared_pvref(a) Perl_save_shared_pvref(aTHX_ a)
#define save_gp(a,b) Perl_save_gp(aTHX_ a,b)
#define save_hash(a) Perl_save_hash(aTHX_ a)
-#define save_helem(a,b,c) Perl_save_helem(aTHX_ a,b,c)
+#define save_helem(a,b,c,d) Perl_save_helem(aTHX_ a,b,c,d)
#define save_hptr(a) Perl_save_hptr(aTHX_ a)
#define save_I16(a) Perl_save_I16(aTHX_ a)
#define save_I32(a) Perl_save_I32(aTHX_ a)
#endif
#if defined(PERL_IN_SCOPE_C) || defined(PERL_DECL_PROT)
#ifdef PERL_CORE
-#define save_scalar_at(a) S_save_scalar_at(aTHX_ a)
+#define save_scalar_at(a,b) S_save_scalar_at(aTHX_ a,b)
#endif
#endif
#if defined(PERL_IN_GV_C) || defined(PERL_IN_SV_C) || defined(PERL_IN_PAD_C) || defined(PERL_DECL_PROT)
/*
=for apidoc mg_localize
-Copy some of the magic from an existing SV to new localized version of
-that SV. Container magic (eg %ENV, $1, tie) gets copied, value magic
-doesn't (eg taint, pos).
+Copy some of the magic from an existing SV to new localized version of that
+SV. Container magic (eg %ENV, $1, tie) gets copied, value magic doesn't (eg
+taint, pos).
+
+If empty is false then no set magic will be called on the new (empty) SV.
+This typically means that assignment will soon follow (e.g. 'local $x = $y'),
+and that will handle the magic.
=cut
*/
void
-Perl_mg_localize(pTHX_ SV *sv, SV *nsv)
+Perl_mg_localize(pTHX_ SV *sv, SV *nsv, I32 empty)
{
dVAR;
MAGIC *mg;
if (SvTYPE(nsv) >= SVt_PVMG && SvMAGIC(nsv)) {
SvFLAGS(nsv) |= SvMAGICAL(sv);
- PL_localizing = 1;
- SvSETMAGIC(nsv);
- PL_localizing = 0;
+ if (empty) {
+ PL_localizing = 1;
+ SvSETMAGIC(nsv);
+ PL_localizing = 0;
+ }
}
}
/* On OP_SMARTMATCH, an implicit smartmatch */
/* On OP_ANONHASH and OP_ANONLIST, create a
reference to the new anon hash or array */
+ /* On OP_HELEM and OP_HSLICE, localization will be followed
+ by assignment, so do not wipe the target if it is special
+ (e.g. a glob or a magic SV) */
/* old names; don't use in new code, but don't break them, either */
#define OPf_LIST OPf_WANT_LIST
save_gp(MUTABLE_GV(*svp), !(PL_op->op_flags & OPf_SPECIAL));
else {
if (preeminent)
- save_helem(hv, keysv, svp);
+ save_helem(hv, keysv, svp, !(PL_op->op_flags & OPf_SPECIAL));
else {
STRLEN keylen;
const char * const key = SvPV_const(keysv, keylen);
SAVEDELETE(hv, savepvn(key,keylen),
SvUTF8(keysv) ? -(I32)keylen : (I32)keylen);
} else
- save_helem(hv, keysv, svp);
+ save_helem(hv, keysv, svp, !(PL_op->op_flags & OPf_SPECIAL));
}
}
else if (PL_op->op_private & OPpDEREF)
#define PERL_ARGS_ASSERT_MG_COPY \
assert(sv); assert(nsv)
-PERL_CALLCONV void Perl_mg_localize(pTHX_ SV* sv, SV* nsv)
+PERL_CALLCONV void Perl_mg_localize(pTHX_ SV* sv, SV* nsv, I32 empty)
__attribute__nonnull__(pTHX_1)
__attribute__nonnull__(pTHX_2);
#define PERL_ARGS_ASSERT_MG_LOCALIZE \
#define PERL_ARGS_ASSERT_SAVE_HASH \
assert(gv)
-PERL_CALLCONV void Perl_save_helem(pTHX_ HV *hv, SV *key, SV **sptr)
+PERL_CALLCONV void Perl_save_helem(pTHX_ HV *hv, SV *key, SV **sptr, I32 empty)
__attribute__nonnull__(pTHX_1)
__attribute__nonnull__(pTHX_2)
__attribute__nonnull__(pTHX_3);
#endif
#if defined(PERL_IN_SCOPE_C) || defined(PERL_DECL_PROT)
-STATIC SV* S_save_scalar_at(pTHX_ SV **sptr)
+STATIC SV* S_save_scalar_at(pTHX_ SV **sptr, I32 empty)
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_SAVE_SCALAR_AT \
assert(sptr)
}
STATIC SV *
-S_save_scalar_at(pTHX_ SV **sptr)
+S_save_scalar_at(pTHX_ SV **sptr, I32 empty)
{
dVAR;
SV * const osv = *sptr;
(SVp_IOK|SVp_NOK|SVp_POK)) >> PRIVSHIFT;
PL_tainted = oldtainted;
}
- mg_localize(osv, sv);
+ mg_localize(osv, sv, empty);
}
return sv;
}
SSPUSHPTR(SvREFCNT_inc_simple(gv));
SSPUSHPTR(SvREFCNT_inc(*sptr));
SSPUSHINT(SAVEt_SV);
- return save_scalar_at(sptr);
+ return save_scalar_at(sptr, TRUE); /* XXX - FIXME - see #60360 */
}
/* Like save_sptr(), but also SvREFCNT_dec()s the new value. Can be used to
GvAV(gv) = NULL;
av = GvAVn(gv);
if (SvMAGIC(oav))
- mg_localize(MUTABLE_SV(oav), MUTABLE_SV(av));
+ mg_localize(MUTABLE_SV(oav), MUTABLE_SV(av), TRUE);
return av;
}
GvHV(gv) = NULL;
hv = GvHVn(gv);
if (SvMAGIC(ohv))
- mg_localize(MUTABLE_SV(ohv), MUTABLE_SV(hv));
+ mg_localize(MUTABLE_SV(ohv), MUTABLE_SV(hv), TRUE);
return hv;
}
/* if it gets reified later, the restore will have the wrong refcnt */
if (!AvREAL(av) && AvREIFY(av))
SvREFCNT_inc_void(*sptr);
- save_scalar_at(sptr);
+ save_scalar_at(sptr, TRUE); /* XXX - FIXME - see #60360 */
sv = *sptr;
/* If we're localizing a tied array element, this new sv
* won't actually be stored in the array - so it won't get
}
void
-Perl_save_helem(pTHX_ HV *hv, SV *key, SV **sptr)
+Perl_save_helem(pTHX_ HV *hv, SV *key, SV **sptr, I32 empty)
{
dVAR;
SV *sv;
SSPUSHPTR(newSVsv(key));
SSPUSHPTR(SvREFCNT_inc(*sptr));
SSPUSHINT(SAVEt_HELEM);
- save_scalar_at(sptr);
+ save_scalar_at(sptr, empty);
sv = *sptr;
/* If we're localizing a tied hash element, this new sv
* won't actually be stored in the hash - so it won't get
SSPUSHPTR(sptr);
SSPUSHPTR(SvREFCNT_inc(*sptr));
SSPUSHINT(SAVEt_SVREF);
- return save_scalar_at(sptr);
+ return save_scalar_at(sptr, TRUE); /* XXX - FIXME - see #60360 */
}
void