From: Ted Kremenek Date: Fri, 8 Aug 2008 20:46:42 +0000 (+0000) Subject: Have scan-build/ccc-analyzer generate preprocessed .i/.mi files for sources that... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=991c54b9b7409656e5593364e065878b5210d556;p=clang Have scan-build/ccc-analyzer generate preprocessed .i/.mi files for sources that clang crashes on. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@54552 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/utils/ccc-analyzer b/utils/ccc-analyzer index 1659c53a5a..fd24a8b2ad 100755 --- a/utils/ccc-analyzer +++ b/utils/ccc-analyzer @@ -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); + } } ##----------------------------------------------------------------------------## diff --git a/utils/scan-build b/utils/scan-build index f5f5f54bb0..9004b354f0 100755 --- a/utils/scan-build +++ b/utils/scan-build @@ -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() { 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 - # Print out the summary table. - - my %Totals; + if (scalar(@files)) { + # Print out the summary table. + 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 "

Bug Summary

"; + + if (defined $BuildName) { + print OUT "\n

Results in this analysis run are based on analyzer build $BuildName.

\n" } - } - - print OUT "

Summary

"; - - if (defined $BuildName) { - print OUT "\n

Results in this analysis run are based on analyzer build $BuildName.

\n" - } print OUT < @@ -490,11 +489,11 @@ print OUT < ENDTEXT - for my $key ( sort { $a cmp $b } keys %Totals ) { - my $x = lc($key); - $x =~ s/[ ,'"]+/_/g; - print OUT "$key$Totals{$key}\n"; - } + for my $key ( sort { $a cmp $b } keys %Totals ) { + my $x = lc($key); + $x =~ s/[ ,'"]+/_/g; + print OUT "$key$Totals{$key}\n"; + } # Print out the table of errors. @@ -511,55 +510,93 @@ print OUT < ENDTEXT - my $prefix = GetPrefix(); - my $regex; - my $InFileRegex; - my $InFilePrefix = "File:"; + my $prefix = GetPrefix(); + my $regex; + my $InFileRegex; + my $InFilePrefix = "File:"; - 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 "\n"; + print OUT "\n"; - my $ReportFile = $row->[0]; + my $ReportFile = $row->[0]; - print OUT " "; - #print OUT lc($row->[1]); - print OUT $row->[1]; - print OUT "\n"; + print OUT " "; + #print OUT lc($row->[1]); + print OUT $row->[1]; + print OUT "\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 "$fname\n"; + print OUT "$fname\n"; - # Print the rest of the columns. - for my $j ( 3 .. $#{$row} ) { - print OUT "$row->[$j]\n" - } + # Print the rest of the columns. + for my $j ( 3 .. $#{$row} ) { + print OUT "$row->[$j]\n" + } - # Emit the "View" link. - print OUT " View\n"; + # Emit the "View" link. + print OUT " View\n"; - # End the row. - print OUT "\n"; + # End the row. + print OUT "\n"; + } + + print OUT "\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 <Analyzer Crashes + +

The analyzer crashed while processing the following files:

+ + + +ENDTEXT - print OUT "
Source FilePreprocessed File
\n\n"; - close(OUT); + 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 = ; + close (INFO); + # Print the information in the table. + print OUT "$srcfileView\n"; + } + print OUT < +

Please consider submitting preprocessed files as bug reports.

+ENDTEXT + } + } + + print OUT "\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; }