This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
PATCH: [perl #121816] Add warning for repetition x < 0
authorKarl Williamson <khw@cpan.org>
Tue, 17 Jun 2014 15:39:51 +0000 (09:39 -0600)
committerKarl Williamson <khw@cpan.org>
Tue, 17 Jun 2014 15:54:50 +0000 (09:54 -0600)
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.

pod/perldelta.pod
pod/perldiag.pod
pp.c
t/lib/warnings/op

index 5639dd9..97d6231 100644 (file)
@@ -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
index ea9aab1..8bd44ac 100644 (file)
@@ -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 f544c39..c240b22 100644 (file)
--- 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";
index a6b3116..364d7e0 100644 (file)
@@ -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.