blob: 113587f60ed69ebdefe2b03f4bdfdbfa7dfaf8e0 [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();
Ted Kremenek30a45342009-12-04 20:34:55 +000039 else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
40 return BD->getBody();
Zhongxing Xu97ab3942009-07-30 01:17:21 +000041
Mike Stump87a05f12009-07-31 01:10:29 +000042 llvm::llvm_unreachable("unknown code decl");
Zhongxing Xu97ab3942009-07-30 01:17:21 +000043}
44
Ted Kremenek82cd37c2009-08-21 23:25:54 +000045const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
46 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
47 return MD->getSelfDecl();
Mike Stump1eb44332009-09-09 15:08:12 +000048
Ted Kremenek82cd37c2009-08-21 23:25:54 +000049 return NULL;
50}
51
Zhongxing Xu97ab3942009-07-30 01:17:21 +000052CFG *AnalysisContext::getCFG() {
Mike Stump1eb44332009-09-09 15:08:12 +000053 if (!cfg)
Zhongxing Xu97ab3942009-07-30 01:17:21 +000054 cfg = CFG::buildCFG(getBody(), &D->getASTContext());
55 return cfg;
56}
57
58ParentMap &AnalysisContext::getParentMap() {
Mike Stump1eb44332009-09-09 15:08:12 +000059 if (!PM)
Zhongxing Xu97ab3942009-07-30 01:17:21 +000060 PM = new ParentMap(getBody());
61 return *PM;
62}
63
64LiveVariables *AnalysisContext::getLiveVariables() {
65 if (!liveness) {
66 CFG *c = getCFG();
67 if (!c)
68 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +000069
Ted Kremenekb1a7b652009-11-26 02:31:33 +000070 liveness = new LiveVariables(*this);
Zhongxing Xu97ab3942009-07-30 01:17:21 +000071 liveness->runOnCFG(*c);
72 liveness->runOnAllBlocks(*c, 0, true);
73 }
Mike Stump1eb44332009-09-09 15:08:12 +000074
Zhongxing Xu97ab3942009-07-30 01:17:21 +000075 return liveness;
76}
77
Ted Kremenek23760022009-08-21 23:58:43 +000078AnalysisContext *AnalysisContextManager::getContext(const Decl *D) {
79 AnalysisContext *&AC = Contexts[D];
80 if (!AC)
81 AC = new AnalysisContext(D);
Mike Stump1eb44332009-09-09 15:08:12 +000082
Ted Kremenek23760022009-08-21 23:58:43 +000083 return AC;
Zhongxing Xu97ab3942009-07-30 01:17:21 +000084}
Zhongxing Xu18c7c062009-08-03 07:23:22 +000085
Ted Kremenekd02e83a2009-12-04 02:03:51 +000086const BlockDecl *BlockInvocationContext::getBlockDecl() const {
87 return Data.is<const BlockDataRegion*>() ?
88 Data.get<const BlockDataRegion*>()->getDecl()
89 : Data.get<const BlockDecl*>();
90}
91
Ted Kremenekdc0d9092009-12-04 00:50:10 +000092//===----------------------------------------------------------------------===//
93// FoldingSet profiling.
94//===----------------------------------------------------------------------===//
95
Ted Kremenekdc0d9092009-12-04 00:50:10 +000096void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
97 ContextKind ck,
98 AnalysisContext *ctx,
99 const LocationContext *parent,
100 const void* data) {
Ted Kremenek0ee41242009-12-04 01:28:56 +0000101 ID.AddInteger(ck);
102 ID.AddPointer(ctx);
103 ID.AddPointer(parent);
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000104 ID.AddPointer(data);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000105}
106
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000107void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
108 Profile(ID, getAnalysisContext(), getParent(), CallSite);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000109}
110
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000111void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
112 Profile(ID, getAnalysisContext(), getParent(), Enter);
113}
114
115void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
Ted Kremenekd02e83a2009-12-04 02:03:51 +0000116 if (const BlockDataRegion *BR = getBlockRegion())
117 Profile(ID, getAnalysisContext(), getParent(), BR);
118 else
119 Profile(ID, getAnalysisContext(), getParent(),
120 Data.get<const BlockDecl*>());
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000121}
122
123//===----------------------------------------------------------------------===//
Ted Kremenek0ee41242009-12-04 01:28:56 +0000124// LocationContext creation.
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000125//===----------------------------------------------------------------------===//
126
Ted Kremenek0ee41242009-12-04 01:28:56 +0000127template <typename LOC, typename DATA>
128const LOC*
129LocationContextManager::getLocationContext(AnalysisContext *ctx,
130 const LocationContext *parent,
131 const DATA *d) {
132 llvm::FoldingSetNodeID ID;
133 LOC::Profile(ID, ctx, parent, d);
134 void *InsertPos;
Ted Kremenek58f5ec72009-10-20 21:39:41 +0000135
Ted Kremenek0ee41242009-12-04 01:28:56 +0000136 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
137
138 if (!L) {
139 L = new LOC(ctx, parent, d);
140 Contexts.InsertNode(L, InsertPos);
141 }
142 return L;
Ted Kremenek58f5ec72009-10-20 21:39:41 +0000143}
144
Ted Kremenek0ee41242009-12-04 01:28:56 +0000145const StackFrameContext*
Mike Stump1eb44332009-09-09 15:08:12 +0000146LocationContextManager::getStackFrame(AnalysisContext *ctx,
Ted Kremenek54c809b2009-08-21 23:39:58 +0000147 const LocationContext *parent,
148 const Stmt *s) {
Ted Kremenek0ee41242009-12-04 01:28:56 +0000149 return getLocationContext<StackFrameContext, Stmt>(ctx, parent, s);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000150}
151
Ted Kremenek0ee41242009-12-04 01:28:56 +0000152const ScopeContext *
153LocationContextManager::getScope(AnalysisContext *ctx,
154 const LocationContext *parent,
155 const Stmt *s) {
156 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
157}
Mike Stump1eb44332009-09-09 15:08:12 +0000158
Ted Kremenek0ee41242009-12-04 01:28:56 +0000159const BlockInvocationContext *
160LocationContextManager::getBlockInvocation(AnalysisContext *ctx,
161 const LocationContext *parent,
Ted Kremenekd02e83a2009-12-04 02:03:51 +0000162 const BlockDataRegion *BR) {
163 return getLocationContext<BlockInvocationContext, BlockDataRegion>(ctx,
164 parent,
165 BR);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000166}
Ted Kremenekb1a7b652009-11-26 02:31:33 +0000167
168//===----------------------------------------------------------------------===//
Ted Kremenek67d12872009-12-07 22:05:27 +0000169// LocationContext methods.
170//===----------------------------------------------------------------------===//
171
172const StackFrameContext *LocationContext::getCurrentStackFrame() const {
173 const LocationContext *LC = this;
174 while (LC) {
175 if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
176 return SFC;
177 LC = LC->getParent();
178 }
179 return NULL;
180}
181
182//===----------------------------------------------------------------------===//
Ted Kremenekb1a7b652009-11-26 02:31:33 +0000183// Lazily generated map to query the external variables referenced by a Block.
184//===----------------------------------------------------------------------===//
185
186namespace {
187class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
188 BumpVector<const VarDecl*> &BEVals;
189 BumpVectorContext &BC;
190public:
191 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
192 BumpVectorContext &bc)
193 : BEVals(bevals), BC(bc) {}
194
195 void VisitStmt(Stmt *S) {
196 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I)
197 if (Stmt *child = *I)
198 Visit(child);
199 }
200
201 void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) {
202 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
203 BEVals.push_back(VD, BC);
204 }
205};
206} // end anonymous namespace
207
208typedef BumpVector<const VarDecl*> DeclVec;
209
210static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
211 void *&Vec,
212 llvm::BumpPtrAllocator &A) {
213 if (Vec)
214 return (DeclVec*) Vec;
215
216 BumpVectorContext BC(A);
217 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
218 new (BV) DeclVec(BC, 10);
219
220 // Find the referenced variables.
221 FindBlockDeclRefExprsVals F(*BV, BC);
222 F.Visit(BD->getBody());
223
224 Vec = BV;
225 return BV;
226}
227
228std::pair<AnalysisContext::referenced_decls_iterator,
229 AnalysisContext::referenced_decls_iterator>
230AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
231 if (!ReferencedBlockVars)
232 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
233
234 DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
235 return std::make_pair(V->begin(), V->end());
236}
237
238//===----------------------------------------------------------------------===//
239// Cleanup.
240//===----------------------------------------------------------------------===//
241
242AnalysisContext::~AnalysisContext() {
243 delete cfg;
244 delete liveness;
245 delete PM;
246 delete ReferencedBlockVars;
247}
248
249AnalysisContextManager::~AnalysisContextManager() {
250 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
251 delete I->second;
252}
Ted Kremenek0ee41242009-12-04 01:28:56 +0000253
254LocationContext::~LocationContext() {}
255
256LocationContextManager::~LocationContextManager() {
257 clear();
258}
259
260void LocationContextManager::clear() {
261 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
262 E = Contexts.end(); I != E; ) {
263 LocationContext *LC = &*I;
264 ++I;
265 delete LC;
266 }
267
268 Contexts.clear();
269}
270