blob: e28b74dff57b30960b6baff7db796e57a00a6248 [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"
16#include "clang/Analysis/Analyses/LiveVariables.h"
17#include "clang/Analysis/CFG.h"
18#include "clang/AST/Decl.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/ParentMap.h"
Ted Kremenekb1a7b652009-11-26 02:31:33 +000021#include "clang/AST/StmtVisitor.h"
22#include "clang/Analysis/Support/BumpVector.h"
Mike Stump87a05f12009-07-31 01:10:29 +000023#include "llvm/Support/ErrorHandling.h"
Zhongxing Xu97ab3942009-07-30 01:17:21 +000024
25using namespace clang;
26
Ted Kremenek58f5ec72009-10-20 21:39:41 +000027void AnalysisContextManager::clear() {
28 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
29 delete I->second;
30 Contexts.clear();
31}
32
Zhongxing Xu97ab3942009-07-30 01:17:21 +000033Stmt *AnalysisContext::getBody() {
Ted Kremenek23760022009-08-21 23:58:43 +000034 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
Zhongxing Xu97ab3942009-07-30 01:17:21 +000035 return FD->getBody();
Ted Kremenek23760022009-08-21 23:58:43 +000036 else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
Zhongxing Xu97ab3942009-07-30 01:17:21 +000037 return MD->getBody();
38
Mike Stump87a05f12009-07-31 01:10:29 +000039 llvm::llvm_unreachable("unknown code decl");
Zhongxing Xu97ab3942009-07-30 01:17:21 +000040}
41
Ted Kremenek82cd37c2009-08-21 23:25:54 +000042const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
43 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
44 return MD->getSelfDecl();
Mike Stump1eb44332009-09-09 15:08:12 +000045
Ted Kremenek82cd37c2009-08-21 23:25:54 +000046 return NULL;
47}
48
Zhongxing Xu97ab3942009-07-30 01:17:21 +000049CFG *AnalysisContext::getCFG() {
Mike Stump1eb44332009-09-09 15:08:12 +000050 if (!cfg)
Zhongxing Xu97ab3942009-07-30 01:17:21 +000051 cfg = CFG::buildCFG(getBody(), &D->getASTContext());
52 return cfg;
53}
54
55ParentMap &AnalysisContext::getParentMap() {
Mike Stump1eb44332009-09-09 15:08:12 +000056 if (!PM)
Zhongxing Xu97ab3942009-07-30 01:17:21 +000057 PM = new ParentMap(getBody());
58 return *PM;
59}
60
61LiveVariables *AnalysisContext::getLiveVariables() {
62 if (!liveness) {
63 CFG *c = getCFG();
64 if (!c)
65 return 0;
Mike Stump1eb44332009-09-09 15:08:12 +000066
Ted Kremenekb1a7b652009-11-26 02:31:33 +000067 liveness = new LiveVariables(*this);
Zhongxing Xu97ab3942009-07-30 01:17:21 +000068 liveness->runOnCFG(*c);
69 liveness->runOnAllBlocks(*c, 0, true);
70 }
Mike Stump1eb44332009-09-09 15:08:12 +000071
Zhongxing Xu97ab3942009-07-30 01:17:21 +000072 return liveness;
73}
74
Ted Kremenek23760022009-08-21 23:58:43 +000075AnalysisContext *AnalysisContextManager::getContext(const Decl *D) {
76 AnalysisContext *&AC = Contexts[D];
77 if (!AC)
78 AC = new AnalysisContext(D);
Mike Stump1eb44332009-09-09 15:08:12 +000079
Ted Kremenek23760022009-08-21 23:58:43 +000080 return AC;
Zhongxing Xu97ab3942009-07-30 01:17:21 +000081}
Zhongxing Xu18c7c062009-08-03 07:23:22 +000082
Ted Kremenekdc0d9092009-12-04 00:50:10 +000083//===----------------------------------------------------------------------===//
84// FoldingSet profiling.
85//===----------------------------------------------------------------------===//
86
Ted Kremenekdc0d9092009-12-04 00:50:10 +000087void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
88 ContextKind ck,
89 AnalysisContext *ctx,
90 const LocationContext *parent,
91 const void* data) {
Ted Kremenek0ee41242009-12-04 01:28:56 +000092 ID.AddInteger(ck);
93 ID.AddPointer(ctx);
94 ID.AddPointer(parent);
Ted Kremenekdc0d9092009-12-04 00:50:10 +000095 ID.AddPointer(data);
Zhongxing Xu18c7c062009-08-03 07:23:22 +000096}
97
Ted Kremenekdc0d9092009-12-04 00:50:10 +000098void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
99 Profile(ID, getAnalysisContext(), getParent(), CallSite);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000100}
101
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000102void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
103 Profile(ID, getAnalysisContext(), getParent(), Enter);
104}
105
106void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
107 Profile(ID, getAnalysisContext(), getParent(), BD);
108}
109
110//===----------------------------------------------------------------------===//
Ted Kremenek0ee41242009-12-04 01:28:56 +0000111// LocationContext creation.
Ted Kremenekdc0d9092009-12-04 00:50:10 +0000112//===----------------------------------------------------------------------===//
113
Ted Kremenek0ee41242009-12-04 01:28:56 +0000114template <typename LOC, typename DATA>
115const LOC*
116LocationContextManager::getLocationContext(AnalysisContext *ctx,
117 const LocationContext *parent,
118 const DATA *d) {
119 llvm::FoldingSetNodeID ID;
120 LOC::Profile(ID, ctx, parent, d);
121 void *InsertPos;
Ted Kremenek58f5ec72009-10-20 21:39:41 +0000122
Ted Kremenek0ee41242009-12-04 01:28:56 +0000123 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
124
125 if (!L) {
126 L = new LOC(ctx, parent, d);
127 Contexts.InsertNode(L, InsertPos);
128 }
129 return L;
Ted Kremenek58f5ec72009-10-20 21:39:41 +0000130}
131
Ted Kremenek0ee41242009-12-04 01:28:56 +0000132const StackFrameContext*
Mike Stump1eb44332009-09-09 15:08:12 +0000133LocationContextManager::getStackFrame(AnalysisContext *ctx,
Ted Kremenek54c809b2009-08-21 23:39:58 +0000134 const LocationContext *parent,
135 const Stmt *s) {
Ted Kremenek0ee41242009-12-04 01:28:56 +0000136 return getLocationContext<StackFrameContext, Stmt>(ctx, parent, s);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000137}
138
Ted Kremenek0ee41242009-12-04 01:28:56 +0000139const ScopeContext *
140LocationContextManager::getScope(AnalysisContext *ctx,
141 const LocationContext *parent,
142 const Stmt *s) {
143 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
144}
Mike Stump1eb44332009-09-09 15:08:12 +0000145
Ted Kremenek0ee41242009-12-04 01:28:56 +0000146const BlockInvocationContext *
147LocationContextManager::getBlockInvocation(AnalysisContext *ctx,
148 const LocationContext *parent,
149 const BlockDecl *BD) {
150 return getLocationContext<BlockInvocationContext, BlockDecl>(ctx, parent, BD);
Zhongxing Xu18c7c062009-08-03 07:23:22 +0000151}
Ted Kremenekb1a7b652009-11-26 02:31:33 +0000152
153//===----------------------------------------------------------------------===//
154// Lazily generated map to query the external variables referenced by a Block.
155//===----------------------------------------------------------------------===//
156
157namespace {
158class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
159 BumpVector<const VarDecl*> &BEVals;
160 BumpVectorContext &BC;
161public:
162 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
163 BumpVectorContext &bc)
164 : BEVals(bevals), BC(bc) {}
165
166 void VisitStmt(Stmt *S) {
167 for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I)
168 if (Stmt *child = *I)
169 Visit(child);
170 }
171
172 void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) {
173 if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
174 BEVals.push_back(VD, BC);
175 }
176};
177} // end anonymous namespace
178
179typedef BumpVector<const VarDecl*> DeclVec;
180
181static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
182 void *&Vec,
183 llvm::BumpPtrAllocator &A) {
184 if (Vec)
185 return (DeclVec*) Vec;
186
187 BumpVectorContext BC(A);
188 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
189 new (BV) DeclVec(BC, 10);
190
191 // Find the referenced variables.
192 FindBlockDeclRefExprsVals F(*BV, BC);
193 F.Visit(BD->getBody());
194
195 Vec = BV;
196 return BV;
197}
198
199std::pair<AnalysisContext::referenced_decls_iterator,
200 AnalysisContext::referenced_decls_iterator>
201AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
202 if (!ReferencedBlockVars)
203 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
204
205 DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
206 return std::make_pair(V->begin(), V->end());
207}
208
209//===----------------------------------------------------------------------===//
210// Cleanup.
211//===----------------------------------------------------------------------===//
212
213AnalysisContext::~AnalysisContext() {
214 delete cfg;
215 delete liveness;
216 delete PM;
217 delete ReferencedBlockVars;
218}
219
220AnalysisContextManager::~AnalysisContextManager() {
221 for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
222 delete I->second;
223}
Ted Kremenek0ee41242009-12-04 01:28:56 +0000224
225LocationContext::~LocationContext() {}
226
227LocationContextManager::~LocationContextManager() {
228 clear();
229}
230
231void LocationContextManager::clear() {
232 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
233 E = Contexts.end(); I != E; ) {
234 LocationContext *LC = &*I;
235 ++I;
236 delete LC;
237 }
238
239 Contexts.clear();
240}
241