summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pod/perldelta.pod6
-rw-r--r--regcomp.c74
-rw-r--r--t/lib/warnings/regcomp25
-rw-r--r--t/re/reg_mesg.t101
4 files changed, 126 insertions, 80 deletions
diff --git a/pod/perldelta.pod b/pod/perldelta.pod
index 48e9c58002..016c1bfd48 100644
--- a/pod/perldelta.pod
+++ b/pod/perldelta.pod
@@ -437,6 +437,12 @@ Stub declarations like C<sub f;> and C<sub f ();> no longer wipe out
constants of the same name declared by C<use constant>. This bug was
introduced in perl 5.10.0.
+=item *
+
+Under some conditions a warning raised in compilation of regular
+expression patterns could be displayed multiple times. This is now
+fixed.
+
=back
=head1 Known Problems
diff --git a/regcomp.c b/regcomp.c
index 1730724dc1..92dc395b50 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -570,80 +570,85 @@ static const scan_data_t zero_scan_data =
REPORT_LOCATION_ARGS(offset)); \
} STMT_END
+/* These have asserts in them because of [perl #122671] Many warnings in
+ * regcomp.c can occur twice. If they get output in pass1 and later in that
+ * pass, the pattern has to be converted to UTF-8 and the pass restarted, they
+ * would get output again. So they should be output in pass2, and these
+ * asserts make sure new warnings follow that paradigm. */
/* m is not necessarily a "literal string", in this macro */
#define reg_warn_non_literal_string(loc, m) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_warner(aTHX_ packWARN(WARN_REGEXP), "%s" REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_warner(aTHX_ packWARN(WARN_REGEXP), "%s" REPORT_LOCATION, \
m, REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define ckWARNreg(loc,m) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define vWARN_dep(loc, m) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), m REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_warner(aTHX_ packWARN(WARN_DEPRECATED), m REPORT_LOCATION, \
REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define ckWARNdep(loc,m) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED), \
+ __ASSERT_(PASS2) Perl_ck_warner_d(aTHX_ packWARN(WARN_DEPRECATED), \
m REPORT_LOCATION, \
REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define ckWARNregdep(loc,m) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_ck_warner_d(aTHX_ packWARN2(WARN_DEPRECATED, WARN_REGEXP), \
+ __ASSERT_(PASS2) Perl_ck_warner_d(aTHX_ packWARN2(WARN_DEPRECATED, WARN_REGEXP), \
m REPORT_LOCATION, \
REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define ckWARN2reg_d(loc,m, a1) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_ck_warner_d(aTHX_ packWARN(WARN_REGEXP), \
+ __ASSERT_(PASS2) Perl_ck_warner_d(aTHX_ packWARN(WARN_REGEXP), \
m REPORT_LOCATION, \
a1, REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define ckWARN2reg(loc, m, a1) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
a1, REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define vWARN3(loc, m, a1, a2) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
a1, a2, REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define ckWARN3reg(loc, m, a1, a2) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
a1, a2, REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define vWARN4(loc, m, a1, a2, a3) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
a1, a2, a3, REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define ckWARN4reg(loc, m, a1, a2, a3) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
a1, a2, a3, REPORT_LOCATION_ARGS(offset)); \
} STMT_END
#define vWARN5(loc, m, a1, a2, a3, a4) STMT_START { \
const IV offset = loc - RExC_precomp; \
- Perl_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
+ __ASSERT_(PASS2) Perl_warner(aTHX_ packWARN(WARN_REGEXP), m REPORT_LOCATION, \
a1, a2, a3, a4, REPORT_LOCATION_ARGS(offset)); \
} STMT_END
@@ -9380,7 +9385,7 @@ S_parse_lparen_question_flags(pTHX_ RExC_state_t *pRExC_state)
/*NOTREACHED*/
case ONCE_PAT_MOD: /* 'o' */
case GLOBAL_PAT_MOD: /* 'g' */
- if (SIZE_ONLY && ckWARN(WARN_REGEXP)) {
+ if (PASS2 && ckWARN(WARN_REGEXP)) {
const I32 wflagbit = *RExC_parse == 'o'
? WASTED_O
: WASTED_G;
@@ -9400,7 +9405,7 @@ S_parse_lparen_question_flags(pTHX_ RExC_state_t *pRExC_state)
break;
case CONTINUE_PAT_MOD: /* 'c' */
- if (SIZE_ONLY && ckWARN(WARN_REGEXP)) {
+ if (PASS2 && ckWARN(WARN_REGEXP)) {
if (! (wastedflags & WASTED_C) ) {
wastedflags |= WASTED_GC;
/* diag_listed_as: Useless (?-%s) - don't use /%s modifier in regex; marked by <-- HERE in m/%s/ */
@@ -9415,7 +9420,7 @@ S_parse_lparen_question_flags(pTHX_ RExC_state_t *pRExC_state)
break;
case KEEPCOPY_PAT_MOD: /* 'p' */
if (flagsp == &negflags) {
- if (SIZE_ONLY)
+ if (PASS2)
ckWARNreg(RExC_parse + 1,"Useless use of (?-p)");
} else {
*flagsp |= RXf_PMf_KEEPCOPY;
@@ -10547,7 +10552,6 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
if (max < min) { /* If can't match, warn and optimize to fail
unconditionally */
if (SIZE_ONLY) {
- ckWARNreg(RExC_parse, "Quantifier {n,m} with n > m can't match");
/* We can't back off the size because we have to reserve
* enough space for all the things we are about to throw
@@ -10556,6 +10560,7 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
RExC_size = PREVOPER(RExC_size) - regarglen[(U8)OPFAIL];
}
else {
+ ckWARNreg(RExC_parse, "Quantifier {n,m} with n > m can't match");
RExC_emit = orig_emit;
}
ret = reg_node(pRExC_state, OPFAIL);
@@ -10565,7 +10570,7 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
&& RExC_parse < RExC_end
&& (*RExC_parse == '?' || *RExC_parse == '+'))
{
- if (SIZE_ONLY) {
+ if (PASS2) {
ckWARN2reg(RExC_parse + 1,
"Useless use of greediness modifier '%c'",
*RExC_parse);
@@ -10837,7 +10842,7 @@ S_grok_bslash_N(pTHX_ RExC_state_t *pRExC_state, regnode** node_p,
*node_p = reg_node(pRExC_state,NOTHING);
}
else if (in_char_class) {
- if (SIZE_ONLY && in_char_class) {
+ if (PASS2 && in_char_class) {
if (strict) {
RExC_parse++; /* Position after the "}" */
vFAIL("Zero length \\N{}");
@@ -11430,7 +11435,7 @@ tryagain:
ret = reg_node(pRExC_state, CANY);
RExC_seen |= REG_CANY_SEEN;
*flagp |= HASWIDTH|SIMPLE;
- if (SIZE_ONLY) {
+ if (PASS2) {
ckWARNdep(RExC_parse+1, "\\C is deprecated");
}
goto finish_meta_pat;
@@ -11930,7 +11935,7 @@ tryagain:
bool valid = grok_bslash_o(&p,
&result,
&error_msg,
- TRUE, /* out warnings */
+ PASS2, /* out warnings */
FALSE, /* not strict */
TRUE, /* Output warnings
for non-
@@ -11959,7 +11964,7 @@ tryagain:
bool valid = grok_bslash_x(&p,
&result,
&error_msg,
- TRUE, /* out warnings */
+ PASS2, /* out warnings */
FALSE, /* not strict */
TRUE, /* Output warnings
for non-
@@ -11982,7 +11987,7 @@ tryagain:
}
case 'c':
p++;
- ender = grok_bslash_c(*p++, SIZE_ONLY);
+ ender = grok_bslash_c(*p++, PASS2);
break;
case '8': case '9': /* must be a backreference */
--p;
@@ -12021,7 +12026,7 @@ tryagain:
REQUIRE_UTF8;
}
p += numlen;
- if (SIZE_ONLY /* like \08, \178 */
+ if (PASS2 /* like \08, \178 */
&& numlen < 3
&& p < RExC_end
&& isDIGIT(*p) && ckWARN(WARN_REGEXP))
@@ -12038,7 +12043,7 @@ tryagain:
if (! RExC_override_recoding) {
SV* enc = PL_encoding;
ender = reg_recode((const char)(U8)ender, &enc);
- if (!enc && SIZE_ONLY)
+ if (!enc && PASS2)
ckWARNreg(p, "Invalid escape in the specified encoding");
REQUIRE_UTF8;
}
@@ -12772,9 +12777,7 @@ S_handle_regex_sets(pTHX_ RExC_state_t *pRExC_state, SV** return_invlist,
* upon an unescaped ']' that isn't one ending a regclass. To do both
* these things, we need to realize that something preceded by a backslash
* is escaped, so we have to keep track of backslashes */
- if (SIZE_ONLY) {
- UV depth = 0; /* how many nested (?[...]) constructs */
-
+ if (PASS2) {
Perl_ck_warner_d(aTHX_
packWARN(WARN_EXPERIMENTAL__REGEX_SETS),
"The regex_sets feature is experimental" REPORT_LOCATION,
@@ -12782,6 +12785,9 @@ S_handle_regex_sets(pTHX_ RExC_state_t *pRExC_state, SV** return_invlist,
UTF8fARG(UTF,
RExC_end - RExC_start - (RExC_parse - RExC_precomp),
RExC_precomp + (RExC_parse - RExC_precomp)));
+ }
+ else {
+ UV depth = 0; /* how many nested (?[...]) constructs */
while (RExC_parse < RExC_end) {
SV* current = NULL;
@@ -13282,7 +13288,9 @@ S_add_above_Latin1_folds(pTHX_ RExC_state_t *pRExC_state, const U8 cp, SV** invl
default:
/* Use deprecated warning to increase the chances of this being
* output */
- ckWARN2reg_d(RExC_parse, "Perl folding rules are not up-to-date for 0x%02X; please use the perlbug utility to report;", cp);
+ if (PASS2) {
+ ckWARN2reg_d(RExC_parse, "Perl folding rules are not up-to-date for 0x%02X; please use the perlbug utility to report;", cp);
+ }
break;
}
}
@@ -13750,8 +13758,8 @@ parseit:
bool valid = grok_bslash_o(&RExC_parse,
&value,
&error_msg,
- SIZE_ONLY, /* warnings in pass
- 1 only */
+ PASS2, /* warnings only in
+ pass 2 */
strict,
silence_non_portable,
UTF);
@@ -13770,7 +13778,7 @@ parseit:
bool valid = grok_bslash_x(&RExC_parse,
&value,
&error_msg,
- TRUE, /* Output warnings */
+ PASS2, /* Output warnings */
strict,
silence_non_portable,
UTF);
@@ -13782,7 +13790,7 @@ parseit:
goto recode_encoding;
break;
case 'c':
- value = grok_bslash_c(*RExC_parse++, SIZE_ONLY);
+ value = grok_bslash_c(*RExC_parse++, PASS2);
break;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7':
@@ -13822,7 +13830,7 @@ parseit:
if (strict) {
vFAIL("Invalid escape in the specified encoding");
}
- else if (SIZE_ONLY) {
+ else if (PASS2) {
ckWARNreg(RExC_parse,
"Invalid escape in the specified encoding");
}
diff --git a/t/lib/warnings/regcomp b/t/lib/warnings/regcomp
index b55959e070..f62f5f19bf 100644
--- a/t/lib/warnings/regcomp
+++ b/t/lib/warnings/regcomp
@@ -1,5 +1,6 @@
regcomp.c These tests have been moved to t/re/reg_mesg.t
- except for those that explicitly test line numbers.
+ except for those that explicitly test line numbers
+ and those that don't have a <-- HERE in them.
__END__
use warnings 'regexp';
@@ -7,3 +8,25 @@ $r=qr/(??{ q"\\b+" })/;
"a" =~ /a$r/; # warning should come from this line
EXPECT
\b+ matches null string many times in regex; marked by <-- HERE in m/\b+ <-- HERE / at - line 3.
+########
+# regcomp.c
+use warnings 'digit' ;
+my $a = qr/\o{1238456}\x{100}/;
+my $a = qr/[\o{6548321}]\x{100}/;
+no warnings 'digit' ;
+my $a = qr/\o{1238456}\x{100}/;
+my $a = qr/[\o{6548321}]\x{100}/;
+EXPECT
+Non-octal character '8'. Resolved as "\o{123}" at - line 3.
+Non-octal character '8'. Resolved as "\o{654}" at - line 4.
+########
+# regcomp.c.c
+use warnings;
+$a = qr/\c,/;
+$a = qr/[\c,]/;
+no warnings 'syntax';
+$a = qr/\c,/;
+$a = qr/[\c,]/;
+EXPECT
+"\c," is more clearly written simply as "l" at - line 3.
+"\c," is more clearly written simply as "l" at - line 4.
diff --git a/t/re/reg_mesg.t b/t/re/reg_mesg.t
index 6c8566d879..c03964bb50 100644
--- a/t/re/reg_mesg.t
+++ b/t/re/reg_mesg.t
@@ -320,21 +320,23 @@ push @death, @death_utf8;
# In the following arrays of warnings, the value can be an array of things to
# expect. If the empty string, it means no warning should be raised.
-##
-## Key-value pairs of code/error of code that should have non-fatal regexp warnings.
-##
-my @warning = (
- 'm/\b*/' => '\b* matches null string many times {#} m/\b*{#}/',
- 'm/[:blank:]/' => 'POSIX syntax [: :] belongs inside character classes {#} m/[:blank:]{#}/',
- "m'[\\y]'" => 'Unrecognized escape \y in character class passed through {#} m/[\y{#}]/',
+# Key-value pairs of code/error of code that should have non-fatal regexp
+# warnings. Most currently have \x{100} appended to them to force them to be
+# upgraded to UTF-8, and the first pass restarted. Previously this would
+# cause some warnings to be output twice. This tests that that behavior has
+# been fixed.
- 'm/[a-\d]/' => 'False [] range "a-\d" {#} m/[a-\d{#}]/',
- 'm/[\w-x]/' => 'False [] range "\w-" {#} m/[\w-{#}x]/',
- 'm/[a-\pM]/' => 'False [] range "a-\pM" {#} m/[a-\pM{#}]/',
- 'm/[\pM-x]/' => 'False [] range "\pM-" {#} m/[\pM-{#}x]/',
+my @warning = (
+ 'm/\b*\x{100}/' => '\b* matches null string many times {#} m/\b*{#}\x{100}/',
+ 'm/[:blank:]\x{100}/' => 'POSIX syntax [: :] belongs inside character classes {#} m/[:blank:]{#}\x{100}/',
+ "m'[\\y]\\x{100}'" => 'Unrecognized escape \y in character class passed through {#} m/[\y{#}]\x{100}/',
+ 'm/[a-\d]\x{100}/' => 'False [] range "a-\d" {#} m/[a-\d{#}]\x{100}/',
+ 'm/[\w-x]\x{100}/' => 'False [] range "\w-" {#} m/[\w-{#}x]\x{100}/',
+ 'm/[a-\pM]\x{100}/' => 'False [] range "a-\pM" {#} m/[a-\pM{#}]\x{100}/',
+ 'm/[\pM-x]\x{100}/' => 'False [] range "\pM-" {#} m/[\pM-{#}x]\x{100}/',
'm/[\N{LATIN CAPITAL LETTER A WITH MACRON AND GRAVE}]/' => 'Using just the first character returned by \N{} in character class {#} m/[\N{U+100{#}.300}]/',
- "m'\\y'" => 'Unrecognized escape \y passed through {#} m/\y{#}/',
+ "m'\\y\\x{100}'" => 'Unrecognized escape \y passed through {#} m/\y{#}\x{100}/',
'/x{3,1}/' => 'Quantifier {n,m} with n > m can\'t match {#} m/x{3,1}{#}/',
'/\08/' => '\'\08\' resolved to \'\o{0}8\' {#} m/\08{#}/',
'/\018/' => '\'\018\' resolved to \'\o{1}8\' {#} m/\018{#}/',
@@ -343,52 +345,59 @@ my @warning = (
'/(?=a)*/' => '(?=a)* matches null string many times {#} m/(?=a)*{#}/',
'my $x = \'\m\'; qr/a$x/' => 'Unrecognized escape \m passed through {#} m/a\m{#}/',
'/\q/' => 'Unrecognized escape \q passed through {#} m/\q{#}/',
- '/(?=a){1,3}/' => 'Quantifier unexpected on zero-length expression {#} m/(?=a){1,3}{#}/',
- '/(a|b)(?=a){3}/' => 'Quantifier unexpected on zero-length expression {#} m/(a|b)(?=a){3}{#}/',
+
+ # Feel free to modify these 2 tests, should they start failing because the
+ # marker of where the problem is becomes wrong. The current behavior is
+ # bad, always marking at the very end of the regex instead of where the
+ # problem is. See [perl #122680] regcomp warning gives wrong position of
+ # problem.
+ '/(?=a){1,3}\x{100}/' => 'Quantifier unexpected on zero-length expression {#} m/(?=a){1,3}\x{100}{#}/',
+ '/(a|b)(?=a){3}\x{100}/' => 'Quantifier unexpected on zero-length expression {#} m/(a|b)(?=a){3}\x{100}{#}/',
+
'/\_/' => "",
'/[\_\0]/' => "",
'/[\07]/' => "",
'/[\006]/' => "",
'/[\0005]/' => "",
- '/[\8\9]/' => ['Unrecognized escape \8 in character class passed through {#} m/[\8{#}\9]/',
- 'Unrecognized escape \9 in character class passed through {#} m/[\8\9{#}]/',
+ '/[\8\9]\x{100}/' => ['Unrecognized escape \8 in character class passed through {#} m/[\8{#}\9]\x{100}/',
+ 'Unrecognized escape \9 in character class passed through {#} m/[\8\9{#}]\x{100}/',
],
- '/[:alpha:]/' => 'POSIX syntax [: :] belongs inside character classes {#} m/[:alpha:]{#}/',
- '/[:zog:]/' => 'POSIX syntax [: :] belongs inside character classes {#} m/[:zog:]{#}/',
- '/[.zog.]/' => 'POSIX syntax [. .] belongs inside character classes {#} m/[.zog.]{#}/',
+ '/[:alpha:]\x{100}/' => 'POSIX syntax [: :] belongs inside character classes {#} m/[:alpha:]{#}\x{100}/',
+ '/[:zog:]\x{100}/' => 'POSIX syntax [: :] belongs inside character classes {#} m/[:zog:]{#}\x{100}/',
+ '/[.zog.]\x{100}/' => 'POSIX syntax [. .] belongs inside character classes {#} m/[.zog.]{#}\x{100}/',
'/[a-b]/' => "",
- '/[a-\d]/' => 'False [] range "a-\d" {#} m/[a-\d{#}]/',
- '/[\d-b]/' => 'False [] range "\d-" {#} m/[\d-{#}b]/',
- '/[\s-\d]/' => 'False [] range "\s-" {#} m/[\s-{#}\d]/',
- '/[\d-\s]/' => 'False [] range "\d-" {#} m/[\d-{#}\s]/',
- '/[a-[:digit:]]/' => 'False [] range "a-[:digit:]" {#} m/[a-[:digit:]{#}]/',
- '/[[:digit:]-b]/' => 'False [] range "[:digit:]-" {#} m/[[:digit:]-{#}b]/',
- '/[[:alpha:]-[:digit:]]/' => 'False [] range "[:alpha:]-" {#} m/[[:alpha:]-{#}[:digit:]]/',
- '/[[:digit:]-[:alpha:]]/' => 'False [] range "[:digit:]-" {#} m/[[:digit:]-{#}[:alpha:]]/',
- '/[a\zb]/' => 'Unrecognized escape \z in character class passed through {#} m/[a\z{#}b]/',
- '/(?c)/' => 'Useless (?c) - use /gc modifier {#} m/(?c{#})/',
- '/(?-c)/' => 'Useless (?-c) - don\'t use /gc modifier {#} m/(?-c{#})/',
- '/(?g)/' => 'Useless (?g) - use /g modifier {#} m/(?g{#})/',
- '/(?-g)/' => 'Useless (?-g) - don\'t use /g modifier {#} m/(?-g{#})/',
- '/(?o)/' => 'Useless (?o) - use /o modifier {#} m/(?o{#})/',
- '/(?-o)/' => 'Useless (?-o) - don\'t use /o modifier {#} m/(?-o{#})/',
- '/(?g-o)/' => [ 'Useless (?g) - use /g modifier {#} m/(?g{#}-o)/',
- 'Useless (?-o) - don\'t use /o modifier {#} m/(?g-o{#})/',
+ '/[a-\d]\x{100}/' => 'False [] range "a-\d" {#} m/[a-\d{#}]\x{100}/',
+ '/[\d-b]\x{100}/' => 'False [] range "\d-" {#} m/[\d-{#}b]\x{100}/',
+ '/[\s-\d]\x{100}/' => 'False [] range "\s-" {#} m/[\s-{#}\d]\x{100}/',
+ '/[\d-\s]\x{100}/' => 'False [] range "\d-" {#} m/[\d-{#}\s]\x{100}/',
+ '/[a-[:digit:]]\x{100}/' => 'False [] range "a-[:digit:]" {#} m/[a-[:digit:]{#}]\x{100}/',
+ '/[[:digit:]-b]\x{100}/' => 'False [] range "[:digit:]-" {#} m/[[:digit:]-{#}b]\x{100}/',
+ '/[[:alpha:]-[:digit:]]\x{100}/' => 'False [] range "[:alpha:]-" {#} m/[[:alpha:]-{#}[:digit:]]\x{100}/',
+ '/[[:digit:]-[:alpha:]]\x{100}/' => 'False [] range "[:digit:]-" {#} m/[[:digit:]-{#}[:alpha:]]\x{100}/',
+ '/[a\zb]\x{100}/' => 'Unrecognized escape \z in character class passed through {#} m/[a\z{#}b]\x{100}/',
+ '/(?c)\x{100}/' => 'Useless (?c) - use /gc modifier {#} m/(?c{#})\x{100}/',
+ '/(?-c)\x{100}/' => 'Useless (?-c) - don\'t use /gc modifier {#} m/(?-c{#})\x{100}/',
+ '/(?g)\x{100}/' => 'Useless (?g) - use /g modifier {#} m/(?g{#})\x{100}/',
+ '/(?-g)\x{100}/' => 'Useless (?-g) - don\'t use /g modifier {#} m/(?-g{#})\x{100}/',
+ '/(?o)\x{100}/' => 'Useless (?o) - use /o modifier {#} m/(?o{#})\x{100}/',
+ '/(?-o)\x{100}/' => 'Useless (?-o) - don\'t use /o modifier {#} m/(?-o{#})\x{100}/',
+ '/(?g-o)\x{100}/' => [ 'Useless (?g) - use /g modifier {#} m/(?g{#}-o)\x{100}/',
+ 'Useless (?-o) - don\'t use /o modifier {#} m/(?g-o{#})\x{100}/',
],
- '/(?g-c)/' => [ 'Useless (?g) - use /g modifier {#} m/(?g{#}-c)/',
- 'Useless (?-c) - don\'t use /gc modifier {#} m/(?g-c{#})/',
+ '/(?g-c)\x{100}/' => [ 'Useless (?g) - use /g modifier {#} m/(?g{#}-c)\x{100}/',
+ 'Useless (?-c) - don\'t use /gc modifier {#} m/(?g-c{#})\x{100}/',
],
# (?c) means (?g) error won't be thrown
- '/(?o-cg)/' => [ 'Useless (?o) - use /o modifier {#} m/(?o{#}-cg)/',
- 'Useless (?-c) - don\'t use /gc modifier {#} m/(?o-c{#}g)/',
+ '/(?o-cg)\x{100}/' => [ 'Useless (?o) - use /o modifier {#} m/(?o{#}-cg)\x{100}/',
+ 'Useless (?-c) - don\'t use /gc modifier {#} m/(?o-c{#}g)\x{100}/',
],
- '/(?ogc)/' => [ 'Useless (?o) - use /o modifier {#} m/(?o{#}gc)/',
- 'Useless (?g) - use /g modifier {#} m/(?og{#}c)/',
- 'Useless (?c) - use /gc modifier {#} m/(?ogc{#})/',
+ '/(?ogc)\x{100}/' => [ 'Useless (?o) - use /o modifier {#} m/(?o{#}gc)\x{100}/',
+ 'Useless (?g) - use /g modifier {#} m/(?og{#}c)\x{100}/',
+ 'Useless (?c) - use /gc modifier {#} m/(?ogc{#})\x{100}/',
],
- '/a{1,1}?/' => 'Useless use of greediness modifier \'?\' {#} m/a{1,1}?{#}/',
- '/b{3} +/x' => 'Useless use of greediness modifier \'+\' {#} m/b{3} +{#}/',
-);
+ '/a{1,1}?\x{100}/' => 'Useless use of greediness modifier \'?\' {#} m/a{1,1}?{#}\x{100}/',
+ '/b{3} +\x{100}/x' => 'Useless use of greediness modifier \'+\' {#} m/b{3} +{#}\x{100}/',
+); # See comments before this for why '\x{100}' is generally needed
my @warnings_utf8 = mark_as_utf8(
'm/ネ\b*ネ/' => '\b* matches null string many times {#} m/ネ\b*{#}ネ/',