Skip to content

Commit 08c90cf

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 dddbfc6 commit 08c90cf

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
@@ -5467,6 +5467,33 @@ character class, just escape the square brackets with the backslash: "\[="
54675467
and "=\]". The S<<-- HERE> shows whereabouts in the regular expression the
54685468
problem was discovered. See L<perlre>.
54695469

5470+
=item Possible attempt to escape whitespace in qw() list
5471+
5472+
(W qw) qw() lists contain items separated by whitespace; contrary to
5473+
what some might expect, backslash characters cannot be used to "protect"
5474+
whitespace from being split, but are instead treated at literal data.
5475+
(You may have used different delimiters than the parentheses shown here;
5476+
braces are also frequently used.)
5477+
5478+
You probably wrote something like this:
5479+
5480+
@list = qw(
5481+
a\ string
5482+
another
5483+
);
5484+
5485+
Expecting to get a two elements list containing the strings C<'a string'>
5486+
and C<'another'>. Instead the list will hold four elements: C<'a\'>
5487+
(with a literal backslash), C<'string'> and C<'another'>.
5488+
5489+
If you really want whitespace in your strings, build your list the
5490+
old-fashioned way, with quotes and commas:
5491+
5492+
@list = ( 'a string', 'another' );
5493+
5494+
Note that this warnings is I<only> emitted when the backslash is followed
5495+
by actual whitespace (that C<qw> splits on).
5496+
54705497
=item Possible attempt to put comments in qw() list
54715498

54725499
(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
@@ -5821,6 +5821,7 @@ yyl_qw(pTHX_ char *s, STRLEN len)
58215821
if (SvCUR(PL_lex_stuff)) {
58225822
int warned_comma = !ckWARN(WARN_QW);
58235823
int warned_comment = warned_comma;
5824+
int warned_escape = warned_comma;
58245825
char *d = SvPV_force(PL_lex_stuff, len);
58255826
while (len) {
58265827
for (; isSPACE(*d) && len; --len, ++d)
@@ -5840,6 +5841,11 @@ yyl_qw(pTHX_ char *s, STRLEN len)
58405841
"Possible attempt to put comments in qw() list");
58415842
++warned_comment;
58425843
}
5844+
else if (!warned_escape && *d == '\\' && len > 1 && isSPACE(*(d+1)) ) {
5845+
warner(packWARN(WARN_QW),
5846+
"Possible attempt to escape whitespace in qw() list");
5847+
++warned_escape;
5848+
}
58435849
}
58445850
}
58455851
else {

0 commit comments

Comments
 (0)