sv_catpv(tmpsv, ",MAYBE_LVSUB");
}
- if ((optype==OP_RV2SV || optype==OP_RV2AV || optype==OP_RV2HV)
- && (o->op_private & OPpDEREFed))
- sv_catpv(tmpsv, ",DEREFed");
-
if (optype == OP_AELEM || optype == OP_HELEM) {
if (o->op_private & OPpLVAL_DEFER)
sv_catpv(tmpsv, ",LVAL_DEFER");
: Used by Data::Alias
EXp |void |vivify_defelem |NN SV* sv
: Used in pp.c
-p |void |vivify_ref |NN SV* sv|U32 to_what
+pR |SV* |vivify_ref |NN SV* sv|U32 to_what
: Used in pp_sys.c
p |I32 |wait4pid |Pid_t pid|NN int* statusp|int flags
: Used in locale.c and perl.c
# l <|> mapwhile(other->m)[t26] lK
# m <#> gv[*_] s
# n <1> rv2sv sKM/DREFAV,1
-# o <1> rv2av[t4] sKR/DREFed,1
+# o <1> rv2av[t4] sKR/1
# p <$> const[IV 0] s
# q <2> aelem sK/2
# - <@> scope lK
# l <|> mapwhile(other->m)[t12] lK
# m <$> gv(*_) s
# n <1> rv2sv sKM/DREFAV,1
-# o <1> rv2av[t2] sKR/DREFed,1
+# o <1> rv2av[t2] sKR/1
# p <$> const(IV 0) s
# q <2> aelem sK/2
# - <@> scope lK
$subs{'%{}'} = '%s';
push @tests, [ {qw(a 1 b 2 c 3)}, 'join "", sort keys %%{%s}',
- '(%{})', undef, [ 1, 2, 0 ], 0 ];
+ '(%{})', undef, [ 1, 1, 0 ], 0 ];
$subs{'&{}'} = '%s';
push @tests, [ sub {99}, 'do {&{%s} for 1,2}',
DEFER(cPMOP->op_pmstashstartu.op_pmreplstart);
break;
- case OP_RV2SV:
- case OP_RV2AV:
- case OP_RV2HV:
- if (oldop &&
- (
- (
- ( oldop->op_type == OP_AELEM
- || oldop->op_type == OP_PADSV
- || oldop->op_type == OP_RV2SV
- || oldop->op_type == OP_RV2GV
- || oldop->op_type == OP_HELEM
- )
- && (oldop->op_private & OPpDEREF)
- )
- || ( oldop->op_type == OP_ENTERSUB
- && oldop->op_private & OPpENTERSUB_DEREF )
- )
- ) {
- o->op_private |= OPpDEREFed;
- }
-
case OP_SORT: {
/* will point to RV2AV or PADAV op on LHS/RHS of assign */
OP *oleft;
#define OPpDEREF_AV 32 /* Want ref to AV. */
#define OPpDEREF_HV 64 /* Want ref to HV. */
#define OPpDEREF_SV (32|64) /* Want ref to SV. */
-/* Private for OP_RV2SV, OP_RV2AV, OP_RV2AV */
-#define OPpDEREFed 4 /* prev op was OPpDEREF */
/* OP_ENTERSUB only */
#define OPpENTERSUB_DB 16 /* Debug subroutine. */
dVAR; dSP; dTOPss;
GV *gv = NULL;
- if (!(PL_op->op_private & OPpDEREFed))
- SvGETMAGIC(sv);
+ SvGETMAGIC(sv);
if (SvROK(sv)) {
if (SvAMAGIC(sv)) {
sv = amagic_deref_call(sv, to_sv_amg);
Perl_croak(aTHX_ "%s", PL_no_localize_ref);
}
else if (PL_op->op_private & OPpDEREF)
- vivify_ref(sv, PL_op->op_private & OPpDEREF);
+ sv = vivify_ref(sv, PL_op->op_private & OPpDEREF);
}
SETs(sv);
RETURN;
assert(cx->blk_sub.retop->op_type == OP_RV2HV);
deref_type = OPpDEREF_HV;
}
- vivify_ref(TOPs, deref_type);
+ TOPs = vivify_ref(TOPs, deref_type);
}
}
}
bool popsub2 = FALSE;
bool clear_errsv = FALSE;
bool lval = FALSE;
- bool gmagic = FALSE;
I32 gimme;
SV **newsp;
PMOP *newpm;
popsub2 = TRUE;
lval = !!CvLVALUE(cx->blk_sub.cv);
retop = cx->blk_sub.retop;
- gmagic = CxLVAL(cx) & OPpENTERSUB_DEREF;
cxstack_ix++; /* preserve cx entry on stack for use by POPSUB */
break;
case CXt_EVAL:
*++newsp = SvREFCNT_inc(*SP);
FREETMPS;
sv_2mortal(*newsp);
- if (gmagic) SvGETMAGIC(*newsp);
}
else {
sv = SvREFCNT_inc(*SP); /* FREETMPS could clobber it */
}
else if (SvTEMP(*SP) && SvREFCNT(*SP) == 1) {
*++newsp = *SP;
- if (gmagic) SvGETMAGIC(*SP);
}
else
*++newsp = sv_mortalcopy(*SP);
SAVECLEARSV(PAD_SVl(PL_op->op_targ));
if (PL_op->op_private & OPpDEREF) {
PUTBACK;
- vivify_ref(PAD_SVl(PL_op->op_targ), PL_op->op_private & OPpDEREF);
+ TOPs = vivify_ref(TOPs, PL_op->op_private & OPpDEREF);
SPAGAIN;
}
}
const bool is_pp_rv2av = PL_op->op_type == OP_RV2AV;
const svtype type = is_pp_rv2av ? SVt_PVAV : SVt_PVHV;
- if (!(PL_op->op_private & OPpDEREFed))
- SvGETMAGIC(sv);
+ SvGETMAGIC(sv);
if (SvROK(sv)) {
if (SvAMAGIC(sv)) {
sv = amagic_deref_call(sv, is_pp_rv2av ? to_av_amg : to_hv_amg);
else
SAVEHDELETE(hv, keysv);
}
- else if (PL_op->op_private & OPpDEREF)
- vivify_ref(*svp, PL_op->op_private & OPpDEREF);
+ else if (PL_op->op_private & OPpDEREF) {
+ PUSHs(vivify_ref(*svp, PL_op->op_private & OPpDEREF));
+ RETURN;
+ }
}
sv = (svp ? *svp : &PL_sv_undef);
/* Originally this did a conditional C<sv = sv_mortalcopy(sv)>; this
I32 gimme;
register PERL_CONTEXT *cx;
SV *sv;
- bool gmagic;
if (CxMULTICALL(&cxstack[cxstack_ix]))
return 0;
POPBLOCK(cx,newpm);
cxstack_ix++; /* temporarily protect top context */
- gmagic = CxLVAL(cx) & OPpENTERSUB_DEREF;
TAINT_NOT;
if (gimme == G_SCALAR) {
*MARK = SvREFCNT_inc(TOPs);
FREETMPS;
sv_2mortal(*MARK);
- if (gmagic) SvGETMAGIC(*MARK);
}
else {
sv = SvREFCNT_inc(TOPs); /* FREETMPS could clobber it */
}
else if (SvTEMP(TOPs) && SvREFCNT(TOPs) == 1) {
*MARK = TOPs;
- if (gmagic) SvGETMAGIC(TOPs);
}
else
*MARK = sv_mortalcopy(TOPs);
else
SAVEADELETE(av, elem);
}
- else if (PL_op->op_private & OPpDEREF)
- vivify_ref(*svp, PL_op->op_private & OPpDEREF);
+ else if (PL_op->op_private & OPpDEREF) {
+ PUSHs(vivify_ref(*svp, PL_op->op_private & OPpDEREF));
+ RETURN;
+ }
}
sv = (svp ? *svp : &PL_sv_undef);
if (!lval && SvRMAGICAL(av) && SvGMAGICAL(sv)) /* see note in pp_helem() */
RETURN;
}
-void
+SV*
Perl_vivify_ref(pTHX_ SV *sv, U32 to_what)
{
PERL_ARGS_ASSERT_VIVIFY_REF;
SvROK_on(sv);
SvSETMAGIC(sv);
}
+ if (SvGMAGICAL(sv)) {
+ /* copy the sv without magic to prevent magic from being
+ executed twice */
+ SV* msv = sv_newmortal();
+ sv_setsv_nomg(msv, sv);
+ return msv;
+ }
+ return sv;
}
PP(pp_method)
#define PERL_ARGS_ASSERT_VIVIFY_DEFELEM \
assert(sv)
-PERL_CALLCONV void Perl_vivify_ref(pTHX_ SV* sv, U32 to_what)
+PERL_CALLCONV SV* Perl_vivify_ref(pTHX_ SV* sv, U32 to_what)
+ __attribute__warn_unused_result__
__attribute__nonnull__(pTHX_1);
#define PERL_ARGS_ASSERT_VIVIFY_REF \
assert(sv)