summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pp_ctl.c14
-rw-r--r--pp_hot.c12
-rw-r--r--t/op/sub_lval.t13
3 files changed, 34 insertions, 5 deletions
diff --git a/pp_ctl.c b/pp_ctl.c
index eed88f8e0a..868ef011f0 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2227,7 +2227,11 @@ S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
sv_2mortal(*newsp);
}
else
- *++newsp = *SP;
+ *++newsp =
+ (!CxLVAL(cx) || CxLVAL(cx) & OPpENTERSUB_INARGS) &&
+ !SvTEMP(*SP)
+ ? sv_2mortal(SvREFCNT_inc_simple_NN(*SP))
+ : *SP;
}
else
*++newsp = &PL_sv_undef;
@@ -2249,7 +2253,13 @@ S_return_lvalues(pTHX_ SV **mark, SV **sp, SV **newsp, I32 gimme,
}
else if (gimme == G_ARRAY) {
assert (!(CxLVAL(cx) & OPpENTERSUB_DEREF));
- while (++MARK <= SP) {
+ if (!CxLVAL(cx) || CxLVAL(cx) & OPpENTERSUB_INARGS)
+ while (++MARK <= SP)
+ *++newsp =
+ SvTEMP(*MARK)
+ ? *MARK
+ : sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
+ else while (++MARK <= SP) {
*++newsp = *MARK;
TAINT_NOT; /* Each item is independent */
}
diff --git a/pp_hot.c b/pp_hot.c
index cd556f3f2a..8d02826249 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2802,7 +2802,9 @@ PP(pp_leavesublv)
sv_2mortal(*MARK);
}
else
- *MARK = TOPs;
+ *MARK = SvTEMP(TOPs)
+ ? TOPs
+ : sv_2mortal(SvREFCNT_inc_simple_NN(TOPs));
}
else {
MEXTEND(MARK, 0);
@@ -2810,6 +2812,13 @@ PP(pp_leavesublv)
}
SP = MARK;
}
+ else if (gimme == G_ARRAY) {
+ rvalue_array:
+ for (MARK = newsp + 1; MARK <= SP; MARK++) {
+ if (!SvTEMP(*MARK))
+ *MARK = sv_2mortal(SvREFCNT_inc_simple_NN(*MARK));
+ }
+ }
}
if (CxLVAL(cx) & OPpENTERSUB_DEREF) {
@@ -2829,7 +2838,6 @@ PP(pp_leavesublv)
}
}
- rvalue_array:
PUTBACK;
LEAVE;
diff --git a/t/op/sub_lval.t b/t/op/sub_lval.t
index de4a8cc17a..a9ff88b087 100644
--- a/t/op/sub_lval.t
+++ b/t/op/sub_lval.t
@@ -3,7 +3,7 @@ BEGIN {
@INC = '../lib';
require './test.pl';
}
-plan tests=>151;
+plan tests=>155;
sub a : lvalue { my $a = 34; ${\(bless \$a)} } # Return a temporary
sub b : lvalue { ${\shift} }
@@ -786,3 +786,14 @@ for my $sub (sub :lvalue {$_}, sub :lvalue {return $_}) {
is join('-',%$_), '4-5', '%{func()} autovivification'.$suffix;
}
continue { $suffix = ' (explicit return)' }
+
+# [perl #92406] [perl #92290] Returning a pad var in rvalue context
+$suffix = '';
+for my $sub (
+ sub :lvalue { my $x = 72; $x },
+ sub :lvalue { my $x = 72; return $x }
+) {
+ is scalar(&$sub), 72, "sub returning pad var in scalar context$suffix";
+ is +(&$sub)[0], 72, "sub returning pad var in list context$suffix";
+}
+continue { $suffix = ' (explicit return)' }