diff options
Diffstat (limited to 'tools/scan-build')
-rwxr-xr-x | tools/scan-build/ccc-analyzer | 77 | ||||
-rwxr-xr-x | tools/scan-build/scan-build | 132 |
2 files changed, 102 insertions, 107 deletions
diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer index 25b9800..aca411f 100755 --- a/tools/scan-build/ccc-analyzer +++ b/tools/scan-build/ccc-analyzer @@ -14,14 +14,38 @@ use strict; use warnings; +use FindBin; use Cwd qw/ getcwd abs_path /; use File::Temp qw/ tempfile /; use File::Path qw / mkpath /; use File::Basename; use Text::ParseWords; -my $CC = $ENV{'CCC_CC'}; -if (!defined $CC) { $CC = "gcc"; } +##===----------------------------------------------------------------------===## +# Compiler command setup. +##===----------------------------------------------------------------------===## + +my $Compiler; +my $Clang; + +if ($FindBin::Script =~ /c\+\+-analyzer/) { + $Compiler = $ENV{'CCC_CXX'}; + if (!defined $Compiler) { $Compiler = "g++"; } + + $Clang = $ENV{'CLANG_CXX'}; + if (!defined $Clang) { $Clang = 'clang++'; } +} +else { + $Compiler = $ENV{'CCC_CC'}; + if (!defined $Compiler) { $Compiler = "gcc"; } + + $Clang = $ENV{'CLANG'}; + if (!defined $Clang) { $Clang = 'clang'; } +} + +##===----------------------------------------------------------------------===## +# Cleanup. +##===----------------------------------------------------------------------===## my $ReportFailures = $ENV{'CCC_REPORT_FAILURES'}; if (!defined $ReportFailures) { $ReportFailures = 1; } @@ -53,7 +77,7 @@ my $ParserRejects = "Parser Rejects"; my $AttributeIgnored = "Attribute Ignored"; sub ProcessClangFailure { - my ($ClangCC, $Lang, $file, $Args, $HtmlDir, $ErrorType, $ofile) = @_; + my ($Clang, $Lang, $file, $Args, $HtmlDir, $ErrorType, $ofile) = @_; my $Dir = "$HtmlDir/failures"; mkpath $Dir; @@ -69,7 +93,7 @@ sub ProcessClangFailure { my ($PPH, $PPFile) = tempfile( $prefix . "_XXXXXX", SUFFIX => GetPPExt($Lang), DIR => $Dir); - system $ClangCC, @$Args, "-E", "-o", $PPFile; + system $Clang, @$Args, "-E", "-o", $PPFile; close ($PPH); # Create the info file. @@ -79,7 +103,7 @@ sub ProcessClangFailure { print OUT "@$Args\n"; close OUT; `uname -a >> $PPFile.info.txt 2>&1`; - `$CC -v >> $PPFile.info.txt 2>&1`; + `$Compiler -v >> $PPFile.info.txt 2>&1`; system 'mv',$ofile,"$PPFile.stderr.txt"; return (basename $PPFile); } @@ -88,10 +112,6 @@ sub ProcessClangFailure { # Running the analyzer. ##----------------------------------------------------------------------------## -# Determine what clang executable to use. -my $Clang = $ENV{'CLANG'}; -if (!defined $Clang) { $Clang = 'clang'; } - sub GetCCArgs { my $Args = shift; @@ -106,14 +126,14 @@ sub GetCCArgs { close(TO_PARENT); my $line; while (<FROM_CHILD>) { - next if (!/clang-cc/); + next if (!/-cc1/); $line = $_; } waitpid($pid,0); close(FROM_CHILD); - die "could not find clang-cc line\n" if (!defined $line); + die "could not find clang line\n" if (!defined $line); # Strip the newline and initial whitspace chomp $line; $line =~ s/^\s+//; @@ -124,19 +144,16 @@ sub GetCCArgs { $items[$i] =~ s/\"$//; } my $cmd = shift @items; - die "cannot find 'clang-cc' in 'clang' command\n" if (!($cmd =~ /clang-cc/)); + die "cannot find 'clang' in 'clang' command\n" if (!($cmd =~ /clang/)); return \@items; } sub Analyze { - my ($ClangCC, $Args, $AnalyzeArgs, $Lang, $Output, $Verbose, $HtmlDir, + my ($Clang, $Args, $AnalyzeArgs, $Lang, $Output, $Verbose, $HtmlDir, $file, $Analyses) = @_; $Args = GetCCArgs($Args); - # Skip anything related to C++. - return if ($Lang =~ /c[+][+]/); - my $RunAnalyzer = 0; my $Cmd; my @CmdArgs; @@ -152,13 +169,15 @@ sub Analyze { @CmdArgsSansAnalyses = @CmdArgs; } else { - $Cmd = $ClangCC; + $Cmd = $Clang; + push @CmdArgs, "-cc1"; push @CmdArgs,'-DIBOutlet=__attribute__((iboutlet))'; - push @CmdArgs,@$Args; + push @CmdArgs, @$Args; @CmdArgsSansAnalyses = @CmdArgs; push @CmdArgs,'-analyze'; push @CmdArgs,"-analyzer-display-progress"; push @CmdArgs,"-analyzer-eagerly-assume"; + push @CmdArgs,"-analyzer-opt-analyze-nested-blocks"; push @CmdArgs,(split /\s/,$Analyses); if (defined $ENV{"CCC_EXPERIMENTAL_CHECKS"}) { @@ -236,13 +255,13 @@ sub Analyze { # Did the command die because of a signal? if ($ReportFailures) { - if ($Result & 127 and $Cmd eq $ClangCC and defined $HtmlDir) { - ProcessClangFailure($ClangCC, $Lang, $file, \@CmdArgsSansAnalyses, + if ($Result & 127 and $Cmd eq $Clang and defined $HtmlDir) { + ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, "Crash", $ofile); } elsif ($Result) { if ($IncludeParserRejects && !($file =~/conftest/)) { - ProcessClangFailure($ClangCC, $Lang, $file, \@CmdArgsSansAnalyses, + ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, $ParserRejects, $ofile); } } @@ -274,7 +293,7 @@ sub Analyze { # Add this file to the list of files that contained this attribute. # Generate a preprocessed file if we haven't already. if (!(defined $ppfile)) { - $ppfile = ProcessClangFailure($ClangCC, $Lang, $file, + $ppfile = ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, $AttributeIgnored, $ofile); } @@ -359,7 +378,9 @@ my %UniqueOptions = ( my %LangsAccepted = ( "objective-c" => 1, - "c" => 1 + "c" => 1, + "c++" => 1, + "objective-c++" => 1 ); ##----------------------------------------------------------------------------## @@ -375,7 +396,7 @@ my $Output; my %Uniqued; # Forward arguments to gcc. -my $Status = system($CC,@ARGV); +my $Status = system($Compiler,@ARGV); if ($Status) { exit($Status >> 8); } # Get the analysis options. @@ -399,10 +420,6 @@ my $Verbose = 0; if (defined $ENV{CCC_ANALYZER_VERBOSE}) { $Verbose = 1; } if (defined $ENV{CCC_ANALYZER_LOG}) { $Verbose = 2; } -# Determine what clang-cc executable to use. -my $ClangCC = $ENV{'CLANG_CC'}; -if (!defined $ClangCC) { $ClangCC = 'clang-cc'; } - # Get the HTML output directory. my $HtmlDir = $ENV{'CCC_ANALYZER_HTML'}; @@ -617,12 +634,12 @@ if ($Action eq 'compile' or $Action eq 'link') { push @NewArgs, '-arch'; push @NewArgs, $arch; push @NewArgs, @CmdArgs; - Analyze($ClangCC, \@NewArgs, \@AnalyzeArgs, $FileLang, $Output, + Analyze($Clang, \@NewArgs, \@AnalyzeArgs, $FileLang, $Output, $Verbose, $HtmlDir, $file, $Analyses); } } else { - Analyze($ClangCC, \@CmdArgs, \@AnalyzeArgs, $FileLang, $Output, + Analyze($Clang, \@CmdArgs, \@AnalyzeArgs, $FileLang, $Output, $Verbose, $HtmlDir, $file, $Analyses); } } diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build index 8d99f07..f978a88 100755 --- a/tools/scan-build/scan-build +++ b/tools/scan-build/scan-build @@ -26,7 +26,6 @@ my $Verbose = 0; # Verbose output from this script. my $Prog = "scan-build"; my $BuildName; my $BuildDate; -my $CXX; # Leave undefined initially. my $TERM = $ENV{'TERM'}; my $UseColor = (defined $TERM and $TERM eq 'xterm-color' and -t STDOUT @@ -81,43 +80,26 @@ sub DieDiag { # Some initial preprocessing of Clang options. ##----------------------------------------------------------------------------## -# First, look for 'clang-cc' in libexec. -my $ClangCCSB = Cwd::realpath("$RealBin/libexec/clang-cc"); -# Second, look for 'clang-cc' in the same directory as scan-build. -if (!defined $ClangCCSB || ! -x $ClangCCSB) { - $ClangCCSB = Cwd::realpath("$RealBin/clang-cc"); -} -# Third, look for 'clang-cc' in ../libexec -if (!defined $ClangCCSB || ! -x $ClangCCSB) { - $ClangCCSB = Cwd::realpath("$RealBin/../libexec/clang-cc"); -} -# Finally, default to looking for 'clang-cc' in the path. -if (!defined $ClangCCSB || ! -x $ClangCCSB) { - $ClangCCSB = "clang-cc"; -} -my $ClangCC = $ClangCCSB; - -# Now find 'clang' +# Find 'clang' my $ClangSB = Cwd::realpath("$RealBin/bin/clang"); +my $ClangCXXSB; if (!defined $ClangSB || ! -x $ClangSB) { $ClangSB = Cwd::realpath("$RealBin/clang"); -} -# Third, look for 'clang' in ../bin -if (!defined $ClangSB || ! -x $ClangSB) { - $ClangSB = Cwd::realpath("$RealBin/../bin/clang"); -} -# Finally, default to looking for 'clang-cc' in the path. -if (!defined $ClangSB || ! -x $ClangSB) { - $ClangSB = "clang"; + if (defined $ClangSB) { $ClangCXXSB = $ClangSB . "++"; } } my $Clang = $ClangSB; - +my $ClangCXX = $ClangCXXSB; +# Default to looking for 'clang' in the path. +if (!defined $Clang || ! -x $Clang) { + $Clang = "clang"; + $ClangCXX = "clang++"; +} my %AvailableAnalyses; # Query clang for analysis options. -open(PIPE, "-|", $ClangCC, "--help") or - DieDiag("Cannot execute '$ClangCC'\n"); +open(PIPE, "-|", $Clang, "-cc1", "--help") or + DieDiag("Cannot execute '$Clang'\n"); my $FoundAnalysis = 0; @@ -128,17 +110,14 @@ while(<PIPE>) { } next; } - if (/^\s\s\s\s([^\s]+)\s(.+)$/) { next if ($1 =~ /-dump/ or $1 =~ /-view/ - or $1 =~ /-warn-uninit/); - + or $1 =~ /-warn-uninit/); $AvailableAnalyses{$1} = $2; next; } last; } - close (PIPE); my %AnalysesDefaultEnabled = ( @@ -156,10 +135,8 @@ my %AnalysesDefaultEnabled = ( ##----------------------------------------------------------------------------## sub GetHTMLRunDir { - die "Not enough arguments." if (@_ == 0); - my $Dir = shift @_; - + my $Dir = shift @_; my $TmpMode = 0; if (!defined $Dir) { if (`uname` =~ /Darwin/) { @@ -168,8 +145,7 @@ sub GetHTMLRunDir { } else { $Dir = "/tmp"; - } - + } $TmpMode = 1; } @@ -177,42 +153,32 @@ sub GetHTMLRunDir { while ($Dir =~ /\/$/) { chop $Dir; } # Get current date and time. - - my @CurrentTime = localtime(); - + my @CurrentTime = localtime(); my $year = $CurrentTime[5] + 1900; my $day = $CurrentTime[3]; my $month = $CurrentTime[4] + 1; - my $DateString = sprintf("%d-%02d-%02d", $year, $month, $day); - # Determine the run number. - + # Determine the run number. my $RunNumber; - if (-d $Dir) { - + if (-d $Dir) { if (! -r $Dir) { DieDiag("directory '$Dir' exists but is not readable.\n"); - } - - # Iterate over all files in the specified directory. - - my $max = 0; - + } + # Iterate over all files in the specified directory. + my $max = 0; opendir(DIR, $Dir); my @FILES = grep { -d "$Dir/$_" } readdir(DIR); closedir(DIR); - - foreach my $f (@FILES) { + foreach my $f (@FILES) { # Strip the prefix '$Prog-' if we are dumping files to /tmp. if ($TmpMode) { next if (!($f =~ /^$Prog-(.+)/)); $f = $1; } - my @x = split/-/, $f; next if (scalar(@x) != 4); next if ($x[0] != $year); @@ -836,14 +802,26 @@ sub RunBuildCommand { $Cmd =~ /(.*\/?ccc-analyzer[^\/]*$)/) { if (!($Cmd =~ /ccc-analyzer/) and !defined $ENV{"CCC_CC"}) { - $ENV{"CCC_CC"} = $1; + $ENV{"CCC_CC"} = $1; } shift @$Args; unshift @$Args, $CCAnalyzer; } + elsif ($Cmd =~ /(.*\/?g\+\+[^\/]*$)/ or + $Cmd =~ /(.*\/?c\+\+[^\/]*$)/ or + $Cmd =~ /(.*\/?llvm-g\+\+[^\/]*$)/ or + $Cmd =~ /(.*\/?c\+\+-analyzer[^\/]*$)/) { + if (!($Cmd =~ /c\+\+-analyzer/) and !defined $ENV{"CCC_CXX"}) { + $ENV{"CCC_CXX"} = $1; + } + shift @$Args; + unshift @$Args, $CCAnalyzer; + } elsif ($IgnoreErrors) { if ($Cmd eq "make" or $Cmd eq "gmake") { + AddIfNotPresent($Args, "CC=$CCAnalyzer"); + AddIfNotPresent($Args, "CXX=$CCAnalyzer"); AddIfNotPresent($Args,"-k"); AddIfNotPresent($Args,"-i"); } @@ -860,6 +838,7 @@ sub RunBuildCommand { if ($Args->[$i] eq "-sdk" && $i + 1 < scalar(@$Args)) { if (@$Args[$i+1] =~ /^iphonesimulator3/) { $ENV{"CCC_CC"} = "gcc-4.2"; + $ENV{"CCC_CXX"} = "g++-4.2"; } } } @@ -874,10 +853,10 @@ sub RunBuildCommand { # When 'CC' is set, xcodebuild uses it to do all linking, even if we are # linking C++ object files. Set 'LDPLUSPLUS' so that xcodebuild uses 'g++' # when linking such files. - die if (!defined $CXX); - my $LDPLUSPLUS = `which $CXX`; - $LDPLUSPLUS =~ s/\015?\012//; # strip newlines - $ENV{'LDPLUSPLUS'} = $LDPLUSPLUS; + if (!defined $ENV{'CCC_CXX'}) { + $ENV{'CCC_CXX'} = 'g++'; + } + $ENV{'LDPLUSPLUS'} = $ENV{'CCC_CXX'}; } return (system(@$Args) >> 8); @@ -1125,16 +1104,19 @@ while (@ARGV) { if ($arg =~ /^--use-c\+\+(=(.+))?$/) { shift @ARGV; + my $cxx; if (!defined $2 || $2 eq "") { if (!@ARGV) { DieDiag("'--use-c++' option requires a compiler executable name.\n"); } - $CXX = shift @ARGV; + $cxx = shift @ARGV; } else { - $CXX = $2; + $cxx = $2; } + + $ENV{"CCC_CXX"} = $cxx; next; } @@ -1206,32 +1188,28 @@ $HtmlDir = GetHTMLRunDir($HtmlDir); # Set the appropriate environment variables. SetHtmlEnv(\@ARGV, $HtmlDir); -my $Cmd = Cwd::realpath("$RealBin/libexec/ccc-analyzer"); +my $AbsRealBin = Cwd::realpath($RealBin); +my $Cmd = "$AbsRealBin/libexec/ccc-analyzer"; +my $CmdCXX = "$AbsRealBin/libexec/c++-analyzer"; + if (!defined $Cmd || ! -x $Cmd) { - $Cmd = Cwd::realpath("$RealBin/ccc-analyzer"); + $Cmd = "$AbsRealBin/ccc-analyzer"; DieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") if(! -x $Cmd); } - -if (!defined $ClangCCSB || ! -x $ClangCCSB) { - Diag("'clang-cc' executable not found in '$RealBin/libexec'.\n"); - Diag("Using 'clang-cc' from path.\n"); +if (!defined $CmdCXX || ! -x $CmdCXX) { + $CmdCXX = "$AbsRealBin/c++-analyzer"; + DieDiag("Executable 'c++-analyzer' does not exist at '$CmdCXX'\n") if(! -x $CmdCXX); } + if (!defined $ClangSB || ! -x $ClangSB) { Diag("'clang' executable not found in '$RealBin/bin'.\n"); Diag("Using 'clang' from path.\n"); } -if (defined $CXX) { - $ENV{'CXX'} = $CXX; -} -else { - $CXX = 'g++'; # This variable is used by other parts of scan-build - # that need to know a default C++ compiler to fall back to. -} - $ENV{'CC'} = $Cmd; -$ENV{'CLANG_CC'} = $ClangCC; +$ENV{'CXX'} = $CmdCXX; $ENV{'CLANG'} = $Clang; +$ENV{'CLANG_CXX'} = $ClangCXX; if ($Verbose >= 2) { $ENV{'CCC_ANALYZER_VERBOSE'} = 1; |