Skip to content

add a new warning against using \ in qw() #23403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: blead
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion pod/perldelta.pod
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,14 @@ XXX L<message|perldiag/"message">

=item *

XXX L<message|perldiag/"message">
L<Possible attempt to escape whitespace in qw() list|perldiag/"Possible attempt to escape whitespace in qw() list">

(W qw) qw() lists contain items separated by whitespace; contrary to
what some might expect, backslash characters cannot be used to "protect"
whitespace from being split, but are instead treated as literal data.

Note that this warnings is I<only> emitted when the backslash is followed
by actual whitespace (that C<qw> splits on).

=back

Expand Down
27 changes: 27 additions & 0 deletions pod/perldiag.pod
Original file line number Diff line number Diff line change
Expand Up @@ -5467,6 +5467,33 @@ character class, just escape the square brackets with the backslash: "\[="
and "=\]". The S<<-- HERE> shows whereabouts in the regular expression the
problem was discovered. See L<perlre>.

=item Possible attempt to escape whitespace in qw() list

(W qw) qw() lists contain items separated by whitespace; contrary to
what some might expect, backslash characters cannot be used to "protect"
whitespace from being split, but are instead treated as literal data.
(You may have used different delimiters than the parentheses shown here;
braces are also frequently used.)

You probably wrote something like this:

@list = qw(
a\ string
another
);

Expecting to get a two elements list containing the strings C<'a string'>
and C<'another'>. Instead the list will hold four elements: C<'a\'>
(with a literal backslash), C<'string'> and C<'another'>.

If you really want whitespace in your strings, build your list the
old-fashioned way, with quotes and commas:

@list = ( 'a string', 'another' );

Note that this warnings is I<only> emitted when the backslash is followed
by actual whitespace (that C<qw> splits on).

=item Possible attempt to put comments in qw() list

(W qw) qw() lists contain items separated by whitespace; as with literal
Expand Down
9 changes: 9 additions & 0 deletions t/lib/warnings/toke
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ toke.c AOK
Possible attempt to put comments in qw() list
@a = qw(a b # c) ;

Possible attempt to escape whitespace in qw() list
@a = qw( foo bar\ baz ) ;

%s (...) interpreted as function
print ("")
printf ("")
Expand Down Expand Up @@ -366,6 +369,12 @@ Possible attempt to separate words with commas at - line 3.
Possible attempt to put comments in qw() list at - line 3.
########
# toke.c
use warnings 'qw';
@a = qw( foo bar\ baz );
EXPECT
Possible attempt to escape whitespace in qw() list at - line 3.
########
# toke.c
use warnings 'syntax' ;
print ("");
print ("") and $x = 1;
Expand Down
6 changes: 6 additions & 0 deletions toke.c
Original file line number Diff line number Diff line change
Expand Up @@ -5821,6 +5821,7 @@ yyl_qw(pTHX_ char *s, STRLEN len)
if (SvCUR(PL_lex_stuff)) {
int warned_comma = !ckWARN(WARN_QW);
int warned_comment = warned_comma;
int warned_escape = warned_comma;
char *d = SvPV_force(PL_lex_stuff, len);
while (len) {
for (; isSPACE(*d) && len; --len, ++d)
Expand All @@ -5840,6 +5841,11 @@ yyl_qw(pTHX_ char *s, STRLEN len)
"Possible attempt to put comments in qw() list");
++warned_comment;
}
else if (!warned_escape && *d == '\\' && len > 1 && isSPACE(*(d+1)) ) {
warner(packWARN(WARN_QW),
"Possible attempt to escape whitespace in qw() list");
++warned_escape;
}
}
}
else {
Expand Down