From 1f991f09df103fff1b3986148ecade6bd3c95aca Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Sat, 9 May 2009 19:19:28 +0000 Subject: [PATCH] Add total hack to get scan-build working again. ccc-analyzer calls 'clang -###' to get the appropriate arguments to pass to clang-cc. This isn't a permanent solution. llvm-svn: 71364 --- clang/utils/ccc-analyzer | 71 +++++++++++++++++++++++++++++++--------- clang/utils/scan-build | 37 ++++++++++++++++----- 2 files changed, 85 insertions(+), 23 deletions(-) diff --git a/clang/utils/ccc-analyzer b/clang/utils/ccc-analyzer index 28e4ad182b2c..8c0e119c30c3 100755 --- a/clang/utils/ccc-analyzer +++ b/clang/utils/ccc-analyzer @@ -48,7 +48,7 @@ my $ParserRejects = "Parser Rejects"; my $AttributeIgnored = "Attribute Ignored"; sub ProcessClangFailure { - my ($Clang, $Lang, $file, $Args, $HtmlDir, $ErrorType, $ofile) = @_; + my ($ClangCC, $Lang, $file, $Args, $HtmlDir, $ErrorType, $ofile) = @_; my $Dir = "$HtmlDir/failures"; mkpath $Dir; @@ -71,7 +71,7 @@ sub ProcessClangFailure { # Generate the preprocessed file with clang. my $PPFile_Clang = $PPFile; $PPFile_Clang =~ s/[.](.+)$/.clang.$1/; - system $Clang, @$Args, "-E", "-o", "$PPFile_Clang"; + system $ClangCC, @$Args, "-E", "-o", "$PPFile_Clang"; # Create the info file. open (OUT, ">", "$PPFile.info.txt") or die "Cannot open $PPFile.info.txt\n"; @@ -89,8 +89,49 @@ 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; + + pipe (FROM_CHILD, TO_PARENT); + my $pid = fork(); + if ($pid == 0) { + close FROM_CHILD; + open(STDOUT,">&", \*TO_PARENT); + open(STDERR,">&", \*TO_PARENT); + exec $Clang, "-###", "-fsyntax-only", @$Args; + } + close(TO_PARENT); + my $line; + while () { + next if (!/clang-cc/); + $line = $_; + } + + waitpid($pid,0); + close(FROM_CHILD); + + die "could not find clang-cc line\n" if (!defined $line); + my @items = ($line =~ /(".*?"|\S+)/g); + + for (my $i = 0; $i < scalar(@items); ++$i) { + my $x = $items[$i]; + $x =~ s/^"//; + $x =~ s/"$//; + $items[$i] = $x; + } + + my $cmd = shift @items; + die "cannot find 'clang-cc' in 'clang' command\n" if (!($cmd =~ /clang-cc/)); + return \@items; +} + sub Analyze { - my ($Clang, $Args, $Lang, $Output, $Verbose, $HtmlDir, $file, $Analyses) = @_; + my ($ClangCC, $Args, $Lang, $Output, $Verbose, $HtmlDir, $file, $Analyses) = @_; + $Args = GetCCArgs($Args); # Skip anything related to C++. return if ($Lang =~ /c[+][+]/); @@ -110,13 +151,12 @@ sub Analyze { @CmdArgsSansAnalyses = @CmdArgs; } else { - $Cmd = $Clang; + $Cmd = $ClangCC; push @CmdArgs,'-DIBOutlet=__attribute__((iboutlet))'; push @CmdArgs,@$Args; @CmdArgsSansAnalyses = @CmdArgs; push @CmdArgs,'-analyze'; push @CmdArgs,"-analyzer-display-progress"; - push @CmdArgs,"-disable-free"; push @CmdArgs,"-analyzer-eagerly-assume"; push @CmdArgs,(split /\s/,$Analyses); $RunAnalyzer = 1; @@ -156,7 +196,7 @@ sub Analyze { if (defined $ENV{'CCC_UBI'}) { push @CmdArgs,"--analyzer-viz-egraph-ubigraph"; } - + # Capture the STDERR of clang and send it to a temporary file. # Capture the STDOUT of clang and reroute it to ccc-analyzer's STDERR. # We save the output file in the 'crashes' directory if clang encounters @@ -179,16 +219,17 @@ sub Analyze { } waitpid($pid,0); + close(FROM_CHILD); my $Result = $?; # Did the command die because of a signal? - if ($Result & 127 and $Cmd eq $Clang and defined $HtmlDir) { - ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, + if ($Result & 127 and $Cmd eq $ClangCC and defined $HtmlDir) { + ProcessClangFailure($ClangCC, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, "Crash", $ofile); } elsif ($Result) { if ($IncludeParserRejects && !($file =~/conftest/)) { - ProcessClangFailure($Clang, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, + ProcessClangFailure($ClangCC, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, $ParserRejects, $ofile); } } @@ -220,7 +261,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($Clang, $Lang, $file, + $ppfile = ProcessClangFailure($ClangCC, $Lang, $file, \@CmdArgsSansAnalyses, $HtmlDir, $AttributeIgnored, $ofile); } @@ -339,9 +380,9 @@ my $Verbose = 0; if (defined $ENV{CCC_ANALYZER_VERBOSE}) { $Verbose = 1; } if (defined $ENV{CCC_ANALYZER_LOG}) { $Verbose = 2; } -# Determine what clang executable to use. -my $Clang = $ENV{'CLANG'}; -if (!defined $Clang) { $Clang = 'clang-cc'; } +# 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'}; @@ -546,12 +587,12 @@ if ($Action eq 'compile' or $Action eq 'link') { push @NewArgs, '-arch'; push @NewArgs, $arch; push @NewArgs, @AnalyzeArgs; - Analyze($Clang, \@NewArgs, $FileLang, $Output, + Analyze($ClangCC, \@NewArgs, $FileLang, $Output, $Verbose, $HtmlDir, $file, $Analyses); } } else { - Analyze($Clang, \@AnalyzeArgs, $FileLang, $Output, + Analyze($ClangCC, \@AnalyzeArgs, $FileLang, $Output, $Verbose, $HtmlDir, $file, $Analyses); } } diff --git a/clang/utils/scan-build b/clang/utils/scan-build index 27883f0d8645..74249f7031ed 100755 --- a/clang/utils/scan-build +++ b/clang/utils/scan-build @@ -82,26 +82,42 @@ sub DieDiag { ##----------------------------------------------------------------------------## # First, look for 'clang-cc' in libexec. -my $ClangSB = Cwd::realpath("$RealBin/libexec/clang-cc"); +my $ClangCCSB = Cwd::realpath("$RealBin/libexec/clang-cc"); # Second, look for 'clang-cc' in the same directory as scan-build. -if (!defined $ClangSB || ! -x $ClangSB) { - $ClangSB = Cwd::realpath("$RealBin/clang-cc"); +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' +my $ClangSB = Cwd::realpath("$RealBin/bin/clang"); if (!defined $ClangSB || ! -x $ClangSB) { - $ClangSB = Cwd::realpath("$RealBin/../libexec/clang-cc"); + $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-cc"; + $ClangSB = "clang"; } my $Clang = $ClangSB; + my %AvailableAnalyses; # Query clang for analysis options. -open(PIPE, "-|", $Clang, "--help") or - DieDiag("Cannot execute '$Clang'\n"); +open(PIPE, "-|", $ClangCC, "--help") or + DieDiag("Cannot execute '$ClangCC'\n"); my $FoundAnalysis = 0; @@ -1167,10 +1183,14 @@ if (!defined $Cmd || ! -x $Cmd) { DieDiag("Executable 'ccc-analyzer' does not exist at '$Cmd'\n") if(! -x $Cmd); } -if (!defined $ClangSB || ! -x $ClangSB) { +if (!defined $ClangCCSB || ! -x $ClangCCSB) { Diag("'clang-cc' executable not found in '$RealBin/libexec'.\n"); Diag("Using 'clang-cc' from path.\n"); } +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; @@ -1181,6 +1201,7 @@ else { } $ENV{'CC'} = $Cmd; +$ENV{'CLANG_CC'} = $ClangCC; $ENV{'CLANG'} = $Clang; if ($Verbose >= 2) {