1//===- AnalysisDeclContext.cpp - Analysis context for Path Sens analysis --===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file defines AnalysisDeclContext, a class that manages the analysis
10// context data for path sensitive analysis.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Analysis/AnalysisDeclContext.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/Decl.h"
17#include "clang/AST/DeclBase.h"
18#include "clang/AST/DeclCXX.h"
19#include "clang/AST/DeclObjC.h"
20#include "clang/AST/DeclTemplate.h"
21#include "clang/AST/Expr.h"
22#include "clang/AST/LambdaCapture.h"
23#include "clang/AST/ParentMap.h"
24#include "clang/AST/PrettyPrinter.h"
25#include "clang/AST/Stmt.h"
26#include "clang/AST/StmtCXX.h"
27#include "clang/AST/StmtVisitor.h"
28#include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
29#include "clang/Analysis/BodyFarm.h"
30#include "clang/Analysis/CFG.h"
31#include "clang/Analysis/CFGStmtMap.h"
32#include "clang/Analysis/Support/BumpVector.h"
33#include "clang/Basic/JsonSupport.h"
34#include "clang/Basic/LLVM.h"
35#include "clang/Basic/SourceLocation.h"
36#include "clang/Basic/SourceManager.h"
37#include "llvm/ADT/DenseMap.h"
38#include "llvm/ADT/FoldingSet.h"
39#include "llvm/ADT/SmallPtrSet.h"
40#include "llvm/ADT/iterator_range.h"
41#include "llvm/Support/Allocator.h"
42#include "llvm/Support/Compiler.h"
43#include "llvm/Support/ErrorHandling.h"
44#include "llvm/Support/SaveAndRestore.h"
45#include "llvm/Support/raw_ostream.h"
46#include <cassert>
47#include <memory>
48
49using namespace clang;
50
51using ManagedAnalysisMap = llvm::DenseMap<const void *, std::unique_ptr<ManagedAnalysis>>;
52
53AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
54 const Decl *D,
55 const CFG::BuildOptions &Options)
56 : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
57 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
58}
59
60AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
61 const Decl *D)
62 : ADCMgr(ADCMgr), D(D) {
63 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
64}
65
66AnalysisDeclContextManager::AnalysisDeclContextManager(
67 ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors,
68 bool addInitializers, bool addTemporaryDtors, bool addLifetime,
69 bool addLoopExit, bool addScopes, bool synthesizeBodies,
70 bool addStaticInitBranch, bool addCXXNewAllocator,
71 bool addRichCXXConstructors, bool markElidedCXXConstructors,
72 bool addVirtualBaseBranches, std::unique_ptr<CodeInjector> injector)
73 : Injector(std::move(injector)), FunctionBodyFarm(ASTCtx, Injector.get()),
74 SynthesizeBodies(synthesizeBodies) {
75 cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
76 cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
77 cfgBuildOptions.AddInitializers = addInitializers;
78 cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
79 cfgBuildOptions.AddLifetime = addLifetime;
80 cfgBuildOptions.AddLoopExit = addLoopExit;
81 cfgBuildOptions.AddScopes = addScopes;
82 cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
83 cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
84 cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
85 cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors;
86 cfgBuildOptions.AddVirtualBaseBranches = addVirtualBaseBranches;
87}
88
89void AnalysisDeclContextManager::clear() { Contexts.clear(); }
90
91Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
92 IsAutosynthesized = false;
93 if (const auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
94 Stmt *Body = FD->getBody();
95 if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Val: Body))
96 Body = CoroBody->getBody();
97 if (ADCMgr && ADCMgr->synthesizeBodies()) {
98 Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(D: FD);
99 if (SynthesizedBody) {
100 Body = SynthesizedBody;
101 IsAutosynthesized = true;
102 }
103 }
104 return Body;
105 }
106 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(Val: D)) {
107 Stmt *Body = MD->getBody();
108 if (ADCMgr && ADCMgr->synthesizeBodies()) {
109 Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(D: MD);
110 if (SynthesizedBody) {
111 Body = SynthesizedBody;
112 IsAutosynthesized = true;
113 }
114 }
115 return Body;
116 } else if (const auto *BD = dyn_cast<BlockDecl>(Val: D))
117 return BD->getBody();
118 else if (const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(Val: D))
119 return FunTmpl->getTemplatedDecl()->getBody();
120 else if (const auto *VD = dyn_cast_or_null<VarDecl>(Val: D)) {
121 if (VD->isFileVarDecl()) {
122 return const_cast<Stmt *>(dyn_cast_or_null<Stmt>(Val: VD->getInit()));
123 }
124 }
125
126 llvm_unreachable("unknown code decl");
127}
128
129Stmt *AnalysisDeclContext::getBody() const {
130 bool Tmp;
131 return getBody(IsAutosynthesized&: Tmp);
132}
133
134bool AnalysisDeclContext::isBodyAutosynthesized() const {
135 bool Tmp;
136 getBody(IsAutosynthesized&: Tmp);
137 return Tmp;
138}
139
140bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
141 bool Tmp;
142 Stmt *Body = getBody(IsAutosynthesized&: Tmp);
143 return Tmp && Body->getBeginLoc().isValid();
144}
145
146/// Returns true if \param VD is an Objective-C implicit 'self' parameter.
147static bool isSelfDecl(const VarDecl *VD) {
148 return isa_and_nonnull<ImplicitParamDecl>(Val: VD) && VD->getName() == "self";
149}
150
151const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
152 if (const auto *MD = dyn_cast<ObjCMethodDecl>(Val: D))
153 return MD->getSelfDecl();
154 if (const auto *BD = dyn_cast<BlockDecl>(Val: D)) {
155 // See if 'self' was captured by the block.
156 for (const auto &I : BD->captures()) {
157 const VarDecl *VD = I.getVariable();
158 if (isSelfDecl(VD))
159 return dyn_cast<ImplicitParamDecl>(Val: VD);
160 }
161 }
162
163 auto *CXXMethod = dyn_cast<CXXMethodDecl>(Val: D);
164 if (!CXXMethod)
165 return nullptr;
166
167 const CXXRecordDecl *parent = CXXMethod->getParent();
168 if (!parent->isLambda())
169 return nullptr;
170
171 for (const auto &LC : parent->captures()) {
172 if (!LC.capturesVariable())
173 continue;
174
175 ValueDecl *VD = LC.getCapturedVar();
176 if (isSelfDecl(VD: dyn_cast<VarDecl>(Val: VD)))
177 return dyn_cast<ImplicitParamDecl>(Val: VD);
178 }
179
180 return nullptr;
181}
182
183void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
184 if (!forcedBlkExprs)
185 forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
186 // Default construct an entry for 'stmt'.
187 if (const auto *e = dyn_cast<Expr>(Val: stmt))
188 stmt = e->IgnoreParens();
189 (void) (*forcedBlkExprs)[stmt];
190}
191
192const CFGBlock *
193AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
194 assert(forcedBlkExprs);
195 if (const auto *e = dyn_cast<Expr>(Val: stmt))
196 stmt = e->IgnoreParens();
197 CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
198 forcedBlkExprs->find(Val: stmt);
199 assert(itr != forcedBlkExprs->end());
200 return itr->second;
201}
202
203/// Add each synthetic statement in the CFG to the parent map, using the
204/// source statement's parent.
205static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) {
206 if (!TheCFG)
207 return;
208
209 for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(),
210 E = TheCFG->synthetic_stmt_end();
211 I != E; ++I) {
212 PM.setParent(S: I->first, Parent: PM.getParent(S: I->second));
213 }
214}
215
216CFG *AnalysisDeclContext::getCFG() {
217 if (!cfgBuildOptions.PruneTriviallyFalseEdges)
218 return getUnoptimizedCFG();
219
220 if (!builtCFG) {
221 cfg = CFG::buildCFG(D, AST: getBody(), C: &D->getASTContext(), BO: cfgBuildOptions);
222 // Even when the cfg is not successfully built, we don't
223 // want to try building it again.
224 builtCFG = true;
225
226 if (PM)
227 addParentsForSyntheticStmts(TheCFG: cfg.get(), PM&: *PM);
228
229 // The Observer should only observe one build of the CFG.
230 getCFGBuildOptions().Observer = nullptr;
231 }
232 return cfg.get();
233}
234
235CFG *AnalysisDeclContext::getUnoptimizedCFG() {
236 if (!builtCompleteCFG) {
237 SaveAndRestore NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges, false);
238 completeCFG =
239 CFG::buildCFG(D, AST: getBody(), C: &D->getASTContext(), BO: cfgBuildOptions);
240 // Even when the cfg is not successfully built, we don't
241 // want to try building it again.
242 builtCompleteCFG = true;
243
244 if (PM)
245 addParentsForSyntheticStmts(TheCFG: completeCFG.get(), PM&: *PM);
246
247 // The Observer should only observe one build of the CFG.
248 getCFGBuildOptions().Observer = nullptr;
249 }
250 return completeCFG.get();
251}
252
253const CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
254 if (cfgStmtMap)
255 return &*cfgStmtMap;
256
257 if (const CFG *c = getCFG()) {
258 cfgStmtMap.emplace(args: *c, args&: getParentMap());
259 return &*cfgStmtMap;
260 }
261
262 return nullptr;
263}
264
265CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
266 if (CFA)
267 return CFA.get();
268
269 if (CFG *c = getCFG()) {
270 CFA.reset(p: new CFGReverseBlockReachabilityAnalysis(*c));
271 return CFA.get();
272 }
273
274 return nullptr;
275}
276
277void AnalysisDeclContext::dumpCFG(bool ShowColors) {
278 getCFG()->dump(LO: getASTContext().getLangOpts(), ShowColors);
279}
280
281ParentMap &AnalysisDeclContext::getParentMap() {
282 if (!PM) {
283 PM.reset(p: new ParentMap(getBody()));
284 if (const auto *C = dyn_cast<CXXConstructorDecl>(Val: getDecl())) {
285 for (const auto *I : C->inits()) {
286 PM->addStmt(S: I->getInit());
287 }
288 }
289 if (builtCFG)
290 addParentsForSyntheticStmts(TheCFG: getCFG(), PM&: *PM);
291 if (builtCompleteCFG)
292 addParentsForSyntheticStmts(TheCFG: getUnoptimizedCFG(), PM&: *PM);
293 }
294 return *PM;
295}
296
297AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
298 if (const auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
299 // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
300 // that has the body.
301 FD->hasBody(Definition&: FD);
302 D = FD;
303 }
304
305 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
306 if (!AC)
307 AC = std::make_unique<AnalysisDeclContext>(args: this, args&: D, args&: cfgBuildOptions);
308 return AC.get();
309}
310
311BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
312
313const StackFrameContext *
314AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC,
315 const Stmt *S, const CFGBlock *Blk,
316 unsigned BlockCount, unsigned Index) {
317 return getLocationContextManager().getStackFrame(ADC: this, ParentLC, S, Block: Blk,
318 BlockCount, Index);
319}
320
321const BlockInvocationContext *AnalysisDeclContext::getBlockInvocationContext(
322 const LocationContext *ParentLC, const BlockDecl *BD, const void *Data) {
323 return getLocationContextManager().getBlockInvocationContext(ADC: this, ParentLC,
324 BD, Data);
325}
326
327bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
328 const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
329 const auto *ND = dyn_cast<NamespaceDecl>(Val: DC);
330 if (!ND)
331 return false;
332
333 while (const DeclContext *Parent = ND->getParent()) {
334 if (!isa<NamespaceDecl>(Val: Parent))
335 break;
336 ND = cast<NamespaceDecl>(Val: Parent);
337 }
338
339 return ND->isStdNamespace();
340}
341
342std::string AnalysisDeclContext::getFunctionName(const Decl *D) {
343 std::string Str;
344 llvm::raw_string_ostream OS(Str);
345 const ASTContext &Ctx = D->getASTContext();
346
347 if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(Val: D)) {
348 OS << FD->getQualifiedNameAsString();
349
350 // In C++, there are overloads.
351
352 if (Ctx.getLangOpts().CPlusPlus) {
353 OS << '(';
354 for (const auto &P : FD->parameters()) {
355 if (P != *FD->param_begin())
356 OS << ", ";
357 OS << P->getType();
358 }
359 OS << ')';
360 }
361
362 } else if (isa<BlockDecl>(Val: D)) {
363 PresumedLoc Loc = Ctx.getSourceManager().getPresumedLoc(Loc: D->getLocation());
364
365 if (Loc.isValid()) {
366 OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
367 << ')';
368 }
369
370 } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(Val: D)) {
371
372 // FIXME: copy-pasted from CGDebugInfo.cpp.
373 OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
374 const DeclContext *DC = OMD->getDeclContext();
375 if (const auto *OID = dyn_cast<ObjCImplementationDecl>(Val: DC)) {
376 OS << OID->getName();
377 } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(Val: DC)) {
378 OS << OID->getName();
379 } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(Val: DC)) {
380 if (OC->IsClassExtension()) {
381 OS << OC->getClassInterface()->getName();
382 } else {
383 OS << OC->getIdentifier()->getNameStart() << '('
384 << OC->getIdentifier()->getNameStart() << ')';
385 }
386 } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(Val: DC)) {
387 OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
388 }
389 OS << ' ' << OMD->getSelector().getAsString() << ']';
390 }
391
392 return Str;
393}
394
395LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
396 assert(
397 ADCMgr &&
398 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
399 return ADCMgr->getLocationContextManager();
400}
401
402//===----------------------------------------------------------------------===//
403// FoldingSet profiling.
404//===----------------------------------------------------------------------===//
405
406void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
407 ContextKind ck,
408 AnalysisDeclContext *ctx,
409 const LocationContext *parent,
410 const void *data) {
411 ID.AddInteger(I: ck);
412 ID.AddPointer(Ptr: ctx);
413 ID.AddPointer(Ptr: parent);
414 ID.AddPointer(Ptr: data);
415}
416
417void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
418 Profile(ID, ADC: getAnalysisDeclContext(), ParentLC: getParent(), S: CallSite, Block,
419 BlockCount, Index);
420}
421
422void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
423 Profile(ID, ADC: getAnalysisDeclContext(), ParentLC: getParent(), BD, Data);
424}
425
426//===----------------------------------------------------------------------===//
427// LocationContext creation.
428//===----------------------------------------------------------------------===//
429
430const StackFrameContext *LocationContextManager::getStackFrame(
431 AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
432 const CFGBlock *blk, unsigned blockCount, unsigned idx) {
433 llvm::FoldingSetNodeID ID;
434 StackFrameContext::Profile(ID, ADC: ctx, ParentLC: parent, S: s, Block: blk, BlockCount: blockCount, Index: idx);
435 void *InsertPos;
436 auto *L =
437 cast_or_null<StackFrameContext>(Val: Contexts.FindNodeOrInsertPos(ID, InsertPos));
438 if (!L) {
439 L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
440 Contexts.InsertNode(N: L, InsertPos);
441 }
442 return L;
443}
444
445const BlockInvocationContext *LocationContextManager::getBlockInvocationContext(
446 AnalysisDeclContext *ADC, const LocationContext *ParentLC,
447 const BlockDecl *BD, const void *Data) {
448 llvm::FoldingSetNodeID ID;
449 BlockInvocationContext::Profile(ID, ADC, ParentLC, BD, Data);
450 void *InsertPos;
451 auto *L =
452 cast_or_null<BlockInvocationContext>(Val: Contexts.FindNodeOrInsertPos(ID,
453 InsertPos));
454 if (!L) {
455 L = new BlockInvocationContext(ADC, ParentLC, BD, Data, ++NewID);
456 Contexts.InsertNode(N: L, InsertPos);
457 }
458 return L;
459}
460
461//===----------------------------------------------------------------------===//
462// LocationContext methods.
463//===----------------------------------------------------------------------===//
464
465const StackFrameContext *LocationContext::getStackFrame() const {
466 const LocationContext *LC = this;
467 while (LC) {
468 if (const auto *SFC = dyn_cast<StackFrameContext>(Val: LC))
469 return SFC;
470 LC = LC->getParent();
471 }
472 return nullptr;
473}
474
475bool LocationContext::inTopFrame() const {
476 return getStackFrame()->inTopFrame();
477}
478
479bool LocationContext::isParentOf(const LocationContext *LC) const {
480 do {
481 const LocationContext *Parent = LC->getParent();
482 if (Parent == this)
483 return true;
484 else
485 LC = Parent;
486 } while (LC);
487
488 return false;
489}
490
491static void printLocation(raw_ostream &Out, const SourceManager &SM,
492 SourceLocation Loc) {
493 if (Loc.isFileID() && SM.isInMainFile(Loc))
494 Out << SM.getExpansionLineNumber(Loc);
495 else
496 Loc.print(OS&: Out, SM);
497}
498
499void LocationContext::dumpStack(raw_ostream &Out) const {
500 ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
501 PrintingPolicy PP(Ctx.getLangOpts());
502 PP.TerseOutput = 1;
503
504 const SourceManager &SM =
505 getAnalysisDeclContext()->getASTContext().getSourceManager();
506
507 unsigned Frame = 0;
508 for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
509 switch (LCtx->getKind()) {
510 case StackFrame:
511 Out << "\t#" << Frame << ' ';
512 ++Frame;
513 if (const auto *D = dyn_cast<NamedDecl>(Val: LCtx->getDecl()))
514 Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
515 else
516 Out << "Calling anonymous code";
517 if (const Stmt *S = cast<StackFrameContext>(Val: LCtx)->getCallSite()) {
518 Out << " at line ";
519 printLocation(Out, SM, Loc: S->getBeginLoc());
520 }
521 break;
522 case Block:
523 Out << "Invoking block";
524 if (const Decl *D = cast<BlockInvocationContext>(Val: LCtx)->getDecl()) {
525 Out << " defined at line ";
526 printLocation(Out, SM, Loc: D->getBeginLoc());
527 }
528 break;
529 }
530 Out << '\n';
531 }
532}
533
534void LocationContext::printJson(raw_ostream &Out, const char *NL,
535 unsigned int Space, bool IsDot,
536 std::function<void(const LocationContext *)>
537 printMoreInfoPerContext) const {
538 ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
539 PrintingPolicy PP(Ctx.getLangOpts());
540 PP.TerseOutput = 1;
541
542 const SourceManager &SM =
543 getAnalysisDeclContext()->getASTContext().getSourceManager();
544
545 unsigned Frame = 0;
546 for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
547 Indent(Out, Space, IsDot)
548 << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";
549 switch (LCtx->getKind()) {
550 case StackFrame:
551 Out << '#' << Frame << " Call\", \"calling\": \"";
552 ++Frame;
553 if (const auto *D = dyn_cast<NamedDecl>(Val: LCtx->getDecl()))
554 Out << D->getQualifiedNameAsString();
555 else
556 Out << "anonymous code";
557
558 Out << "\", \"location\": ";
559 if (const Stmt *S = cast<StackFrameContext>(Val: LCtx)->getCallSite()) {
560 printSourceLocationAsJson(Out, Loc: S->getBeginLoc(), SM);
561 } else {
562 Out << "null";
563 }
564
565 Out << ", \"items\": ";
566 break;
567 case Block:
568 Out << "Invoking block\" ";
569 if (const Decl *D = cast<BlockInvocationContext>(Val: LCtx)->getDecl()) {
570 Out << ", \"location\": ";
571 printSourceLocationAsJson(Out, Loc: D->getBeginLoc(), SM);
572 Out << ' ';
573 }
574 break;
575 }
576
577 printMoreInfoPerContext(LCtx);
578
579 Out << '}';
580 if (LCtx->getParent())
581 Out << ',';
582 Out << NL;
583 }
584}
585
586LLVM_DUMP_METHOD void LocationContext::dump() const { printJson(Out&: llvm::errs()); }
587
588//===----------------------------------------------------------------------===//
589// Lazily generated map to query the external variables referenced by a Block.
590//===----------------------------------------------------------------------===//
591
592namespace {
593
594class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
595 BumpVector<const VarDecl *> &BEVals;
596 BumpVectorContext &BC;
597 llvm::SmallPtrSet<const VarDecl *, 4> Visited;
598 llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
599
600public:
601 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
602 BumpVectorContext &bc)
603 : BEVals(bevals), BC(bc) {}
604
605 void VisitStmt(Stmt *S) {
606 for (auto *Child : S->children())
607 if (Child)
608 Visit(S: Child);
609 }
610
611 void VisitDeclRefExpr(DeclRefExpr *DR) {
612 // Non-local variables are also directly modified.
613 if (const auto *VD = dyn_cast<VarDecl>(Val: DR->getDecl())) {
614 if (!VD->hasLocalStorage()) {
615 if (Visited.insert(Ptr: VD).second)
616 BEVals.push_back(Elt: VD, C&: BC);
617 }
618 }
619 }
620
621 void VisitBlockExpr(BlockExpr *BR) {
622 // Blocks containing blocks can transitively capture more variables.
623 IgnoredContexts.insert(Ptr: BR->getBlockDecl());
624 Visit(S: BR->getBlockDecl()->getBody());
625 }
626
627 void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
628 for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
629 et = PE->semantics_end(); it != et; ++it) {
630 Expr *Semantic = *it;
631 if (auto *OVE = dyn_cast<OpaqueValueExpr>(Val: Semantic))
632 Semantic = OVE->getSourceExpr();
633 Visit(S: Semantic);
634 }
635 }
636};
637
638} // namespace
639
640using DeclVec = BumpVector<const VarDecl *>;
641
642static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
643 void *&Vec,
644 llvm::BumpPtrAllocator &A) {
645 if (Vec)
646 return (DeclVec*) Vec;
647
648 BumpVectorContext BC(A);
649 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
650 new (BV) DeclVec(BC, 10);
651
652 // Go through the capture list.
653 for (const auto &CI : BD->captures()) {
654 BV->push_back(Elt: CI.getVariable(), C&: BC);
655 }
656
657 // Find the referenced global/static variables.
658 FindBlockDeclRefExprsVals F(*BV, BC);
659 F.Visit(S: BD->getBody());
660
661 Vec = BV;
662 return BV;
663}
664
665llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
666AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
667 if (!ReferencedBlockVars)
668 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
669
670 const DeclVec *V =
671 LazyInitializeReferencedDecls(BD, Vec&: (*ReferencedBlockVars)[BD], A);
672 return llvm::make_range(x: V->begin(), y: V->end());
673}
674
675std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(const void *tag) {
676 if (!ManagedAnalyses)
677 ManagedAnalyses = new ManagedAnalysisMap();
678 ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
679 return (*M)[tag];
680}
681
682//===----------------------------------------------------------------------===//
683// Cleanup.
684//===----------------------------------------------------------------------===//
685
686ManagedAnalysis::~ManagedAnalysis() = default;
687
688AnalysisDeclContext::~AnalysisDeclContext() {
689 delete forcedBlkExprs;
690 delete ReferencedBlockVars;
691 delete (ManagedAnalysisMap*) ManagedAnalyses;
692}
693
694LocationContext::~LocationContext() = default;
695
696LocationContextManager::~LocationContextManager() {
697 clear();
698}
699
700void LocationContextManager::clear() {
701 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
702 E = Contexts.end(); I != E; ) {
703 LocationContext *LC = &*I;
704 ++I;
705 delete LC;
706 }
707 Contexts.clear();
708}
709