This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Deprecate wide chars in logical string ops
authorKarl Williamson <khw@cpan.org>
Wed, 16 Dec 2015 00:58:30 +0000 (17:58 -0700)
committerKarl Williamson <khw@cpan.org>
Wed, 16 Dec 2015 19:14:46 +0000 (12:14 -0700)
See thread starting at
http://nntp.perl.org/group/perl.perl5.porters/227698

Ricardo Signes provided the perldelta and perldiag text.

doop.c
op.h
pod/perldelta.pod
pod/perldiag.pod
pp.c
t/lib/warnings/doop
t/lib/warnings/pp
t/op/substr.t

diff --git a/doop.c b/doop.c
index 293542b..dbf26d6 100644 (file)
--- a/doop.c
+++ b/doop.c
@@ -1002,6 +1002,7 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
     const char *rsave;
     bool left_utf;
     bool right_utf;
+    bool do_warn_above_ff = ckWARN_d(WARN_DEPRECATED);
     STRLEN needlen = 0;
 
     PERL_ARGS_ASSERT_DO_VOP;
@@ -1082,6 +1083,12 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
                rulen -= ulen;
                duc = luc & ruc;
                dc = (char*)uvchr_to_utf8((U8*)dc, duc);
+                if (do_warn_above_ff && (luc > 0xff || ruc > 0xff)) {
+                    Perl_warner(aTHX_ packWARN(WARN_DEPRECATED),
+                                deprecated_above_ff_msg, PL_op_desc[optype]);
+                    /* Warn only once per operation */
+                    do_warn_above_ff = FALSE;
+                }
            }
            if (sv == left || sv == right)
                (void)sv_usepvn(sv, dcorig, needlen);
@@ -1097,6 +1104,11 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
                rulen -= ulen;
                duc = luc ^ ruc;
                dc = (char*)uvchr_to_utf8((U8*)dc, duc);
+                if (do_warn_above_ff && (luc > 0xff || ruc > 0xff)) {
+                    Perl_warner(aTHX_ packWARN(WARN_DEPRECATED),
+                                deprecated_above_ff_msg, PL_op_desc[optype]);
+                    do_warn_above_ff = FALSE;
+                }
            }
            goto mop_up_utf;
        case OP_BIT_OR:
@@ -1109,6 +1121,11 @@ Perl_do_vop(pTHX_ I32 optype, SV *sv, SV *left, SV *right)
                rulen -= ulen;
                duc = luc | ruc;
                dc = (char*)uvchr_to_utf8((U8*)dc, duc);
+                if (do_warn_above_ff && (luc > 0xff || ruc > 0xff)) {
+                    Perl_warner(aTHX_ packWARN(WARN_DEPRECATED),
+                                deprecated_above_ff_msg, PL_op_desc[optype]);
+                    do_warn_above_ff = FALSE;
+                }
            }
          mop_up_utf:
            if (rulen)
diff --git a/op.h b/op.h
index ff0713b..13afa8a 100644 (file)
--- a/op.h
+++ b/op.h
@@ -1075,6 +1075,12 @@ C<sib> is non-null. For a higher-level interface, see C<L</op_sibling_splice>>.
 #define MDEREF_MASK         0x7F
 #define MDEREF_SHIFT           7
 
