diff options
author | Tom Care <tom.care@uqconnect.edu.au> | 2010-09-30 01:12:05 +0000 |
---|---|---|
committer | Tom Care <tom.care@uqconnect.edu.au> | 2010-09-30 01:12:05 +0000 |
commit | 4f2b10b24bab0049020d268382eda144e2aa064c (patch) | |
tree | 3974aec6500e9d5e8d357e3f55d925aa15e4d686 | |
parent | a54e824d2322dfd785c2716d0472a8aace2f61b8 (diff) |
Updated scan-build:
- Idempotent operations are on by default, to match --analyze in the driver.
- Integrated stats calculation based on parsing warnings emitted with the -analyzer-stats flag. The new -stats flag enables this.
- New -maxloop flag to pass down a maxloop value to the analyzer.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@115123 91177308-0d34-0410-b5e6-96231b3b80d8
-rwxr-xr-x | tools/scan-build/scan-build | 146 |
1 files changed, 134 insertions, 12 deletions
diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build index 8a7afbb3ea..425b58e769 100755 --- a/tools/scan-build/scan-build +++ b/tools/scan-build/scan-build @@ -120,7 +120,8 @@ my %AnalysesDefaultEnabled = ( # Do not enable the missing -dealloc check by default. # '-analyzer-check-objc-missing-dealloc' => 1, '-analyzer-check-objc-unused-ivars' => 1, - '-analyzer-check-security-syntactic' => 1 + '-analyzer-check-security-syntactic' => 1, + '-analyzer-check-idempotent-operations' => 1 ); ##----------------------------------------------------------------------------## @@ -304,6 +305,38 @@ sub UpdateInFilePath { } ##----------------------------------------------------------------------------## +# AddStatLine - Decode and insert a statistics line into the database. +##----------------------------------------------------------------------------## + +sub AddStatLine { + my $Line = shift; + my $Stats = shift; + + print $Line . "\n"; + + my $Regex = qr/(.*?)\ :\ (.*?)\ ->\ Total\ CFGBlocks:\ (\d+)\ \|\ Unreachable + \ CFGBlocks:\ (\d+)\ \|\ Aborted\ Block:\ (yes|no)\ \|\ Empty\ WorkList: + \ (yes|no)/x; + + if ($Line !~ $Regex) { + return; + } + + # Create a hash of the interesting fields + my $Row = { + Filename => $1, + Function => $2, + Total => $3, + Unreachable => $4, + Aborted => $5, + Empty => $6 + }; + + # Add them to the stats array + push @$Stats, $Row; +} + +##----------------------------------------------------------------------------## # ScanFile - Scan a report file for various identifying attributes. ##----------------------------------------------------------------------------## @@ -317,6 +350,7 @@ sub ScanFile { my $Index = shift; my $Dir = shift; my $FName = shift; + my $Stats = shift; # Compute a digest for the report file. Determine if we have already # scanned a file that looks just like it. @@ -337,11 +371,12 @@ sub ScanFile { # Scan the report file for tags. open(IN, "$Dir/$FName") or DieDiag("Cannot open '$Dir/$FName'\n"); - my $BugType = ""; - my $BugFile = ""; - my $BugCategory; - my $BugPathLength = 1; - my $BugLine = 0; + my $BugType = ""; + my $BugFile = ""; + my $BugCategory = ""; + my $BugDescription = ""; + my $BugPathLength = 1; + my $BugLine = 0; while (<IN>) { last if (/<!-- BUGMETAEND -->/); @@ -362,6 +397,9 @@ sub ScanFile { elsif (/<!-- BUGCATEGORY (.*) -->$/) { $BugCategory = $1; } + elsif (/<!-- BUGDESC (.*) -->$/) { + $BugDescription = $1; + } } close(IN); @@ -369,7 +407,13 @@ sub ScanFile { if (!defined $BugCategory) { $BugCategory = "Other"; } - + + # Don't add internal statistics to the bug reports + if ($BugCategory =~ /statistics/i) { + AddStatLine($BugDescription, $Stats); + return; + } + push @$Index,[ $FName, $BugCategory, $BugType, $BugFile, $BugLine, $BugPathLength ]; } @@ -404,13 +448,61 @@ sub CopyFiles { } ##----------------------------------------------------------------------------## +# CalcStats - Calculates visitation statistics and returns the string. +##----------------------------------------------------------------------------## + +sub CalcStats { + my $Stats = shift; + + my $TotalBlocks = 0; + my $UnreachedBlocks = 0; + my $TotalFunctions = scalar(@$Stats); + my $BlockAborted = 0; + my $WorkListAborted = 0; + my $Aborted = 0; + + # Calculate the unique files + my $FilesHash = {}; + + foreach my $Row (@$Stats) { + $FilesHash->{$Row->{Filename}} = 1; + $TotalBlocks += $Row->{Total}; + $UnreachedBlocks += $Row->{Unreachable}; + $BlockAborted++ if $Row->{Aborted} eq 'yes'; + $WorkListAborted++ if $Row->{Empty} eq 'no'; + $Aborted++ if $Row->{Aborted} eq 'yes' || $Row->{Empty} eq 'no'; + } + + my $TotalFiles = scalar(keys(%$FilesHash)); + + # Calculations + my $PercentAborted = sprintf("%.2f", $Aborted / $TotalFunctions * 100); + my $PercentBlockAborted = sprintf("%.2f", $BlockAborted / $TotalFunctions + * 100); + my $PercentWorkListAborted = sprintf("%.2f", $WorkListAborted / + $TotalFunctions * 100); + my $PercentBlocksUnreached = sprintf("%.2f", $UnreachedBlocks / $TotalBlocks + * 100); + + my $StatsString = "Analyzed $TotalBlocks blocks in $TotalFunctions functions" + . " in $TotalFiles files\n" + . "$Aborted functions aborted early ($PercentAborted%)\n" + . "$BlockAborted had aborted blocks ($PercentBlockAborted%)\n" + . "$WorkListAborted had unfinished worklists ($PercentWorkListAborted%)\n" + . "$UnreachedBlocks blocks were never reached ($PercentBlocksUnreached%)\n"; + + return $StatsString; +} + +##----------------------------------------------------------------------------## # Postprocess - Postprocess the results of an analysis scan. ##----------------------------------------------------------------------------## sub Postprocess { - my $Dir = shift; - my $BaseDir = shift; + my $Dir = shift; + my $BaseDir = shift; + my $AnalyzerStats = shift; die "No directory specified." if (!defined $Dir); @@ -430,8 +522,9 @@ sub Postprocess { } # Scan each report file and build an index. - my @Index; - foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); } + my @Index; + my @Stats; + foreach my $file (@files) { ScanFile(\@Index, $Dir, $file, \@Stats); } # Scan the failures directory and use the information in the .info files # to update the common prefix directory. @@ -745,6 +838,9 @@ ENDTEXT system("chmod", "755", $Dir); if (defined $BaseDir) { system("chmod", "755", $BaseDir); } + # Print statistics + print CalcStats(\@Stats) if $AnalyzerStats; + my $Num = scalar(@Index); Diag("$Num bugs found.\n"); if ($Num > 0 && -r "$Dir/index.html") { @@ -930,6 +1026,12 @@ ADVANCED OPTIONS: -no-failure-reports - Do not create a 'failures' subdirectory that includes analyzer crash reports and preprocessed source files. + -stats - Generates visitation statistics for the project being analyzed. + + -maxloop N - specifiy the number of times a block can be visited before giving + up. Default is 3. Increase for more comprehensive coverage at a + cost of speed. + AVAILABLE ANALYSES (multiple analyses may be specified): ENDTEXT @@ -1004,6 +1106,8 @@ my @AnalysesToRun; my $StoreModel; my $ConstraintsModel; my $OutputFormat = "html"; +my $AnalyzerStats = 0; +my $MaxLoop = 0; if (!@ARGV) { DisplayHelp(); @@ -1156,6 +1260,16 @@ while (@ARGV) { $ENV{"CCC_REPORT_FAILURES"} = 0; next; } + if ($arg eq "-stats") { + shift @ARGV; + $AnalyzerStats = 1; + next; + } + if ($arg eq "-maxloop") { + shift @ARGV; + $MaxLoop = shift @ARGV; + next; + } DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); @@ -1220,6 +1334,14 @@ if ($AnalyzeHeaders) { push @AnalysesToRun,"-analyzer-opt-analyze-headers"; } +if ($AnalyzerStats) { + push @AnalysesToRun, '-analyzer-stats'; +} + +if ($MaxLoop > 0) { + push @AnalysesToRun, '-analyzer-max-loop ' . $MaxLoop; +} + $ENV{'CCC_ANALYZER_ANALYSIS'} = join ' ',@AnalysesToRun; if (defined $StoreModel) { @@ -1244,7 +1366,7 @@ if (defined $OutputFormat) { } elsif ($OutputFormat =~ /html/) { # Postprocess the HTML directory. - my $NumBugs = Postprocess($HtmlDir, $BaseDir); + my $NumBugs = Postprocess($HtmlDir, $BaseDir, $AnalyzerStats); if ($ViewResults and -r "$HtmlDir/index.html") { Diag "Analysis run complete.\n"; |