Skip to content

Commit f347ee8

Browse files
committed
add a new warning against using \ in qw()
I've seen AI-generated code try to use qw() to create lists containing strings with embedded whitespace using qw and \ to "protect" the whitespace. Things like: my @list = qw( foo bar\ baz ); Just like occurences of ',' and '#', I believe this should warn. Note that the warning will only be emitted when the \ is followed by actual whitespace, so code like the following (from lib/App/Cpan.pm) will not warn: my $epic_fail_words = join '|', qw( Error stop(?:ping)? problems force not unsupported fail(?:ed)? Cannot\s+install );
1 parent dd99ef8 commit f347ee8

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

pod/perldiag.pod

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5480,6 +5480,33 @@ character class, just escape the square brackets with the backslash: "\[="
54805480
and "=\]". The S<<-- HERE> shows whereabouts in the regular expression the
54815481
problem was discovered. See L<perlre>.
54825482

5483+
=item Possible attempt to escape whitespace in qw() list
5484+
5485+
(W qw) qw() lists contain items separated by whitespace; contrary to
5486+
what some might expect, backslash characters cannot be used to "protect"
5487+
whitespace from being split, but are instead treated as literal data.
5488+
(You may have used different delimiters than the parentheses shown here;
5489+
braces are also frequently used.)
5490+
5491+
You probably wrote something like this:
5492+
5493+
@list = qw(
5494+
a\ string
5495+
another
5496+
);
5497+
5498+
expecting to get a two elements list containing the strings C<'a string'>
5499+
and C<'another'>. Instead the list will hold four elements: C<'a\'>
5500+
(with a literal backslash), C<'string'> and C<'another'>.
5501+
5502+
If you really want whitespace in your strings, build your list the
5503+
old-fashioned way, with quotes and commas:
5504+
5505+
@list = ( 'a string', 'another' );
5506+
5507+
Note that this warnings is I<only> emitted when the backslash is followed
5508+
by actual whitespace (that C<qw> splits on).
5509+
54835510
=item Possible attempt to put comments in qw() list
54845511

54855512
(W qw) qw() lists contain items separated by whitespace; as with literal

t/lib/warnings/toke

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,9 @@ toke.c AOK
4949
Possible attempt to put comments in qw() list
5050
@a = qw(a b # c) ;
5151

52+
Possible attempt to escape whitespace in qw() list
53+
@a = qw( foo bar\ baz ) ;
54+
5255
%s (...) interpreted as function
5356
print ("")
5457
printf ("")
@@ -366,6 +369,12 @@ Possible attempt to separate words with commas at - line 3.
366369
Possible attempt to put comments in qw() list at - line 3.
367370
########
368371
# toke.c
372+
use warnings 'qw';
373+
@a = qw( foo bar\ baz );
374+
EXPECT
375+
Possible attempt to escape whitespace in qw() list at - line 3.
376+
########
377+
# toke.c
369378
use warnings 'syntax' ;
370379
print ("");
371380
print ("") and $x = 1;

toke.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5818,6 +5818,7 @@ yyl_qw(pTHX_ char *s, STRLEN len)
58185818
if (SvCUR(PL_lex_stuff)) {
58195819
int warned_comma = !ckWARN(WARN_QW);
58205820
int warned_comment = warned_comma;
5821+
int warned_escape = warned_comma;
58215822
char *d = SvPV_force(PL_lex_stuff, len);
58225823
while (len) {
58235824
for (; isSPACE(*d) && len; --len, ++d)
@@ -5837,6 +5838,11 @@ yyl_qw(pTHX_ char *s, STRLEN len)
58375838
"Possible attempt to put comments in qw() list");
58385839
++warned_comment;
58395840
}
5841+
else if (!warned_escape && *d == '\\' && len > 1 && isSPACE(*(d+1)) ) {
5842+
warner(packWARN(WARN_QW),
5843+
"Possible attempt to escape whitespace in qw() list");
5844+
++warned_escape;
5845+
}
58405846
}
58415847
}
58425848
else {

0 commit comments

Comments
 (0)