http://www.perlmonks.org?node_id=1187988

Just a hack as prove of concept for Re^4: determine the variable causing the error: Use of uninitialized value

Can be improved in different ways ...

Due to limitations of B::Deparse it's only working if warning happens within a subroutine.

use strict; use warnings; use Data::Dump qw/pp dd/; use B::Deparse qw/coderef2text/; use PadWalker qw/peek_my/; my %warncache; my $result; BEGIN { $SIG{__WARN__} = sub { my ($err)=@_; # ignore other warnings unless ($err =~ m/^(Use of uninitialized value) (in (\w+) .* +)$/) { warn "$err"; return; } # ignore other undef vars return if $warncache{$err}++; my ($msg_start, $msg_end, $msg_type) =($1,$2,$3); #warn "* OrigWarn:\t $err"; my ($file,$line) = (caller(0))[1,2]; my $subname = (caller(1))[3]; my ($subref,$subline) = get_subline($subname,$file,$line,$er +r); #warn "LINE:<$subline>"; my $peek_sub = PadWalker::peek_sub ($subref); my $sep = { concatenation => '\\.', printf => ',', sprintf => ',', }->{$msg_type}; my $chomp = { sprintf => '\)', }->{$msg_type}; $subline =~ s/$chomp$// if $chomp; my @split = split /\s*$sep\s*/, $subline; #dd [$subline, @split, $peek_sub]; my @undefined; for my $snippet ( @split) { while ( my ($var,$ref) = each %$peek_sub){ $var =~ s/^\%/\$/; $var =~ s/^\@/\$/; my $match="\\$var"; if ( $snippet =~ /^(.*?)($match)(.*)$/ ) { my $new="$1\$ref$3"; #warn "match VAR <$match> in $snippet as $new"; next if defined eval($new); #warn "UNDEF $snippet"; push @undefined, $snippet; } } } #dd \@undefined; # build new warning my $plural = @undefined > 1 ? "s" :""; my $new_err = "${msg_start}$plural @undefined $msg_end"; warn # ". NewWarn:\t". "$new_err\n"; $result = { oldmsg => $err, newmsg => $new_err, vars => [@undefined], line => $subline, split => [@split], peek => $peek_sub, }; }; } sub get_subline { my ($name,$file,$line,$err) =@_; #dd \@_; my $subref = \&{$name}; my $subbody = B::Deparse->new('-q','-l','-x0')->coderef2text($subr +ef); my $start = "#line \Q$line\E \"\Q$file\E\"\n"; my $end = "\n(#line|})"; #warn $subbody; #dd "match:", $subbody =~ m/($start)/; my ($subline) = $subbody =~ m/$start\s+(.*?);$end/s; return ($subref, $subline); } #warn "Version $]"; my %hash=(a=>undef,b=>[]); my $h=\%hash; my @array=({a=>undef}); my $a=\@array; while (my $case = <DATA>) { chomp $case; next unless $case; next if $case =~ /^#/; my ($name,$var) = split /\s*:\s*/,$case; warn "*** TESTING".pp [$name,$var]; no warnings 'redefine'; my $out =""; open OUT,">",\$out; my @lines = ( # one undef var qq# print OUT "$name: $var"; #, qq# printf OUT '$name %s',$var; #, qq# print OUT sprintf '$name %s',$var; #, # multiple undef vars qq# print OUT "$name: $var $var" #, qq# printf OUT '$name %s %s',$var,$var; #, qq# print OUT sprintf '$name %s %s',$var,$var; #, ); for my $line (@lines) { my $code = <<"__CODE__"; sub tst { $line }; __CODE__ eval $code; if ($@) { warn "SKIPPING TEST $@ in \n<<<$code>>>"; next; } undef $result; tst(); die "$case", pp $result if $result and not @{$result->{vars}}; #warn pp $code,$result; } #last; } exit; __DATA__ hash_ref: $h->{a} hoa_ref: $h->{b}[0] hash: $hash{a} hoa: $hash{b}[0] array: $array[1] aoh: $array[0]{a} array_ref:$a->[1] aoh_ref: $a->[0]{a} #aoh_ref: $a->[$b]{'a b'}

Output:

Name "main::OUT" used only once: possible typo at /home/lanx/pm/warn_u +ndef.pl line 141. *** TESTING["hash_ref", "\$h->{a}"] at /home/lanx/pm/warn_undef.pl lin +e 138, <DATA> line 2. Use of uninitialized value $$h{'a'} in concatenation (.) or string at +(eval 10) line 2, <DATA> line 2. Use of uninitialized value $$h{'a'} in printf at (eval 12) line 2, <DA +TA> line 2. Use of uninitialized value $$h{'a'} in sprintf at (eval 14) line 2, <D +ATA> line 2. Use of uninitialized values $$h{'a'} $$h{'a'} in concatenation (.) or +string at (eval 16) line 2, <DATA> line 2. Use of uninitialized values $$h{'a'} $$h{'a'} in printf at (eval 19) l +ine 2, <DATA> line 2. Use of uninitialized values $$h{'a'} $$h{'a'} in sprintf at (eval 22) +line 2, <DATA> line 2. *** TESTING["hoa_ref", "\$h->{b}[0]"] at /home/lanx/pm/warn_undef.pl l +ine 138, <DATA> line 3. Use of uninitialized value $$h{'b'}[0] in concatenation (.) or string +at (eval 25) line 2, <DATA> line 3. Use of uninitialized value $$h{'b'}[0] in printf at (eval 27) line 2, +<DATA> line 3. Use of uninitialized value $$h{'b'}[0] in sprintf at (eval 29) line 2, + <DATA> line 3. Use of uninitialized values $$h{'b'}[0] $$h{'b'}[0] in concatenation ( +.) or string at (eval 31) line 2, <DATA> line 3. Use of uninitialized values $$h{'b'}[0] $$h{'b'}[0] in printf at (eval + 34) line 2, <DATA> line 3. Use of uninitialized values $$h{'b'}[0] $$h{'b'}[0] in sprintf at (eva +l 37) line 2, <DATA> line 3. *** TESTING["hash", "\$hash{a}"] at /home/lanx/pm/warn_undef.pl line 1 +38, <DATA> line 5. Use of uninitialized value $hash{"a"} in concatenation (.) or string a +t (eval 40) line 2, <DATA> line 5. Use of uninitialized value $hash{"a"} in printf at (eval 41) line 2, < +DATA> line 5. Use of uninitialized value $hash{"a"} in sprintf at (eval 42) line 2, +<DATA> line 5. Use of uninitialized value $hash{"a"} in concatenation (.) or string a +t (eval 43) line 2, <DATA> line 5. Use of uninitialized value $hash{"a"} in concatenation (.) or string a +t (eval 43) line 2, <DATA> line 5. Use of uninitialized value $hash{"a"} in printf at (eval 44) line 2, < +DATA> line 5. Use of uninitialized value $hash{"a"} in printf at (eval 44) line 2, < +DATA> line 5. Use of uninitialized value $hash{"a"} in sprintf at (eval 45) line 2, +<DATA> line 5. Use of uninitialized value $hash{"a"} in sprintf at (eval 45) line 2, +<DATA> line 5. *** TESTING["hoa", "\$hash{b}[0]"] at /home/lanx/pm/warn_undef.pl line + 138, <DATA> line 6. Use of uninitialized value $hash{'b'}[0] in concatenation (.) or strin +g at (eval 46) line 2, <DATA> line 6. Use of uninitialized value $hash{'b'}[0] in printf at (eval 48) line 2 +, <DATA> line 6. Use of uninitialized value $hash{'b'}[0] in sprintf at (eval 50) line +2, <DATA> line 6. Use of uninitialized values $hash{'b'}[0] $hash{'b'}[0] in concatenati +on (.) or string at (eval 52) line 2, <DATA> line 6. Use of uninitialized values $hash{'b'}[0] $hash{'b'}[0] in printf at ( +eval 55) line 2, <DATA> line 6. Use of uninitialized values $hash{'b'}[0] $hash{'b'}[0] in sprintf at +(eval 58) line 2, <DATA> line 6. *** TESTING["array", "\$array[1]"] at /home/lanx/pm/warn_undef.pl line + 138, <DATA> line 8. Use of uninitialized value $array[1] in concatenation (.) or string at + (eval 61) line 2, <DATA> line 8. Use of uninitialized value $array[1] in printf at (eval 62) line 2, <D +ATA> line 8. Use of uninitialized value $array[1] in sprintf at (eval 64) line 2, < +DATA> line 8. Use of uninitialized value $array[1] in concatenation (.) or string at + (eval 65) line 2, <DATA> line 8. Use of uninitialized values $array[1] $array[1] in concatenation (.) o +r string at (eval 65) line 2, <DATA> line 8. Use of uninitialized values $array[1] $array[1] in printf at (eval 68) + line 2, <DATA> line 8. Use of uninitialized values $array[1] $array[1] in sprintf at (eval 71 +) line 2, <DATA> line 8. *** TESTING["aoh", "\$array[0]{a}"] at /home/lanx/pm/warn_undef.pl lin +e 138, <DATA> line 9. Use of uninitialized value $array[0]{'a'} in concatenation (.) or stri +ng at (eval 74) line 2, <DATA> line 9. Use of uninitialized value $array[0]{'a'} in printf at (eval 76) line +2, <DATA> line 9. Use of uninitialized value $array[0]{'a'} in sprintf at (eval 78) line + 2, <DATA> line 9. Use of uninitialized values $array[0]{'a'} $array[0]{'a'} in concatena +tion (.) or string at (eval 80) line 2, <DATA> line 9. Use of uninitialized values $array[0]{'a'} $array[0]{'a'} in printf at + (eval 83) line 2, <DATA> line 9. Use of uninitialized values $array[0]{'a'} $array[0]{'a'} in sprintf a +t (eval 86) line 2, <DATA> line 9. *** TESTING["array_ref", "\$a->[1]"] at /home/lanx/pm/warn_undef.pl li +ne 138, <DATA> line 11. Use of uninitialized value $$a[1] in concatenation (.) or string at (e +val 89) line 2, <DATA> line 11. Use of uninitialized value $$a[1] in printf at (eval 91) line 2, <DATA +> line 11. Use of uninitialized value $$a[1] in sprintf at (eval 93) line 2, <DAT +A> line 11. Use of uninitialized values $$a[1] $$a[1] in concatenation (.) or stri +ng at (eval 95) line 2, <DATA> line 11. Use of uninitialized values $$a[1] $$a[1] in printf at (eval 98) line +2, <DATA> line 11. Use of uninitialized values $$a[1] $$a[1] in sprintf at (eval 101) lin +e 2, <DATA> line 11. *** TESTING["aoh_ref", "\$a->[0]{a}"] at /home/lanx/pm/warn_undef.pl l +ine 138, <DATA> line 12. Use of uninitialized value $$a[0]{'a'} in concatenation (.) or string +at (eval 104) line 2, <DATA> line 12. Use of uninitialized value $$a[0]{'a'} in printf at (eval 106) line 2, + <DATA> line 12. Use of uninitialized value $$a[0]{'a'} in sprintf at (eval 108) line 2 +, <DATA> line 12. Use of uninitialized values $$a[0]{'a'} $$a[0]{'a'} in concatenation ( +.) or string at (eval 110) line 2, <DATA> line 12. Use of uninitialized values $$a[0]{'a'} $$a[0]{'a'} in printf at (eval + 113) line 2, <DATA> line 12. Use of uninitialized values $$a[0]{'a'} $$a[0]{'a'} in sprintf at (eva +l 116) line 2, <DATA> line 12.

Cheers Rolf
(addicted to the Perl Programming Language and ☆☆☆☆ :)
Je suis Charlie!