blob: 89eddb356242de485b79a2ab263e45d10d15b0f2 [file] [log] [blame]
Zhongxing Xu579855f2010-08-25 01:15:20 +00001//===--- clang-wpa.cpp - clang whole program analyzer ---------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This tool reads a sequence of precompiled AST files, and do various
11// cross translation unit analyses.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Basic/FileManager.h"
16#include "clang/Basic/SourceManager.h"
Argyrios Kyrtzidis27af04b2011-02-15 16:54:12 +000017#include "clang/StaticAnalyzer/Frontend/CheckerRegistration.h"
Ted Kremenek9b663712011-02-10 01:03:03 +000018#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h"
19#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
20#include "clang/StaticAnalyzer/Core/PathSensitive/TransferFuncs.h"
Argyrios Kyrtzidis27af04b2011-02-15 16:54:12 +000021#include "clang/StaticAnalyzer/Core/CheckerManager.h"
Ted Kremenek8691e0b2011-01-18 04:22:19 +000022#include "clang/StaticAnalyzer/Checkers/LocalCheckers.h"
Zhongxing Xu579855f2010-08-25 01:15:20 +000023#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"
Argyrios Kyrtzidis27af04b2011-02-15 16:54:12 +000031#include "clang/Basic/TargetInfo.h"
Zhongxing Xu579855f2010-08-25 01:15:20 +000032#include "llvm/ADT/IntrusiveRefCntPtr.h"
33#include "llvm/Support/CommandLine.h"
34#include "llvm/Support/raw_ostream.h"
35using namespace clang;
36using namespace idx;
37
38static llvm::cl::list<std::string>
39InputFilenames(llvm::cl::Positional, llvm::cl::desc("<input AST files>"));
40
41static llvm::cl::opt<bool>
42ViewCallGraph("view-call-graph", llvm::cl::desc("Display the call graph."));
43
44static llvm::cl::opt<std::string>
45AnalyzeFunction("analyze-function",
46 llvm::cl::desc("Specify the entry function."));
47
48namespace {
49// A thin wrapper over ASTUnit implementing the TranslationUnit interface.
50class ASTUnitTU : public TranslationUnit {
51 ASTUnit *AST;
52 DeclReferenceMap DeclRefMap;
53 SelectorMap SelMap;
54
55public:
56 ASTUnitTU(ASTUnit *ast)
57 : AST(ast), DeclRefMap(AST->getASTContext()), SelMap(AST->getASTContext()) {
58 }
59
60 virtual ASTContext &getASTContext() {
61 return AST->getASTContext();
62 }
63
64 virtual Preprocessor &getPreprocessor() {
65 return AST->getPreprocessor();
66 }
67
68 virtual Diagnostic &getDiagnostic() {
69 return AST->getDiagnostics();
70 }
71
72 virtual DeclReferenceMap &getDeclReferenceMap() {
73 return DeclRefMap;
74 }
75
76 virtual SelectorMap &getSelectorMap() {
77 return SelMap;
78 }
79};
80}
81
82int main(int argc, char **argv) {
83 llvm::cl::ParseCommandLineOptions(argc, argv, "clang-wpa");
84 std::vector<ASTUnit*> ASTUnits;
85
86 Program Prog;
87 Indexer Idxer(Prog);
88
89 if (InputFilenames.empty())
90 return 0;
91
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];
Ted Kremenek8691e0b2011-01-18 04:22:19 +000097 llvm::OwningPtr<ASTUnit> AST(ASTUnit::LoadFromASTFile(InFile, Diags,
98 FileSystemOptions(),
99 false, 0, 0, true));
Zhongxing Xu579855f2010-08-25 01:15:20 +0000100 if (!AST)
101 return 1;
102
103 ASTUnits.push_back(AST.take());
104 }
105
106 if (ViewCallGraph) {
107 llvm::OwningPtr<CallGraph> CG;
108 CG.reset(new CallGraph(Prog));
109
110 for (unsigned i = 0, e = ASTUnits.size(); i != e; ++i)
111 CG->addTU(ASTUnits[i]->getASTContext());
112
113 CG->ViewCallGraph();
114 return 0;
115 }
116
117 if (AnalyzeFunction.empty())
118 return 0;
119
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]);
123 Idxer.IndexAST(TU);
124 }
125
126 Entity Ent = Entity::get(AnalyzeFunction, Prog);
127 FunctionDecl *FD;
128 TranslationUnit *TU;
129 llvm::tie(FD, TU) = Idxer.getDefinitionFor(Ent);
130
131 if (!FD)
132 return 0;
133
134 // Create an analysis engine.
135 Preprocessor &PP = TU->getPreprocessor();
136
Argyrios Kyrtzidis27af04b2011-02-15 16:54:12 +0000137 AnalyzerOptions Opts;
138
139 // Hard code options and checkers for now.
140
141 Opts.MaxNodes = 300000;
142 Opts.MaxLoop = 3;
143 Opts.InlineCall = true;
144 Opts.CFGAddImplicitDtors = true;
145 Opts.EagerlyTrimEGraph = true;
146
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));
152
153 // Checks to perform for Objective-C/Objective-C++.
154 if (PP.getLangOptions().ObjC1)
155 Opts.CheckersControlList.push_back(std::make_pair("cocoa", true));
156
157 llvm::OwningPtr<ento::CheckerManager> checkerMgr;
Argyrios Kyrtzidis2e471a32011-02-23 07:19:14 +0000158 checkerMgr.reset(ento::registerCheckers(Opts, PP.getLangOptions(),
159 PP.getDiagnostics()));
Argyrios Kyrtzidis27af04b2011-02-15 16:54:12 +0000160
Ted Kremenek8691e0b2011-01-18 04:22:19 +0000161 using namespace clang::ento;
Zhongxing Xu579855f2010-08-25 01:15:20 +0000162 AnalysisManager AMgr(TU->getASTContext(), PP.getDiagnostics(),
163 PP.getLangOptions(), /* PathDiagnostic */ 0,
164 CreateRegionStoreManager,
Argyrios Kyrtzidis27af04b2011-02-15 16:54:12 +0000165 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);
Zhongxing Xu579855f2010-08-25 01:15:20 +0000173
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000174 TransferFuncs* TF = MakeCFRefCountTF(AMgr.getASTContext(), /*GC*/false,
Zhongxing Xu579855f2010-08-25 01:15:20 +0000175 AMgr.getLangOptions());
Argyrios Kyrtzidisd2592a32010-12-22 18:53:44 +0000176 ExprEngine Eng(AMgr, TF);
Zhongxing Xu579855f2010-08-25 01:15:20 +0000177
178 Eng.ExecuteWorkList(AMgr.getStackFrame(FD, TU), AMgr.getMaxNodes());
179
180 return 0;
181}