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.
PP(pp_sassign)
{
dVAR; dSP; dPOPTOPssrl;
+ U32 wasfake = 0;
if (PL_op->op_private & OPpASSIGN_BACKWARDS) {
SV * const temp = left;
}
}
+ /* 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;
}
use warnings;
require './test.pl';
-plan( tests => 191 );
+plan( tests => 192 );
# type coersion on assignment
$foo = 'foo';
is (scalar $::{fake}, "*main::sym",
"Localized FAKE glob's value was correctly restored");
+# [perl #1804] *$x assignment when $x is a copy of another glob
+{
+ no warnings 'once';
+ my $x = *_random::glob_that_is_not_used_elsewhere;
+ *$x = sub{};
+ is(
+ "$x", '*_random::glob_that_is_not_used_elsewhere',
+ '[perl #1804] *$x assignment when $x is FAKE',
+ );
+}
+
__END__
Perl
Rules