Skip to content

Commit 4cfda98

Browse files
committed
add SV_FORCE_OVERLOAD to the sv_numcmp() APIs
and add AMGf_force_overload to amagic_call() which does the actual work.
1 parent ef8c420 commit 4cfda98

File tree

6 files changed

+112
-22
lines changed

6 files changed

+112
-22
lines changed

ext/XS-APItest/Makefile.PL

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ my @names = (qw(HV_DELETE HV_DISABLE_UVAR_XKEY HV_FETCH_ISSTORE
2525
G_SCALAR G_LIST G_VOID G_DISCARD G_EVAL G_NOARGS
2626
G_KEEPERR G_NODEBUG G_METHOD G_FAKINGEVAL G_RETHROW
2727
GV_NOADD_NOINIT G_USEHINTS
28-
SV_GMAGIC SV_SKIP_OVERLOAD SV_POSBYTES
28+
SV_GMAGIC SV_SKIP_OVERLOAD SV_FORCE_OVERLOAD SV_POSBYTES
2929
IS_NUMBER_IN_UV IS_NUMBER_GREATER_THAN_UV_MAX
3030
IS_NUMBER_NOT_INT IS_NUMBER_NEG IS_NUMBER_INFINITY
3131
IS_NUMBER_NAN IS_NUMBER_TRAILING PERL_SCAN_TRAILING

ext/XS-APItest/t/sv_numne.t

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!perl
22

3-
use Test::More tests => 24;
3+
use Test::More tests => 34;
44
use XS::APItest;
55
use Config;
66

@@ -43,13 +43,30 @@ ok !sv_numne_flags($1, 11, SV_GMAGIC), 'sv_numne_flags with SV_GMAGIC does';
4343
ok !sv_numne(12, $obj), 'AlwaysTwelve is 12 on right';
4444
ok sv_numne(11, $obj), 'AlwayeTwelve is not 11 on the right';
4545

46-
ok !sv_numne_flags($obj, 11, SV_SKIP_OVERLOAD), 'AlwaysTwelve is 12 with SV_SKIP_OVERLOAD';
46+
# neither '!=' nor '0+' overloading applies
47+
ok sv_numne_flags($obj, 11, SV_SKIP_OVERLOAD), 'AlwaysTwelve is not 11 with SV_SKIP_OVERLOAD';
48+
ok sv_numne_flags($obj, 12, SV_SKIP_OVERLOAD), 'AlwaysTwelve is not 12 with SV_SKIP_OVERLOAD';
4749

4850
my $result;
4951
void_sv_numne($obj, 11, $result);
5052
ok($result, "overloaded sv_numne() (ne) in void context");
5153
void_sv_numne($obj, 12, $result);
5254
ok(!$result, "overloaded sv_numne() (eq) in void context");
55+
56+
no overloading;
57+
ok sv_numne($obj, 11), 'AlwaysTwelve is not 11 with no overloading (api)';
58+
ok $obj != 11, 'AlwaysTwelve is not 11 with no overloading (op)';
59+
60+
ok sv_numne($obj, 12), 'AlwaysTwelve is not 12 with no overloading (api)';
61+
ok $obj != 12, 'AlwaysTwelve is not 12 with no overloading (op)';
62+
63+
ok !sv_numne_flags($obj, 12, SV_FORCE_OVERLOAD), 'AlwaysTwelve is 12 with no overloading and SV_FORCE_OVERLOAD';
64+
use overloading;
65+
no overloading '!=';
66+
ok !sv_numne($obj, 11), 'AlwaysTwelve is 11 with no overloading "!=" (api)';
67+
ok !($obj != 11), 'AlwaysTwelve is 11 with no overloading "!=" (op)';
68+
ok sv_numne($obj, 12), 'AlwaysTwelve is not 12 with no overloading "!=" (api)';
69+
ok $obj != 12, 'AlwaysTwelve is not 12 with no overloading "!=" (op)';
5370
}
5471

5572
# +0 overloading with large numbers and using fallback

gv.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3754,13 +3754,18 @@ In many cases amagic_call() uses the L</GIMME_V> context of the
37543754
current OP when calling the sub handling the overload. This flag
37553755
forces amagic_call() to use scalar context.
37563756
3757+
=item C<AMGf_force_overload>
3758+
3759+
Perform overloading even in the context of C<no overloading;>.
3760+
37573761
=back
37583762
37593763
=for apidoc Amnh||AMGf_noleft
37603764
=for apidoc Amnh||AMGf_noright
37613765
=for apidoc Amnh||AMGf_unary
37623766
=for apidoc Amnh||AMGf_assign
37633767
=for apidoc Amnh||AMGf_force_scalar
3768+
=for apidoc Amnh||AMGf_force_overload
37643769
37653770
=cut
37663771
*/
@@ -3785,7 +3790,8 @@ Perl_amagic_call(pTHX_ SV *left, SV *right, int method, int flags)
37853790

37863791
PERL_ARGS_ASSERT_AMAGIC_CALL;
37873792

3788-
if ( PL_curcop->cop_hints & HINT_NO_AMAGIC ) {
3793+
if ( (PL_curcop->cop_hints & HINT_NO_AMAGIC)
3794+
&& !(flags & AMGf_force_overload)) {
37893795
if (!amagic_is_enabled(method)) return NULL;
37903796
}
37913797

pp.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,7 @@ Does not use C<TARG>. See also C<L</XPUSHu>>, C<L</mPUSHu>> and C<L</PUSHu>>.
662662
#define AMGf_want_list 0x0040
663663
#define AMGf_numarg 0x0080
664664
#define AMGf_force_scalar 0x0100
665+
#define AMGf_force_overload SV_FORCE_OVERLOAD /* ignore HINTS_NO_AMAGIC */
665666

666667

667668
/* do SvGETMAGIC on the stack args before checking for overload */
@@ -677,9 +678,23 @@ Does not use C<TARG>. See also C<L</XPUSHu>>, C<L</mPUSHu>> and C<L</PUSHu>>.
677678
return NORMAL; \
678679
} STMT_END
679680

681+
/*
682+
=for apidoc Am|SV *|AMG_CALLunary|SV *sv|int meth
683+
=for apidoc_item |SV *|AMG_CALLunary_flags|SV *sv|int meth|int flags
684+
685+
Macro wrappers around L</amagic_call> to call any unary magic.
686+
687+
Sets the C<AMGf_noright> and C<AMGf_unary> flags.
688+
689+
=cut
690+
*/
691+
680692
#define AMG_CALLunary(sv,meth) \
681693
amagic_call(sv,&PL_sv_undef, meth, AMGf_noright | AMGf_unary)
682694

695+
#define AMG_CALLunary_flags(sv,meth, flags) \
696+
amagic_call(sv,&PL_sv_undef, meth, AMGf_noright | AMGf_unary | (flags))
697+
683698
/* No longer used in core. Use AMG_CALLunary instead */
684699
#define AMG_CALLun(sv,meth) AMG_CALLunary(sv, CAT2(meth,_amg))
685700

sv.c

Lines changed: 69 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2765,14 +2765,25 @@ Perl_sv_2nv_flags(pTHX_ SV *const sv, const I32 flags)
27652765
/*
27662766
=for apidoc sv_2num_flags
27672767
=for apidoc_item sv_2num
2768-
X<SV_SKIP_OVERLOAD>
27692768

27702769
Return an SV with the numeric value of the source SV, doing any necessary
27712770
reference or overload conversion. The caller is expected to have handled
27722771
get-magic already.
27732772

2774-
For sv_2num_flags() you can set C<SV_SKIP_OVERLOAD> in flags to avoid
2775-
any numeric context overloading.
2773+
For sv_2num_flags() you can set the following flags:
2774+
2775+
=over
2776+
2777+
=item *
2778+
2779+
C<SV_SKIP_OVERLOAD> - avoid any numeric context overloading.
2780+
2781+
=item *
2782+
2783+
C<SV_FORCE_OVERLOAD> - use numeric context overloading even if
2784+
disabled in hints by C<no overloading;>.
2785+
2786+
=back
27762787

27772788
=cut
27782789
*/
@@ -2782,15 +2793,18 @@ Perl_sv_2num_flags(pTHX_ SV *const sv, int flags)
27822793
{
27832794
PERL_ARGS_ASSERT_SV_2NUM_FLAGS;
27842795

2785-
assert((flags & ~SV_SKIP_OVERLOAD) == 0);
2796+
assert((flags & ~(SV_SKIP_OVERLOAD|SV_FORCE_OVERLOAD)) == 0);
27862797

27872798
if (!SvROK(sv))
27882799
return sv;
27892800
if (SvAMAGIC(sv) && !(flags & SV_SKIP_OVERLOAD)) {
2790-
SV * const tmpsv = AMG_CALLunary(sv, numer_amg);
2801+
STATIC_ASSERT_STMT(AMGf_force_overload == SV_FORCE_OVERLOAD);
2802+
SV * const tmpsv =
2803+
AMG_CALLunary_flags(sv, numer_amg,
2804+
(flags & SV_FORCE_OVERLOAD));
27912805
TAINT_IF(tmpsv && SvTAINTED(tmpsv));
27922806
if (tmpsv && (!SvROK(tmpsv) || (SvRV(tmpsv) != SvRV(sv))))
2793-
return sv_2num(tmpsv);
2807+
return sv_2num_flags(tmpsv, flags);
27942808
}
27952809
return sv_2mortal(newSVuv(PTR2UV(SvRV(sv))));
27962810
}
@@ -8735,8 +8749,12 @@ S_sv_numcmp_common(pTHX_ SV **sv1, SV **sv2, const U32 flags,
87358749
*sv2 = &PL_sv_undef;
87368750

87378751
if (SvAMAGIC(*sv1) || SvAMAGIC(*sv2)) {
8738-
if (!(flags & SV_SKIP_OVERLOAD)) {
8739-
if ((*result = amagic_call(*sv1, *sv2, method, AMGf_force_scalar)))
8752+
STATIC_ASSERT_STMT(AMGf_force_overload == SV_FORCE_OVERLOAD);
8753+
if (!(flags & SV_SKIP_OVERLOAD)
8754+
|| (flags & SV_FORCE_OVERLOAD)) {
8755+
int amg_flags = AMGf_force_scalar
8756+
| (flags & AMGf_force_overload);
8757+
if ((*result = amagic_call(*sv1, *sv2, method, amg_flags)))
87408758
return true;
87418759
}
87428760

@@ -8817,7 +8835,8 @@ different to C< !sv_numne(sv1, sv2) >.
88178835

88188836
The non-C<_flags> suffix versions of these functions always perform
88198837
get magic and handle the appropriate type of overloading. See
8820-
L<overload> for details.
8838+
L<overload> for details. Be aware that like the builtin operators,
8839+
C<no overloading;> will disable overloading.
88218840

88228841
These each return a boolean indicating if the numbers in the two SV
88238842
arguments satisfy the given relationship, coercing them to numbers if
@@ -8836,11 +8855,22 @@ otherwise 'get' magic is ignored.
88368855

88378856
=item C<SV_SKIP_OVERLOAD>
88388857

8839-
Skip any operator overloading implemented for this type and operator.
8858+
Skip any operator or numeric overloading implemented for this type and
8859+
operator. Be aware that for overloaded values this will compare the
8860+
addresses of the references, as for the usual numeric comparison of
8861+
non-overloaded references.
8862+
8863+
=item C<SV_FORCE_OVERLOAD>
8864+
8865+
Force overloading on even in the context of C<no overloading;>.
88408866

88418867
=back
88428868

8869+
If neither overload flag is set overloading is honored unless C<no
8870+
overloading;> has disabled it.
8871+
88438872
=for apidoc Amnh||SV_SKIP_OVERLOAD
8873+
=for apidoc Amnh||SV_FORCE_OVERLOAD
88448874

88458875
=cut
88468876
*/
@@ -8954,15 +8984,36 @@ because one of them is C<NaN>, though overloads can extend that.
89548984

89558985
=back
89568986

8957-
C<sv_numcmp> always performs 'get' magic. C<sv_numcmp_flags> performs
8958-
'get' magic on if C<flags> has the C<SV_GMAGIC> bit set.
8987+
C<sv_numcmp> always performs 'get' magic.
8988+
8989+
<sv_numcmp_flags> accepts these flags:
89598990

8960-
C<sv_numcmp> always checks for, and if present, handles C<< <=> >>
8961-
overloading. If not present, regular numerical comparison will be
8962-
used instead.
8963-
C<sv_numcmp_flags> normally does the same, but if the
8964-
C<SV_SKIP_OVERLOAD> bit is set in C<flags> any C<< <=> >> overloading
8965-
is ignored and a regular numerical comparison is done instead.
8991+
=over
8992+
8993+
=item *
8994+
8995+
C<SV_GMAGIC> - Perform 'get' magic on both C<sv1> amd C<sv2> if this
8996+
flag is set, otherwise 'get' magic is ignored.
8997+
8998+
=item *
8999+
9000+
C<SV_SKIP_OVERLOAD> - If this is set any C<< <=> >> or numeric
9001+
overloading implemented for this type is ignored. Be aware that for
9002+
overloaded values this will compare the addresses of the references,
9003+
as for the usual numeric comparison of non-overloaded references.
9004+
9005+
=item *
9006+
9007+
C<SV_FORCE_OVERLOAD> - Force overloading on even in the context of
9008+
C<no overloading;>.
9009+
9010+
=back
9011+
9012+
If neither overload flag is set overloading is honored unless C<no
9013+
overloading;> has disabled it.
9014+
9015+
=for apidoc Amnh||SV_SKIP_OVERLOAD
9016+
=for apidoc Amnh||SV_FORCE_OVERLOAD
89669017

89679018
=cut
89689019
*/

sv.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2147,6 +2147,7 @@ Returns the hash for C<sv> created by C<L</newSVpvn_share>>.
21472147
#define SV_SKIP_OVERLOAD (1 << 13) /* 0x2000 - 8192 */
21482148
#define SV_CATBYTES (1 << 14) /* 0x4000 - 16384 */
21492149
#define SV_CATUTF8 (1 << 15) /* 0x8000 - 32768 */
2150+
#define SV_FORCE_OVERLOAD (1 << 16) /* 0x10000 - 65536 */
21502151

21512152
/* sv_regex_global_pos_*() should count in bytes, not chars */
21522153
#define SV_POSBYTES SV_CATBYTES

0 commit comments

Comments
 (0)