blob: e903c805974e5456c1ae375ed8d69b586b726130 [file] [log] [blame]
Zhongxing Xu97ab3942009-07-30 01:17:21 +00001//== AnalysisContext.cpp - Analysis context for Path Sens analysis -*- C++ -*-//
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 file defines AnalysisContext, a class that manages the analysis context
11// data for path sensitive analysis.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Analysis/PathSensitive/AnalysisContext.h"
Ted Kremenekd02e83a2009-12-04 02:03:51 +000016#include "clang/Analysis/PathSensitive/MemRegion.h"
Zhongxing Xu97ab3942009-07-30 01:17:21 +000017#include "clang/Analysis/Analyses/LiveVariables.h"
18#include "clang/Analysis/CFG.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclObjC.h"
21#include "clang/AST/ParentMap.h"
Ted Kremenekb1a7b652009-11-26 02:31:33 +000022#include "clang/AST/StmtVisitor.h"
23#include "clang/Analysis/Support/BumpVector.h"
Mike Stump87a05f12009-07-31 01:10:29 +000024#include "llvm/Support/ErrorHandling.h"
Zhongxing Xu97ab3942009-07-30 01:17:21 +000025
26using namespace clang;
27
Ted Kremenek58f5ec72009-10-20 21:39:41 +000028void AnalysisContextManager::clear() {
29 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
30 delete I->second;
31 Contexts.clear();
32}
33
Zhongxing Xu97ab3942009-07-30 01:17:21 +000034Stmt *AnalysisContext::getBody() {
Ted Kremenek23760022009-08-21 23:58:43 +000035 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
Zhongxing Xu97ab3942009-07-30 01:17:21 +000036 return FD->getBody();
Ted Kremenek23760022009-08-21 23:58:43 +000037 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
Zhongxing Xu97ab3942009-07-30 01:17:21 +000038 return MD->getBody();
39
Mike Stump87a05f12009-07-31 01:10:29 +000040 llvm::llvm_unreachable("unknown code decl");
Zhongxing Xu97ab3942009-07-30 01:17:21 +000041}
42
Ted Kremenek82cd37c2009-08-21 23:25:54 +000043const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
44 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
45 return MD->getSelfDecl();
Mike Stump1eb44332009-09-09 15:08:12 +000046
Ted Kremenek82cd37c2009-08-21 23:25:54 +000047 return NULL;
48}
49
Zhongxing Xu97ab3942009-07-30 01:17:21 +000050CFG *AnalysisContext::getCFG() {
Mike Stump1eb44332009-09-09 15:08:12 +000051 if (!cfg)
Zhongxing Xu97ab3942009-07-30 01:17:21 +000052 cfg = CFG::buildCFG(getBody(), &D->getASTContext());
53 return cfg;
54}
55
56ParentMap &AnalysisContext::getParentMap() {
Mike Stump1eb44332009-09-09 15:08:12 +000057 if (!PM)
Zhongxing Xu97ab3942009-07-30 01:17:21 +000058 PM = new ParentMap(getBody());
59 return *PM;
60}
61
62LiveVariables *AnalysisContext::getLiveVariables() {
63 if (!liveness) {
64 CFG *c = getCFG();
65 if (!c)
66 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +000067
Ted Kremenekb1a7b652009-11-26 02:31:33 +000068 liveness = new LiveVariables(*this);
Zhongxing Xu97ab3942009-07-30 01:17:21 +000069 liveness->runOnCFG(*c);
70 liveness->runOnAllBlocks(*c, 0, true);
71 }
Mike Stump1eb44332009-09-09 15:08:12 +000072
Zhongxing Xu97ab3942009-07-30 01:17:21 +000073 return liveness;
74}
75
Ted Kremenek23760022009-08-21 23:58:43 +000076AnalysisContext *AnalysisContextManager::getContext(const Decl *D) {
77 AnalysisContext *&AC = Contexts[D];
78 if (!AC)
79 AC = new AnalysisContext(D);
Mike Stump1eb44332009-09-09 15:08:12 +000080
Ted Kremenek23760022009-08-21 23:58:43 +000081 return AC;
Zhongxing Xu97ab3942009-07-30 01:17:21 +000082}
Zhongxing Xu18c7c062009-08-03 07:23:22 +000083
Ted Kremenekd02e83a2009-12-04 02:03:51 +000084const BlockDecl *BlockInvocationContext::getBlockDecl() const {
85 return Data.is<const BlockDataRegion*>() ?
86 Data.get<const BlockDataRegion*>()->getDecl()
87 : Data.get<const BlockDecl*>();
88}
89
Ted Kremenekdc0d9092009-12-04 00:50:10 +000090//===----------------------------------------------------------------------===//
91// FoldingSet profiling.
92//===----------------------------------------------------------------------===//
93
Ted Kremenekdc0d9092009-12-04 00:50:10 +000094void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
95 ContextKind ck,
96 AnalysisContext *ctx,
97 const LocationContext *parent,
98 const void* data) {
Ted Kremenek0ee41242009-12-04 01:28:56 +000099 ID.AddInteger(ck);
100 ID.AddPointer(ctx);
101 ID.AddPointer(parent);
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000102 ID.AddPointer(data);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000103}
104
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000105void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
106 Profile(ID, getAnalysisContext(), getParent(), CallSite);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000107}
108
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000109void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
110 Profile(ID, getAnalysisContext(), getParent(), Enter);
111}
112
113void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
Ted Kremenekd02e83a2009-12-04 02:03:51 +0000114 if (const BlockDataRegion *BR = getBlockRegion())
115 Profile(ID, getAnalysisContext(), getParent(), BR);
116 else
117 Profile(ID, getAnalysisContext(), getParent(),
118 Data.get<const BlockDecl*>());
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000119}
120
121//===----------------------------------------------------------------------===//
Ted Kremenek0ee41242009-12-04 01:28:56 +0000122// LocationContext creation.
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000123//===----------------------------------------------------------------------===//
124
Ted Kremenek0ee41242009-12-04 01:28:56 +0000125template <typename LOC, typename DATA>
126const LOC*
127LocationContextManager::getLocationContext(AnalysisContext *ctx,
128 const LocationContext *parent,
129 const DATA *d) {
130 llvm::FoldingSetNodeID ID;
131 LOC::Profile(ID, ctx, parent, d);
132 void *InsertPos;
Ted Kremenek58f5ec72009-10-20 21:39:41 +0000133
Ted Kremenek0ee41242009-12-04 01:28:56 +0000134 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
135
136 if (!L) {
137 L = new LOC(ctx, parent, d);
138 Contexts.InsertNode(L, InsertPos);
139 }
140 return L;
Ted Kremenek58f5ec72009-10-20 21:39:41 +0000141}
142
Ted Kremenek0ee41242009-12-04 01:28:56 +0000143const StackFrameContext*
Mike Stump1eb44332009-09-09 15:08:12 +0000144LocationContextManager::getStackFrame(AnalysisContext *ctx,
Ted Kremenek54c809b2009-08-21 23:39:58 +0000145 const LocationContext *parent,
146 const Stmt *s) {
Ted Kremenek0ee41242009-12-04 01:28:56 +0000147 return getLocationContext<StackFrameContext, Stmt>(ctx, parent, s);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000148}
149
Ted Kremenek0ee41242009-12-04 01:28:56 +0000150const ScopeContext *
151LocationContextManager::getScope(AnalysisContext *ctx,
152 const LocationContext *parent,
153 const Stmt *s) {
154 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
155}
Mike Stump1eb44332009-09-09 15:08:12 +0000156
Ted Kremenek0ee41242009-12-04 01:28:56 +0000157const BlockInvocationContext *
158LocationContextManager::getBlockInvocation(AnalysisContext *ctx,
159 const LocationContext *parent,
Ted Kremenekd02e83a2009-12-04 02:03:51 +0000160 const BlockDataRegion *BR) {
161 return getLocationContext<BlockInvocationContext, BlockDataRegion>(ctx,
162 parent,
163 BR);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000164}
Ted Kremenekb1a7b652009-11-26 02:31:33 +0000165
166//===----------------------------------------------------------------------===//
167// Lazily generated map to query the external variables referenced by a Block.
168//===----------------------------------------------------------------------===//
169
170namespace {
171class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
172 BumpVector<const VarDecl*> &BEVals;
173 BumpVectorContext &BC;
174public:
175 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
176 BumpVectorContext &bc)
177 : BEVals(bevals), BC(bc) {}
178
179 void VisitStmt(Stmt *S) {
180 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I)
181 if (Stmt *child = *I)
182 Visit(child);
183 }
184
185 void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) {
186 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
187 BEVals.push_back(VD, BC);
188 }
189};
190} // end anonymous namespace
191
192typedef BumpVector<const VarDecl*> DeclVec;
193
194static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
195 void *&Vec,
196 llvm::BumpPtrAllocator &A) {
197 if (Vec)
198 return (DeclVec*) Vec;
199
200 BumpVectorContext BC(A);
201 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
202 new (BV) DeclVec(BC, 10);
203
204 // Find the referenced variables.
205 FindBlockDeclRefExprsVals F(*BV, BC);
206 F.Visit(BD->getBody());
207
208 Vec = BV;
209 return BV;
210}
211
212std::pair<AnalysisContext::referenced_decls_iterator,
213 AnalysisContext::referenced_decls_iterator>
214AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
215 if (!ReferencedBlockVars)
216 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
217
218 DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
219 return std::make_pair(V->begin(), V->end());
220}
221
222//===----------------------------------------------------------------------===//
223// Cleanup.
224//===----------------------------------------------------------------------===//
225
226AnalysisContext::~AnalysisContext() {
227 delete cfg;
228 delete liveness;
229 delete PM;
230 delete ReferencedBlockVars;
231}
232
233AnalysisContextManager::~AnalysisContextManager() {
234 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
235 delete I->second;
236}
Ted Kremenek0ee41242009-12-04 01:28:56 +0000237
238LocationContext::~LocationContext() {}
239
240LocationContextManager::~LocationContextManager() {
241 clear();
242}
243
244void LocationContextManager::clear() {
245 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
246 E = Contexts.end(); I != E; ) {
247 LocationContext *LC = &*I;
248 ++I;
249 delete LC;
250 }
251
252 Contexts.clear();
253}
254