summaryrefslogtreecommitdiff
path: root/pp_hot.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2010-07-10 15:09:51 -0400
committerRafael Garcia-Suarez <rgs@consttype.org>2010-07-26 10:16:55 +0200
commit0fe688f528b0e1b5bef6fb30d5e45316430e8a41 (patch)
treea38f5eb47badce81268c3c57df36562d8ac90c91 /pp_hot.c
parent1eb3f3ad74c5c8cb35d027485b9938eb0a64db40 (diff)
downloadperl-0fe688f528b0e1b5bef6fb30d5e45316430e8a41.tar.gz
Fix for RT#1804: Anonymous glob breaks when assigned through
The problem here is that globs are scalars and the = operator can only distinguish between scalar and glob assignments by the flags on the glob. It only sees the return value of *{}, not the *{} itself. We can fix this by having the pp_sassign look for a rv2gv (*{}) on its LHS, to decide what type of assignment to do.
Diffstat (limited to 'pp_hot.c')
-rw-r--r--pp_hot.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/pp_hot.c b/pp_hot.c
index d5a457279c..bd0f909025 100644
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -112,6 +112,7 @@ PP(pp_and)
PP(pp_sassign)
{
dVAR; dSP; dPOPTOPssrl;
+ U32 wasfake = 0;
if (PL_op->op_private & OPpASSIGN_BACKWARDS) {
SV * const temp = left;
@@ -197,7 +198,14 @@ PP(pp_sassign)
}
}
+ /* Allow glob assignments like *$x = ..., which, when the glob has a
+ SVf_FAKE flag, cannot be distinguished from $x = ... without looking
+ at the op tree. */
+ if( SvTYPE(right) == SVt_PVGV && cBINOP->op_last->op_type == OP_RV2GV
+ && (wasfake = SvFLAGS(right) & SVf_FAKE) )
+ SvFLAGS(right) &= ~SVf_FAKE;
SvSetMagicSV(right, left);
+ if(wasfake) SvFLAGS(right) |= SVf_FAKE;
SETs(right);
RETURN;
}