forked from OSchip/llvm-project
Have scan-build/ccc-analyzer generate preprocessed .i/.mi files for sources that clang crashes on.
llvm-svn: 54552
This commit is contained in:
parent
c893a67fe3
commit
994c8e393d
|
@ -15,6 +15,33 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use Cwd;
|
||||
use File::Temp qw/ tempfile /;
|
||||
use File::Path qw / mkpath /;
|
||||
|
||||
##----------------------------------------------------------------------------##
|
||||
# Process Clang Crashes.
|
||||
##----------------------------------------------------------------------------##
|
||||
|
||||
sub GetPPExt {
|
||||
my $Lang = shift;
|
||||
if ($Lang =~ /objective-c/) { return ".mi"; }
|
||||
return ".i";
|
||||
}
|
||||
|
||||
sub ProcessClangCrash {
|
||||
my ($Clang, $Lang, $file, $Args, $HtmlDir) = @_;
|
||||
my $Dir = "$HtmlDir/crashes";
|
||||
mkpath $Dir;
|
||||
my ($PPH, $PPFile) = tempfile("clang_crash_XXXXXX",
|
||||
SUFFIX => GetPPExt($Lang),
|
||||
DIR => $Dir);
|
||||
|
||||
system $Clang, @$Args, "-E", "-o", $PPFile;
|
||||
close ($PPH);
|
||||
open (OUT, ">", "$PPFile.info") or die "Cannot open $PPFile.info\n";
|
||||
print OUT "$file";
|
||||
close OUT;
|
||||
}
|
||||
|
||||
##----------------------------------------------------------------------------##
|
||||
# Running the analyzer.
|
||||
|
@ -29,6 +56,7 @@ sub Analyze {
|
|||
my $RunAnalyzer = 0;
|
||||
my $Cmd;
|
||||
my @CmdArgs;
|
||||
my @CmdArgsSansAnalyses;
|
||||
|
||||
if ($Lang =~ /header/) {
|
||||
exit 0 if (!defined ($Output));
|
||||
|
@ -37,12 +65,14 @@ sub Analyze {
|
|||
# Remove the PCH extension.
|
||||
$Output =~ s/[.]gch$//;
|
||||
push @CmdArgs,$Output;
|
||||
@CmdArgsSansAnalyses = @CmdArgs;
|
||||
}
|
||||
else {
|
||||
$Cmd = $Clang;
|
||||
push @CmdArgs,(split /\s/,$Analyses);
|
||||
push @CmdArgs,'-DIBOutlet=__attribute__((iboutlet))';
|
||||
push @CmdArgs,@$Args;
|
||||
@CmdArgsSansAnalyses = @CmdArgs;
|
||||
push @CmdArgs,(split /\s/,$Analyses);
|
||||
$RunAnalyzer = 1;
|
||||
}
|
||||
|
||||
|
@ -70,8 +100,13 @@ sub Analyze {
|
|||
push @CmdArgs,'-o';
|
||||
push @CmdArgs,$HtmlDir;
|
||||
}
|
||||
|
||||
system $Cmd,@CmdArgs;
|
||||
|
||||
system $Cmd,@CmdArgs;
|
||||
|
||||
# Did the command die because of a signal?
|
||||
if ($? & 127 and $Cmd eq $Clang and defined $HtmlDir) {
|
||||
ProcessClangCrash($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir);
|
||||
}
|
||||
}
|
||||
|
||||
##----------------------------------------------------------------------------##
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
use strict;
|
||||
use warnings;
|
||||
use File::Temp qw/ :mktemp /;
|
||||
use FindBin qw($RealBin);
|
||||
use Digest::MD5;
|
||||
use File::Basename;
|
||||
|
@ -43,6 +42,14 @@ sub Diag {
|
|||
}
|
||||
}
|
||||
|
||||
sub DiagCrashes {
|
||||
my $Dir = shift;
|
||||
Diag ("The analyzer crashed on some source files.\n");
|
||||
Diag ("Preprocessed versions of crashed files were depositied in '$Dir/crashes'.\n");
|
||||
Diag ("Please consider submitting a bug report using these files:\n");
|
||||
Diag (" http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs\n")
|
||||
}
|
||||
|
||||
sub DieDiag {
|
||||
if ($UseColor) {
|
||||
print BOLD, RED "$Prog: ";
|
||||
|
@ -79,7 +86,7 @@ while(<PIPE>) {
|
|||
if (/Available Source Code Analyses/) {
|
||||
$FoundAnalysis = 1;
|
||||
}
|
||||
|
||||
|
||||
next;
|
||||
}
|
||||
|
||||
|
@ -385,24 +392,21 @@ sub Postprocess {
|
|||
}
|
||||
|
||||
opendir(DIR, $Dir);
|
||||
my @files = grep(/^report-.*\.html$/,readdir(DIR));
|
||||
my $Crashes = 0;
|
||||
my @files = grep { if ($_ eq "crashes") { $Crashes++; }
|
||||
/^report-.*\.html$/; } readdir(DIR);
|
||||
closedir(DIR);
|
||||
|
||||
if (scalar(@files) == 0) {
|
||||
if (scalar(@files) == 0 and $Crashes == 0) {
|
||||
Diag("Removing directory '$Dir' because it contains no reports.\n");
|
||||
system ("rm", "-fR", $Dir);
|
||||
|
||||
# Remove the base directory if it contains no files (don't use '-R').
|
||||
if (defined $BaseDir) { system ("rm", "-f", $BaseDir); }
|
||||
|
||||
Diag("No bugs found.\n");
|
||||
system ("rm", "-f", $BaseDir) if (defined $BaseDir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
# Scan each report file and build an index.
|
||||
|
||||
my @Index;
|
||||
|
||||
# Scan each report file and build an index.
|
||||
my @Index;
|
||||
foreach my $file (@files) { ScanFile(\@Index, $Dir, $file); }
|
||||
|
||||
# Generate an index.html file.
|
||||
|
@ -418,7 +422,7 @@ print OUT <<ENDTEXT;
|
|||
body { color:#000000; background-color:#ffffff }
|
||||
body { font-family: Helvetica, sans-serif; font-size:9pt }
|
||||
h1 { font-size:12pt }
|
||||
table.sortable thead {
|
||||
table thead {
|
||||
background-color:#eee; color:#666666;
|
||||
font-weight: bold; cursor: default;
|
||||
text-align:center;
|
||||
|
@ -426,8 +430,8 @@ print OUT <<ENDTEXT;
|
|||
border-bottom: 2px solid #000000;
|
||||
font-weight: bold; font-family: Verdana
|
||||
}
|
||||
table.sortable { border: 1px #000000 solid }
|
||||
table.sortable { border-collapse: collapse; border-spacing: 0px }
|
||||
table { border: 1px #000000 solid }
|
||||
table { border-collapse: collapse; border-spacing: 0px }
|
||||
td { border-bottom: 1px #000000 dotted }
|
||||
td { padding:5px; padding-left:8px; padding-right:8px }
|
||||
td { text-align:left; font-size:9pt }
|
||||
|
@ -458,28 +462,23 @@ function ToggleDisplay(CheckButton, ClassName) {
|
|||
<body>
|
||||
ENDTEXT
|
||||
|
||||
# Print out the summary table.
|
||||
if (scalar(@files)) {
|
||||
# Print out the summary table.
|
||||
my %Totals;
|
||||
|
||||
my %Totals;
|
||||
|
||||
for my $row ( @Index ) {
|
||||
for my $row ( @Index ) {
|
||||
#my $bug_type = lc($row->[1]);
|
||||
my $bug_type = ($row->[1]);
|
||||
|
||||
#my $bug_type = lc($row->[1]);
|
||||
my $bug_type = ($row->[1]);
|
||||
|
||||
if (!defined $Totals{$bug_type}) {
|
||||
$Totals{$bug_type} = 1;
|
||||
if (!defined $Totals{$bug_type}) { $Totals{$bug_type} = 1; }
|
||||
else { $Totals{$bug_type}++; }
|
||||
}
|
||||
else {
|
||||
$Totals{$bug_type}++;
|
||||
|
||||
print OUT "<h3>Bug Summary</h3>";
|
||||
|
||||
if (defined $BuildName) {
|
||||
print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
|
||||
}
|
||||
}
|
||||
|
||||
print OUT "<h3>Summary</h3>";
|
||||
|
||||
if (defined $BuildName) {
|
||||
print OUT "\n<p>Results in this analysis run are based on analyzer build <b>$BuildName</b>.</p>\n"
|
||||
}
|
||||
|
||||
print OUT <<ENDTEXT;
|
||||
<table class="sortable">
|
||||
|
@ -490,11 +489,11 @@ print OUT <<ENDTEXT;
|
|||
</tr>
|
||||
ENDTEXT
|
||||
|
||||
for my $key ( sort { $a cmp $b } keys %Totals ) {
|
||||
my $x = lc($key);
|
||||
$x =~ s/[ ,'"]+/_/g;
|
||||
print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n";
|
||||
}
|
||||
for my $key ( sort { $a cmp $b } keys %Totals ) {
|
||||
my $x = lc($key);
|
||||
$x =~ s/[ ,'"]+/_/g;
|
||||
print OUT "<tr><td>$key</td><td>$Totals{$key}</td><td><input type=\"checkbox\" onClick=\"ToggleDisplay(this,'bt_$x');\" checked/></td></tr>\n";
|
||||
}
|
||||
|
||||
# Print out the table of errors.
|
||||
|
||||
|
@ -511,55 +510,93 @@ print OUT <<ENDTEXT;
|
|||
</tr>
|
||||
ENDTEXT
|
||||
|
||||
my $prefix = GetPrefix();
|
||||
my $regex;
|
||||
my $InFileRegex;
|
||||
my $InFilePrefix = "File:</td><td>";
|
||||
my $prefix = GetPrefix();
|
||||
my $regex;
|
||||
my $InFileRegex;
|
||||
my $InFilePrefix = "File:</td><td>";
|
||||
|
||||
if (defined $prefix) {
|
||||
$regex = qr/^\Q$prefix\E/is;
|
||||
$InFileRegex = qr/\Q$InFilePrefix$prefix\E/is;
|
||||
}
|
||||
if (defined $prefix) {
|
||||
$regex = qr/^\Q$prefix\E/is;
|
||||
$InFileRegex = qr/\Q$InFilePrefix$prefix\E/is;
|
||||
}
|
||||
|
||||
for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) {
|
||||
for my $row ( sort { $a->[1] cmp $b->[1] } @Index ) {
|
||||
|
||||
my $x = lc($row->[1]);
|
||||
$x =~ s/[ ,'"]+/_/g;
|
||||
my $x = lc($row->[1]);
|
||||
$x =~ s/[ ,'"]+/_/g;
|
||||
|
||||
print OUT "<tr class=\"bt_$x\">\n";
|
||||
print OUT "<tr class=\"bt_$x\">\n";
|
||||
|
||||
my $ReportFile = $row->[0];
|
||||
my $ReportFile = $row->[0];
|
||||
|
||||
print OUT " <td class=\"DESC\">";
|
||||
#print OUT lc($row->[1]);
|
||||
print OUT $row->[1];
|
||||
print OUT "</td>\n";
|
||||
print OUT " <td class=\"DESC\">";
|
||||
#print OUT lc($row->[1]);
|
||||
print OUT $row->[1];
|
||||
print OUT "</td>\n";
|
||||
|
||||
# Update the file prefix.
|
||||
# Update the file prefix.
|
||||
|
||||
my $fname = $row->[2];
|
||||
if (defined $regex) {
|
||||
$fname =~ s/$regex//;
|
||||
UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix)
|
||||
}
|
||||
my $fname = $row->[2];
|
||||
if (defined $regex) {
|
||||
$fname =~ s/$regex//;
|
||||
UpdateInFilePath("$Dir/$ReportFile", $InFileRegex, $InFilePrefix)
|
||||
}
|
||||
|
||||
print OUT "<td>$fname</td>\n";
|
||||
print OUT "<td>$fname</td>\n";
|
||||
|
||||
# Print the rest of the columns.
|
||||
for my $j ( 3 .. $#{$row} ) {
|
||||
print OUT "<td>$row->[$j]</td>\n"
|
||||
}
|
||||
# Print the rest of the columns.
|
||||
for my $j ( 3 .. $#{$row} ) {
|
||||
print OUT "<td>$row->[$j]</td>\n"
|
||||
}
|
||||
|
||||
# Emit the "View" link.
|
||||
print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n";
|
||||
# Emit the "View" link.
|
||||
print OUT " <td class=\"View\"><a href=\"$ReportFile#EndPath\">View</a></td>\n";
|
||||
|
||||
# End the row.
|
||||
print OUT "</tr>\n";
|
||||
# End the row.
|
||||
print OUT "</tr>\n";
|
||||
}
|
||||
|
||||
print OUT "</table>\n";
|
||||
}
|
||||
|
||||
if ($Crashes) {
|
||||
# Read the crash directory for files.
|
||||
opendir(DIR, "$Dir/crashes");
|
||||
my @files = grep { /[.]info$/ } readdir(DIR);
|
||||
closedir(DIR);
|
||||
|
||||
if (scalar(@files)) {
|
||||
print OUT <<ENDTEXT;
|
||||
<h3>Analyzer Crashes</h3>
|
||||
|
||||
<p>The analyzer crashed while processing the following files:</p>
|
||||
|
||||
<table>
|
||||
<thead><tr><td>Source File</td><td>Preprocessed File</td></tr></thead>
|
||||
ENDTEXT
|
||||
|
||||
foreach my $file (sort @files) {
|
||||
$file =~ /(.+).info$/;
|
||||
# Get the preprocessed file.
|
||||
my $ppfile = $1;
|
||||
# Open the info file and get the name of the source file.
|
||||
open (INFO, "$Dir/crashes/$file") or
|
||||
die "Cannot open $Dir/crashes/$file\n";
|
||||
my $srcfile = <INFO>;
|
||||
close (INFO);
|
||||
# Print the information in the table.
|
||||
print OUT "<tr><td>$srcfile</td><td class=\"View\"><a href=\"crashes/$ppfile\">View</a></td></tr>\n";
|
||||
}
|
||||
|
||||
print OUT <<ENDTEXT;
|
||||
</table>
|
||||
<p>Please consider submitting preprocessed files as <a href="http://clang.llvm.org/StaticAnalysisUsage.html#filingbugs">bug reports</a>.</p>
|
||||
ENDTEXT
|
||||
}
|
||||
}
|
||||
|
||||
print OUT "</table>\n</body></html>\n";
|
||||
print OUT "</body></html>\n";
|
||||
close(OUT);
|
||||
|
||||
CopyJS($Dir);
|
||||
|
||||
# Make sure $Dir and $BaseDir are world readable/executable.
|
||||
|
@ -572,6 +609,8 @@ ENDTEXT
|
|||
Diag("Open '$Dir/index.html' to examine bug reports.\n");
|
||||
}
|
||||
|
||||
DiagCrashes($Dir) if ($Crashes);
|
||||
|
||||
return $Num;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue