Updated the patch.
The patch now includes the fix for D9357 <http://reviews.llvm.org/D9357> that 
happen to be related to this issue. Perl 'system' and 'exec' routines process 
arguments differently depending on the perl port (tested with MSYS Perl, 
Dwimperl, Strawberry Perl and ActiveState Perl, got different results in terms 
of processing quotes and escaped characters) and on the OS (because arguments 
are passed to the system's command shell for parsing). 
The patch replaces all 'exec' and 'system' calls with pipe form of 'open' that 
behaves consistently in all tested perl ports and operating systems (Windows 7, 
OS X, Ubuntu).
Tested with arguments like -DMACRO="\"'A=a' 'B=b'\"" and -DMACRO='"include.h"'.
Please review!

In http://reviews.llvm.org/D8774#187749, @sylvestre.ledru wrote:

> I am not sure what is going on but a rebuild without your patch works


Fixed issues, please test it once again.


http://reviews.llvm.org/D8774

Files:
  tools/scan-build/ccc-analyzer
  tools/scan-build/scan-build

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: tools/scan-build/ccc-analyzer
===================================================================
--- tools/scan-build/ccc-analyzer
+++ tools/scan-build/ccc-analyzer
@@ -136,45 +136,49 @@
                                  SUFFIX => GetPPExt($Lang),
                                  DIR => $Dir);
   close ($PPH);
-  system $Clang, @$Args, "-E", "-o", $PPFile;
+  my $ExecLine = join(' ', qq/"$Clang"/, @{PrepareArgs($Args)}, "-E", "-o", $PPFile, "2>&1", "|");
+  open(PS, $ExecLine);
+  while ( <PS> ) {}
+  close PS;
 
   # Create the info file.
   open (OUT, ">", "$PPFile.info.txt") or die "Cannot open $PPFile.info.txt\n";
   print OUT abs_path($file), "\n";
   print OUT "$ErrorType\n";
   print OUT "@$Args\n";
   close OUT;
   `uname -a >> $PPFile.info.txt 2>&1`;
-  `$Compiler -v >> $PPFile.info.txt 2>&1`;
+  `"$Compiler" -v >> $PPFile.info.txt 2>&1`;
   rename($ofile, "$PPFile.stderr.txt");
   return (basename $PPFile);
 }
 
 ##----------------------------------------------------------------------------##
 #  Running the analyzer.
 ##----------------------------------------------------------------------------##
 
+sub PrepareArgs {
+  my $Args = shift;
+  my @TempArgs = @$Args;
+  foreach (@TempArgs) {
+    $_ =~ s/"/\\"/g;
+    $_ = qq/"$_"/;
+  }
+  return \@TempArgs;
+}
+
 sub GetCCArgs {
   my $mode = shift;
   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, "-###", $mode, @$Args;
-  }
-  close(TO_PARENT);
   my $line;
-  while (<FROM_CHILD>) {
+  my $ExecLine = join(' ', qq/"$Clang"/, "-###", $mode, @{PrepareArgs($Args)}, "2>&1", "|");
+  open(PS, $ExecLine);
+  while ( <PS> ) {
     next if (!/\s"?-cc1"?\s/);
     $line = $_;
   }
-
-  waitpid($pid,0);
-  close(FROM_CHILD);
+  close PS;
 
   die "could not find clang line\n" if (!defined $line);
   # Strip leading and trailing whitespace characters.
@@ -255,31 +259,21 @@
     print STDERR "#SHELL (cd '$dir' && @PrintArgs)\n";
   }
 
-  # 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.
+  # Save STDOUT and STDERR of clang to a temporary file and reroute
+  # all clang output to ccc-analyzer's STDERR.
   # We save the output file in the 'crashes' directory if clang encounters
   # any problems with the file.
-  pipe (FROM_CHILD, TO_PARENT);
-  my $pid = fork();
-  if ($pid == 0) {
-    close FROM_CHILD;
-    open(STDOUT,">&", \*TO_PARENT);
-    open(STDERR,">&", \*TO_PARENT);
-    exec $Cmd, @CmdArgs;
-  }
-
-  close TO_PARENT;
   my ($ofh, $ofile) = tempfile("clang_output_XXXXXX", DIR => $HtmlDir);
 
