diff options
Diffstat (limited to 'tools/scan-build')
-rwxr-xr-x | tools/scan-build/ccc-analyzer | 2 | ||||
-rwxr-xr-x | tools/scan-build/scan-build | 338 | ||||
-rw-r--r-- | tools/scan-build/scan-build.1 | 15 | ||||
-rwxr-xr-x | tools/scan-build/set-xcode-analyzer | 22 |
4 files changed, 230 insertions, 147 deletions
diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer index c7636f9..8717225 100755 --- a/tools/scan-build/ccc-analyzer +++ b/tools/scan-build/ccc-analyzer @@ -346,6 +346,7 @@ my %LinkerOptionMap = ( my %CompilerLinkerOptionMap = ( '-fobjc-arc' => 0, + '-fno-objc-arc' => 0, '-fobjc-abi-version' => 0, # This is really a 1 argument, but always has '=' '-fobjc-legacy-dispatch' => 0, '-mios-simulator-version-min' => 0, # This really has 1 argument, but always has '=' @@ -353,6 +354,7 @@ my %CompilerLinkerOptionMap = ( '-arch' => 1, '-m32' => 0, '-m64' => 0, + '-stdlib' => 0, # This is really a 1 argument, but always has '=' '-v' => 0, '-fpascal-strings' => 0, '-mmacosx-version-min' => 0, # This is really a 1 argument, but always has '=' diff --git a/tools/scan-build/scan-build b/tools/scan-build/scan-build index 65c4893..a13b235 100755 --- a/tools/scan-build/scan-build +++ b/tools/scan-build/scan-build @@ -93,30 +93,13 @@ if (grep /^--help-checkers$/, @ARGV) { } ##----------------------------------------------------------------------------## -# Some initial preprocessing of Clang options. +# Declaration of Clang options. Populated later. ##----------------------------------------------------------------------------## -# Find 'clang' -my $ClangSB = Cwd::realpath("$RealBin/bin/clang"); -if (!defined $ClangSB || ! -x $ClangSB) { - $ClangSB = Cwd::realpath("$RealBin/clang"); -} my $Clang; -if (!defined $ClangSB || ! -x $ClangSB) { - # Default to looking for 'clang' in the path. - $Clang = `which clang`; - chomp $Clang; - if ($Clang eq "") { - DieDiag("No 'clang' executable found in path.\n"); - } -} -else { - $Clang = $ClangSB; -} -my $ClangCXX = $Clang; -$ClangCXX =~ s/\-\d+\.\d+$//; -$ClangCXX .= "++"; -my $ClangVersion = HtmlEscape(`$Clang --version`); +my $ClangSB; +my $ClangCXX; +my $ClangVersion; ##----------------------------------------------------------------------------## # GetHTMLRunDir - Construct an HTML directory name for the current sub-run. @@ -1003,74 +986,107 @@ ENDTEXT print <<ENDTEXT; OPTIONS: - -analyze-headers - Also analyze functions in #included files. + -analyze-headers + + Also analyze functions in #included files. By default, such functions + are skipped unless they are called by functions within the main source file. - -o - Target directory for HTML report files. Subdirectories - will be created as needed to represent separate "runs" of - the analyzer. If this option is not specified, a directory - is created in /tmp (TMPDIR on Mac OS X) to store the reports. - - -h - Display this message. + -o <output location> + + Specifies the output directory for analyzer reports. Subdirectories will be + created as needed to represent separate "runs" of the analyzer. If this + option is not specified, a directory is created in /tmp (TMPDIR on Mac OS X) + to store the reports. + + -h --help - -k - Add a "keep on going" option to the specified build command. - --keep-going This option currently supports make and xcodebuild. - This is a convenience option; one can specify this - behavior directly using build options. + Display this message. - --html-title [title] - Specify the title used on generated HTML pages. - --html-title=[title] If not specified, a default title will be used. + -k + --keep-going + + Add a "keep on going" option to the specified build command. This option + currently supports make and xcodebuild. This is a convenience option; one + can specify this behavior directly using build options. - -plist - By default the output of scan-build is a set of HTML files. - This option outputs the results as a set of .plist files. - - -plist-html - By default the output of scan-build is a set of HTML files. - This option outputs the results as a set of HTML - and .plist files. - - --status-bugs - By default, the exit status of $Prog is the same as the - executed build command. Specifying this option causes the - exit status of $Prog to be 1 if it found potential bugs - and 0 otherwise. + --html-title [title] + --html-title=[title] - --use-cc [compiler path] - $Prog attempts to guess the default compiler for - --use-cc=[compiler path] your C and Objective-C code. Use this option - to specify an alternate compiler. + Specify the title used on generated HTML pages. If not specified, a default + title will be used. - --use-c++ [compiler path] - $Prog attempts to guess the default compiler for - --use-c++=[compiler path] your C++ and Objective-C++ code. Use this option - to specify an alternate compiler. + -plist + + By default the output of scan-build is a set of HTML files. This option + outputs the results as a set of .plist files. + + -plist-html + + By default the output of scan-build is a set of HTML files. This option + outputs the results as a set of HTML and .plist files. + + --status-bugs + + By default, the exit status of scan-build is the same as the executed build + command. Specifying this option causes the exit status of scan-build to be 1 + if it found potential bugs and 0 otherwise. + + --use-cc [compiler path] + --use-cc=[compiler path] + + scan-build analyzes a project by interposing a "fake compiler", which + executes a real compiler for compilation and the static analyzer for analysis. + Because of the current implementation of interposition, scan-build does not + know what compiler your project normally uses. Instead, it simply overrides + the CC environment variable, and guesses your default compiler. + + In the future, this interposition mechanism to be improved, but if you need + scan-build to use a specific compiler for *compilation* then you can use + this option to specify a path to that compiler. + + --use-c++ [compiler path] + --use-c++=[compiler path] + + This is the same as "-use-cc" but for C++ code. + + -v + + Enable verbose output from scan-build. A second and third '-v' increases + verbosity. - -v - Verbose output from $Prog and the analyzer. - A second and third '-v' increases verbosity. + -V + --view - -V - View analysis results in a web browser when the build - --view completes. + View analysis results in a web browser when the build completes. ADVANCED OPTIONS: - -constraints [model] - Specify the contraint engine used by the analyzer. - By default the 'range' model is used. Specifying - 'basic' uses a simpler, less powerful constraint model - used by checker-0.160 and earlier. - - -store [model] - Specify the store model used by the analyzer. By default, - the 'region' store model is used. 'region' specifies a field- - sensitive store model. Users can also specify 'basic', which - is far less precise but can more quickly analyze code. - 'basic' was the default store model for checker-0.221 and - earlier. - - -no-failure-reports - Do not create a 'failures' subdirectory that includes - analyzer crash reports and preprocessed source files. + -no-failure-reports + + Do not create a 'failures' subdirectory that includes analyzer crash reports + and preprocessed source files. - -stats - Generates visitation statistics for the project being analyzed. + -stats + + Generates visitation statistics for the project being analyzed. - -maxloop N - specifiy the number of times a block can be visited before giving - up. Default is 4. Increase for more comprehensive coverage at a - cost of speed. - -internal-stats - Generate internal analyzer statistics. + -maxloop <loop count> + + Specifiy the number of times a block can be visited before giving up. + Default is 4. Increase for more comprehensive coverage at a cost of speed. + + -internal-stats + + Generate internal analyzer statistics. + + --use-analyzer [Xcode|path to clang] + --use-analyzer=[Xcode|path to clang] + scan-build uses the 'clang' executable relative to itself for static + analysis. One can override this behavior with this option by using the + 'clang' packaged with Xcode (on OS X) or from the PATH. + CONTROLLING CHECKERS: A default group of checkers are always run unless explicitly disabled. @@ -1119,85 +1135,86 @@ foreach my $lang ("c", "objective-c", "objective-c++", "c++") { } # Query clang for complete list of checkers. -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 $foundCheckers = 0; -while(<FROM_CHILD>) { - if (/CHECKERS:/) { - $foundCheckers = 1; - last; +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'); } -} -if (!$foundCheckers) { - print " *** Could not query Clang for the list of available checkers."; -} -else { - print("\nAVAILABLE CHECKERS:\n\n"); - my $skip = 0; + close(TO_PARENT); + my $foundCheckers = 0; while(<FROM_CHILD>) { - if (/experimental/) { - $skip = 1; - next; - } - if ($skip) { - next if (!/^\s\s[^\s]/); - $skip = 0; + if (/CHECKERS:/) { + $foundCheckers = 1; + last; } - s/^\s\s//; - if (/^([^\s]+)/) { - # Is the checker enabled? - my $checker = $1; - my $enabled = 0; - my $aggregate = ""; - foreach my $domain (split /\./, $checker) { - $aggregate .= $domain; - if ($EnabledCheckers{$aggregate}) { - $enabled =1; - last; - } - # append a dot, if an additional domain is added in the next iteration - $aggregate .= "."; + } + if (!$foundCheckers) { + print " *** Could not query Clang for the list of available checkers."; + } + else { + print("\nAVAILABLE CHECKERS:\n\n"); + my $skip = 0; + while(<FROM_CHILD>) { + if (/experimental/) { + $skip = 1; + next; + } + if ($skip) { + next if (!/^\s\s[^\s]/); + $skip = 0; } + s/^\s\s//; + if (/^([^\s]+)/) { + # Is the checker enabled? + my $checker = $1; + my $enabled = 0; + my $aggregate = ""; + foreach my $domain (split /\./, $checker) { + $aggregate .= $domain; + if ($EnabledCheckers{$aggregate}) { + $enabled =1; + last; + } + # append a dot, if an additional domain is added in the next iteration + $aggregate .= "."; + } - if ($enabled) { - print " + "; + if ($enabled) { + print " + "; + } + else { + print " "; + } } else { print " "; } + print $_; } - else { - print " "; - } - print $_; - } + print "\nNOTE: \"+\" indicates that an analysis is enabled by default.\n" + } + waitpid($pid,0); + close(FROM_CHILD); } -waitpid($pid,0); -close(FROM_CHILD); print <<ENDTEXT - NOTE: "+" indicates that an analysis is enabled by default. - BUILD OPTIONS You can specify any build option acceptable to the build command. EXAMPLE - $Prog -o /tmp/myhtmldir make -j4 + scan-build -o /tmp/myhtmldir make -j4 - The above example causes analysis reports to be deposited into - a subdirectory of "/tmp/myhtmldir" and to run "make" with the "-j4" option. - A different subdirectory is created each time $Prog analyzes a project. - The analyzer should support most parallel builds, but not distributed builds. +The above example causes analysis reports to be deposited into a subdirectory +of "/tmp/myhtmldir" and to run "make" with the "-j4" option. A different +subdirectory is created each time scan-build analyzes a project. The analyzer +should support most parallel builds, but not distributed builds. ENDTEXT } @@ -1251,6 +1268,7 @@ if (!@ARGV) { my $displayHelp = 0; +my $AnalyzerDiscoveryMethod; while (@ARGV) { @@ -1418,6 +1436,16 @@ while (@ARGV) { push @PluginsToLoad, "-load", shift @ARGV; next; } + if ($arg eq "--use-analyzer") { + shift @ARGV; + $AnalyzerDiscoveryMethod = shift @ARGV; + next; + } + if ($arg =~ /^--use-analyzer=(.+)$/) { + shift @ARGV; + $AnalyzerDiscoveryMethod = $1; + next; + } DieDiag("unrecognized option '$arg'\n") if ($arg =~ /^-/); @@ -1429,11 +1457,50 @@ if (!@ARGV and $displayHelp == 0) { $displayHelp = 1; } +# Find 'clang' +if (!defined $AnalyzerDiscoveryMethod) { + $Clang = Cwd::realpath("$RealBin/bin/clang"); + if (!defined $Clang || ! -x $Clang) { + $Clang = Cwd::realpath("$RealBin/clang"); + } + if (!defined $Clang || ! -x $Clang) { + if (!$displayHelp) { + DieDiag("error: Cannot find an executable 'clang' relative to scan-build." . + " Consider using --use-analyzer to pick a version of 'clang' to use for static analysis.\n"); + } + } +} +else { + if ($AnalyzerDiscoveryMethod =~ /^[Xx]code$/) { + my $xcrun = `which xcrun`; + chomp $xcrun; + if ($xcrun eq "") { + DieDiag("Cannot find 'xcrun' to find 'clang' for analysis.\n"); + } + $Clang = `$xcrun -toolchain XcodeDefault -find clang`; + chomp $Clang; + if ($Clang eq "") { + DieDiag("No 'clang' executable found by 'xcrun'\n"); + } + } + else { + $Clang = Cwd::realpath($AnalyzerDiscoveryMethod); + if (! -x $Clang) { + DieDiag("Cannot find an executable clang at '$Clang'\n"); + } + } +} + if ($displayHelp) { DisplayHelp(); exit 1; } +$ClangCXX = $Clang; +$ClangCXX =~ s/\-\d+\.\d+$//; +$ClangCXX .= "++"; +$ClangVersion = HtmlEscape(`$Clang --version`); + # Determine where results go. $CmdArgs = HtmlEscape(join(' ', map(ShellEscape($_), @ARGV))); $HtmlTitle = "${CurrentDirSuffix} - scan-build results" @@ -1457,15 +1524,12 @@ if (!defined $CmdCXX || ! -x $CmdCXX) { 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: $Clang\n"); -} +Diag("Using '$Clang' for static analysis\n"); SetHtmlEnv(\@ARGV, $HtmlDir); if ($AnalyzeHeaders) { push @AnalysesToRun,"-analyzer-opt-analyze-headers"; } if ($AnalyzerStats) { push @AnalysesToRun, '-analyzer-checker=debug.Stats'; } -if ($MaxLoop > 0) { push @AnalysesToRun, '-analyzer-max-loop=$MaxLoop'; } +if ($MaxLoop > 0) { push @AnalysesToRun, "-analyzer-max-loop $MaxLoop"; } # Delay setting up other environment variables in case we can do true # interposition. diff --git a/tools/scan-build/scan-build.1 b/tools/scan-build/scan-build.1 index 0f43196..0c7ef1d 100644 --- a/tools/scan-build/scan-build.1 +++ b/tools/scan-build/scan-build.1 @@ -1,9 +1,9 @@ .\" This file is distributed under the University of Illinois Open Source .\" License. See LICENSE.TXT for details. -.\" $Id: scan-build.1 157412 2012-05-24 20:16:00Z kremenek $ +.\" $Id: scan-build.1 167537 2012-11-07 17:12:37Z jrose $ .Dd May 25, 2012 +.Dt SCAN-BUILD 1 .Os "clang" "3.1" -.Dt SCAN-BUILD \&1 CLANG .Sh NAME .Nm scan-build .Nd Clang static analyzer @@ -139,7 +139,7 @@ which is far less precise but can more quickly analyze code. was the default store model for checker-0.221 and earlier. .\" .El -.Sh RETURN VALUES +.Sh EXIT STATUS .Nm returns the value returned by .Ar build_command @@ -188,10 +188,10 @@ Check for undefined results of binary operators. .It core.VLASize Check for declarations of VLA of undefined or zero size. .It core.builtin.BuiltinFunctions -Evaluate compiler builtin functions, e.g. +Evaluate compiler builtin functions, e.g. .Fn alloca . .It core.builtin.NoReturnFunctions -Evaluate +Evaluate .Ql panic functions that are known to not return to the caller. .It core.uninitialized.ArraySubscript @@ -270,9 +270,10 @@ Check for proper uses of .Fn CFNumberCreate . .It osx.coreFoundation.CFRetainRelease Check for null arguments to -.Fn CFRetain +.Fn CFRetain , +.Fn CFRelease , and -.Fn CFRelease . +.Fn CFMakeCollectable . .It osx.coreFoundation.containers.OutOfBounds Checks for index out-of-bounds when using the .Vt CFArray diff --git a/tools/scan-build/set-xcode-analyzer b/tools/scan-build/set-xcode-analyzer index c280bb4..93824af 100755 --- a/tools/scan-build/set-xcode-analyzer +++ b/tools/scan-build/set-xcode-analyzer @@ -20,10 +20,19 @@ def FindClangSpecs(path): if f.endswith(".xcspec") and f.startswith("Clang LLVM"): yield os.path.join(root, f) -def ModifySpec(path, pathToChecker): +def ModifySpec(path, isBuiltinAnalyzer, pathToChecker): t = tempfile.NamedTemporaryFile(delete=False) foundAnalyzer = False with open(path) as f: + if isBuiltinAnalyzer: + # First search for CLANG_ANALYZER_EXEC. Newer + # versions of Xcode set EXEC_PATH to be CLANG_ANALYZER_EXEC. + with open(path) as f2: + for line in f2: + if line.find("CLANG_ANALYZER_EXEC") >= 0: + pathToChecker = "$(CLANG_ANALYZER_EXEC)" + break + # Now create a new file. for line in f: if not foundAnalyzer: if line.find("Static Analyzer") >= 0: @@ -63,6 +72,7 @@ def main(): print "(-) You must quit Xcode first before modifying its configuration files." return + isBuiltinAnalyzer = False if options.path: # Expand tildes. path = os.path.expanduser(options.path) @@ -74,19 +84,25 @@ def main(): else: print "(+) Using the Clang bundled with Xcode" path = options.default + isBuiltinAnalyzer = True try: xcode_path = subprocess.check_output(["xcode-select", "-print-path"]) except AttributeError: # Fall back to the default install location when using Python < 2.7.0 xcode_path = "/Developer" - if (re.search("Xcode.app", xcode_path)): + if (xcode_path.find(".app/") != -1): # Cut off the 'Developer' dir, as the xcspec lies in another part # of the Xcode.app subtree. xcode_path = os.path.dirname(xcode_path) + foundSpec = False for x in FindClangSpecs(xcode_path): - ModifySpec(x, path) + foundSpec = True + ModifySpec(x, isBuiltinAnalyzer, path) + + if foundSpec == False: + print "(-) No compiler configuration file was found. Xcode's analyzer has not been updated." if __name__ == '__main__': main() |