#define refto(a) S_refto(aTHX_ a)
# endif
# if defined(PERL_IN_PP_CTL_C)
-#define adjust_stack_on_leave(a,b,c,d,e) S_adjust_stack_on_leave(aTHX_ a,b,c,d,e)
+#define adjust_stack_on_leave(a,b,c,d,e,f) S_adjust_stack_on_leave(aTHX_ a,b,c,d,e,f)
#define check_type_and_open(a) S_check_type_and_open(aTHX_ a)
#define destroy_matcher(a) S_destroy_matcher(aTHX_ a)
#define do_smartmatch(a,b,c) S_do_smartmatch(aTHX_ a,b,c)
return NORMAL;
}
+/* SVs on the stack that have any of the flags passed in are left as is.
+ Other SVs are protected via the mortals stack if lvalue is true, and
+ copied otherwise. */
+
STATIC SV **
-S_adjust_stack_on_leave(pTHX_ SV **newsp, SV **sp, SV **mark, I32 gimme, U32 flags)
+S_adjust_stack_on_leave(pTHX_ SV **newsp, SV **sp, SV **mark, I32 gimme,
+ U32 flags, bool lvalue)
{
bool padtmp = 0;
PERL_ARGS_ASSERT_ADJUST_STACK_ON_LEAVE;
if (gimme == G_SCALAR) {
if (MARK < SP)
*++newsp = ((SvFLAGS(*SP) & flags) || (padtmp && SvPADTMP(*SP)))
- ? *SP : sv_mortalcopy(*SP);
+ ? *SP
+ : lvalue
+ ? sv_2mortal(SvREFCNT_inc_simple_NN(*SP))
+ : sv_mortalcopy(*SP);
else {
/* MEXTEND() only updates MARK, so reuse it instead of newsp. */
MARK = newsp;
if ((SvFLAGS(*MARK) & flags) || (padtmp && SvPADTMP(*MARK)))
*++newsp = *MARK;
else {
- *++newsp = sv_mortalcopy(*MARK);
+ *++newsp = lvalue
+ ? sv_2mortal(SvREFCNT_inc_simple_NN(*MARK))
+ : sv_mortalcopy(*MARK);
TAINT_NOT; /* Each item is independent */
}
}
gimme = OP_GIMME(PL_op, (cxstack_ix >= 0) ? gimme : G_SCALAR);
TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+ SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP,
+ PL_op->op_private & OPpLVALUE);
PL_curpm = newpm; /* Don't pop $1 et al till now */
LEAVE_with_name("block");
newsp = PL_stack_base + cx->blk_loop.resetsp;
TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, MARK, gimme, 0);
+ SP = adjust_stack_on_leave(newsp, SP, MARK, gimme, 0, FALSE);
PUTBACK;
POPLOOP(cx); /* Stack values are safe: release loop vars ... */
TAINT_NOT;
SP = adjust_stack_on_leave((gimme == G_VOID) ? SP : newsp, SP, newsp,
- gimme, SVs_TEMP);
+ gimme, SVs_TEMP, FALSE);
PL_curpm = newpm; /* Don't pop $1 et al till now */
#ifdef DEBUGGING
PERL_UNUSED_VAR(optype);
TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+ SP = adjust_stack_on_leave(newsp, SP, newsp, gimme,
+ SVs_PADTMP|SVs_TEMP, FALSE);
PL_curpm = newpm; /* Don't pop $1 et al till now */
LEAVE_with_name("eval_scope");
assert(CxTYPE(cx) == CXt_GIVEN);
TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+ SP = adjust_stack_on_leave(newsp, SP, newsp, gimme,
+ SVs_PADTMP|SVs_TEMP, FALSE);
PL_curpm = newpm; /* Don't pop $1 et al till now */
LEAVE_with_name("given");
assert(CxTYPE(cx) == CXt_WHEN);
TAINT_NOT;
- SP = adjust_stack_on_leave(newsp, SP, newsp, gimme, SVs_PADTMP|SVs_TEMP);
+ SP = adjust_stack_on_leave(newsp, SP, newsp, gimme,
+ SVs_PADTMP|SVs_TEMP, FALSE);
PL_curpm = newpm; /* pop $1 et al */
LEAVE_with_name("when");
@INC = '../lib';
require './test.pl';
}
-plan tests=>193;
+plan tests=>201;
sub a : lvalue { my $a = 34; ${\(bless \$a)} } # Return a temporary
sub b : lvalue { ${\shift} }
eval { &{\&utf8::is_utf8}("") = 3 };
like $@, qr/^Can't modify non-lvalue subroutine call at /,
'XSUB not seen at compile time dies in lvalue context';
+
+# [perl #119797] else implicitly returning value
+# This used to cause Bizarre copy of ARRAY in pp_leave
+sub else119797 : lvalue {
+ if ($_[0]) {
+ 1; # two statements force a leave op
+ @119797
+ }
+ else {
+ @119797
+ }
+}
+eval { (else119797(0)) = 1..3 };
+is $@, "", '$@ after writing to array returned by else';
+is "@119797", "1 2 3", 'writing to array returned by else';
+eval { (else119797(1)) = 4..6 };
+is $@, "", '$@ after writing to array returned by if (with else)';
+is "@119797", "4 5 6", 'writing to array returned by if (with else)';
+sub if119797 : lvalue {
+ if ($_[0]) {
+ @119797
+ }
+}
+@119797 = ();
+eval { (if119797(1)) = 4..6 };
+is $@, "", '$@ after writing to array returned by if';
+is "@119797", "4 5 6", 'writing to array returned by if';
+sub unless119797 : lvalue {
+ unless ($_[0]) {
+ @119797
+ }
+}
+@119797 = ();
+eval { (unless119797(0)) = 4..6 };
+is $@, "", '$@ after writing to array returned by unless';
+is "@119797", "4 5 6", 'writing to array returned by unless';