+#if defined(PERL_IN_DOOP_C) || defined(PERL_IN_PP_C)
+static const char * const deprecated_above_ff_msg
+    = "Use of strings with code points over 0xFF as arguments to "
+      "%s operator is deprecated";
+#endif
+
 
 /*
  * ex: set ts=8 sts=4 sw=4 et:
index b891b1b..141a054 100644 (file)
@@ -98,6 +98,15 @@ a deprecation warning, unless that warning category is turned off.
 C<IV_MAX> is typically 2**31 -1 on 32-bit platforms, and 2**63-1 on
 64-bit ones.
 
+=head2 Doing bitwise operations on strings containing code points above
+0xFF is deprecated
+
+The string bitwise operators treat their operands as strings of bytes,
+and values beyond 0xFF are nonsensical in this context.  To operate on
+encoded bytes, first encode the strings.  To operate on code points'
+numeric values, use C<split> and C<map ord>.  In the future, this
+warning will be replaced by an exception.
+
 =head1 Performance Enhancements
 
 XXX Changes which enhance performance without changing behaviour go here.
index 6d05072..ae061f9 100644 (file)
@@ -6819,6 +6819,14 @@ operators and then you presumably know what you are doing.
 its behavior may change or even be removed in any future release of perl.
 See the explanation under L<perlvar/$_>.
 
+=item Use of strings with code points over 0xFF as arguments to %s
+operator is deprecated
+
+(D deprecated) You tried to use one of the string bitwise operators
+(C<&> or C<|> or C<^> or C<~>) on a string containing a code point over
+0xFF.  The string bitwise operators treat their operands as strings of
+bytes, and values beyond 0xFF are nonsensical in this context.
+
 =item Use of tainted arguments in %s is deprecated
 
 (W taint, deprecated) You have supplied C<system()> or C<exec()> with multiple
diff --git a/pp.c b/pp.c
index e6eb799..7071478 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -2642,6 +2642,8 @@ S_scomplement(pTHX_ SV *targ, SV *sv)
              U8 *result;
              U8 *p;
 
+              Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED),
+                        deprecated_above_ff_msg, PL_op_desc[PL_op->op_type]);
              Newx(result, targlen + 1, U8);
              p = result;
              while (tmps < send) {
index 74c3e90..bcc85a3 100644 (file)
@@ -5,3 +5,33 @@ $_ = "\x80  \xff" ;
 chop ;
 EXPECT
 ########
+# NAME deprecation of logical bit operations with above ff code points
+$_ = "\xFF" & "\x{100}";        # Above ff second
+$_ = "\xFF" | "\x{101}";
+$_ = "\xFF" ^ "\x{102}";
+$_ = "\x{100}" & "\x{FF}";      # Above ff first
+$_ = "\x{101}" | "\x{FF}";
+$_ = "\x{102}" ^ "\x{FF}";
+$_ = "\x{100}" & "\x{103}";     # both above ff has just one message raised
+$_ = "\x{101}" | "\x{104}";
+$_ = "\x{102}" ^ "\x{105}";
+no warnings 'deprecated';
+$_ = "\xFF" & "\x{100}";
+$_ = "\xFF" | "\x{101}";
+$_ = "\xFF" ^ "\x{101}";
+$_ = "\x{100}" & "\x{FF}";
+$_ = "\x{101}" | "\x{FF}";
+$_ = "\x{102}" ^ "\x{FF}";
+$_ = "\x{100}" & "\x{103}";
+$_ = "\x{101}" | "\x{104}";
+$_ = "\x{102}" ^ "\x{105}";
+EXPECT
+Use of strings with code points over 0xFF as arguments to bitwise and (&) operator is deprecated at - line 1.
+Use of strings with code points over 0xFF as arguments to bitwise or (|) operator is deprecated at - line 2.
+Use of strings with code points over 0xFF as arguments to bitwise xor (^) operator is deprecated at - line 3.
+Use of strings with code points over 0xFF as arguments to bitwise and (&) operator is deprecated at - line 4.
+Use of strings with code points over 0xFF as arguments to bitwise or (|) operator is deprecated at - line 5.
+Use of strings with code points over 0xFF as arguments to bitwise xor (^) operator is deprecated at - line 6.
+Use of strings with code points over 0xFF as arguments to bitwise and (&) operator is deprecated at - line 7.
+Use of strings with code points over 0xFF as arguments to bitwise or (|) operator is deprecated at - line 8.
+Use of strings with code points over 0xFF as arguments to bitwise xor (^) operator is deprecated at - line 9.
index ab8f951..3324ccc 100644 (file)
@@ -128,3 +128,11 @@ use utf8 ;
 $_ = "\x80  \xff" ;
 reverse ;
 EXPECT
+########
+# NAME deprecation of complement with above ff code points
+$_ = ~ "\xff";
+$_ = ~ "\x{100}";
+EXPECT
+OPTION regex
+Use of strings with code points over 0xFF as arguments to 1's complement \(~\) operator is deprecated at - line \d+.
+Use of code point 0xFF+EFF is deprecated; the permissible max is 0x7F+ at - line \d+.
index 71e9e89..eae2403 100644 (file)
@@ -714,6 +714,7 @@ is($x, "\x{100}\x{200}\xFFb");
 # [perl #23765]
 {
     my $a = pack("C", 0xbf);
+    no warnings 'deprecated';
     substr($a, -1) &= chr(0xfeff);
     is($a, "\xbf");
 }