PADNAME *name;
PADOFFSET pax = o->op_targ;
CV *outcv = CvOUTSIDE(PL_compcv);
+ CV *clonee = NULL;
HEK *hek = NULL;
+ bool reusable = FALSE;
PERL_ARGS_ASSERT_NEWMYSUB;
goto redo;
}
svspot =
- &PadARRAY(PadlistARRAY(CvPADLIST(outcv))[1])[pax];
+ &PadARRAY(PadlistARRAY(CvPADLIST(outcv))
+ [CvDEPTH(outcv) ? CvDEPTH(outcv) : 1])[pax];
spot = (CV **)svspot;
if (proto) {
goto done;
}
- if (PadnameIsSTATE(name))
+ if (CvDEPTH(outcv) && CvCLONE(compcv)) {
+ cv = *spot;
+ svspot = (SV **)(spot = &clonee);
+ }
+ else if (PadnameIsSTATE(name) || CvDEPTH(outcv))
cv = *spot;
else {
MAGIC *mg;
cv = NULL;
}
}
+ else if (CvDEPTH(outcv) && CvCLONE(compcv)) {
+ cv = NULL;
+ reusable = TRUE;
+ }
}
if (const_sv) {
SvREFCNT_inc_simple_void_NN(const_sv);
op_free(block);
SvREFCNT_dec(compcv);
PL_compcv = NULL;
- goto done;
+ goto clone;
}
/* Checking whether outcv is CvOUTSIDE(compcv) is not sufficient to
determine whether this sub definition is in the same scope as its
}
}
+ clone:
+ if (clonee) {
+ assert(CvDEPTH(outcv));
+ spot = (CV **)
+ &PadARRAY(PadlistARRAY(CvPADLIST(outcv))[CvDEPTH(outcv)])[pax];
+ if (reusable) cv_clone_into(clonee, *spot);
+ else *spot = cv_clone(clonee);
+ SvREFCNT_dec(clonee);
+ cv = *spot;
+ SvPADMY_on(cv);
+ }
+ if (CvDEPTH(outcv) && !reusable && PadnameIsSTATE(name)) {
+ PADOFFSET depth = CvDEPTH(outcv);
+ while (--depth) {
+ SV *oldcv;
+ svspot = &PadARRAY(PadlistARRAY(CvPADLIST(outcv))[depth])[pax];
+ oldcv = *svspot;
+ *svspot = SvREFCNT_inc_simple_NN(cv);
+ SvREFCNT_dec(oldcv);
+ }
+ }
+
done:
if (PL_parser)
PL_parser->copline = NOLINE;
*bar::like = *like;
}
no warnings 'deprecated';
-plan 122;
+plan 124;
# -------------------- our -------------------- #
state sub x;
eval 'sub x {3}';
is x, 3, 'state sub defined inside eval';
+
+ sub r {
+ state sub foo { 3 };
+ if (@_) { # outer call
+ r();
+ is foo(), 42,
+ 'state sub run-time redefinition applies to all recursion levels';
+ }
+ else { # inner call
+ eval 'sub foo { 42 }';
+ }
+ }
+ r(1);
}
# -------------------- my -------------------- #
x();
is $count, 11, 'my recursive subs';
}
+{
+ my sub x;
+ eval 'sub x {3}';
+ is x, 3, 'my sub defined inside eval';
+}
# -------------------- Interactions (and misc tests) -------------------- #