/home/runner/work/DirectXShaderCompiler/DirectXShaderCompiler/tools/clang/lib/Analysis/AnalysisDeclContext.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //== AnalysisDeclContext.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 AnalysisDeclContext, a class that manages the analysis context |
11 | | // data for path sensitive analysis. |
12 | | // |
13 | | //===----------------------------------------------------------------------===// |
14 | | |
15 | | #include "clang/Analysis/AnalysisContext.h" |
16 | | #include "BodyFarm.h" |
17 | | #include "clang/AST/ASTContext.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/Analyses/CFGReachabilityAnalysis.h" |
24 | | #include "clang/Analysis/Analyses/LiveVariables.h" |
25 | | #include "clang/Analysis/Analyses/PseudoConstantAnalysis.h" |
26 | | #include "clang/Analysis/CFG.h" |
27 | | #include "clang/Analysis/CFGStmtMap.h" |
28 | | #include "clang/Analysis/Support/BumpVector.h" |
29 | | #include "llvm/ADT/SmallPtrSet.h" |
30 | | #include "llvm/Support/ErrorHandling.h" |
31 | | #include "llvm/Support/SaveAndRestore.h" |
32 | | #include "llvm/Support/raw_ostream.h" |
33 | | |
34 | | using namespace clang; |
35 | | |
36 | | typedef llvm::DenseMap<const void *, ManagedAnalysis *> ManagedAnalysisMap; |
37 | | |
38 | | AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr, |
39 | | const Decl *d, |
40 | | const CFG::BuildOptions &buildOptions) |
41 | 312 | : Manager(Mgr), |
42 | 312 | D(d), |
43 | 312 | cfgBuildOptions(buildOptions), |
44 | 312 | forcedBlkExprs(nullptr), |
45 | 312 | builtCFG(false), |
46 | 312 | builtCompleteCFG(false), |
47 | 312 | ReferencedBlockVars(nullptr), |
48 | 312 | ManagedAnalyses(nullptr) |
49 | 312 | { |
50 | 312 | cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; |
51 | 312 | } |
52 | | |
53 | | AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr, |
54 | | const Decl *d) |
55 | 60.0k | : Manager(Mgr), |
56 | 60.0k | D(d), |
57 | 60.0k | forcedBlkExprs(nullptr), |
58 | 60.0k | builtCFG(false), |
59 | 60.0k | builtCompleteCFG(false), |
60 | 60.0k | ReferencedBlockVars(nullptr), |
61 | 60.0k | ManagedAnalyses(nullptr) |
62 | 60.0k | { |
63 | 60.0k | cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs; |
64 | 60.0k | } |
65 | | |
66 | | AnalysisDeclContextManager::AnalysisDeclContextManager(bool useUnoptimizedCFG, |
67 | | bool addImplicitDtors, |
68 | | bool addInitializers, |
69 | | bool addTemporaryDtors, |
70 | | bool synthesizeBodies, |
71 | | bool addStaticInitBranch, |
72 | | bool addCXXNewAllocator, |
73 | | CodeInjector *injector) |
74 | 312 | : Injector(injector), SynthesizeBodies(synthesizeBodies) |
75 | 312 | { |
76 | 312 | cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG; |
77 | 312 | cfgBuildOptions.AddImplicitDtors = addImplicitDtors; |
78 | 312 | cfgBuildOptions.AddInitializers = addInitializers; |
79 | 312 | cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors; |
80 | 312 | cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch; |
81 | 312 | cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator; |
82 | 312 | } |
83 | | |
84 | 0 | void AnalysisDeclContextManager::clear() { |
85 | 0 | llvm::DeleteContainerSeconds(Contexts); |
86 | 0 | } |
87 | | |
88 | 0 | static BodyFarm &getBodyFarm(ASTContext &C, CodeInjector *injector = nullptr) { |
89 | 0 | static BodyFarm *BF = new BodyFarm(C, injector); |
90 | 0 | return *BF; |
91 | 0 | } |
92 | | |
93 | 60.2k | Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const { |
94 | 60.2k | IsAutosynthesized = false; |
95 | 60.2k | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
96 | 60.2k | Stmt *Body = FD->getBody(); |
97 | 60.2k | if (!Body && Manager0 && Manager->synthesizeBodies()0 ) { |
98 | 0 | Body = getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(FD); |
99 | 0 | if (Body) |
100 | 0 | IsAutosynthesized = true; |
101 | 0 | } |
102 | 60.2k | return Body; |
103 | 60.2k | } |
104 | 0 | else if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) { |
105 | 0 | Stmt *Body = MD->getBody(); |
106 | 0 | if (!Body && Manager && Manager->synthesizeBodies()) { |
107 | 0 | Body = getBodyFarm(getASTContext(), Manager->Injector.get()).getBody(MD); |
108 | 0 | if (Body) |
109 | 0 | IsAutosynthesized = true; |
110 | 0 | } |
111 | 0 | return Body; |
112 | 0 | } else if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) |
113 | 0 | return BD->getBody(); |
114 | 0 | else if (const FunctionTemplateDecl *FunTmpl |
115 | 0 | = dyn_cast_or_null<FunctionTemplateDecl>(D)) |
116 | 0 | return FunTmpl->getTemplatedDecl()->getBody(); |
117 | | |
118 | 60.2k | llvm_unreachable0 ("unknown code decl"); |
119 | 60.2k | } |
120 | | |
121 | 60.2k | Stmt *AnalysisDeclContext::getBody() const { |
122 | 60.2k | bool Tmp; |
123 | 60.2k | return getBody(Tmp); |
124 | 60.2k | } |
125 | | |
126 | 0 | bool AnalysisDeclContext::isBodyAutosynthesized() const { |
127 | 0 | bool Tmp; |
128 | 0 | getBody(Tmp); |
129 | 0 | return Tmp; |
130 | 0 | } |
131 | | |
132 | 0 | bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const { |
133 | 0 | bool Tmp; |
134 | 0 | Stmt *Body = getBody(Tmp); |
135 | 0 | return Tmp && Body->getLocStart().isValid(); |
136 | 0 | } |
137 | | |
138 | | |
139 | 0 | const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const { |
140 | 0 | if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) |
141 | 0 | return MD->getSelfDecl(); |
142 | 0 | if (const BlockDecl *BD = dyn_cast<BlockDecl>(D)) { |
143 | | // See if 'self' was captured by the block. |
144 | 0 | for (const auto &I : BD->captures()) { |
145 | 0 | const VarDecl *VD = I.getVariable(); |
146 | 0 | if (VD->getName() == "self") |
147 | 0 | return dyn_cast<ImplicitParamDecl>(VD); |
148 | 0 | } |
149 | 0 | } |
150 | | |
151 | 0 | return nullptr; |
152 | 0 | } |
153 | | |
154 | 1.35k | void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) { |
155 | 1.35k | if (!forcedBlkExprs) |
156 | 360 | forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs(); |
157 | | // Default construct an entry for 'stmt'. |
158 | 1.35k | if (const Expr *e = dyn_cast<Expr>(stmt)) |
159 | 1.35k | stmt = e->IgnoreParens(); |
160 | 1.35k | (void) (*forcedBlkExprs)[stmt]; |
161 | 1.35k | } |
162 | | |
163 | | const CFGBlock * |
164 | 1.35k | AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) { |
165 | 1.35k | assert(forcedBlkExprs); |
166 | 1.35k | if (const Expr *e = dyn_cast<Expr>(stmt)) |
167 | 1.35k | stmt = e->IgnoreParens(); |
168 | 1.35k | CFG::BuildOptions::ForcedBlkExprs::const_iterator itr = |
169 | 1.35k | forcedBlkExprs->find(stmt); |
170 | 1.35k | assert(itr != forcedBlkExprs->end()); |
171 | 1.35k | return itr->second; |
172 | 1.35k | } |
173 | | |
174 | | /// Add each synthetic statement in the CFG to the parent map, using the |
175 | | /// source statement's parent. |
176 | 0 | static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) { |
177 | 0 | if (!TheCFG) |
178 | 0 | return; |
179 | | |
180 | 0 | for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(), |
181 | 0 | E = TheCFG->synthetic_stmt_end(); |
182 | 0 | I != E; ++I) { |
183 | 0 | PM.setParent(I->first, PM.getParent(I->second)); |
184 | 0 | } |
185 | 0 | } |
186 | | |
187 | 125k | CFG *AnalysisDeclContext::getCFG() { |
188 | 125k | if (!cfgBuildOptions.PruneTriviallyFalseEdges) |
189 | 0 | return getUnoptimizedCFG(); |
190 | | |
191 | 125k | if (!builtCFG) { |
192 | 60.2k | cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions); |
193 | | // Even when the cfg is not successfully built, we don't |
194 | | // want to try building it again. |
195 | 60.2k | builtCFG = true; |
196 | | |
197 | 60.2k | if (PM) |
198 | 0 | addParentsForSyntheticStmts(cfg.get(), *PM); |
199 | | |
200 | | // The Observer should only observe one build of the CFG. |
201 | 60.2k | getCFGBuildOptions().Observer = nullptr; |
202 | 60.2k | } |
203 | 125k | return cfg.get(); |
204 | 125k | } |
205 | | |
206 | 0 | CFG *AnalysisDeclContext::getUnoptimizedCFG() { |
207 | 0 | if (!builtCompleteCFG) { |
208 | 0 | SaveAndRestore<bool> NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges, |
209 | 0 | false); |
210 | 0 | completeCFG = |
211 | 0 | CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions); |
212 | | // Even when the cfg is not successfully built, we don't |
213 | | // want to try building it again. |
214 | 0 | builtCompleteCFG = true; |
215 | |
|
216 | 0 | if (PM) |
217 | 0 | addParentsForSyntheticStmts(completeCFG.get(), *PM); |
218 | | |
219 | | // The Observer should only observe one build of the CFG. |
220 | 0 | getCFGBuildOptions().Observer = nullptr; |
221 | 0 | } |
222 | 0 | return completeCFG.get(); |
223 | 0 | } |
224 | | |
225 | 0 | CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() { |
226 | 0 | if (cfgStmtMap) |
227 | 0 | return cfgStmtMap.get(); |
228 | | |
229 | 0 | if (CFG *c = getCFG()) { |
230 | 0 | cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap())); |
231 | 0 | return cfgStmtMap.get(); |
232 | 0 | } |
233 | | |
234 | 0 | return nullptr; |
235 | 0 | } |
236 | | |
237 | 1.35k | CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() { |
238 | 1.35k | if (CFA) |
239 | 998 | return CFA.get(); |
240 | | |
241 | 360 | if (CFG *c = getCFG()) { |
242 | 360 | CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c)); |
243 | 360 | return CFA.get(); |
244 | 360 | } |
245 | | |
246 | 0 | return nullptr; |
247 | 360 | } |
248 | | |
249 | 0 | void AnalysisDeclContext::dumpCFG(bool ShowColors) { |
250 | 0 | getCFG()->dump(getASTContext().getLangOpts(), ShowColors); |
251 | 0 | } |
252 | | |
253 | 0 | ParentMap &AnalysisDeclContext::getParentMap() { |
254 | 0 | if (!PM) { |
255 | 0 | PM.reset(new ParentMap(getBody())); |
256 | 0 | if (const CXXConstructorDecl *C = dyn_cast<CXXConstructorDecl>(getDecl())) { |
257 | 0 | for (const auto *I : C->inits()) { |
258 | 0 | PM->addStmt(I->getInit()); |
259 | 0 | } |
260 | 0 | } |
261 | 0 | if (builtCFG) |
262 | 0 | addParentsForSyntheticStmts(getCFG(), *PM); |
263 | 0 | if (builtCompleteCFG) |
264 | 0 | addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM); |
265 | 0 | } |
266 | 0 | return *PM; |
267 | 0 | } |
268 | | |
269 | 0 | PseudoConstantAnalysis *AnalysisDeclContext::getPseudoConstantAnalysis() { |
270 | 0 | if (!PCA) |
271 | 0 | PCA.reset(new PseudoConstantAnalysis(getBody())); |
272 | 0 | return PCA.get(); |
273 | 0 | } |
274 | | |
275 | 312 | AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) { |
276 | 312 | if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
277 | | // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl |
278 | | // that has the body. |
279 | 312 | FD->hasBody(FD); |
280 | 312 | D = FD; |
281 | 312 | } |
282 | | |
283 | 312 | AnalysisDeclContext *&AC = Contexts[D]; |
284 | 312 | if (!AC) |
285 | 312 | AC = new AnalysisDeclContext(this, D, cfgBuildOptions); |
286 | 312 | return AC; |
287 | 312 | } |
288 | | |
289 | | const StackFrameContext * |
290 | | AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S, |
291 | 0 | const CFGBlock *Blk, unsigned Idx) { |
292 | 0 | return getLocationContextManager().getStackFrame(this, Parent, S, Blk, Idx); |
293 | 0 | } |
294 | | |
295 | | const BlockInvocationContext * |
296 | | AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent, |
297 | | const clang::BlockDecl *BD, |
298 | 0 | const void *ContextData) { |
299 | 0 | return getLocationContextManager().getBlockInvocationContext(this, parent, |
300 | 0 | BD, ContextData); |
301 | 0 | } |
302 | | |
303 | 0 | LocationContextManager & AnalysisDeclContext::getLocationContextManager() { |
304 | 0 | assert(Manager && |
305 | 0 | "Cannot create LocationContexts without an AnalysisDeclContextManager!"); |
306 | 0 | return Manager->getLocationContextManager(); |
307 | 0 | } |
308 | | |
309 | | //===----------------------------------------------------------------------===// |
310 | | // FoldingSet profiling. |
311 | | //===----------------------------------------------------------------------===// |
312 | | |
313 | | void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID, |
314 | | ContextKind ck, |
315 | | AnalysisDeclContext *ctx, |
316 | | const LocationContext *parent, |
317 | 0 | const void *data) { |
318 | 0 | ID.AddInteger(ck); |
319 | 0 | ID.AddPointer(ctx); |
320 | 0 | ID.AddPointer(parent); |
321 | 0 | ID.AddPointer(data); |
322 | 0 | } |
323 | | |
324 | 0 | void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) { |
325 | 0 | Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block, Index); |
326 | 0 | } |
327 | | |
328 | 0 | void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) { |
329 | 0 | Profile(ID, getAnalysisDeclContext(), getParent(), Enter); |
330 | 0 | } |
331 | | |
332 | 0 | void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) { |
333 | 0 | Profile(ID, getAnalysisDeclContext(), getParent(), BD, ContextData); |
334 | 0 | } |
335 | | |
336 | | //===----------------------------------------------------------------------===// |
337 | | // LocationContext creation. |
338 | | //===----------------------------------------------------------------------===// |
339 | | |
340 | | template <typename LOC, typename DATA> |
341 | | const LOC* |
342 | | LocationContextManager::getLocationContext(AnalysisDeclContext *ctx, |
343 | | const LocationContext *parent, |
344 | 0 | const DATA *d) { |
345 | 0 | llvm::FoldingSetNodeID ID; |
346 | 0 | LOC::Profile(ID, ctx, parent, d); |
347 | 0 | void *InsertPos; |
348 | |
|
349 | 0 | LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); |
350 | |
|
351 | 0 | if (!L) { |
352 | 0 | L = new LOC(ctx, parent, d); |
353 | 0 | Contexts.InsertNode(L, InsertPos); |
354 | 0 | } |
355 | 0 | return L; |
356 | 0 | } |
357 | | |
358 | | const StackFrameContext* |
359 | | LocationContextManager::getStackFrame(AnalysisDeclContext *ctx, |
360 | | const LocationContext *parent, |
361 | | const Stmt *s, |
362 | 0 | const CFGBlock *blk, unsigned idx) { |
363 | 0 | llvm::FoldingSetNodeID ID; |
364 | 0 | StackFrameContext::Profile(ID, ctx, parent, s, blk, idx); |
365 | 0 | void *InsertPos; |
366 | 0 | StackFrameContext *L = |
367 | 0 | cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos)); |
368 | 0 | if (!L) { |
369 | 0 | L = new StackFrameContext(ctx, parent, s, blk, idx); |
370 | 0 | Contexts.InsertNode(L, InsertPos); |
371 | 0 | } |
372 | 0 | return L; |
373 | 0 | } |
374 | | |
375 | | const ScopeContext * |
376 | | LocationContextManager::getScope(AnalysisDeclContext *ctx, |
377 | | const LocationContext *parent, |
378 | 0 | const Stmt *s) { |
379 | 0 | return getLocationContext<ScopeContext, Stmt>(ctx, parent, s); |
380 | 0 | } |
381 | | |
382 | | const BlockInvocationContext * |
383 | | LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx, |
384 | | const LocationContext *parent, |
385 | | const BlockDecl *BD, |
386 | 0 | const void *ContextData) { |
387 | 0 | llvm::FoldingSetNodeID ID; |
388 | 0 | BlockInvocationContext::Profile(ID, ctx, parent, BD, ContextData); |
389 | 0 | void *InsertPos; |
390 | 0 | BlockInvocationContext *L = |
391 | 0 | cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID, |
392 | 0 | InsertPos)); |
393 | 0 | if (!L) { |
394 | 0 | L = new BlockInvocationContext(ctx, parent, BD, ContextData); |
395 | 0 | Contexts.InsertNode(L, InsertPos); |
396 | 0 | } |
397 | 0 | return L; |
398 | 0 | } |
399 | | |
400 | | //===----------------------------------------------------------------------===// |
401 | | // LocationContext methods. |
402 | | //===----------------------------------------------------------------------===// |
403 | | |
404 | 0 | const StackFrameContext *LocationContext::getCurrentStackFrame() const { |
405 | 0 | const LocationContext *LC = this; |
406 | 0 | while (LC) { |
407 | 0 | if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) |
408 | 0 | return SFC; |
409 | 0 | LC = LC->getParent(); |
410 | 0 | } |
411 | 0 | return nullptr; |
412 | 0 | } |
413 | | |
414 | 0 | bool LocationContext::inTopFrame() const { |
415 | 0 | return getCurrentStackFrame()->inTopFrame(); |
416 | 0 | } |
417 | | |
418 | 0 | bool LocationContext::isParentOf(const LocationContext *LC) const { |
419 | 0 | do { |
420 | 0 | const LocationContext *Parent = LC->getParent(); |
421 | 0 | if (Parent == this) |
422 | 0 | return true; |
423 | 0 | else |
424 | 0 | LC = Parent; |
425 | 0 | } while (LC); |
426 | | |
427 | 0 | return false; |
428 | 0 | } |
429 | | |
430 | 0 | void LocationContext::dumpStack(raw_ostream &OS, StringRef Indent) const { |
431 | 0 | ASTContext &Ctx = getAnalysisDeclContext()->getASTContext(); |
432 | 0 | PrintingPolicy PP(Ctx.getLangOpts()); |
433 | 0 | PP.TerseOutput = 1; |
434 | |
|
435 | 0 | unsigned Frame = 0; |
436 | 0 | for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) { |
437 | 0 | switch (LCtx->getKind()) { |
438 | 0 | case StackFrame: |
439 | 0 | OS << Indent << '#' << Frame++ << ' '; |
440 | 0 | cast<StackFrameContext>(LCtx)->getDecl()->print(OS, PP); |
441 | 0 | OS << '\n'; |
442 | 0 | break; |
443 | 0 | case Scope: |
444 | 0 | OS << Indent << " (scope)\n"; |
445 | 0 | break; |
446 | 0 | case Block: |
447 | 0 | OS << Indent << " (block context: " |
448 | 0 | << cast<BlockInvocationContext>(LCtx)->getContextData() |
449 | 0 | << ")\n"; |
450 | 0 | break; |
451 | 0 | } |
452 | 0 | } |
453 | 0 | } |
454 | | |
455 | 0 | LLVM_DUMP_METHOD void LocationContext::dumpStack() const { |
456 | 0 | dumpStack(llvm::errs()); |
457 | 0 | } |
458 | | |
459 | | //===----------------------------------------------------------------------===// |
460 | | // Lazily generated map to query the external variables referenced by a Block. |
461 | | //===----------------------------------------------------------------------===// |
462 | | |
463 | | namespace { |
464 | | class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{ |
465 | | BumpVector<const VarDecl*> &BEVals; |
466 | | BumpVectorContext &BC; |
467 | | llvm::SmallPtrSet<const VarDecl*, 4> Visited; |
468 | | llvm::SmallPtrSet<const DeclContext*, 4> IgnoredContexts; |
469 | | public: |
470 | | FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals, |
471 | | BumpVectorContext &bc) |
472 | 0 | : BEVals(bevals), BC(bc) {} |
473 | | |
474 | 0 | void VisitStmt(Stmt *S) { |
475 | 0 | for (Stmt *Child : S->children()) |
476 | 0 | if (Child) |
477 | 0 | Visit(Child); |
478 | 0 | } |
479 | | |
480 | 0 | void VisitDeclRefExpr(DeclRefExpr *DR) { |
481 | | // Non-local variables are also directly modified. |
482 | 0 | if (const VarDecl *VD = dyn_cast<VarDecl>(DR->getDecl())) { |
483 | 0 | if (!VD->hasLocalStorage()) { |
484 | 0 | if (Visited.insert(VD).second) |
485 | 0 | BEVals.push_back(VD, BC); |
486 | 0 | } |
487 | 0 | } |
488 | 0 | } |
489 | | |
490 | 0 | void VisitBlockExpr(BlockExpr *BR) { |
491 | | // Blocks containing blocks can transitively capture more variables. |
492 | 0 | IgnoredContexts.insert(BR->getBlockDecl()); |
493 | 0 | Visit(BR->getBlockDecl()->getBody()); |
494 | 0 | } |
495 | | |
496 | 0 | void VisitPseudoObjectExpr(PseudoObjectExpr *PE) { |
497 | 0 | for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(), |
498 | 0 | et = PE->semantics_end(); it != et; ++it) { |
499 | 0 | Expr *Semantic = *it; |
500 | 0 | if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Semantic)) |
501 | 0 | Semantic = OVE->getSourceExpr(); |
502 | 0 | Visit(Semantic); |
503 | 0 | } |
504 | 0 | } |
505 | | }; |
506 | | } // end anonymous namespace |
507 | | |
508 | | typedef BumpVector<const VarDecl*> DeclVec; |
509 | | |
510 | | static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD, |
511 | | void *&Vec, |
512 | 0 | llvm::BumpPtrAllocator &A) { |
513 | 0 | if (Vec) |
514 | 0 | return (DeclVec*) Vec; |
515 | | |
516 | 0 | BumpVectorContext BC(A); |
517 | 0 | DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>(); |
518 | 0 | new (BV) DeclVec(BC, 10); |
519 | | |
520 | | // Go through the capture list. |
521 | 0 | for (const auto &CI : BD->captures()) { |
522 | 0 | BV->push_back(CI.getVariable(), BC); |
523 | 0 | } |
524 | | |
525 | | // Find the referenced global/static variables. |
526 | 0 | FindBlockDeclRefExprsVals F(*BV, BC); |
527 | 0 | F.Visit(BD->getBody()); |
528 | |
|
529 | 0 | Vec = BV; |
530 | 0 | return BV; |
531 | 0 | } |
532 | | |
533 | | llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator> |
534 | 0 | AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) { |
535 | 0 | if (!ReferencedBlockVars) |
536 | 0 | ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>(); |
537 | |
|
538 | 0 | const DeclVec *V = |
539 | 0 | LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A); |
540 | 0 | return llvm::make_range(V->begin(), V->end()); |
541 | 0 | } |
542 | | |
543 | 25.8k | ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) { |
544 | 25.8k | if (!ManagedAnalyses) |
545 | 25.8k | ManagedAnalyses = new ManagedAnalysisMap(); |
546 | 25.8k | ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; |
547 | 25.8k | return (*M)[tag]; |
548 | 25.8k | } |
549 | | |
550 | | //===----------------------------------------------------------------------===// |
551 | | // Cleanup. |
552 | | //===----------------------------------------------------------------------===// |
553 | | |
554 | 26.1k | ManagedAnalysis::~ManagedAnalysis() {} |
555 | | |
556 | 60.3k | AnalysisDeclContext::~AnalysisDeclContext() { |
557 | 60.3k | delete forcedBlkExprs; |
558 | 60.3k | delete ReferencedBlockVars; |
559 | | // Release the managed analyses. |
560 | 60.3k | if (ManagedAnalyses) { |
561 | 25.8k | ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses; |
562 | 25.8k | llvm::DeleteContainerSeconds(*M); |
563 | 25.8k | delete M; |
564 | 25.8k | } |
565 | 60.3k | } |
566 | | |
567 | 312 | AnalysisDeclContextManager::~AnalysisDeclContextManager() { |
568 | 312 | llvm::DeleteContainerSeconds(Contexts); |
569 | 312 | } |
570 | | |
571 | 0 | LocationContext::~LocationContext() {} |
572 | | |
573 | 312 | LocationContextManager::~LocationContextManager() { |
574 | 312 | clear(); |
575 | 312 | } |
576 | | |
577 | 312 | void LocationContextManager::clear() { |
578 | 312 | for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(), |
579 | 312 | E = Contexts.end(); I != E; ) { |
580 | 0 | LocationContext *LC = &*I; |
581 | 0 | ++I; |
582 | 0 | delete LC; |
583 | 0 | } |
584 | | |
585 | 312 | Contexts.clear(); |
586 | 312 | } |
587 | | |