blob: 2093b5e23e852cfb7b825c22a5ab610fb9c9b8a0 [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"
Mike Stumpfa6ef182010-01-13 02:59:54 +000021#include "clang/AST/DeclTemplate.h"
Zhongxing Xu97ab3942009-07-30 01:17:21 +000022#include "clang/AST/ParentMap.h"
Ted Kremenekb1a7b652009-11-26 02:31:33 +000023#include "clang/AST/StmtVisitor.h"
24#include "clang/Analysis/Support/BumpVector.h"
Mike Stump87a05f12009-07-31 01:10:29 +000025#include "llvm/Support/ErrorHandling.h"
Zhongxing Xu97ab3942009-07-30 01:17:21 +000026
27using namespace clang;
28
Ted Kremenek58f5ec72009-10-20 21:39:41 +000029void AnalysisContextManager::clear() {
30 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
31 delete I->second;
32 Contexts.clear();
33}
34
Zhongxing Xu97ab3942009-07-30 01:17:21 +000035Stmt *AnalysisContext::getBody() {
Ted Kremenek23760022009-08-21 23:58:43 +000036 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
Zhongxing Xu97ab3942009-07-30 01:17:21 +000037 return FD->getBody();
Ted Kremenek23760022009-08-21 23:58:43 +000038 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
Zhongxing Xu97ab3942009-07-30 01:17:21 +000039 return MD->getBody();
Ted Kremenek30a45342009-12-04 20:34:55 +000040 else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
41 return BD->getBody();
Mike Stumpfa6ef182010-01-13 02:59:54 +000042 else if (const FunctionTemplateDecl *FunTmpl
43 = dyn_cast_or_null<FunctionTemplateDecl>(D))
44 return FunTmpl->getTemplatedDecl()->getBody();
Zhongxing Xu97ab3942009-07-30 01:17:21 +000045
Jeffrey Yasskin9f61aa92009-12-12 05:05:38 +000046 llvm_unreachable("unknown code decl");
Zhongxing Xu97ab3942009-07-30 01:17:21 +000047}
48
Ted Kremenek82cd37c2009-08-21 23:25:54 +000049const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
50 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
51 return MD->getSelfDecl();
Mike Stump1eb44332009-09-09 15:08:12 +000052
Ted Kremenek82cd37c2009-08-21 23:25:54 +000053 return NULL;
54}
55
Zhongxing Xu97ab3942009-07-30 01:17:21 +000056CFG *AnalysisContext::getCFG() {
Mike Stump1eb44332009-09-09 15:08:12 +000057 if (!cfg)
Zhongxing Xu97ab3942009-07-30 01:17:21 +000058 cfg = CFG::buildCFG(getBody(), &D->getASTContext());
59 return cfg;
60}
61
62ParentMap &AnalysisContext::getParentMap() {
Mike Stump1eb44332009-09-09 15:08:12 +000063 if (!PM)
Zhongxing Xu97ab3942009-07-30 01:17:21 +000064 PM = new ParentMap(getBody());
65 return *PM;
66}
67
68LiveVariables *AnalysisContext::getLiveVariables() {
69 if (!liveness) {
70 CFG *c = getCFG();
71 if (!c)
72 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +000073
Ted Kremenekb1a7b652009-11-26 02:31:33 +000074 liveness = new LiveVariables(*this);
Zhongxing Xu97ab3942009-07-30 01:17:21 +000075 liveness->runOnCFG(*c);
76 liveness->runOnAllBlocks(*c, 0, true);
77 }
Mike Stump1eb44332009-09-09 15:08:12 +000078
Zhongxing Xu97ab3942009-07-30 01:17:21 +000079 return liveness;
80}
81
Ted Kremenek23760022009-08-21 23:58:43 +000082AnalysisContext *AnalysisContextManager::getContext(const Decl *D) {
83 AnalysisContext *&AC = Contexts[D];
84 if (!AC)
85 AC = new AnalysisContext(D);
Mike Stump1eb44332009-09-09 15:08:12 +000086
Ted Kremenek23760022009-08-21 23:58:43 +000087 return AC;
Zhongxing Xu97ab3942009-07-30 01:17:21 +000088}
Zhongxing Xu18c7c062009-08-03 07:23:22 +000089
Ted Kremenekd02e83a2009-12-04 02:03:51 +000090const BlockDecl *BlockInvocationContext::getBlockDecl() const {
91 return Data.is<const BlockDataRegion*>() ?
92 Data.get<const BlockDataRegion*>()->getDecl()
93 : Data.get<const BlockDecl*>();
94}
95
Ted Kremenekdc0d9092009-12-04 00:50:10 +000096//===----------------------------------------------------------------------===//
97// FoldingSet profiling.
98//===----------------------------------------------------------------------===//
99
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000100void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
101 ContextKind ck,
102 AnalysisContext *ctx,
103 const LocationContext *parent,
104 const void* data) {
Ted Kremenek0ee41242009-12-04 01:28:56 +0000105 ID.AddInteger(ck);
106 ID.AddPointer(ctx);
107 ID.AddPointer(parent);
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000108 ID.AddPointer(data);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000109}
110
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000111void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
Zhongxing Xu62d399e2009-12-24 03:34:38 +0000112 Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000113}
114
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000115void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
116 Profile(ID, getAnalysisContext(), getParent(), Enter);
117}
118
119void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
Ted Kremenekd02e83a2009-12-04 02:03:51 +0000120 if (const BlockDataRegion *BR = getBlockRegion())
121 Profile(ID, getAnalysisContext(), getParent(), BR);
122 else
123 Profile(ID, getAnalysisContext(), getParent(),
124 Data.get<const BlockDecl*>());
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000125}
126
127//===----------------------------------------------------------------------===//
Ted Kremenek0ee41242009-12-04 01:28:56 +0000128// LocationContext creation.
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000129//===----------------------------------------------------------------------===//
130
Ted Kremenek0ee41242009-12-04 01:28:56 +0000131template <typename LOC, typename DATA>
132const LOC*
133LocationContextManager::getLocationContext(AnalysisContext *ctx,
134 const LocationContext *parent,
135 const DATA *d) {
136 llvm::FoldingSetNodeID ID;
137 LOC::Profile(ID, ctx, parent, d);
138 void *InsertPos;
Ted Kremenek58f5ec72009-10-20 21:39:41 +0000139
Ted Kremenek0ee41242009-12-04 01:28:56 +0000140 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
141
142 if (!L) {
143 L = new LOC(ctx, parent, d);
144 Contexts.InsertNode(L, InsertPos);
145 }
146 return L;
Ted Kremenek58f5ec72009-10-20 21:39:41 +0000147}
148
Ted Kremenek0ee41242009-12-04 01:28:56 +0000149const StackFrameContext*
Mike Stump1eb44332009-09-09 15:08:12 +0000150LocationContextManager::getStackFrame(AnalysisContext *ctx,
Ted Kremenek54c809b2009-08-21 23:39:58 +0000151 const LocationContext *parent,
Zhongxing Xu62d399e2009-12-24 03:34:38 +0000152 const Stmt *s, const CFGBlock *blk,
153 unsigned idx) {
154 llvm::FoldingSetNodeID ID;
155 StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
156 void *InsertPos;
157 StackFrameContext *L =
158 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
159 if (!L) {
160 L = new StackFrameContext(ctx, parent, s, blk, idx);
161 Contexts.InsertNode(L, InsertPos);
162 }
163 return L;
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000164}
165
Ted Kremenek0ee41242009-12-04 01:28:56 +0000166const ScopeContext *
167LocationContextManager::getScope(AnalysisContext *ctx,
168 const LocationContext *parent,
169 const Stmt *s) {
170 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
171}
Mike Stump1eb44332009-09-09 15:08:12 +0000172
Ted Kremenek0ee41242009-12-04 01:28:56 +0000173const BlockInvocationContext *
174LocationContextManager::getBlockInvocation(AnalysisContext *ctx,
175 const LocationContext *parent,
Ted Kremenekd02e83a2009-12-04 02:03:51 +0000176 const BlockDataRegion *BR) {
177 return getLocationContext<BlockInvocationContext, BlockDataRegion>(ctx,
178 parent,
179 BR);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000180}
Ted Kremenekb1a7b652009-11-26 02:31:33 +0000181
182//===----------------------------------------------------------------------===//
Ted Kremenek67d12872009-12-07 22:05:27 +0000183// LocationContext methods.
184//===----------------------------------------------------------------------===//
185
186const StackFrameContext *LocationContext::getCurrentStackFrame() const {
187 const LocationContext *LC = this;
188 while (LC) {
189 if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
190 return SFC;
191 LC = LC->getParent();
192 }
193 return NULL;
194}
195
Ted Kremenek2b87ae42009-12-11 06:43:27 +0000196const StackFrameContext *
197LocationContext::getStackFrameForDeclContext(const DeclContext *DC) const {
198 const LocationContext *LC = this;
199 while (LC) {
200 if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
201 if (cast<DeclContext>(SFC->getDecl()) == DC)
202 return SFC;
203 }
204 LC = LC->getParent();
205 }
206 return NULL;
207}
208
Ted Kremenek67d12872009-12-07 22:05:27 +0000209//===----------------------------------------------------------------------===//
Ted Kremenekb1a7b652009-11-26 02:31:33 +0000210// Lazily generated map to query the external variables referenced by a Block.
211//===----------------------------------------------------------------------===//
212
213namespace {
214class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
215 BumpVector<const VarDecl*> &BEVals;
216 BumpVectorContext &BC;
217public:
218 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
219 BumpVectorContext &bc)
220 : BEVals(bevals), BC(bc) {}
221
222 void VisitStmt(Stmt *S) {
223 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I)
224 if (Stmt *child = *I)
225 Visit(child);
226 }
227
228 void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) {
229 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
230 BEVals.push_back(VD, BC);
231 }
232};
233} // end anonymous namespace
234
235typedef BumpVector<const VarDecl*> DeclVec;
236
237static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
238 void *&Vec,
239 llvm::BumpPtrAllocator &A) {
240 if (Vec)
241 return (DeclVec*) Vec;
242
243 BumpVectorContext BC(A);
244 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
245 new (BV) DeclVec(BC, 10);
246
247 // Find the referenced variables.
248 FindBlockDeclRefExprsVals F(*BV, BC);
249 F.Visit(BD->getBody());
250
251 Vec = BV;
252 return BV;
253}
254
255std::pair<AnalysisContext::referenced_decls_iterator,
256 AnalysisContext::referenced_decls_iterator>
257AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
258 if (!ReferencedBlockVars)
259 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
260
261 DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
262 return std::make_pair(V->begin(), V->end());
263}
264
265//===----------------------------------------------------------------------===//
266// Cleanup.
267//===----------------------------------------------------------------------===//
268
269AnalysisContext::~AnalysisContext() {
270 delete cfg;
271 delete liveness;
272 delete PM;
273 delete ReferencedBlockVars;
274}
275
276AnalysisContextManager::~AnalysisContextManager() {
277 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
278 delete I->second;
279}
Ted Kremenek0ee41242009-12-04 01:28:56 +0000280
281LocationContext::~LocationContext() {}
282
283LocationContextManager::~LocationContextManager() {
284 clear();
285}
286
287void LocationContextManager::clear() {
288 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
289 E = Contexts.end(); I != E; ) {
290 LocationContext *LC = &*I;
291 ++I;
292 delete LC;
293 }
294
295 Contexts.clear();
296}
297