summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2013-09-09 01:59:33 -0700
committerFather Chrysostomos <sprout@cpan.org>2013-09-09 08:47:13 -0700
commitad39f3a27b57b8caeb757155ed38da916b768bc1 (patch)
treea3f5c2b03c18db19036c62f6642e3712092054e6 /pp_hot.c
parentda4b417be87225fdd8306a157367330012c6b7d4 (diff)
downloadperl-ad39f3a27b57b8caeb757155ed38da916b768bc1.tar.gz
Make &xsub and goto &xsub work with tied @_
This is the only place where tied @_ does not work, and there appears to be no reason why it shouldn’t, apart from the fact that it hasn’t been implemented. Commit 67955e0c was what made &xsub work to begin with. 93965878572 introduced tied arrays and added the comment to pp_entersub saying that @_ is not tiable. goto &xsub has worked since perl 5.000, but 93965878572 did not make it work with tied arrays.
Diffstat (limited to 'pp_hot.c')
-rw-r--r--pp_hot.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/pp_hot.c b/pp_hot.c
index 9641b19222..11553285b1 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -2715,17 +2715,26 @@ try_autoload:
* switch stack to @_, and copy return values
* back. This would allow popping @_ in XSUB, e.g.. XXXX */
AV * const av = GvAV(PL_defgv);
- const SSize_t items = AvFILLp(av) + 1; /* @_ is not tieable */
+ const SSize_t items = AvFILL(av) + 1;
if (items) {
SSize_t i = 0;
+ const bool m = cBOOL(SvRMAGICAL(av));
/* Mark is at the end of the stack. */
EXTEND(SP, items);
for (; i < items; ++i)
- if (AvARRAY(av)[i]) SP[i+1] = AvARRAY(av)[i];
+ {
+ SV *sv;
+ if (m) {
+ SV ** const svp = av_fetch(av, i, 0);
+ sv = svp ? *svp : NULL;
+ }
+ else sv = AvARRAY(av)[i];
+ if (sv) SP[i+1] = sv;
else {
SP[i+1] = newSVavdefelem(av, i, 1);
}
+ }
SP += items;
PUTBACK ;
}