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;
# 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";
# 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 (<FROM_CHILD>) {
+ 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[+][+]/);
@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;
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
}
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);
}
}
# 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);
}
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'};
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);
}
}
##----------------------------------------------------------------------------##
# 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;
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;
}
$ENV{'CC'} = $Cmd;
+$ENV{'CLANG_CC'} = $ClangCC;
$ENV{'CLANG'} = $Clang;
if ($Verbose >= 2) {