-  while (<FROM_CHILD>) {
+  my $ExecLine = join(' ', qq/"$Cmd"/, @{PrepareArgs(\@CmdArgs)}, "2>&1", "|");
+  open(PS, $ExecLine);
+  while ( <PS> ) {
     print $ofh $_;
     print STDERR $_;
   }
-  close $ofh;
-
-  waitpid($pid,0);
-  close(FROM_CHILD);
+  close PS;
   my $Result = $?;
+  close $ofh;
 
   # Did the command die because of a signal?
   if ($ReportFailures) {
@@ -446,11 +440,21 @@
 my %Uniqued;
 
 # Forward arguments to gcc.
-my $Status = system($Compiler,@ARGV);
-if (defined $ENV{'CCC_ANALYZER_LOG'}) {
-  print STDERR "$Compiler @ARGV\n";
+{
+  my $PreparedARGV = PrepareArgs(\@ARGV);
+  my $ExecLine = join(' ', qq/"$Compiler"/, @{$PreparedARGV}, "|");
+  open(PS, $ExecLine);
+  while ( <PS> ) {
+    print $_;
+  }
+  close PS;
+  my $Status = $?;
+
+  if (defined $ENV{'CCC_ANALYZER_LOG'}) {
+    print STDERR "$Compiler @{$PreparedARGV}\n";
+  }
+  if ($Status) { exit($Status >> 8); }
 }
-if ($Status) { exit($Status >> 8); }
 
 # Get the analysis options.
 my $Analyses = $ENV{'CCC_ANALYZER_ANALYSIS'};
Index: tools/scan-build/scan-build
===================================================================
--- tools/scan-build/scan-build
+++ tools/scan-build/scan-build
@@ -1232,40 +1232,24 @@
   }
   my %EnabledCheckers;
   foreach my $lang ("c", "objective-c", "objective-c++", "c++") {
-    pipe(FROM_CHILD, TO_PARENT);
-    my $pid = fork();
-    if ($pid == 0) {
-      close FROM_CHILD;
-      open(STDOUT,">&", \*TO_PARENT);
-      open(STDERR,">&", \*TO_PARENT);
-      exec $Clang, ( @PluginLoadCommandline_xclang, '--analyze', '-x', $lang, '-', '-###');
-    }
-    close(TO_PARENT);
-    while(<FROM_CHILD>) {
+    my $ExecLine = join(' ', qq/"$Clang"/, @PluginLoadCommandline_xclang, "--analyze", "-x", $lang, "-", "-###", "2>&1", "|");
+    open(PS, $ExecLine);
+    while (<PS>) {
       foreach my $val (split /\s+/) {
         $val =~ s/\"//g;
         if ($val =~ /-analyzer-checker\=([^\s]+)/) {
           $EnabledCheckers{$1} = 1;
         }
       }
     }
-    waitpid($pid,0);
-    close(FROM_CHILD);
   }
 
   # Query clang for complete list of checkers.
   if (defined $Clang && -x $Clang) {
-    pipe(FROM_CHILD, TO_PARENT);
-    my $pid = fork();
-    if ($pid == 0) {
-      close FROM_CHILD;
-      open(STDOUT,">&", \*TO_PARENT);
-      open(STDERR,">&", \*TO_PARENT);
-      exec $Clang, ('-cc1', @PluginsToLoad , '-analyzer-checker-help');
-    }
-    close(TO_PARENT);
+    my $ExecLine = join(' ', qq/"$Clang"/, "-cc1", @PluginsToLoad, "-analyzer-checker-help", "2>&1", "|");
+    open(PS, $ExecLine);
     my $foundCheckers = 0;
-    while(<FROM_CHILD>) {
+    while (<PS>) {
       if (/CHECKERS:/) {
         $foundCheckers = 1;
         last;
@@ -1277,7 +1261,7 @@
     else {
       print("\nAVAILABLE CHECKERS:\n\n");
       my $skip = 0;
-      while(<FROM_CHILD>) {
+       while(<PS>) {
         if (/experimental/) {
           $skip = 1;
           next;
@@ -1314,10 +1298,9 @@
         }
         print $_;
       }
-      print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n"
+      print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n";
     }
-    waitpid($pid,0);
-    close(FROM_CHILD);
+    close PS;
   }
 
 print <<ENDTEXT
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to