This a bug in toke.c, in the following code:
STATIC void
S_checkcomma(pTHX_ register char *s, char *name, char *what)
{
char *w;
if (*s == ' ' && s[1] == '(') { /* XXX gotta be a better way *
+/
if (ckWARN(WARN_SYNTAX)) {
int level = 1;
for (w = s+2; *w && level; w++) {
if (*w == '(')
++level;
else if (*w == ')')
--level;
}
if (*w)
for (; *w && isSPACE(*w); w++) ;
if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory
+ hack only... */
Perl_warner(aTHX_ WARN_SYNTAX,
"%s (...) interpreted as function",name);
}
}
# [the S_checkcomma function continues from here with an unrelated
+ syntax check]
Here's the code again, this time with comments interspersed:
STATIC void
S_checkcomma(pTHX_ register char *s, char *name, char *what)
{
char *w;
if (*s == ' ' && s[1] == '(') { /* XXX gotta be a better way *
+/
When this function is called, the tokenizer has just grabbed the name of a function. If the current character is a space, and the next character is an open paren, then we'll do the following...
if (ckWARN(WARN_SYNTAX)) {
(...but only if syntax warnings are turned on...)
int level = 1;
for (w = s+2; *w && level; w++) {
if (*w == '(')
++level;
else if (*w == ')')
--level;
}
That for loop should be familiar to many programmers. It's simply counting open and close parens. The conditional, *w && level, will cause the loop to exit either at the end of the line (when *w is null) or when the matching close paren for the first open paren is found (level is 0). However, note that the loop ignores anything that isn't a paren.
if (*w)
for (; *w && isSPACE(*w); w++) ;
This extra loop just skips any whitespace after that last closing paren.
if (!*w || !strchr(";|})]oaiuw!=", *w)) /* an advisory hack only... */
Now, if we're at the end of the line (*w is null) or the current character is not one of ;|})]oaiuw!=, then the warning in question is produced:
Perl_warner(aTHX_ WARN_SYNTAX,
"%s (...) interpreted as function",name);
}
}
Remember the part about the counting of parens ignoring anything that isn't a paren? So, in print ("hey)");, this bit of toke.c thinks that the first close paren is the matching paren, even though that paren is inside a string. The character after that paren is a double quote, which is not in that set of acceptable characters, and so the warning is produced.
This suggests some other interesting snippets:
print (/\)/); # warning
print (/./); # no warning
print ("hey))"); # no warning
print ("hey")&&1; # warning
print ("hey")||1; # no warning
As the comment says, there's "gotta be a better way". :)
To avoid this warning, you could remove the space before the open paren, add a plus before the open paren, or remove the parens entirely if they're unneeded.
By the way, you're probably wondering why the set of characters ;|})]oaiuw!= is special. Frankly, I just don't know!
|