Fix scrambled and incorrect proto mismatch error
$ ./perl -Ilib -e 'use constant foo=>bar; sub foo(@);'
Prototype mismatch:: none vs (@) at -e line 1.
$ ./perl -Ilib -e 'sub foo(); sub foo(@);'
Prototype mismatch: () vs (@) at -e line 1.
Notice the double colon and the ‘none’ in the first example?
We also have this bug, where the prototype is the same, but we get the
warning anyway:
$ ./perl -Ilib -e 'use constant foo=>bar; sub foo();'
Prototype mismatch:: none vs () at -e line 1.
When the $::{foo} = \1 constant optimisation was added in 5.10.0, pro-
totype warnings were not taken into account. A forward declaration
like sub foo() puts a string in the stash element. newATTRSUB was
passing a non-SVt_NULL non-gv stash element to cv_ckproto_len_flags,
which assumed that !SvPOK meant no prototype. That’s not the case
with a reference.
The double colon, which goes back to 5.8.4 (
ebe643b99/
59e7bac08e),
occurs when the sub name is not available:
$ perl5.8.4 -e 'sub foo; sub foo();'
Prototype mismatch:: none vs () at -e line 1.
(Before that the message was worse:
$ perl5.8.3 -e 'sub foo; sub foo();'
Prototype mismatch: vs () at -e line 1.)
In 5.10.0, it started applying to constants as well, which used to
show the sub name:
$ perl5.8.9 -e 'use constant foo=>bar; sub foo(@);'
Prototype mismatch: sub main::foo () vs (@) at -e line 1.
$ perl5.10.0 -e 'use constant foo=>bar; sub foo(@);'
Runaway prototype at -e line 1.
Prototype mismatch:: none vs (@) at -e line 1.
(‘Runaway prototype’ is already gone in blead [
acfcf464b177, in which
I stated wrongly that the warning could only come about with stash
manipulation].)
This commit changes cv_ckproto_len_flags to assume that a reference
is a constant with an empty string for a prototype. It also makes
newATTRSUB pass the sub name sv instead of a gv in those cases where
the stash element isn’t a gv. This doesn’t restore things to exactly
the way they were before (foo instead of main::foo), but I’m not sure
it’s worth the added complexity of constructing the fully-qualified
name, just for a warning.