1 //===--- clang-wpa.cpp - clang whole program analyzer ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This tool reads a sequence of precompiled AST files, and do various
11 // cross translation unit analyses.
13 //===----------------------------------------------------------------------===//
15 #include "clang/Basic/FileManager.h"
16 #include "clang/Basic/SourceManager.h"
17 #include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
18 #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
19 #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
20 #include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
21 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
22 #include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
23 #include "clang/Frontend/ASTUnit.h"
24 #include "clang/Frontend/CompilerInstance.h"
25 #include "clang/Index/CallGraph.h"
26 #include "clang/Index/Indexer.h"
27 #include "clang/Index/TranslationUnit.h"
28 #include "clang/Index/DeclReferenceMap.h"
29 #include "clang/Index/SelectorMap.h"
30 #include "clang/Lex/Preprocessor.h"
31 #include "clang/Basic/TargetInfo.h"
32 #include "llvm/ADT/IntrusiveRefCntPtr.h"
33 #include "llvm/Support/CommandLine.h"
34 #include "llvm/Support/raw_ostream.h"
35 using namespace clang
;
38 static llvm::cl::list
<std::string
>
39 InputFilenames(llvm::cl::Positional
, llvm::cl::desc("<input AST files>"));
41 static llvm::cl::opt
<bool>
42 ViewCallGraph("view-call-graph", llvm::cl::desc("Display the call graph."));
44 static llvm::cl::opt
<std::string
>
45 AnalyzeFunction("analyze-function",
46 llvm::cl::desc("Specify the entry function."));
49 // A thin wrapper over ASTUnit implementing the TranslationUnit interface.
50 class ASTUnitTU
: public TranslationUnit
{
52 DeclReferenceMap DeclRefMap
;
56 ASTUnitTU(ASTUnit
*ast
)
57 : AST(ast
), DeclRefMap(AST
->getASTContext()), SelMap(AST
->getASTContext()) {
60 virtual ASTContext
&getASTContext() {
61 return AST
->getASTContext();
64 virtual Preprocessor
&getPreprocessor() {
65 return AST
->getPreprocessor();
68 virtual Diagnostic
&getDiagnostic() {
69 return AST
->getDiagnostics();
72 virtual DeclReferenceMap
&getDeclReferenceMap() {
76 virtual SelectorMap
&getSelectorMap() {
82 int main(int argc
, char **argv
) {
83 llvm::cl::ParseCommandLineOptions(argc
, argv
, "clang-wpa");
84 std::vector
<ASTUnit
*> ASTUnits
;
89 if (InputFilenames
.empty())
92 DiagnosticOptions DiagOpts
;
93 llvm::IntrusiveRefCntPtr
<Diagnostic
> Diags
94 = CompilerInstance::createDiagnostics(DiagOpts
, argc
, argv
);
95 for (unsigned i
= 0, e
= InputFilenames
.size(); i
!= e
; ++i
) {
96 const std::string
&InFile
= InputFilenames
[i
];
97 llvm::OwningPtr
<ASTUnit
> AST(ASTUnit::LoadFromASTFile(InFile
, Diags
,
103 ASTUnits
.push_back(AST
.take());
107 llvm::OwningPtr
<CallGraph
> CG
;
108 CG
.reset(new CallGraph(Prog
));
110 for (unsigned i
= 0, e
= ASTUnits
.size(); i
!= e
; ++i
)
111 CG
->addTU(ASTUnits
[i
]->getASTContext());
117 if (AnalyzeFunction
.empty())
120 // Feed all ASTUnits to the Indexer.
121 for (unsigned i
= 0, e
= ASTUnits
.size(); i
!= e
; ++i
) {
122 ASTUnitTU
*TU
= new ASTUnitTU(ASTUnits
[i
]);
126 Entity Ent
= Entity::get(AnalyzeFunction
, Prog
);
129 llvm::tie(FD
, TU
) = Idxer
.getDefinitionFor(Ent
);
134 // Create an analysis engine.
135 Preprocessor
&PP
= TU
->getPreprocessor();
137 AnalyzerOptions Opts
;
139 // Hard code options and checkers for now.
141 Opts
.MaxNodes
= 300000;
143 Opts
.InlineCall
= true;
144 Opts
.CFGAddImplicitDtors
= true;
145 Opts
.EagerlyTrimEGraph
= true;
147 Opts
.CheckersControlList
.push_back(std::make_pair("core", true));
148 if (PP
.getTargetInfo().getTriple().getOS() != llvm::Triple::Win32
)
149 Opts
.CheckersControlList
.push_back(std::make_pair("unix", true));
150 if (PP
.getTargetInfo().getTriple().getVendor() == llvm::Triple::Apple
)
151 Opts
.CheckersControlList
.push_back(std::make_pair("macosx", true));
153 // Checks to perform for Objective-C/Objective-C++.
154 if (PP
.getLangOptions().ObjC1
)
155 Opts
.CheckersControlList
.push_back(std::make_pair("cocoa", true));
157 llvm::OwningPtr
<ento::CheckerManager
> checkerMgr
;
158 checkerMgr
.reset(ento::registerCheckers(Opts
, PP
.getLangOptions(),
159 PP
.getDiagnostics()));
161 using namespace clang::ento
;
162 AnalysisManager
AMgr(TU
->getASTContext(), PP
.getDiagnostics(),
163 PP
.getLangOptions(), /* PathDiagnostic */ 0,
164 CreateRegionStoreManager
,
165 CreateRangeConstraintManager
, checkerMgr
.get(), &Idxer
,
166 Opts
.MaxNodes
, Opts
.MaxLoop
,
167 Opts
.VisualizeEGDot
, Opts
.VisualizeEGUbi
,
168 Opts
.PurgeDead
, Opts
.EagerlyAssume
,
169 Opts
.TrimGraph
, Opts
.InlineCall
,
170 Opts
.UnoptimizedCFG
, Opts
.CFGAddImplicitDtors
,
171 Opts
.CFGAddInitializers
,
172 Opts
.EagerlyTrimEGraph
);
174 TransferFuncs
* TF
= MakeCFRefCountTF(AMgr
.getASTContext(), /*GC*/false,
175 AMgr
.getLangOptions());
176 ExprEngine
Eng(AMgr
, TF
);
178 Eng
.ExecuteWorkList(AMgr
.getStackFrame(FD
, TU
), AMgr
.getMaxNodes());