In mr.dunstan's particular case, perhaps "half as useful" is just enough.

If I were creating a tool to find undefined subs, and that tool was only to be used by myself and other Perl programmers within my (hypothetical) company, I could tune it to our site standards. We know which directories hold our in-house modules, and what AUTOLOADs those modules do. I would design for zero false negatives, and then tweak to reduce the false positives. I think the result would be useful, though imperfect.

I have included a working example below. It uses B::Xref to get a listing of subroutines defined or used in the analysed program, including any modules used. Simply listing the subroutines used, but not defined, would clutter the list with runtime-defined subroutines from modules in the Perl library. I get around this by populating %known with the full pathnames of all the modules in @INC, except for those in the current directory, and skipping over the 'subused' lines from those files. You could add another hash to skip over known AUTOLOADed subs from your own modules.

This is a proof-of-concept; much more could be done with a little more code. This version does not even tell you where the undefined subs occurred. It is lightweight enough to be cloned and hacked for multiple projects without creating maintenance issues.

test.pl
use MightyMod; use XML::Simple; my $y = BadSub(0); my $z = GoodSub(0); print "$y $z";
MightyMod.pm
package MightyMod; use strict; require Exporter; our @EXPORT = qw(GoodSub); our @ISA = qw(Exporter); sub GoodSub { return 42 + LostSub(@_); } 1;
Find_Undefined_Subroutines.pl
#!/usr/bin/perl -w use strict; use File::Find; my %known; find( sub{$known{$File::Find::name}=1 if /\.pm$/}, grep {$_ ne '.'} @INC ); my $pgm = shift or die; my @xref = `perl -MO=Xref,-r $pgm 2>/dev/null` or die; # Xref data looks like this: # test.pl (definitions) 5 main & GoodSub subdef # test.pl (main) 4 (lexical) $ y intro # test.pl (main) 4 main & BadSub subused my %h; foreach (@xref) { my ($file, $where, $line, $package, $sym, $name, $how) = split; next if $how eq 'subused' and $known{$file}; $h{$how}{$name}++; } foreach (sort keys %{$h{subused}}) { print "$_\n" unless $h{subdef}{$_}; }
Output:
$ ./Find_Undefined_Subroutines.pl test.pl BadSub LostSub

By the way, B::Lint has an option, undefined-subs, which is supposed to do something similar to my code, but I could not make it find any errors. Perhaps it is because all my Perl interpreters are threaded; B::Lint's documentation says 'This module doesn't work correctly on thread-enabled perls'.


In reply to Re: Compile-time checking for undef subroutines? by Util
in thread Compile-time checking for undef subroutines? by mr.dunstan

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.