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