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