summaryrefslogtreecommitdiff
path: root/sv.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2021-07-02 12:45:42 +0000
committerNicholas Clark <nick@ccl4.org>2022-02-19 19:46:37 +0000
commitbb5bc97fde9ef2f16cffdfb44d7f42a03311ab2f (patch)
treebb279aaf82ca65990a0c0edb8007a97fda158002 /sv.c
parent9cb26ed2ae572b61849be5ef0d9e2fc19c8e49a8 (diff)
downloadperl-bb5bc97fde9ef2f16cffdfb44d7f42a03311ab2f.tar.gz
Don't set SVf_POK in Perl_sv_2pv_flags() when caching the string for an IV.
This permits XS code (such as serialisers) to distinguish between values that started as IVs but had a string representation cached, and values that started as PVs but had an (exact) integer representation cached. As implemented, the change in flags means that Perl_sv_2pv_flags() will be entered each time the string for an IV is wanted. The next commit will fix SvPV() and the other macros to avoid calling Perl_sv_2pv_flags() more than once, restoring the previous behaviour.
Diffstat (limited to 'sv.c')
-rw-r--r--sv.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/sv.c b/sv.c
index a98d144faa..6eb6c5c295 100644
--- a/sv.c
+++ b/sv.c
@@ -3309,7 +3309,19 @@ Perl_sv_2pv_flags(pTHX_ SV *const sv, STRLEN *const lp, const U32 flags)
Move(ptr, s, len, char);
s += len;
*s = '\0';
- SvPOK_on(sv);
+ /* We used to call SvPOK_on(). Whilst this is fine for (most) Perl code,
+ it means that after this stringification is cached, there is no way
+ to distinguish between values originally assigned as $a = 42; and
+ $a = "42"; (or results of string operators vs numeric operators)
+ where the value has subsequently been used in the other sense
+ and had a value cached.
+ This (somewhat) hack means that we retain the cached stringification,
+ but the existing SvPV() macros end up entering this function (which
+ returns the cached value) instead of using it directly inline.
+ However, the result is that if a value is SVf_IOK|SVf_POK then it
+ originated as "42", whereas if it's SVf_IOK then it originated as 42.
+ (ignore SVp_IOK and SVp_POK) */
+ SvPOKp_on(sv);
}
else if (SvNOK(sv)) {
if (SvTYPE(sv) < SVt_PVNV)