summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKarl Williamson <khw@cpan.org>2014-06-17 09:39:51 -0600
committerKarl Williamson <khw@cpan.org>2014-06-17 09:54:50 -0600
commitb3211734a7d280a8b7c6acaaba333f8f6a314675 (patch)
tree6757b4dd98bba1bb29c215588121d22914f175e3
parente21c1f156f378627d5dcc0a326f14b0a11d80fde (diff)
downloadperl-b3211734a7d280a8b7c6acaaba333f8f6a314675.tar.gz
PATCH: [perl #121816] Add warning for repetition x < 0
I consider this experimental, so that if code breaks as a result, we will remove it. I chose the numeric warnings category. But misc or a new subcategory of numeric might be better choices. There is also the issue if someone is calculating the repeat count in floating point and gets something that would be 0 if there were infinite precision, but ends up being a very small negative number. The current implementation will warn on that, but probably shouldn't. I suspect that this would be extremely rare in practice.
-rw-r--r--pod/perldelta.pod11
-rw-r--r--pod/perldiag.pod6
-rw-r--r--pp.c14
-rw-r--r--t/lib/warnings/op12
4 files changed, 37 insertions, 6 deletions
diff --git a/pod/perldelta.pod b/pod/perldelta.pod
index 5639dd94e1..97d623107c 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -546,6 +546,17 @@ simply disable this warning:
no warnings "experimental::win32_perlio";
+=item *
+
+L<Negative repeat count does nothing|perldiag/Negative repeat count does nothing>
+
+(W numeric) This warns when the repeat count of the
+L<C<x>|perlop/Multiplicative Operators> repetition operator is
+negative.
+
+This warning may be changed or removed if it turn out that it was
+unwise to have added it.
+
=back
=head2 Changes to Existing Diagnostics
diff --git a/pod/perldiag.pod b/pod/perldiag.pod
index ea9aab1511..8bd44acb09 100644
--- a/pod/perldiag.pod
+++ b/pod/perldiag.pod
@@ -3241,6 +3241,12 @@ length that is less than 0. This is difficult to imagine.
(F) When C<vec> is called in an lvalue context, the second argument must be
greater than or equal to zero.
+=item Negative repeat count does nothing
+
+(W numeric) You tried to execute the
+L<C<x>|perlop/Multiplicative Operators> repetition operator fewer than 0
+times, which doesn't make sense.
+
=item Nested quantifiers in regex; marked by S<<-- HERE> in m/%s/
(F) You can't quantify a quantifier without intervening parentheses.
diff --git a/pp.c b/pp.c
index f544c39a94..c240b22f26 100644
--- a/pp.c
+++ b/pp.c
@@ -1656,23 +1656,25 @@ PP(pp_repeat)
else
count = uv;
} else {
- const IV iv = SvIV_nomg(sv);
- if (iv < 0)
- count = 0;
- else
- count = iv;
+ count = SvIV_nomg(sv);
}
}
else if (SvNOKp(sv)) {
const NV nv = SvNV_nomg(sv);
if (nv < 0.0)
- count = 0;
+ count = -1; /* An arbitrary negative integer */
else
count = (IV)nv;
}
else
count = SvIV_nomg(sv);
+ if (count < 0) {
+ count = 0;
+ Perl_ck_warner(aTHX_ packWARN(WARN_NUMERIC),
+ "Negative repeat count does nothing");
+ }
+
if (GIMME == G_ARRAY && PL_op->op_private & OPpREPEAT_DOLIST) {
dMARK;
static const char* const oom_list_extend = "Out of memory during list extend";
diff --git a/t/lib/warnings/op b/t/lib/warnings/op
index a6b311654d..364d7e08a7 100644
--- a/t/lib/warnings/op
+++ b/t/lib/warnings/op
@@ -1914,3 +1914,15 @@ sub bbb ($a) { 4 }
$aaa = sub { 2 };
$bbb = sub ($a) { 4 };
EXPECT
+########
+use warnings 'numeric';
+my $c = -4.5;
+my $a = "y" x $c;
+my $b = "y" x -3;
+no warnings 'numeric';
+my $d = "y" x $c;
+my $e = "y" x -3;
+no warnings 'numeric';
+EXPECT
+Negative repeat count does nothing at - line 3.
+Negative repeat count does nothing at - line 4.