#!/usr/bin/perl -w require 5.003; # # Copyright by The HDF Group. # All rights reserved. # # This file is part of HDF5. The full HDF5 copyright notice, including # terms governing use, modification, and redistribution, is contained in # the files COPYING and Copyright.html. COPYING can be found at the root # of the source code distribution tree; Copyright.html can be found at the # root level of an installed copy of the electronic HDF5 document set and # is linked from the top-level documents page. It can also be found at # http://hdfgroup.org/HDF5/doc/Copyright.html. If you do not have # access to either file, you may request a copy from help@hdfgroup.org. # # Quincey Koziol, koziol@hdfgroup.org # 9 Aug 2013 # # Purpose: Given an input file containing the output from a build of the # library, gather the file names and line numbers, alias # identical types of warnings together into a single bin and # report the number of warnings for each type of warning, each file # and the total count of warnings # Perl modules/settings use strict; use Getopt::Std; # Global variables, for accumulating information my $totalcount = 0; my %warn_count = (); my $warncount; my %warn_file = (); my %warn_file_line = (); my %file_count = (); my $filecount; my $ignorecount = 0; my @ignorenames; my %ignored_files = (); my %warn_file_indices = (); my %file_warn_indices = (); my @warn_match_strings; my @file_match_strings; my %file_warn = (); my %file_warn_line = (); my $current_warning = 0; my $current_file = 0; my $warn_index; my $last_c_name; my $last_fort_name; my $last_fort_line; # Display usage sub do_help { print "Usage: 'warnhist [-h, --help] [-t ] [-w ] [-W] [-f ] [-F] [-s ] [-S ] [file]'\n"; print "\t-h, --help\tDisplay this usage\n"; print "\t-t \tTrim pathname prefix from filenames, \n"; print "\t-w \tDisplay files for a given warning index list, \n"; print "\t\t can be a single value, a range, or a comma separated list\n"; print "\t\tFor example: '0' or '0,4' or '8-10' or '0,2-4,8-10,13'\n"; print "\t-W\tDisplay files for all warnings\n"; print "\t-f \tDisplay warnings for a given file index list, \n"; print "\t\t can be a single value, a range, or a comma separated list\n"; print "\t\tFor example: '0' or '0,4' or '8-10' or '0,2-4,8-10,13'\n"; print "\t-F\tDisplay warnings for all files\n"; print "\t-s \tDisplay files for warnings which contain a string, \n"; print "\t\t is a comma separated list, with no spaces\n"; print "\t\tFor example: 'Wunused-dummy-argument' or 'Wunused-dummy-argument,Wunused-variable'\n"; print "\t-S \tDisplay warnings for files which contain a string, \n"; print "\t\t is a comma separated list, with no spaces\n"; print "\t\tFor example: 'H5Fint' or 'H5Fint,H5Gnode'\n"; print "\t-l\tDisplay line nunbers for file/warning\n"; print "\t-i \tIgnore named files, \n"; print "\t\t is a comma separated list, with no spaces\n"; print "\t\tFor example: 'H5LTparse' or 'H5LTparse,H5LTanalyze'\n"; print "\tfile\tFilename containing build output\n"; print "\t\tIf no file is given, standard input is used.\n"; exit; } sub main::HELP_MESSAGE { do_help(); } # declare the Perl command line flags/options we want to allow my %options=(); getopts("FWht:w:f:s:S:i:l", \%options); # Display usage, if requested if($options{h}) { do_help(); } # Parse list of file names to ignore if(exists $options{i}) { @ignorenames = split /,/, $options{i}; #print @ignorenames; } # Parse list of warning indices to expand file names if(exists $options{w}) { my @tmp_indices; @tmp_indices = split /,/, $options{w}; #print @tmp_indices; for my $x (@tmp_indices) { #print "x = '$x'\n"; if($x =~ /\-/) { my $start_index; my $end_index; #print "matched = '$x'\n"; ($start_index, $end_index) = split /\-/, $x; #print "start_index = '$start_index', end_index = '$end_index'\n"; for my $y ($start_index..$end_index) { #print "y = '$y'\n"; if(!exists $warn_file_indices{$y}) { $warn_file_indices{$y} = $y; } } } else { if(!exists $warn_file_indices{$x}) { $warn_file_indices{$x} = $x; } } } #foreach (sort keys %warn_file_indices) { # print "$_ : $warn_file_indices{$_}\n"; #} } # Parse list of warning strings to expand file names if(exists $options{s}) { @warn_match_strings = split /,/, $options{s}; # print @warn_match_strings; } # Parse list of file indices to expand warnings if(exists $options{f}) { my @tmp_indices; @tmp_indices = split /,/, $options{f}; #print @tmp_indices; for my $x (@tmp_indices) { #print "x = '$x'\n"; if($x =~ /\-/) { my $start_index; my $end_index; #print "matched = '$x'\n"; ($start_index, $end_index) = split /\-/, $x; #print "start_index = '$start_index', end_index = '$end_index'\n"; for my $y ($start_index..$end_index) { #print "y = '$y'\n"; if(!exists $file_warn_indices{$y}) { $file_warn_indices{$y} = $y; } } } else { if(!exists $file_warn_indices{$x}) { $file_warn_indices{$x} = $x; } } } #foreach (sort keys %warn_file_indices) { # print "$_ : $warn_file_indices{$_}\n"; #} } # Parse list of warning strings for files to expand warnings if(exists $options{S}) { @file_match_strings = split /,/, $options{S}; # print @file_match_strings; } PARSE_LINES: while (<>) { my $name; my $line; my $prev_line; my $toss; my $offset; my $warning; my $extra; my $extra2; # Retain last FORTRAN compile line, which comes a few lines before warning if($_ =~ /.*\.[fF]90:.*/) { ($last_fort_name, $last_fort_line, $toss) = split /\:/, $_; ($last_fort_line, $toss) = split /\./, $last_fort_line; } # Retain last C/C++ compile line, which possibly comes a few lines before warning if($_ =~ /.*[A-Za-z0-9_]\.[cC]:.*/) { ($last_c_name, $toss) = split /\:/, $_; } # Skip lines that don't have the word "warning" next if $_ !~ /[Ww]arning:/; # Skip warnings from linker next if $_ =~ /ld: warning:/; # Skip warnings from build_py and install_lib next if $_ =~ /warning: (build_py|install_lib)/; # "Hide" the C++ '::' symbol until we've parsed out the parts of the line while($_ =~ /\:\:/) { $_ =~ s/\:\:/@@@@/g; } # Check for weird formatting of warning message if($_ =~ /^cc1: warning:.*/) { $name = $last_c_name; $line = "??"; ($toss, $toss, $warning, $extra, $extra2) = split /\:/, $_; # Check for CMAKE build with warning on first line and no filename } elsif($_ =~ /^\s*[Ww]arning:.*/) { $name = $last_c_name; $line = "??"; ($toss, $warning, $extra, $extra2) = split /\:/, $_; # Check for FORTRAN warning output } elsif($_ =~ /^Warning:.*/) { $name = $last_fort_name; $line = $last_fort_line; ($toss, $warning, $extra, $extra2) = split /\:/, $_; #print "1:",$.,":",$_; # $_ = <>; #print "2:",$.,":",$_; # if($_ =~ /^\sFC.*/) { # $_ = <>; #print "3:",$.,":",$_; # } # ($name, $line, $toss) = split /\:/, $_; #print "4:","'",$name,"'","-","'",$line,"'","\n"; # Check for improperly parsed filename or line if($name =~ /^$/) { print "Filename is a null string! Input line #$. is: '$_'"; next } if($line =~ /^$/) { print "Line is a null string! Input line #$. is: '$_'"; next } } else { # Check for 'character offset' field appended to file & line # if($_ =~ /^.*[0-9]+\:[0-9]+\:/) { ($name, $line, $offset, $toss, $warning, $extra, $extra2) = split /\:/, $_; } else { ($name, $line, $toss, $warning, $extra, $extra2) = split /\:/, $_; } } # Check for extra ':' followed by more text in original warning string, # and append the ':' and text back onto the parsed warning # (Use 'length $extra' idiom to avoid warning when $extra is undefined) if(length $extra ) { $warning = join ':', $warning, $extra; } if(length $extra2 ) { $warning = join ':', $warning, $extra2; } # Restore the C++ '::' symbol now that we've parsed out the parts of the line while($warning =~ /@@@@/) { $warning =~ s/@@@@/\:\:/g; } # Trim leading '..' paths from filename while($name =~ /^\.\.\//) { $name =~ s/^\.\.\///g; } # Check for trimming prefix if((exists $options{t}) && ($name =~ /$options{t}/)) { $name =~ s/^$options{t}\///g; } # Check for ignored file if(exists $options{i}) { for my $x (@ignorenames) { #print "x = '$x'\n"; if($name =~ /$x/) { # print "matched name = '$name'\n"; $ignorecount++; if(!(exists $ignored_files{$name})) { $ignored_files{$name} = $name; } next PARSE_LINES; } } } # Check for improperly parsed warning (usually an undefined warning string) if(!defined $warning) { print "Warning Undefined! Input line is: '$_'"; next } # Get rid of leading & trailing whitespace $warning =~ s/^\s//g; $warning =~ s/\s$//g; # Check for improperly parsed warning if($warning =~ /^$/) { print "Warning is a null string! Input line is: '$_'"; next } # Convert all quotes to ' $warning =~ s/‘/'/g; $warning =~ s/’/'/g; # Skip supplemental warning message next if $warning =~ /near initialization for/; # Skip C++ supplemental warning message next if $warning =~ /in call to/; # Skip GCC warning that should be a note next if $_ =~ /\(this will be reported only once per input file\)/; # Eliminate "{aka }" and "{aka ''}" info if($warning =~ /\s(\{|\()aka '?[A-Za-z_0-9]+[A-Za-z_0-9\(\)\*\,\[\]\ ]*'?(\}|\))/) { $warning =~ s/\s(\{|\()aka '?[A-Za-z_0-9]+[A-Za-z_0-9\(\)\*\,\[\]\ ]*'?(\}|\))//g; } # print "warning = $warning\n"; # Genericize warnings if($warning =~ /variable '[A-Za-z_0-9]*' set but not used.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /unused variable '[A-Za-z_0-9]*'.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /unused function '[A-Za-z_0-9]*'.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /implicit conversion from '[A-Za-z_0-9]*' to '[A-Za-z_0-9]*' when passing argument to function.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /implicit conversion from '[A-Za-z_0-9]*' to '[A-Za-z_0-9]*' to match other operand of binary expression.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /conversion to '[A-Za-z_0-9\s]*' from '[A-Za-z_0-9\s]*' may alter its value.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /conversion to '[A-Za-z_0-9\s]*' from '[A-Za-z_0-9\s]*' may change the sign of the result.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /passing argument [0-9]* of '[A-Za-z_0-9\s]*' discards '[A-Za-z_0-9\s]*'.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /'[A-Za-z_0-9\s]*' defined but not used.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /cast discards '[A-Za-z_0-9\(\)\s]*'.*/) { $warning =~ s/'[A-Za-z_0-9\(\)\s]*'/'-'/g; } elsif($warning =~ /size of '[A-Za-z_0-9\(\)\s\*\.]*' is [0-9]* bytes.*/) { $warning =~ s/is [0-9]* bytes/is - bytes/g; $warning =~ s/'[A-Za-z_0-9\(\)\s\*\.]*'/'-'/g; } elsif($warning =~ /passing argument [0-9]* of '[A-Za-z_0-9\(\)\s]*' from incompatible.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9\(\)\s]*'/'-'/g; } elsif($warning =~ /stack usage is [0-9]* bytes.*/) { $warning =~ s/stack usage is [0-9]*/stack usage is -/g; } elsif($warning =~ /stack usage might be [0-9]* bytes.*/) { $warning =~ s/stack usage might be [0-9]*/stack usage might be -/g; } elsif($warning =~ /the frame size of [0-9]* bytes is larger than [0-9]* bytes.*/) { $warning =~ s/the frame size of [0-9]* bytes is larger than [0-9]*/the frame size of - bytes is larger than -/g; } elsif($warning =~ /enumeration value '[A-Za-z_0-9\s]*' not handled in switch.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /"[A-Za-z_0-9\s]*" is not defined.*/) { $warning =~ s/"[A-Za-z_0-9\s]*"/"-"/g; } elsif($warning =~ /macro "[A-Za-z_0-9\s]*" is not used.*/) { $warning =~ s/"[A-Za-z_0-9\s]*"/"-"/g; } elsif($warning =~ /unused parameter '[A-Za-z_0-9\s]*'.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /request for implicit conversion from '[A-Za-z_0-9\s\*]*' to '[A-Za-z_0-9\s\<\>\[\]\(\)\*]*' not permitted in C\+\+.*/) { $warning =~ s/'[A-Za-z_0-9\s\*\<\>\[\]\(\)]*'/'-'/g; } elsif($warning =~ /no previous prototype for '[A-Za-z_0-9\s]*'.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /declaration of '[A-Za-z_0-9\s]*' shadows a previous local.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /cast from function call of type '[A-Za-z_0-9\s\*]*' to non-matching type '[A-Za-z_0-9\s\*]*'.*/) { $warning =~ s/'[A-Za-z_0-9\s\*]*'/'-'/g; } elsif($warning =~ /'[A-Za-z_0-9\s]*' declared '[A-Za-z_0-9\s]*' but never defined.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /declaration of '[A-Za-z_0-9\s]*' shadows a global declaration.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /typedef '[A-Za-z_0-9\s]*' locally defined but not used.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /format '%[a-z]*' expects argument of type '[A-Za-z_0-9\s\*]*', but argument [0-9]* has type '[A-Za-z_0-9\s\*\(\),]*'.*/) { $warning =~ s/but argument [0-9]*/but argument -/g; $warning =~ s/'[%A-Za-z_0-9\s\*\(\),]*'/'-'/g; } elsif($warning =~ /conversion to '[A-Za-z_0-9\s]*' alters '[A-Za-z_0-9\s]*' constant value.*/) { $warning =~ s/'[A-Za-z_0-9\s]*'/'-'/g; } elsif($warning =~ /to be safe all intermediate pointers in cast from '[A-Za-z_0-9\s\*]*' to '[A-Za-z_0-9\s\*]*' must be 'const' qualified.*/) { $warning =~ s/'[A-Za-z_0-9\s\*]*'/'-'/g; } elsif($warning =~ /identifier '[A-Za-z_0-9]*' conflicts with C\+\+ keyword.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /nested extern declaration of '[A-Za-z_0-9]*'.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /Procedure '[A-Za-z_0-9]*' called with an implicit interface.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /Unused dummy argument '[A-Za-z_0-9]*'.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/\([0-9]+\)/\(-\)/g; } elsif($warning =~ /Unused parameter '[A-Za-z_0-9]*' declared at.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/\([0-9]+\)/\(-\)/g; } elsif($warning =~ /Unused variable '[A-Za-z_0-9]*' declared at.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /Inequality comparison for REAL\([0-9]*\) at.*/) { $warning =~ s/REAL\([0-9]*\)/REAL\(-\)/g; $warning =~ s/\([0-9]+\)/\(-\)/g; } elsif($warning =~ /Possible change of value in conversion from INTEGER\([0-9]*\) to (INTEGER|REAL)\([0-9]*\) at.*/) { $warning =~ s/INTEGER\([0-9]*\)/INTEGER\(-\)/g; $warning =~ s/REAL\([0-9]*\)/REAL\(-\)/g; } elsif($warning =~ /Equality comparison for REAL\([0-9]*\) at.*/) { $warning =~ s/REAL\([0-9]*\)/REAL\(-\)/g; $warning =~ s/\([0-9]+\)/\(-\)/g; } elsif($warning =~ /passing argument [0-9]* of '[A-Za-z_0-9]*' with different width due to prototype.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /passing argument [0-9]* of '[A-Za-z_0-9]*' as unsigned due to prototype.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /passing argument [0-9]* of '[A-Za-z_0-9]*' discards qualifiers from pointer target type.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /passing argument [0-9]* of '[A-Za-z_0-9]*' as floating rather than integer due to prototype.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /passing argument [0-9]* of '[A-Za-z_0-9]*' as 'float' rather than 'double' due to prototype.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9]*'/'-'/; } elsif($warning =~ /passing argument [0-9]* of '[A-Za-z_0-9]*' as signed due to prototype.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /format '\%[A-Za-z0-9]*' expects type '[a-z][a-z\s\*]*', but argument [0-9]* has type '[a-z][a-z\(\)_,\s\*]*'.*/) { $warning =~ s/but argument [0-9]*/but argument -/g; $warning =~ s/'\%[A-Za-z0-9]*'/'\%-'/g; $warning =~ s/'[a-z][a-z_,\s\*\(\)]*'/'-'/g; } elsif($warning =~ /implicit declaration of function '[A-Za-z_0-9]*'.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /'[A-Za-z_\.\[\]\(\)\*\&\+0-9]+[A-Za-z_\.\[\]\(\)\*\&\+0-9\ ]*' may be used uninitialized in this function.*/) { $warning =~ s/'[A-Za-z_\.\[\]\(\)\*\&\+0-9]+[A-Za-z_\.\[\]\(\)\*\&\+0-9\ ]*'/'-'/g; } elsif($warning =~ /redundant redeclaration of '[A-Za-z_0-9]*'.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /declaration of '[A-Za-z_0-9]*' shadows a parameter.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /ISO C90 does not support the '[a-z]*' gnu_scanf length modifier.*/) { $warning =~ s/'[a-z]*'/'-'/g; } elsif($warning =~ /ISO C90 does not support the '[a-z]*' gnu_printf length modifier.*/) { $warning =~ s/'[a-z]*'/'-'/g; } elsif($warning =~ /ISO C90 does not support the '%[a-z]*' gnu_printf format.*/) { $warning =~ s/'%[a-z]*'/'%-'/g; } elsif($warning =~ /string length '[0-9]*' is greater than the length.*/) { $warning =~ s/string length '[0-9]*' is/string length '-' is/g; } elsif($warning =~ /enum conversion when passing argument [0-9]* of '[A-Za-z_0-9]*' is invalid.*/) { $warning =~ s/passing argument [0-9]*/passing argument -/g; $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /enum conversion from '[A-Za-z_0-9]*' to '[A-Za-z_0-9]*' in assignment is invalid in C\+\+.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /duplicate declaration of '[A-Za-z_0-9]*' is invalid in.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /Variable '[A-Za-z_0-9]*' at \([0-9]*\) is a dummy argument of the BIND\(C\) procedure '[A-Za-z_0-9]*' but may not be C interoperable.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/at \([0-9]*\)/at \(-\)/g; } elsif($warning =~ /Variable '[A-Za-z_0-9]*' at \([0-9]*\) may not be a C interoperable kind but it is BIND\(C\).*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/at \([0-9]*\)/at \(-\)/g; } elsif($warning =~ /Component '[A-Za-z_0-9]*' in derived type '[A-Za-z_0-9]*' at \([0-9]*\) may not be C interoperable, even though derived type '[A-Za-z_0-9]*' is BIND\(C\).*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/at \([0-9]*\)/at \(-\)/g; } elsif($warning =~ /function might be candidate for attribute '[A-Za-z_0-9]*' if it is known to return normally.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/=[A-Za-z_0-9]*\]/=-\]/g; } elsif($warning =~ /function might be candidate for attribute '[A-Za-z_0-9]*'.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/=[A-Za-z_0-9]*\]/=-\]/g; } elsif($warning =~ /passing argument [0-9]+ of '[A-Za-z_0-9]*' makes integer from pointer without a cast.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /function '[A-Za-z_0-9]*' might be a candidate for '[A-Za-z_0-9]*' format attribute.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /inlining failed in call to '[A-Za-z_0-9]*': call is unlikely and code size would grow.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /'%[0-9]*[\.\*]*[0-9]*L*[dfsu]' directive writing ((between [0-9]+ and [0-9]+)|(up to [0-9]+)) bytes into a region of size ((between [0-9]+ and [0-9]+)|([0-9]+)).*/) { $warning =~ s/'%[0-9]*[\.\*]*[0-9]*L*[dfsu]'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /'((%[0-9]*[\.\*]*[0-9]*[dfsu])|([A-Za-z_0-9\/]+))' directive output may be truncated writing ((between [0-9]+ and [0-9]+)|(up to [0-9]+)|([0-9+)|(likely 1 or more)) byte(s)? into a region of size ((between [0-9]+ and [0-9]+)|([0-9]+)).*/) { $warning =~ s/'%[0-9]*[\.\*]*[0-9]*[dfsu]'/'-'/g; $warning =~ s/'[A-Za-z_0-9\/]+'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /'%[0-9]*[\.\*]*[0-9]*[dfsu]' directive argument is null.*/) { $warning =~ s/'%[0-9]*[\.\*]*[0-9]*[dfsu]'/'-'/g; } elsif($warning =~ /conversion to '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' from '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' may change the sign of the result.*/) { $warning =~ s/'[A-Za-z_0-9]+[A-Za-z_0-9\ ]*'/'-'/g; } elsif($warning =~ /unsigned conversion from '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' to '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' changes value from '-?[0-9]+' to '[0-9]+'.*/) { $warning =~ s/'[A-Za-z_0-9]+[A-Za-z_0-9\ ]*'/'-'/g; $warning =~ s/'-?[0-9]+'/'-'/g; } elsif($warning =~ /conversion from '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' to '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' may change value.*/) { $warning =~ s/'[A-Za-z_0-9]+[A-Za-z_0-9\ ]*'/'-'/g; } elsif($warning =~ /overflow in conversion from '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' to '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' changes value from '-?[0-9]+' to '-?[0-9]+'.*/) { $warning =~ s/'[A-Za-z_0-9]+[A-Za-z_0-9\ ]*'/'-'/g; $warning =~ s/'-?[0-9]+'/'-'/g; } elsif($warning =~ /cast between incompatible function types from '[A-Za-z_0-9]+[A-Za-z_0-9\(\)\*\,\ ]*' to '[A-Za-z_0-9]+[A-Za-z_0-9\(\)\*\,\ ]*'.*/) { $warning =~ s/'[A-Za-z_0-9]+[A-Za-z_0-9\(\)\*\,\ ]*'/'-'/g; } elsif($warning =~ /(return|initialization|assignment) discards '[A-Za-z_0-9]*' qualifier from pointer target type.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /'[A-Za-z_0-9]*' attribute on function returning '[A-Za-z_0-9]*'.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /ignoring return value of '[A-Za-z_0-9]*', declared with attribute warn_unused_result.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /passing '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' chooses '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*' over '[A-Za-z_0-9]+[A-Za-z_0-9\ ]*'.*/) { $warning =~ s/'[A-Za-z_0-9]+[A-Za-z_0-9\ ]*'/'-'/g; } elsif($warning =~ /'[A-Za-z_\:0-9]+[A-Za-z_\:0-9\ ]*' should be initialized in the member initialization list.*/) { $warning =~ s/'[A-Za-z_\:0-9]+[A-Za-z_\:0-9\ ]*'/'-'/g; } elsif($warning =~ /\[deprecation\] [A-Za-z_0-9]*\([A-Za-z_,0-9]*\) in [A-Za-z_0-9]* has been deprecated.*/) { $warning =~ s/[A-Za-z_0-9]*\([A-Za-z_,0-9]*\) in [A-Za-z_0-9]*/-\(-\) in -/g; } elsif($warning =~ /size of '[A-Za-z_\*0-9]*' [0-9]+ bytes exceeds maximum object size [0-9]+ .*/) { $warning =~ s/'[A-Za-z_\*0-9]*'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /'[A-Za-z_0-9]*' output truncated before terminating nul copying [0-9]+ bytes from a string of the same length.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /assignment to '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' from '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' makes pointer from integer without a cast.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /assignment to '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' from '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' makes integer from pointer without a cast.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /assignment to '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' from incompatible pointer type '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /ignoring attribute '[a-z]*' because it conflicts with attribute '[a-z]*'.*/) { $warning =~ s/'[a-z]*'/'-'/g; } elsif($warning =~ /passing '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' to parameter of type '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' discards qualifiers.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /assigning to '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' from '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' discards qualifiers.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /unknown warning group '[A-Za-z-=]*', ignored.*/) { $warning =~ s/'[A-Za-z-=]*'/'-'/g; } elsif($warning =~ /'[A-Za-z_0-9]*' macro redefined.*/) { $warning =~ s/'[A-Za-z_0-9]*'/'-'/g; } elsif($warning =~ /"[A-Za-z_0-9]*" redefined.*/) { $warning =~ s/"[A-Za-z_0-9]*"/"-"/g; } elsif($warning =~ /incompatible (pointer|integer) to (pointer|integer) conversion assigning to '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' from '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /returning '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' from a function with result type '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' discards qualifiers.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /array index [0-9]+ is past the end of the array \(which contains [0-9]+ elements\).*/) { $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /array subscript [0-9]+ is above array bounds of '[A-Za-z_\*\.0-9]+[A-Za-z_\*\.\[\]0-9\ ]*'.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*\.\[\]0-9\ ]*'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /expression which evaluates to zero treated as a null pointer constant of type '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /result of comparison of constant [0-9]+ with expression of type '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' is always (true|false).*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /initializing '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' with an expression of type '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' discards qualifiers.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; } elsif($warning =~ /implicit conversion from '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' to '[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*' changes value from -?[0-9]+ to -?[0-9]+.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*0-9\ ]*'/'-'/g; $warning =~ s/-?[0-9]+/-/g; } elsif($warning =~ /passing '[A-Za-z_\*0-9]+[A-Za-z_\*\[\]0-9\ ]*' to parameter of type '[A-Za-z_\*0-9]+[A-Za-z_\*\[\]0-9\ ]*' converts between pointers to integer types with different sign.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*\[\]0-9\ ]*'/'-'/g; } elsif($warning =~ /address of '[A-Za-z_\*\.0-9]+[A-Za-z_\*\.0-9\ ]*' will always evaluate to 'true'.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*\.0-9\ ]*'/'-'/g; } elsif($warning =~ /length modifier '[A-Za-z]' results in undefined behavior or no effect with '[A-Za-z]' conversion specifier.*/) { $warning =~ s/'[A-Za-z]'/'-'/g; } elsif($warning =~ /'[A-Za-z_]+' specified bound depends on the length of the source argument.*/) { $warning =~ s/'[A-Za-z_]+'/'-'/g; } elsif($warning =~ /'[A-Za-z_]+' specified bound [0-9]+ equals destination size.*/) { $warning =~ s/'[A-Za-z_]+'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /'[A-Za-z_]+' output may be truncated copying between [0-9]+ and [0-9]+ bytes from a string of length [0-9]+.*/) { $warning =~ s/'[A-Za-z_]+'/'-'/g; $warning =~ s/[0-9]+/-/g; } elsif($warning =~ /'[A-Za-z_]+' output may be truncated before the last format character.*/) { $warning =~ s/'[A-Za-z_]+'/'-'/g; } elsif($warning =~ /'[A-Za-z_]+' output truncated before terminating nul copying as many bytes from a string as its length.*/) { $warning =~ s/'[A-Za-z_]+'/'-'/g; } elsif($warning =~ /'[A-Za-z_\:0-9]+' hides overloaded virtual function.*/) { $warning =~ s/'[A-Za-z_\:0-9]+'/'-'/g; } elsif($warning =~ /'[A-Za-z_]+' storage class specifier is deprecated and incompatible with C\+\+1z.*/) { $warning =~ s/'[A-Za-z_]+'/'-'/g; } elsif($warning =~ /explicitly assigning value of variable of type '[A-Za-z_\*\.0-9]+[A-Za-z_\*\.0-9\ ]*' to itself.*/) { $warning =~ s/'[A-Za-z_\*0-9]+[A-Za-z_\*\.0-9\ ]*'/'-'/g; } elsif($warning =~ /private field '[A-Za-z_0-9]+' is not used.*/) { $warning =~ s/'[A-Za-z_0-9]+'/'-'/g; } elsif($warning =~ /field '[A-Za-z_0-9]+' will be initialized after field '[A-Za-z_0-9]+'.*/) { $warning =~ s/'[A-Za-z_0-9]+'/'-'/g; } # print "warning = $warning\n"; # Check if we've already seen this warning on this line in this file # (Can happen for warnings from inside header files) if( !exists $warn_file_line{$warning}{$name}{$line} ) { # Increment count for [generic] warning $warn_count{$warning}++; $warn_file{$warning}{$name}++; $warn_file_line{$warning}{$name}{$line}++; # Increment count for filename $file_count{$name}++; $file_warn{$name}{$warning}++; $file_warn_line{$name}{$warning}{$line}++; # Increment total count of warnings $totalcount++; } # print "name = $name\n"; # print "line = $line\n"; # print "offset = $offset\n"; # print "warning = \"$warning\"\n"; } print "Total unique [non-ignored] warnings: $totalcount\n"; print "Total ignored warnings: $ignorecount\n"; $warncount = keys %warn_count; print "Total unique kinds of warnings: $warncount\n"; $filecount = keys %file_count; print "Total files with warnings: $filecount\n\n"; # Print warnings in decreasing frequency print "# of Warnings by frequency (file count)\n"; print "=======================================\n"; for my $x (sort {$warn_count{$b} <=> $warn_count{$a}} keys(%warn_count)) { printf ("[%2d] %4d (%2d) - %s\n", $current_warning++, $warn_count{$x}, scalar(keys %{$warn_file_line{$x}}), $x); if((exists $options{W}) || (exists $options{w}) || (exists $options{s})) { my $curr_index = $current_warning - 1; my $match = 0; # Check for string from list in current warning if(exists $options{s}) { for my $y (@warn_match_strings) { # print "y = '$y'\n"; if($x =~ /$y/) { # print "matched warning = '$x'\n"; $match = 1; last; } } } # Check if current warning index matches if((exists $warn_file_indices{$curr_index}) && $curr_index == $warn_file_indices{$curr_index}) { $match = 1; } if($match) { for my $y (sort {$warn_file{$x}{$b} <=> $warn_file{$x}{$a}} keys(%{$warn_file{$x}})) { printf ("\t%4d - %s\n", $warn_file{$x}{$y}, $y); if(exists $options{l}) { my $lines = join ", ", sort {$a <=> $b} keys $warn_file_line{$x}{$y}; printf("\t\tLines: $lines \n"); } } } } } # Print warnings in decreasing frequency, by filename print "\n# of Warnings by filename (warning type)\n"; print "========================================\n"; for my $x (sort {$file_count{$b} <=> $file_count{$a}} keys(%file_count)) { printf ("[%3d] %4d (%2d) - %s\n", $current_file++, $file_count{$x}, scalar(keys %{$file_warn_line{$x}}), $x); if((exists $options{F}) || (exists $options{f})) { my $curr_index = $current_file - 1; my $match = 0; # Check for string from list in current file if(exists $options{S}) { for my $y (@file_match_strings) { # print "y = '$y'\n"; if($x =~ /$y/) { # print "matched warning = '$x'\n"; $match = 1; last; } } } # Check if current file index matches if((exists $file_warn_indices{$curr_index}) && $curr_index == $file_warn_indices{$curr_index}) { $match = 1; } if($match) { for my $y (sort {$file_warn{$x}{$b} <=> $file_warn{$x}{$a}} keys(%{$file_warn{$x}})) { printf ("\t%4d - %s\n", $file_warn{$x}{$y}, $y); if(exists $options{l}) { my $lines = join ", ", sort {$a <=> $b} keys $file_warn_line{$x}{$y}; printf("\t\tLines: $lines \n"); } } } } } # Print names of files that were ignored print "\nIgnored filenames\n"; print "=================\n"; for my $x (sort keys(%ignored_files)) { print "$x\n"; }