summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2014-12-05 06:21:35 -0800
committerFather Chrysostomos <sprout@cpan.org>2014-12-05 15:51:38 -0800
commit67359f08ae288ccd943818bc458394bda2c8409f (patch)
treee7aace706ac6be8efd7f574fb0ef6a39920a3931 /lib
parentb68eab22f47f27e55acb9cccd69e982cdd595f45 (diff)
downloadperl-67359f08ae288ccd943818bc458394bda2c8409f.tar.gz
Deparse predeclared prototyped subs
A predeclared sub without a prototype works fine: $ ./perl -Ilib -MO=Deparse -e 'sub f; sub f{}; foo()' sub f { } foo(); -e syntax OK A prototyped sub with no predeclaration is fine: $ ./perl -Ilib -MO=Deparse -e ' sub f($){}; foo()' sub f ($) { } foo(); -e syntax OK A prototyped stub is fine: $ ./perl -Ilib -MO=Deparse -e 'sub f($); foo()' sub f ($); foo(); -e syntax OK Only a predeclared prototyped sub seems to have trouble appear- ing properly: $ ./perl -Ilib -MO=Deparse -e 'sub f($); sub f($){}; foo()' sub f; foo(); -e syntax OK The code that searches the stashes (stash_subs) was assuming that any- thing of type B::PV was a prototype. In this case, the stash entry started as a string and then got ‘downgraded’ to a reference, so internally it is of type PV (which can hold a ref), which B represents as B::PV, so the assumption that a PV is a prototyped stub is wrong.
Diffstat (limited to 'lib')
-rw-r--r--lib/B/Deparse.pm21
-rw-r--r--lib/B/Deparse.t6
2 files changed, 16 insertions, 11 deletions
diff --git a/lib/B/Deparse.pm b/lib/B/Deparse.pm
index dea21a9aa6..513e2d1ba5 100644
--- a/lib/B/Deparse.pm
+++ b/lib/B/Deparse.pm
@@ -699,7 +699,16 @@ sub stash_subs {
my %stash = svref_2object($stash)->ARRAY;
while (my ($key, $val) = each %stash) {
my $class = class($val);
- if ($class eq "PV") {
+ if ($val->FLAGS & SVf_ROK) {
+ # A reference. Dump this if it is a reference to a CV.
+ # But skip proxy constant subroutines, as some form of perl-
+ # space visible code must have created them, be it a use
+ # statement, or some direct symbol-table manipulation code that
+ # we will Deparse.
+ if (class(my $cv = $val->RV) eq "CV") {
+ $self->todo($cv, 0);
+ }
+ } elsif ($class eq "PV") {
# Just a prototype. As an ugly but fairly effective way
# to find out if it belongs here is to see if the AUTOLOAD
# (if any) for the stash was defined in one of our files.
@@ -710,11 +719,8 @@ sub stash_subs {
next unless $AF eq $0 || exists $self->{'files'}{$AF};
}
push @{$self->{'protos_todo'}}, [$pack . $key, $val->PV];
- } elsif ($class eq "IV" && !($val->FLAGS & SVf_ROK)) {
+ } elsif ($class eq "IV") {
# Just a name. As above.
- # But skip proxy constant subroutines, as some form of perl-space
- # visible code must have created them, be it a use statement, or
- # some direct symbol-table manipulation code that we will Deparse
my $A = $stash{"AUTOLOAD"};
if (defined ($A) && class($A) eq "GV" && defined($A->CV)
&& class($A->CV) eq "CV") {
@@ -722,11 +728,6 @@ sub stash_subs {
next unless $AF eq $0 || exists $self->{'files'}{$AF};
}
push @{$self->{'protos_todo'}}, [$pack . $key, undef];
- } elsif ($class eq "IV") {
- # A reference. Dump this if it is a reference to a CV.
- if (class(my $cv = $val->RV) eq "CV") {
- $self->todo($cv, 0);
- }
} elsif ($class eq "GV") {
if (class(my $cv = $val->CV) ne "SPECIAL") {
next if $self->{'subs_done'}{$$val}++;
diff --git a/lib/B/Deparse.t b/lib/B/Deparse.t
index f39e1c8483..1f2efdd070 100644
--- a/lib/B/Deparse.t
+++ b/lib/B/Deparse.t
@@ -13,7 +13,7 @@ BEGIN {
use warnings;
use strict;
-my $tests = 33; # not counting those in the __DATA__ section
+my $tests = 34; # not counting those in the __DATA__ section
use B::Deparse;
my $deparse = B::Deparse->new();
@@ -343,6 +343,10 @@ like($a, qr/my sub __DATA__;\n.*\nCORE::__DATA__/s,
# sub declarations
$a = readpipe qq`$^X $path "-MO=Deparse" -e "sub foo{}" 2>&1`;
like($a, qr/sub foo\s*\{\s+\}/, 'sub declarations');
+like runperl(stderr => 1, switches => [ '-MO=-qq,Deparse', $path ],
+ prog => 'sub f($); sub f($){}'),
+ qr/sub f\s*\(\$\)\s*\{\s*\}/,
+ 'predeclared prototyped subs';
# BEGIN blocks
SKIP : {