My Favorite Warnings: syntax

Warnings category syntax contains a number of sub-categories representing possibly-problematic syntax. These include ambiguous syntax, problematic bareword usage, invalid printf conversions, and more. But there are also syntax diagnostics that do not fall under any of the sub-categories. These tend to be a miscellaneous group, and a normal-sized blog post can do no more than to give a sample.

What brought this to my attention was a noisy test in Template-Toolkit. under Perl 5.35.2 and up. The noisy code was untainting a variable using code like

$foo = each %{ { $foo => undef } } if ${^TAINT};

This makes use of the fact that hash keys are (so far) never tainted. The new warning was each on anonymous hash will always start from the beginning.

The adopted fix was to put this in the scope of a no warnings 'syntax';, which I initially thought was overkill, knowing that syntax was a group category. But further investigation showed that this diagnostic was, in fact, not a member of any sub-category of syntax. I got curious about what other warning categories were in syntax but not in a sub-category.

Some of my findings are in fact old friends: %s found where operator expected was there, as were (Missing operator before %s?) and (Missing semicolon on previous line?).

Others struck me as pointing out interesting or out-of-the way features of Perl that might need a diagnostic as an alternative to a hard-to-diagnose bug. The completely-random selection below is from the Perl 5.34.0 perldiag. Comments by me are in italics.

Array passed to stat will be coerced to a scalar%s

(W syntax) You called stat() on an array, but the array will be
coerced to a scalar - the number of elements in the array.

elseif should be elsif

(S syntax) There is no keyword "elseif" in Perl because Larry thinks
it's ugly. Your code will be interpreted as an attempt to call a
method named "elseif" for the class returned by the following block.
This is unlikely to be what you want.

"my %s" used in sort comparison

(W syntax) The package variables $a and $b are used for sort
comparisons. You used $a or $b in as an operand to the "<=>" or
"cmp" operator inside a sort comparison block, and the variable had
earlier been declared as a lexical variable. Either qualify the sort
variable with the package name, or rename the lexical variable.

And this, boys and girls,
is why variables $a and $b should
be avoided, even as lexicals.

Old package separator used in string

(W syntax) You used the old package separator, "'", in a variable
named inside a double-quoted string; e.g., "In $name's house". This
is equivalent to "In $name::s house". If you meant the former, put a
backslash before the apostrophe ("In $name\'s house").

The apostrophe as a package separator (i.e.
Foo'Bar rather than Foo::Bar) is
left over from Perl 4. In the given example,
"In ${name}'s house" also works.

!=~ should be !~

(W syntax) The non-matching operator is !~, not !=~. !=~ will be
interpreted as the != (numeric not equal) and ~ (1's complement)
operators: probably not what you intended.

This seems only to be emitted if the
right-hand side is a match (i.e. /foo/ or
m/foo/). It appears not to be emitted if the
right-hand side is qr/foo/ or 'foo'

Previous entries in this series:

  1. A Belated Introduction
  2. once
  3. redundant and missing
  4. exiting
  5. uninitialized
  6. redefine
  7. Ex-Warnings
  8. deprecated
  9. experimental
  10. shadow

Leave a comment

About Tom Wyant

user-pic I blog about Perl.