From: Daniel Dunbar Date: Wed, 21 Jan 2009 01:07:49 +0000 (+0000) Subject: ccc: Add --analyze driver mode (for running static analyzer). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=de388a56b3a9cdeeb764cc5e21ccf95b6f4fef8a;p=clang ccc: Add --analyze driver mode (for running static analyzer). - For now forces generation of plist files, need to think about the right interface. - Changed -fsyntax-only mode to be its own phase (more consistent). - Add -WA, for passing options verbatim to analyzer. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@62649 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/tools/ccc/ccclib/Arguments.py b/tools/ccc/ccclib/Arguments.py index 04dfbbf1e2..d9fd11d389 100644 --- a/tools/ccc/ccclib/Arguments.py +++ b/tools/ccc/ccclib/Arguments.py @@ -527,6 +527,8 @@ class OptionParser: # Blanket pass-through options. + self.WAOption = self.addOption(CommaJoinedOption('-WA,')) + self.WaOption = self.addOption(CommaJoinedOption('-Wa,')) self.XassemblerOption = self.addOption(SeparateOption('-Xassembler')) @@ -831,6 +833,9 @@ class OptionParser: self.addOption(JoinedOrSeparateOption('-V')) self.addOption(JoinedOrSeparateOption('-b')) + # Clang static analyzer options (also see -WA,). + self.analyzeOption = self.addOption(FlagOption('--analyze')) + def addOption(self, opt): self.options.append(opt) return opt diff --git a/tools/ccc/ccclib/Driver.py b/tools/ccc/ccclib/Driver.py index 65b53166a7..de4596bf2c 100644 --- a/tools/ccc/ccclib/Driver.py +++ b/tools/ccc/ccclib/Driver.py @@ -333,6 +333,7 @@ class Driver(object): sys.exit(1) def buildNormalPipeline(self, args): + hasAnalyze = args.getLastArg(self.parser.analyzeOption) hasCombine = args.getLastArg(self.parser.combineOption) hasSyntaxOnly = args.getLastArg(self.parser.syntaxOnlyOption) hasDashC = args.getLastArg(self.parser.cOption) @@ -406,6 +407,9 @@ class Driver(object): if hasDashE or hasDashM or hasDashMM: finalPhase = Phases.Phase.eOrderPreprocess finalPhaseOpt = hasDashE + elif hasAnalyze: + finalPhase = Phases.Phase.eOrderCompile + finalPhaseOpt = hasAnalyze elif hasSyntaxOnly: finalPhase = Phases.Phase.eOrderCompile finalPhaseOpt = hasSyntaxOnly @@ -455,6 +459,10 @@ class Driver(object): linkPhase]) elif klass.onlyPrecompile: sequence.append(Phases.PrecompilePhase()) + elif hasAnalyze: + sequence.append(Phases.AnalyzePhase()) + elif hasSyntaxOnly: + sequence.append(Phases.SyntaxOnlyPhase()) else: sequence.extend([Phases.CompilePhase(), Phases.AssemblePhase(), @@ -487,11 +495,18 @@ class Driver(object): current = Phases.JobAction(transition, [current], Types.PCHType) + elif isinstance(transition, Phases.AnalyzePhase): + output = Types.PlistType + current = Phases.JobAction(transition, + [current], + output) + elif isinstance(transition, Phases.SyntaxOnlyPhase): + output = Types.NothingType + current = Phases.JobAction(transition, + [current], + output) elif isinstance(transition, Phases.CompilePhase): - if hasSyntaxOnly: - output = Types.NothingType - else: - output = Types.AsmTypeNoPP + output = Types.AsmTypeNoPP current = Phases.JobAction(transition, [current], output) diff --git a/tools/ccc/ccclib/Phases.py b/tools/ccc/ccclib/Phases.py index 0384b8fa4f..160e72c06e 100644 --- a/tools/ccc/ccclib/Phases.py +++ b/tools/ccc/ccclib/Phases.py @@ -68,6 +68,14 @@ class PrecompilePhase(Phase): def __init__(self): super(PrecompilePhase, self).__init__("precompiler", Phase.eOrderCompile) +class AnalyzePhase(Phase): + def __init__(self): + super(AnalyzePhase, self).__init__("analyze", Phase.eOrderCompile) + +class SyntaxOnlyPhase(Phase): + def __init__(self): + super(SyntaxOnlyPhase, self).__init__("syntax-only", Phase.eOrderCompile) + class CompilePhase(Phase): def __init__(self): super(CompilePhase, self).__init__("compiler", Phase.eOrderCompile) diff --git a/tools/ccc/ccclib/ToolChain.py b/tools/ccc/ccclib/ToolChain.py index ac1cc0a0ba..ee244d7ec0 100644 --- a/tools/ccc/ccclib/ToolChain.py +++ b/tools/ccc/ccclib/ToolChain.py @@ -51,15 +51,17 @@ class Darwin_X86_ToolChain(ToolChain): self.gccVersion = gccVersion self.archName = archName + self.clangTool = Tools.Clang_CompileTool(self) self.toolMap = { Phases.PreprocessPhase : Tools.Darwin_X86_PreprocessTool(self), + Phases.AnalyzePhase : self.clangTool, + Phases.SyntaxOnlyPhase : Tools.Darwin_X86_CompileTool(self), Phases.CompilePhase : Tools.Darwin_X86_CompileTool(self), Phases.PrecompilePhase : Tools.Darwin_X86_CompileTool(self), Phases.AssemblePhase : Tools.Darwin_AssembleTool(self), Phases.LinkPhase : Tools.Darwin_X86_LinkTool(self), Phases.LipoPhase : Tools.LipoTool(), } - self.clangTool = Tools.Clang_CompileTool() def getToolChainDir(self): return 'i686-apple-darwin%d/%s' % (self.darwinVersion[0], @@ -171,6 +173,8 @@ class Generic_GCC_ToolChain(ToolChain): super(Generic_GCC_ToolChain, self).__init__(driver) self.toolMap = { Phases.PreprocessPhase : Tools.GCC_PreprocessTool(), + Phases.AnalyzePhase : Tools.Clang_CompileTool(self), + Phases.SyntaxOnlyPhase : Tools.GCC_CompileTool(), Phases.CompilePhase : Tools.GCC_CompileTool(), Phases.PrecompilePhase : Tools.GCC_PrecompileTool(), Phases.AssemblePhase : Tools.GCC_AssembleTool(), diff --git a/tools/ccc/ccclib/Tools.py b/tools/ccc/ccclib/Tools.py index 2bb694c4e2..11a6047182 100644 --- a/tools/ccc/ccclib/Tools.py +++ b/tools/ccc/ccclib/Tools.py @@ -3,6 +3,7 @@ import sys # FIXME: Shouldn't be needed. import Arguments import Jobs +import Phases import Types class Tool(object): @@ -39,9 +40,10 @@ class GCC_Common_Tool(Tool): cmd_args.extend(arglist.render(arch)) if isinstance(output, Jobs.PipedJob): cmd_args.extend(['-o', '-']) - elif output is None: + elif isinstance(phase.phase, Phases.SyntaxOnlyPhase): cmd_args.append('-fsyntax-only') else: + assert output cmd_args.extend(arglist.render(output)) if (isinstance(self, GCC_LinkTool) and @@ -163,18 +165,22 @@ class Darwin_AssembleTool(Tool): cmd_args)) class Clang_CompileTool(Tool): - def __init__(self): + def __init__(self, toolChain): super(Clang_CompileTool, self).__init__('clang', (Tool.eFlagsPipedInput | Tool.eFlagsPipedOutput | Tool.eFlagsIntegratedCPP)) + self.toolChain = toolChain def constructJob(self, phase, arch, jobs, inputs, output, outputType, arglist, linkingOutput): cmd_args = [] patchOutputNameForPTH = False - if output is None: + + if isinstance(phase.phase, Phases.AnalyzePhase): + cmd_args.append('-analyze') + elif isinstance(phase.phase, Phases.SyntaxOnlyPhase): cmd_args.append('-fsyntax-only') elif outputType is Types.AsmTypeNoPP: cmd_args.append('-S') @@ -198,6 +204,22 @@ class Clang_CompileTool(Tool): else: raise ValueError,"Unexpected output type for clang tool." + if isinstance(phase.phase, Phases.AnalyzePhase): + # Add default argument set. + # + # FIXME: Move into clang? + cmd_args.extend(['-warn-dead-stores', + '-checker-cfref', + '-warn-objc-methodsigs', + '-warn-objc-missing-dealloc', + '-warn-objc-unused-ivars']) + + cmd_args.append('-analyzer-output-plist') + + # Add -WA, arguments when running as analyzer. + for arg in arglist.getArgs(arglist.parser.WAOption): + cmd_args.extend(arglist.renderAsInput(arg)) + arglist.addAllArgs(cmd_args, arglist.parser.vOption) arglist.addAllArgs2(cmd_args, arglist.parser.DOption, arglist.parser.UOption) arglist.addAllArgs2(cmd_args, arglist.parser.IOption, arglist.parser.FOption) @@ -252,7 +274,7 @@ class Clang_CompileTool(Tool): suffix = '.pth' cmd_args.append('-o') cmd_args.append(base + suffix) - else: + elif output: cmd_args.extend(arglist.render(output)) for input in inputs: diff --git a/tools/ccc/ccclib/Types.py b/tools/ccc/ccclib/Types.py index 19c1f5fffb..c04e61d91d 100644 --- a/tools/ccc/ccclib/Types.py +++ b/tools/ccc/ccclib/Types.py @@ -69,6 +69,7 @@ FortranType = InputType('f95-cpp-input', FortranTypeNoPP, canBeUserSpecified=Tru JavaType = InputType('java', canBeUserSpecified=True) # Misc. +PlistType = InputType('plist', tempSuffix='plist') PCHType = InputType('precompiled-header', tempSuffix='gch') ObjectType = InputType('object', tempSuffix='o') TreelangType = InputType('treelang', canBeUserSpecified=True) diff --git a/tools/ccc/ccclib/__init__.py b/tools/ccc/ccclib/__init__.py index e69de29bb2..a9a2c5b3bb 100644 --- a/tools/ccc/ccclib/__init__.py +++ b/tools/ccc/ccclib/__init__.py @@ -0,0 +1 @@ +__all__ = [] diff --git a/tools/ccc/test/ccc/phases.c b/tools/ccc/test/ccc/phases.c index 902ceb4298..2f4571a769 100644 --- a/tools/ccc/test/ccc/phases.c +++ b/tools/ccc/test/ccc/phases.c @@ -30,7 +30,7 @@ // RUN: xcc -ccc-host-system unknown -ccc-print-phases -E %s > %t && // RUN: not grep ': compiler, ' %t && // RUN: xcc -ccc-host-system unknown -ccc-print-phases -fsyntax-only %s > %t && -// RUN: grep ': compiler, {1}, nothing' %t && +// RUN: grep ': syntax-only, {1}, nothing' %t && // RUN: not grep ': assembler, ' %t && // RUN: xcc -ccc-host-system unknown -ccc-print-phases -S %s > %t && // RUN: not grep ': assembler, ' %t &&