This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Fix scrambled and incorrect proto mismatch error
authorFather Chrysostomos <sprout@cpan.org>
Sun, 29 Jul 2012 06:41:00 +0000 (23:41 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 29 Jul 2012 07:13:56 +0000 (00:13 -0700)
commit105ff74ce063d3eef3434a4ce97c533fde909e43
tree7ff1b6d50535317a6d76beb47a77c113a96b3d94
parentafc04f16a85625bbb9c291b91861c1c5e3c450b7
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.
op.c
t/lib/warnings/op