scan-build/ccc-analyzer: start analyzing C++ FTW.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91398 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer
index 9fca432..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; }
@@ -79,7 +103,7 @@
   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 @@
 #  Running the analyzer.
 ##----------------------------------------------------------------------------##
 
-# Determine what clang executable to use.
-my $Clang = $ENV{'CLANG'};
-if (!defined $Clang) { $Clang = 'clang'; }
-
 sub GetCCArgs {
   my $Args = shift;
   
@@ -134,9 +154,6 @@
   
   $Args = GetCCArgs($Args);
 
-  # Skip anything related to C++.
-  return if ($Lang =~ /c[+][+]/);
-
   my $RunAnalyzer = 0;
   my $Cmd;
   my @CmdArgs;
@@ -361,7 +378,9 @@
 
 my %LangsAccepted = (
   "objective-c" => 1,
-  "c" => 1
+  "c" => 1,
+  "c++" => 1,
+  "objective-c++" => 1
 );
 
 ##----------------------------------------------------------------------------##
@@ -377,7 +396,7 @@
 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.
diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build
index 518632e..f978a88 100755
--- a/tools/scan-build/scan-build
+++ b/tools/scan-build/scan-build
@@ -26,7 +26,6 @@
 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
@@ -83,13 +82,17 @@
 
 # Find 'clang'
 my $ClangSB = Cwd::realpath("$RealBin/bin/clang");
+my $ClangCXXSB;
 if (!defined $ClangSB || ! -x $ClangSB) {
   $ClangSB = Cwd::realpath("$RealBin/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;
@@ -799,12 +802,22 @@
       $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");
@@ -825,6 +838,7 @@
         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";            
           }
         }
       }
@@ -839,10 +853,10 @@
     # 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);
@@ -1090,16 +1104,19 @@
   
   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;
   }
   
@@ -1171,27 +1188,28 @@
 # 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 $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{'CXX'} = $CmdCXX;
 $ENV{'CLANG'} = $Clang;
+$ENV{'CLANG_CXX'} = $ClangCXX;
 
 if ($Verbose >= 2) {
   $ENV{'CCC_ANALYZER_VERBOSE'} = 1;