diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-06-05 20:09:32 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-06-07 08:18:54 -0700 |
commit | 01f91bf275559c4ad5a42efe7848a0db00ceb317 (patch) | |
tree | d1210a4901f728e53a84cc155c635ddb4bdefc0f /sv.c | |
parent | ef5fe392ebd662891a80860e9ba74cc961823c81 (diff) | |
download | perl-01f91bf275559c4ad5a42efe7848a0db00ceb317.tar.gz |
[perl #109542] Make num ops treat $1 as "$1"
Numeric ops were not taking magical variables into account. So $1 (a
magical variable) would be treated differently from "$1" (a non-magi-
cal variable0.
In determining whether to use an integer operation, they would call
SvIV_please_nomg, and then check whether the sv was SvIOK as a result.
SvIV_please_nomg would call SvIV_nomg if the sv were SvPOK or SvNOK.
The problem here is that gmagical variables are never SvIOK, but
only SvIOKp.
In fact, the private flags are used differently for gmagical and non-
magical variables. For non-gmagical variables, the private flag indi-
cates that there is a cached value. If the public flag is not set,
then the cached value is imprecise. For gmagical variables, imprecise
values are never cached; only the private flags are used, and they are
equivalent to the public flags on non-gmagical variables.
This commit changes SvIV_please_nomg to take gmagical variables
into account, using the newly-added sv_gmagical_2iv_please (see the
docs for it in the diff). SvIV_please_nomg now returns true or
false, not void, since a subsequent SvIOK is not reliable. So
‘SvIV_please_nomg(sv); if(SvIOK)’ becomes ‘if(SvIV_please_nomg(sv))’.
Diffstat (limited to 'sv.c')
-rw-r--r-- | sv.c | 22 |
1 files changed, 22 insertions, 0 deletions
@@ -2332,6 +2332,28 @@ Perl_sv_2iv_flags(pTHX_ register SV *const sv, const I32 flags) } /* +=for apidoc sv_gmagical_2iv_please + +Used internally by C<SvIV_please_nomg>, this function sets the C<SvIVX> +slot if C<sv_2iv> would have made the scalar C<SvIOK> had it not been +magical. In that case it returns true. + +=cut +*/ + +bool +Perl_sv_gmagical_2iv_please(pTHX_ register SV *sv) +{ + bool has_int; + PERL_ARGS_ASSERT_SV_GMAGICAL_2IV_PLEASE; + assert(SvGMAGICAL(sv) && !SvIOKp(sv) && (SvNOKp(sv) || SvPOKp(sv))); + if (S_sv_2iuv_common(aTHX_ sv)) { SvNIOK_off(sv); return 0; } + has_int = !!SvIOK(sv); + SvFLAGS(sv) &= ~(SVf_IOK|SVf_NOK); + return has_int; +} + +/* =for apidoc sv_2uv_flags Return the unsigned integer value of an SV, doing any necessary string |