 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
71.9% |
69 / 96 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
77.1% |
74 / 96 |
| |
|
Line Coverage: |
84.0% |
126 / 150 |
| |
 |
|
 |
1 : //== 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/CFG.h"
16 : #include "clang/Analysis/AnalysisContext.h"
17 : #include "clang/Analysis/Analyses/LiveVariables.h"
18 : #include "clang/AST/Decl.h"
19 : #include "clang/AST/DeclObjC.h"
20 : #include "clang/AST/DeclTemplate.h"
21 : #include "clang/AST/ParentMap.h"
22 : #include "clang/AST/StmtVisitor.h"
23 : #include "clang/Analysis/Support/BumpVector.h"
24 : #include "llvm/Support/ErrorHandling.h"
25 :
26 : using namespace clang;
27 :
28 2016: void AnalysisContextManager::clear() {
1827: branch 5 taken
2016: branch 6 taken
29 3843: for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
1827: branch 1 taken
0: branch 2 not taken
30 1827: delete I->second;
31 2016: Contexts.clear();
32 2016: }
33 :
34 6251: Stmt *AnalysisContext::getBody() {
5399: branch 1 taken
852: branch 2 taken
35 6251: if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
36 5399: return FD->getBody();
788: branch 1 taken
64: branch 2 taken
37 852: else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
38 788: return MD->getBody();
64: branch 1 taken
0: branch 2 not taken
39 64: else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D))
40 64: return BD->getBody();
0: branch 0 not taken
0: branch 1 not taken
41 0: else if (const FunctionTemplateDecl *FunTmpl
42 0: = dyn_cast_or_null<FunctionTemplateDecl>(D))
43 0: return FunTmpl->getTemplatedDecl()->getBody();
44 :
45 0: llvm_unreachable("unknown code decl");
46 : }
47 :
48 214: const ImplicitParamDecl *AnalysisContext::getSelfDecl() const {
214: branch 1 taken
0: branch 2 not taken
49 214: if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
50 214: return MD->getSelfDecl();
51 :
52 0: return NULL;
53 : }
54 :
55 60682: CFG *AnalysisContext::getCFG() {
5486: branch 0 taken
55196: branch 1 taken
56 60682: if (!cfg)
57 5486: cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), AddEHEdges);
58 60682: return cfg;
59 : }
60 :
61 8405: ParentMap &AnalysisContext::getParentMap() {
765: branch 0 taken
7640: branch 1 taken
62 8405: if (!PM)
63 765: PM = new ParentMap(getBody());
64 8405: return *PM;
65 : }
66 :
67 15243: LiveVariables *AnalysisContext::getLiveVariables() {
1998: branch 0 taken
13245: branch 1 taken
68 15243: if (!liveness) {
69 1998: CFG *c = getCFG();
0: branch 0 not taken
1998: branch 1 taken
70 1998: if (!c)
71 0: return 0;
72 :
73 1998: liveness = new LiveVariables(*this);
74 1998: liveness->runOnCFG(*c);
75 1998: liveness->runOnAllBlocks(*c, 0, true);
76 : }
77 :
78 15243: return liveness;
79 : }
80 :
81 5044: AnalysisContext *AnalysisContextManager::getContext(const Decl *D) {
82 5044: AnalysisContext *&AC = Contexts[D];
2006: branch 0 taken
3038: branch 1 taken
83 5044: if (!AC)
84 2006: AC = new AnalysisContext(D);
85 :
86 5044: return AC;
87 : }
88 :
89 : //===----------------------------------------------------------------------===//
90 : // FoldingSet profiling.
91 : //===----------------------------------------------------------------------===//
92 :
93 : void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
94 : ContextKind ck,
95 : AnalysisContext *ctx,
96 : const LocationContext *parent,
97 2331: const void* data) {
98 2331: ID.AddInteger(ck);
99 2331: ID.AddPointer(ctx);
100 2331: ID.AddPointer(parent);
101 2331: ID.AddPointer(data);
102 2331: }
103 :
104 193: void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
105 193: Profile(ID, getAnalysisContext(), getParent(), CallSite, Block, Index);
106 193: }
107 :
108 0: void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
109 0: Profile(ID, getAnalysisContext(), getParent(), Enter);
110 0: }
111 :
112 0: void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
113 0: Profile(ID, getAnalysisContext(), getParent(), BD);
114 0: }
115 :
116 : //===----------------------------------------------------------------------===//
117 : // LocationContext creation.
118 : //===----------------------------------------------------------------------===//
119 :
120 : template <typename LOC, typename DATA>
121 : const LOC*
122 : LocationContextManager::getLocationContext(AnalysisContext *ctx,
123 : const LocationContext *parent,
124 0: const DATA *d) {
125 0: llvm::FoldingSetNodeID ID;
126 0: LOC::Profile(ID, ctx, parent, d);
127 : void *InsertPos;
128 :
129 0: LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
130 :
0: branch 0 not taken
0: branch 1 not taken
131 0: if (!L) {
132 0: L = new LOC(ctx, parent, d);
0: branch 0 not taken
0: branch 1 not taken
133 0: Contexts.InsertNode(L, InsertPos);
134 : }
135 0: return L;
136 : }
137 :
138 : const StackFrameContext*
139 : LocationContextManager::getStackFrame(AnalysisContext *ctx,
140 : const LocationContext *parent,
141 : const Stmt *s, const CFGBlock *blk,
142 2138: unsigned idx) {
143 2138: llvm::FoldingSetNodeID ID;
144 2138: StackFrameContext::Profile(ID, ctx, parent, s, blk, idx);
145 : void *InsertPos;
146 : StackFrameContext *L =
147 2138: cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
1946: branch 0 taken
192: branch 1 taken
148 2138: if (!L) {
149 1946: L = new StackFrameContext(ctx, parent, s, blk, idx);
1946: branch 0 taken
0: branch 1 not taken
150 1946: Contexts.InsertNode(L, InsertPos);
151 : }
152 2138: return L;
153 : }
154 :
155 : const ScopeContext *
156 : LocationContextManager::getScope(AnalysisContext *ctx,
157 : const LocationContext *parent,
158 0: const Stmt *s) {
159 0: return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
160 : }
161 :
162 : //===----------------------------------------------------------------------===//
163 : // LocationContext methods.
164 : //===----------------------------------------------------------------------===//
165 :
166 12003: const StackFrameContext *LocationContext::getCurrentStackFrame() const {
167 12003: const LocationContext *LC = this;
12003: branch 0 taken
0: branch 1 not taken
168 24006: while (LC) {
12003: branch 1 taken
0: branch 2 not taken
169 12003: if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC))
170 12003: return SFC;
171 0: LC = LC->getParent();
172 : }
173 0: return NULL;
174 : }
175 :
176 : const StackFrameContext *
177 12894: LocationContext::getStackFrameForDeclContext(const DeclContext *DC) const {
178 12894: const LocationContext *LC = this;
12894: branch 0 taken
26: branch 1 taken
179 25814: while (LC) {
12894: branch 1 taken
0: branch 2 not taken
180 12894: if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
12868: branch 2 taken
26: branch 3 taken
181 12894: if (cast<DeclContext>(SFC->getDecl()) == DC)
182 12868: return SFC;
183 : }
184 26: LC = LC->getParent();
185 : }
186 26: return NULL;
187 : }
188 :
189 : //===----------------------------------------------------------------------===//
190 : // Lazily generated map to query the external variables referenced by a Block.
191 : //===----------------------------------------------------------------------===//
192 :
193 : namespace {
194 73: class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
195 : BumpVector<const VarDecl*> &BEVals;
196 : BumpVectorContext &BC;
197 : llvm::DenseMap<const VarDecl*, unsigned> Visited;
198 : public:
199 : FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
200 73: BumpVectorContext &bc)
201 73: : BEVals(bevals), BC(bc) {}
202 :
203 373: void VisitStmt(Stmt *S) {
435: branch 4 taken
373: branch 5 taken
204 808: for (Stmt::child_iterator I = S->child_begin(), E = S->child_end();I!=E;++I)
426: branch 1 taken
9: branch 2 taken
205 435: if (Stmt *child = *I)
206 426: Visit(child);
207 373: }
208 :
209 45: void VisitDeclRefExpr(const DeclRefExpr *DR) {
210 : // Non-local variables are also directly modified.
21: branch 2 taken
24: branch 3 taken
211 45: if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl()))
5: branch 1 taken
16: branch 2 taken
212 21: if (!VD->hasLocalStorage()) {
213 5: unsigned &flag = Visited[VD];
5: branch 0 taken
0: branch 1 not taken
214 5: if (!flag) {
215 5: flag = 1;
216 5: BEVals.push_back(VD, BC);
217 : }
218 : }
219 45: }
220 :
221 81: void VisitBlockDeclRefExpr(BlockDeclRefExpr *DR) {
81: branch 2 taken
0: branch 3 not taken
222 81: if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) {
223 81: unsigned &flag = Visited[VD];
81: branch 0 taken
0: branch 1 not taken
224 81: if (!flag) {
225 81: flag = 1;
226 81: BEVals.push_back(VD, BC);
227 : }
228 : }
229 81: }
230 : };
231 : } // end anonymous namespace
232 :
233 : typedef BumpVector<const VarDecl*> DeclVec;
234 :
235 : static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
236 : void *&Vec,
237 256: llvm::BumpPtrAllocator &A) {
183: branch 0 taken
73: branch 1 taken
238 256: if (Vec)
239 183: return (DeclVec*) Vec;
240 :
241 73: BumpVectorContext BC(A);
242 73: DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
73: branch 1 taken
0: branch 2 not taken
243 73: new (BV) DeclVec(BC, 10);
244 :
245 : // Find the referenced variables.
246 73: FindBlockDeclRefExprsVals F(*BV, BC);
247 73: F.Visit(BD->getBody());
248 :
249 73: Vec = BV;
250 73: return BV;
251 : }
252 :
253 : std::pair<AnalysisContext::referenced_decls_iterator,
254 : AnalysisContext::referenced_decls_iterator>
255 256: AnalysisContext::getReferencedBlockVars(const BlockDecl *BD) {
66: branch 0 taken
190: branch 1 taken
256 256: if (!ReferencedBlockVars)
257 66: ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
258 :
259 256: DeclVec *V = LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
260 256: return std::make_pair(V->begin(), V->end());
261 : }
262 :
263 : //===----------------------------------------------------------------------===//
264 : // Cleanup.
265 : //===----------------------------------------------------------------------===//
266 :
267 11950: AnalysisContext::~AnalysisContext() {
5478: branch 0 taken
6472: branch 1 taken
5478: branch 4 taken
5478: branch 5 taken
268 11950: delete cfg;
1998: branch 0 taken
9952: branch 1 taken
1998: branch 4 taken
1998: branch 5 taken
269 11950: delete liveness;
765: branch 0 taken
11185: branch 1 taken
765: branch 4 taken
765: branch 5 taken
270 11950: delete PM;
66: branch 0 taken
11884: branch 1 taken
66: branch 4 taken
66: branch 5 taken
271 11950: delete ReferencedBlockVars;
272 11950: }
273 :
274 188: AnalysisContextManager::~AnalysisContextManager() {
179: branch 5 taken
188: branch 6 taken
0: branch 12 not taken
0: branch 13 not taken
275 367: for (ContextMap::iterator I = Contexts.begin(), E = Contexts.end(); I!=E; ++I)
179: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
0: branch 7 not taken
276 179: delete I->second;
277 188: }
278 :
1946: branch 0 taken
1946: branch 1 taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 6 not taken
1946: branch 7 taken
279 1946: LocationContext::~LocationContext() {}
280 :
281 188: LocationContextManager::~LocationContextManager() {
282 188: clear();
283 188: }
284 :
285 2204: void LocationContextManager::clear() {
1946: branch 2 taken
2204: branch 3 taken
286 8558: for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
287 2204: E = Contexts.end(); I != E; ) {
288 1946: LocationContext *LC = &*I;
289 1946: ++I;
1946: branch 0 taken
0: branch 1 not taken
290 1946: delete LC;
291 : }
292 :
293 2204: Contexts.clear();
294 2204: }
295 :
Generated: 2010-02-10 01:31 by zcov