summaryrefslogtreecommitdiff
path: root/pp.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-01-17 22:51:32 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-01-17 22:51:32 -0800
commit5ee80e13ad1338a061ce31e1c7ea5c074fc5a0ff (patch)
treea147ea2cd65e3149b6168e8193cbd3448acc7b23 /pp.c
parent485495c37ef9e4aac088b1f65dff57b9b274003c (diff)
downloadperl-5ee80e13ad1338a061ce31e1c7ea5c074fc5a0ff.tar.gz
[perl #108480] $cow |= number undefines $cow
If a read-only scalar is passed to one of | & ^ and it decides to do a numeric operation, the numeric flags on the read-only scalar are turned off afterwards if they were not on to begin with. This was introduced in commit b20c4ee1f, which did so to stop $x | "0" from coercing the rhs and making it behave differently the second time through. What that commit did not take into account was that the read-only flag is set on cow scalars, and the same pp function is used for the assignment forms. So it was turning off the numeric flags after $cow |= 1, leaving $cow undef. I made this numeric flag-twiddling apply only to read-only scalars (supposedly), because that seemed the most conservative and acceptable change. I am actually in favour of extending it to all scalars, to make these operators less surprising. For that reason, this commit preserves the current behaviour with cows in the non-assignment case: they don’t get coerced into numbers. Changing them to work the same way as non-cow writable scalars would make things more consistent, but more consistently buggy. I would like to make this non-coercion apply to all scalars in 5.18. This commit simply skips the flag-twiddling on the lhs in the assign- ment case.
Diffstat (limited to 'pp.c')
-rw-r--r--pp.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/pp.c b/pp.c
index b54b3abc8b..2bc1a1a34f 100644
--- a/pp.c
+++ b/pp.c
@@ -2193,7 +2193,7 @@ PP(pp_bit_and)
const UV u = SvUV_nomg(left) & SvUV_nomg(right);
SETu(u);
}
- if (left_ro_nonnum) SvNIOK_off(left);
+ if (left_ro_nonnum && left != TARG) SvNIOK_off(left);
if (right_ro_nonnum) SvNIOK_off(right);
}
else {
@@ -2227,7 +2227,7 @@ PP(pp_bit_or)
const UV result = op_type == OP_BIT_OR ? (l | r) : (l ^ r);
SETu(result);
}
- if (left_ro_nonnum) SvNIOK_off(left);
+ if (left_ro_nonnum && left != TARG) SvNIOK_off(left);
if (right_ro_nonnum) SvNIOK_off(right);
}
else {