xref: /freebsd/contrib/llvm-project/clang/lib/Analysis/AnalysisDeclContext.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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_and_nonnull<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     ValueDecl *VD = LC.getCapturedVar();
173     if (isSelfDecl(dyn_cast<VarDecl>(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 NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges, false);
235     completeCFG =
236         CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
237     // Even when the cfg is not successfully built, we don't
238     // want to try building it again.
239     builtCompleteCFG = true;
240 
241     if (PM)
242       addParentsForSyntheticStmts(completeCFG.get(), *PM);
243 
244     // The Observer should only observe one build of the CFG.
245     getCFGBuildOptions().Observer = nullptr;
246   }
247   return completeCFG.get();
248 }
249 
getCFGStmtMap()250 CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
251   if (cfgStmtMap)
252     return cfgStmtMap.get();
253 
254   if (CFG *c = getCFG()) {
255     cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
256     return cfgStmtMap.get();
257   }
258 
259   return nullptr;
260 }
261 
getCFGReachablityAnalysis()262 CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
263   if (CFA)
264     return CFA.get();
265 
266   if (CFG *c = getCFG()) {
267     CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
268     return CFA.get();
269   }
270 
271   return nullptr;
272 }
273 
dumpCFG(bool ShowColors)274 void AnalysisDeclContext::dumpCFG(bool ShowColors) {
275   getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
276 }
277 
getParentMap()278 ParentMap &AnalysisDeclContext::getParentMap() {
279   if (!PM) {
280     PM.reset(new ParentMap(getBody()));
281     if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
282       for (const auto *I : C->inits()) {
283         PM->addStmt(I->getInit());
284       }
285     }
286     if (builtCFG)
287       addParentsForSyntheticStmts(getCFG(), *PM);
288     if (builtCompleteCFG)
289       addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);
290   }
291   return *PM;
292 }
293 
getContext(const Decl * D)294 AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
295   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
296     // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
297     // that has the body.
298     FD->hasBody(FD);
299     D = FD;
300   }
301 
302   std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
303   if (!AC)
304     AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions);
305   return AC.get();
306 }
307 
getBodyFarm()308 BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
309 
310 const StackFrameContext *
getStackFrame(const LocationContext * ParentLC,const Stmt * S,const CFGBlock * Blk,unsigned BlockCount,unsigned Index)311 AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC,
312                                    const Stmt *S, const CFGBlock *Blk,
313                                    unsigned BlockCount, unsigned Index) {
314   return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk,
315                                                    BlockCount, Index);
316 }
317 
getBlockInvocationContext(const LocationContext * ParentLC,const BlockDecl * BD,const void * Data)318 const BlockInvocationContext *AnalysisDeclContext::getBlockInvocationContext(
319     const LocationContext *ParentLC, const BlockDecl *BD, const void *Data) {
320   return getLocationContextManager().getBlockInvocationContext(this, ParentLC,
321                                                                BD, Data);
322 }
323 
isInStdNamespace(const Decl * D)324 bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
325   const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
326   const auto *ND = dyn_cast<NamespaceDecl>(DC);
327   if (!ND)
328     return false;
329 
330   while (const DeclContext *Parent = ND->getParent()) {
331     if (!isa<NamespaceDecl>(Parent))
332       break;
333     ND = cast<NamespaceDecl>(Parent);
334   }
335 
336   return ND->isStdNamespace();
337 }
338 
getFunctionName(const Decl * D)339 std::string AnalysisDeclContext::getFunctionName(const Decl *D) {
340   std::string Str;
341   llvm::raw_string_ostream OS(Str);
342   const ASTContext &Ctx = D->getASTContext();
343 
344   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
345     OS << FD->getQualifiedNameAsString();
346 
347     // In C++, there are overloads.
348 
349     if (Ctx.getLangOpts().CPlusPlus) {
350       OS << '(';
351       for (const auto &P : FD->parameters()) {
352         if (P != *FD->param_begin())
353           OS << ", ";
354         OS << P->getType();
355       }
356       OS << ')';
357     }
358 
359   } else if (isa<BlockDecl>(D)) {
360     PresumedLoc Loc = Ctx.getSourceManager().getPresumedLoc(D->getLocation());
361 
362     if (Loc.isValid()) {
363       OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
364          << ')';
365     }
366 
367   } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
368 
369     // FIXME: copy-pasted from CGDebugInfo.cpp.
370     OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
371     const DeclContext *DC = OMD->getDeclContext();
372     if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
373       OS << OID->getName();
374     } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
375       OS << OID->getName();
376     } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
377       if (OC->IsClassExtension()) {
378         OS << OC->getClassInterface()->getName();
379       } else {
380         OS << OC->getIdentifier()->getNameStart() << '('
381            << OC->getIdentifier()->getNameStart() << ')';
382       }
383     } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
384       OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
385     }
386     OS << ' ' << OMD->getSelector().getAsString() << ']';
387   }
388 
389   return Str;
390 }
391 
getLocationContextManager()392 LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
393   assert(
394       ADCMgr &&
395       "Cannot create LocationContexts without an AnalysisDeclContextManager!");
396   return ADCMgr->getLocationContextManager();
397 }
398 
399 //===----------------------------------------------------------------------===//
400 // FoldingSet profiling.
401 //===----------------------------------------------------------------------===//
402 
ProfileCommon(llvm::FoldingSetNodeID & ID,ContextKind ck,AnalysisDeclContext * ctx,const LocationContext * parent,const void * data)403 void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
404                                     ContextKind ck,
405                                     AnalysisDeclContext *ctx,
406                                     const LocationContext *parent,
407                                     const void *data) {
408   ID.AddInteger(ck);
409   ID.AddPointer(ctx);
410   ID.AddPointer(parent);
411   ID.AddPointer(data);
412 }
413 
Profile(llvm::FoldingSetNodeID & ID)414 void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
415   Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block,
416           BlockCount, Index);
417 }
418 
Profile(llvm::FoldingSetNodeID & ID)419 void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
420   Profile(ID, getAnalysisDeclContext(), getParent(), BD, Data);
421 }
422 
423 //===----------------------------------------------------------------------===//
424 // LocationContext creation.
425 //===----------------------------------------------------------------------===//
426 
getStackFrame(AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s,const CFGBlock * blk,unsigned blockCount,unsigned idx)427 const StackFrameContext *LocationContextManager::getStackFrame(
428     AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
429     const CFGBlock *blk, unsigned blockCount, unsigned idx) {
430   llvm::FoldingSetNodeID ID;
431   StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx);
432   void *InsertPos;
433   auto *L =
434    cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
435   if (!L) {
436     L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
437     Contexts.InsertNode(L, InsertPos);
438   }
439   return L;
440 }
441 
getBlockInvocationContext(AnalysisDeclContext * ADC,const LocationContext * ParentLC,const BlockDecl * BD,const void * Data)442 const BlockInvocationContext *LocationContextManager::getBlockInvocationContext(
443     AnalysisDeclContext *ADC, const LocationContext *ParentLC,
444     const BlockDecl *BD, const void *Data) {
445   llvm::FoldingSetNodeID ID;
446   BlockInvocationContext::Profile(ID, ADC, ParentLC, BD, Data);
447   void *InsertPos;
448   auto *L =
449     cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
450                                                                     InsertPos));
451   if (!L) {
452     L = new BlockInvocationContext(ADC, ParentLC, BD, Data, ++NewID);
453     Contexts.InsertNode(L, InsertPos);
454   }
455   return L;
456 }
457 
458 //===----------------------------------------------------------------------===//
459 // LocationContext methods.
460 //===----------------------------------------------------------------------===//
461 
getStackFrame() const462 const StackFrameContext *LocationContext::getStackFrame() const {
463   const LocationContext *LC = this;
464   while (LC) {
465     if (const auto *SFC = dyn_cast<StackFrameContext>(LC))
466       return SFC;
467     LC = LC->getParent();
468   }
469   return nullptr;
470 }
471 
inTopFrame() const472 bool LocationContext::inTopFrame() const {
473   return getStackFrame()->inTopFrame();
474 }
475 
isParentOf(const LocationContext * LC) const476 bool LocationContext::isParentOf(const LocationContext *LC) const {
477   do {
478     const LocationContext *Parent = LC->getParent();
479     if (Parent == this)
480       return true;
481     else
482       LC = Parent;
483   } while (LC);
484 
485   return false;
486 }
487 
printLocation(raw_ostream & Out,const SourceManager & SM,SourceLocation Loc)488 static void printLocation(raw_ostream &Out, const SourceManager &SM,
489                           SourceLocation Loc) {
490   if (Loc.isFileID() && SM.isInMainFile(Loc))
491     Out << SM.getExpansionLineNumber(Loc);
492   else
493     Loc.print(Out, SM);
494 }
495 
dumpStack(raw_ostream & Out) const496 void LocationContext::dumpStack(raw_ostream &Out) const {
497   ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
498   PrintingPolicy PP(Ctx.getLangOpts());
499   PP.TerseOutput = 1;
500 
501   const SourceManager &SM =
502       getAnalysisDeclContext()->getASTContext().getSourceManager();
503 
504   unsigned Frame = 0;
505   for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
506     switch (LCtx->getKind()) {
507     case StackFrame:
508       Out << "\t#" << Frame << ' ';
509       ++Frame;
510       if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
511         Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
512       else
513         Out << "Calling anonymous code";
514       if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
515         Out << " at line ";
516         printLocation(Out, SM, S->getBeginLoc());
517       }
518       break;
519     case Block:
520       Out << "Invoking block";
521       if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
522         Out << " defined at line ";
523         printLocation(Out, SM, D->getBeginLoc());
524       }
525       break;
526     }
527     Out << '\n';
528   }
529 }
530 
printJson(raw_ostream & Out,const char * NL,unsigned int Space,bool IsDot,std::function<void (const LocationContext *)> printMoreInfoPerContext) const531 void LocationContext::printJson(raw_ostream &Out, const char *NL,
532                                 unsigned int Space, bool IsDot,
533                                 std::function<void(const LocationContext *)>
534                                     printMoreInfoPerContext) const {
535   ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
536   PrintingPolicy PP(Ctx.getLangOpts());
537   PP.TerseOutput = 1;
538 
539   const SourceManager &SM =
540       getAnalysisDeclContext()->getASTContext().getSourceManager();
541 
542   unsigned Frame = 0;
543   for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
544     Indent(Out, Space, IsDot)
545         << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";
546     switch (LCtx->getKind()) {
547     case StackFrame:
548       Out << '#' << Frame << " Call\", \"calling\": \"";
549       ++Frame;
550       if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
551         Out << D->getQualifiedNameAsString();
552       else
553         Out << "anonymous code";
554 
555       Out << "\", \"location\": ";
556       if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
557         printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
558       } else {
559         Out << "null";
560       }
561 
562       Out << ", \"items\": ";
563       break;
564     case Block:
565       Out << "Invoking block\" ";
566       if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
567         Out << ", \"location\": ";
568         printSourceLocationAsJson(Out, D->getBeginLoc(), SM);
569         Out << ' ';
570       }
571       break;
572     }
573 
574     printMoreInfoPerContext(LCtx);
575 
576     Out << '}';
577     if (LCtx->getParent())
578       Out << ',';
579     Out << NL;
580   }
581 }
582 
dump() const583 LLVM_DUMP_METHOD void LocationContext::dump() const { printJson(llvm::errs()); }
584 
585 //===----------------------------------------------------------------------===//
586 // Lazily generated map to query the external variables referenced by a Block.
587 //===----------------------------------------------------------------------===//
588 
589 namespace {
590 
591 class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
592   BumpVector<const VarDecl *> &BEVals;
593   BumpVectorContext &BC;
594   llvm::SmallPtrSet<const VarDecl *, 4> Visited;
595   llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
596 
597 public:
FindBlockDeclRefExprsVals(BumpVector<const VarDecl * > & bevals,BumpVectorContext & bc)598   FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
599                             BumpVectorContext &bc)
600       : BEVals(bevals), BC(bc) {}
601 
VisitStmt(Stmt * S)602   void VisitStmt(Stmt *S) {
603     for (auto *Child : S->children())
604       if (Child)
605         Visit(Child);
606   }
607 
VisitDeclRefExpr(DeclRefExpr * DR)608   void VisitDeclRefExpr(DeclRefExpr *DR) {
609     // Non-local variables are also directly modified.
610     if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
611       if (!VD->hasLocalStorage()) {
612         if (Visited.insert(VD).second)
613           BEVals.push_back(VD, BC);
614       }
615     }
616   }
617 
VisitBlockExpr(BlockExpr * BR)618   void VisitBlockExpr(BlockExpr *BR) {
619     // Blocks containing blocks can transitively capture more variables.
620     IgnoredContexts.insert(BR->getBlockDecl());
621     Visit(BR->getBlockDecl()->getBody());
622   }
623 
VisitPseudoObjectExpr(PseudoObjectExpr * PE)624   void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
625     for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
626          et = PE->semantics_end(); it != et; ++it) {
627       Expr *Semantic = *it;
628       if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
629         Semantic = OVE->getSourceExpr();
630       Visit(Semantic);
631     }
632   }
633 };
634 
635 } // namespace
636 
637 using DeclVec = BumpVector<const VarDecl *>;
638 
LazyInitializeReferencedDecls(const BlockDecl * BD,void * & Vec,llvm::BumpPtrAllocator & A)639 static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
640                                               void *&Vec,
641                                               llvm::BumpPtrAllocator &A) {
642   if (Vec)
643     return (DeclVec*) Vec;
644 
645   BumpVectorContext BC(A);
646   DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
647   new (BV) DeclVec(BC, 10);
648 
649   // Go through the capture list.
650   for (const auto &CI : BD->captures()) {
651     BV->push_back(CI.getVariable(), BC);
652   }
653 
654   // Find the referenced global/static variables.
655   FindBlockDeclRefExprsVals F(*BV, BC);
656   F.Visit(BD->getBody());
657 
658   Vec = BV;
659   return BV;
660 }
661 
662 llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl * BD)663 AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
664   if (!ReferencedBlockVars)
665     ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
666 
667   const DeclVec *V =
668       LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
669   return llvm::make_range(V->begin(), V->end());
670 }
671 
getAnalysisImpl(const void * tag)672 std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(const void *tag) {
673   if (!ManagedAnalyses)
674     ManagedAnalyses = new ManagedAnalysisMap();
675   ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
676   return (*M)[tag];
677 }
678 
679 //===----------------------------------------------------------------------===//
680 // Cleanup.
681 //===----------------------------------------------------------------------===//
682 
683 ManagedAnalysis::~ManagedAnalysis() = default;
684 
~AnalysisDeclContext()685 AnalysisDeclContext::~AnalysisDeclContext() {
686   delete forcedBlkExprs;
687   delete ReferencedBlockVars;
688   delete (ManagedAnalysisMap*) ManagedAnalyses;
689 }
690 
691 LocationContext::~LocationContext() = default;
692 
~LocationContextManager()693 LocationContextManager::~LocationContextManager() {
694   clear();
695 }
696 
clear()697 void LocationContextManager::clear() {
698   for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
699        E = Contexts.end(); I != E; ) {
700     LocationContext *LC = &*I;
701     ++I;
702     delete LC;
703   }
704   Contexts.clear();
705 }
706