Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Warnings for unused subs

by VSarkiss (Monsignor)
on Jul 25, 2002 at 15:20 UTC ( [id://185220]=perlquestion: print w/replies, xml ) Need Help??

VSarkiss has asked for the wisdom of the Perl Monks concerning the following question:

Yesterday I was (re-)refactoring some old code. My tests ran OK, so I was about to check the thing back in, when I decided to eyeball it one more time. To my surprise, I noticed I'd removed the last reference to a sub (in other words, it wasn't getting called from anywhere), and hadn't received any notice or warning, even though I was using strict and warnings.

I realized the warning I was thinking of is for "variable appears only once", not "sub appears only once". I went looking thru the docs to see if there was some way to coax Perl into telling me that I had dead code, but didn't find one. Searching through the monastery proved fruitless as well. The B::Lint module sounded promising, but it doesn't want to run on my box, and the docs don't mention catching this type of oversight anyway. This sounds so simple, I'm sure I'm overlooking something obvious.

So, fellow monks, how do I make Perl tell me I've got a sub that is not being referenced anywhere else in the program? Just a simple compile-time check would be plenty. It doesn't have to be bulletproof; some reasonably good hints would be OK.

Replies are listed 'Best First'.
Re: Warnings for unused subs
by Abigail-II (Bishop) on Jul 25, 2002 at 15:40 UTC
    That isn't really solvable, as function names can be generate during run-time, using "eval" for instance, but also with: $obj -> $method, or because they are exported to another package (which happens after such a package was compiled). Also, functions can be called from other packages. Not to mention that there are lots of functions that are never explicitly called, like BEGIN, AUTOLOAD, DESTROY, FETCH and import.

    Abigail

      You're right, there are many ways to break something like this, but I was just thinking of something for the common case: sub foo appears, but a call to foo(...) doesn't appear in the same package. That's what I was trying to say with "it doesn't have to be bulletproof".

      I guess an analogy would be perltidy. It can be thrown off without trying very hard, but in the common cases it can be helpful.

        Given that both OO modules and exporting modules are very common, the case of having sub foo appear in a package without a call to it is indeed common. It's also not an unused sub.

        Abigail

Re: Warnings for unused subs
by FoxtrotUniform (Prior) on Jul 25, 2002 at 15:51 UTC

    Looks like you should be able to use Devel::DProf to check for dead subroutines in the same way you'd check for hot-spot subroutines. If you're running automated tests, adding an automated dead-code check shouldn't be too difficult.

    --
    The hell with paco, vote for Erudil!
    :wq

Re: Warnings for unused subs
by danger (Priest) on Jul 25, 2002 at 16:52 UTC

    Just an additional note --- 'used only once' won't come into play in a variety of situations:

    #!/usr/bin/perl -w use strict; use vars qw/$abc @def %ghi/; our($jkl, @mno, %pqr); my($stu, @vwx, %y_and_z); sub qux {} open(FOO,$0) or die $!; opendir(DIR, '.') or die $!;

    In 5.6.1, the above throws warnings for FOO and DIR, and all of the our variables, but nothing else --- in 5.8.0, only FOO and DIR elicit warnings. Variables declared with 'use vars' (and now our) are exempt, as are subroutines and lexicals.

    To top it off, 'used only once' really only applies to things in the symbol table, and in particular, is elicited only when the *typeglob is used but once --- as soon as two or more slots in a typeglob are filled, all identifiers within that typeglob are exempt:

    #!/usr/bin/perl -w use strict; use vars '$foo'; our(@foo); # second use of *foo $main::bar = 42; %main::bar = (a => 1); # second use of *bar our($FOO, @DIR); open(FOO,$0) or die $!; # second use of *FOO opendir(DIR, '.') or die $!; # second use of *DIR sub blah {} our($blah); # second use of *blah

    No warnings --- even though $main::bar is used only once, the *bar identifier is used more than once.

Re: Warnings for unused subs? here's find_unused_subs.pl!
by dada (Chaplain) on Jul 26, 2002 at 10:12 UTC
    here is a simple, little program called find_unused_subs.pl:
    #!/usr/bin/perl use strict; my $F = shift || die "no file specified"; my $xref_cmd = "$^X -MO=Xref,-r $F"; my %subdef; my %subused; my @fields = qw( file context line package sigil name action ); open TMP, "$xref_cmd |"; # Xref mangles up filenames, so we need to binmode it binmode TMP; while(<TMP>) { chomp; my %data; @data{ @fields } = split( /\s+/ ); if( $data{action} eq "subdef" and $data{package} eq "main" and $data{file} eq $F ) { $subdef{ $data{name} } = "$data{file}:$data{line}"; } if( $data{action} eq "subused" and $data{package} eq "main" and $data{file} eq $F ) { $subused{ $data{name} } = "$data{file}:$data{line}"; } } close TMP; foreach my $sub (keys %subdef) { next if exists $subused{ $sub }; print "$subdef{ $sub } $sub\n"; }
    it only works on plain scripts, where subs are in the main package. feel free to enhance it :-)

    cheers,
    Aldo

    __END__ $_=q,just perl,,s, , another ,,s,$, hacker,,print;

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://185220]
Front-paged by TStanley
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others contemplating the Monastery: (4)
As of 2024-04-18 03:27 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found