11c1057afSEugene Zelenko //===- AnalysisDeclContext.cpp - Analysis context for Path Sens analysis --===//
26f2e6522SChandler Carruth //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
66f2e6522SChandler Carruth //
76f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
86f2e6522SChandler Carruth //
91c1057afSEugene Zelenko // This file defines AnalysisDeclContext, a class that manages the analysis
101c1057afSEugene Zelenko // context data for path sensitive analysis.
116f2e6522SChandler Carruth //
126f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
136f2e6522SChandler Carruth 
1450657f6bSGeorge Karpenkov #include "clang/Analysis/AnalysisDeclContext.h"
154ab984e7SBenjamin Kramer #include "clang/AST/ASTContext.h"
166f2e6522SChandler Carruth #include "clang/AST/Decl.h"
171c1057afSEugene Zelenko #include "clang/AST/DeclBase.h"
181c1057afSEugene Zelenko #include "clang/AST/DeclCXX.h"
196f2e6522SChandler Carruth #include "clang/AST/DeclObjC.h"
206f2e6522SChandler Carruth #include "clang/AST/DeclTemplate.h"
211c1057afSEugene Zelenko #include "clang/AST/Expr.h"
221c1057afSEugene Zelenko #include "clang/AST/LambdaCapture.h"
236f2e6522SChandler Carruth #include "clang/AST/ParentMap.h"
241c1057afSEugene Zelenko #include "clang/AST/PrettyPrinter.h"
251c1057afSEugene Zelenko #include "clang/AST/Stmt.h"
261c1057afSEugene Zelenko #include "clang/AST/StmtCXX.h"
276f2e6522SChandler Carruth #include "clang/AST/StmtVisitor.h"
283a02247dSChandler Carruth #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
293d64d6eeSGeorge Karpenkov #include "clang/Analysis/BodyFarm.h"
306f2e6522SChandler Carruth #include "clang/Analysis/CFG.h"
316f2e6522SChandler Carruth #include "clang/Analysis/CFGStmtMap.h"
326f2e6522SChandler Carruth #include "clang/Analysis/Support/BumpVector.h"
339ce37466SCsaba Dabis #include "clang/Basic/JsonSupport.h"
341c1057afSEugene Zelenko #include "clang/Basic/LLVM.h"
351c1057afSEugene Zelenko #include "clang/Basic/SourceLocation.h"
361c1057afSEugene Zelenko #include "clang/Basic/SourceManager.h"
371c1057afSEugene Zelenko #include "llvm/ADT/DenseMap.h"
381c1057afSEugene Zelenko #include "llvm/ADT/FoldingSet.h"
391c1057afSEugene Zelenko #include "llvm/ADT/STLExtras.h"
40616f8022SBenjamin Kramer #include "llvm/ADT/SmallPtrSet.h"
411c1057afSEugene Zelenko #include "llvm/ADT/iterator_range.h"
421c1057afSEugene Zelenko #include "llvm/Support/Allocator.h"
431c1057afSEugene Zelenko #include "llvm/Support/Casting.h"
441c1057afSEugene Zelenko #include "llvm/Support/Compiler.h"
456f2e6522SChandler Carruth #include "llvm/Support/ErrorHandling.h"
463a02247dSChandler Carruth #include "llvm/Support/SaveAndRestore.h"
475553d0d4SChandler Carruth #include "llvm/Support/raw_ostream.h"
481c1057afSEugene Zelenko #include <cassert>
491c1057afSEugene Zelenko #include <memory>
5014f779c4STed Kremenek 
516f2e6522SChandler Carruth using namespace clang;
526f2e6522SChandler Carruth 
53e265f92bSDavid Blaikie using ManagedAnalysisMap = llvm::DenseMap<const void *, std::unique_ptr<ManagedAnalysis>>;
546f2e6522SChandler Carruth 
AnalysisDeclContext(AnalysisDeclContextManager * ADCMgr,const Decl * D,const CFG::BuildOptions & Options)557e1a6ca9SCharusso AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
567e1a6ca9SCharusso                                          const Decl *D,
577e1a6ca9SCharusso                                          const CFG::BuildOptions &Options)
587e1a6ca9SCharusso     : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
596f2e6522SChandler Carruth   cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
606f2e6522SChandler Carruth }
616f2e6522SChandler Carruth 
AnalysisDeclContext(AnalysisDeclContextManager * ADCMgr,const Decl * D)627e1a6ca9SCharusso AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
637e1a6ca9SCharusso                                          const Decl *D)
647e1a6ca9SCharusso     : ADCMgr(ADCMgr), D(D) {
656f2e6522SChandler Carruth   cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
666f2e6522SChandler Carruth }
676f2e6522SChandler Carruth 
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)683d64d6eeSGeorge Karpenkov AnalysisDeclContextManager::AnalysisDeclContextManager(
693d64d6eeSGeorge Karpenkov     ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors,
703d64d6eeSGeorge Karpenkov     bool addInitializers, bool addTemporaryDtors, bool addLifetime,
71debca45eSMaxim Ostapenko     bool addLoopExit, bool addScopes, bool synthesizeBodies,
72debca45eSMaxim Ostapenko     bool addStaticInitBranch, bool addCXXNewAllocator,
73ff267df0SArtem Dergachev     bool addRichCXXConstructors, bool markElidedCXXConstructors,
74192a7474SArtem Dergachev     bool addVirtualBaseBranches, CodeInjector *injector)
75050b53b3SGeorge Karpenkov     : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
76ed017b63SGeorge Karpenkov       SynthesizeBodies(synthesizeBodies) {
776f2e6522SChandler Carruth   cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
786f2e6522SChandler Carruth   cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
796f2e6522SChandler Carruth   cfgBuildOptions.AddInitializers = addInitializers;
806d671cc3SJordan Rose   cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
81351c218dSMatthias Gehre   cfgBuildOptions.AddLifetime = addLifetime;
82999a25ffSPeter Szecsi   cfgBuildOptions.AddLoopExit = addLoopExit;
83debca45eSMaxim Ostapenko   cfgBuildOptions.AddScopes = addScopes;
84233c1b0cSTed Kremenek   cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
85c9176072SJordan Rose   cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
8641ffb307SArtem Dergachev   cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
87ff267df0SArtem Dergachev   cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors;
88192a7474SArtem Dergachev   cfgBuildOptions.AddVirtualBaseBranches = addVirtualBaseBranches;
896f2e6522SChandler Carruth }
906f2e6522SChandler Carruth 
clear()915cb35e16SJustin Lebar void AnalysisDeclContextManager::clear() { Contexts.clear(); }
926f2e6522SChandler Carruth 
getBody(bool & IsAutosynthesized) const9300c69a59SAnna Zaks Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
94cc4aaef0SNAKAMURA Takumi   IsAutosynthesized = false;
951c1057afSEugene Zelenko   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
9614f779c4STed Kremenek     Stmt *Body = FD->getBody();
97da8f9b5bSEric Fiselier     if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
98da8f9b5bSEric Fiselier       Body = CoroBody->getBody();
997e1a6ca9SCharusso     if (ADCMgr && ADCMgr->synthesizeBodies()) {
1007e1a6ca9SCharusso       Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(FD);
1017646ebe6SDevin Coughlin       if (SynthesizedBody) {
1027646ebe6SDevin Coughlin         Body = SynthesizedBody;
10300c69a59SAnna Zaks         IsAutosynthesized = true;
10400c69a59SAnna Zaks       }
1057646ebe6SDevin Coughlin     }
10614f779c4STed Kremenek     return Body;
10714f779c4STed Kremenek   }
1081c1057afSEugene Zelenko   else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
1091a866cd5SJordan Rose     Stmt *Body = MD->getBody();
1107e1a6ca9SCharusso     if (ADCMgr && ADCMgr->synthesizeBodies()) {
1117e1a6ca9SCharusso       Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(MD);
1127646ebe6SDevin Coughlin       if (SynthesizedBody) {
1137646ebe6SDevin Coughlin         Body = SynthesizedBody;
1141a866cd5SJordan Rose         IsAutosynthesized = true;
1151a866cd5SJordan Rose       }
1167646ebe6SDevin Coughlin     }
1171a866cd5SJordan Rose     return Body;
1181c1057afSEugene Zelenko   } else if (const auto *BD = dyn_cast<BlockDecl>(D))
1196f2e6522SChandler Carruth     return BD->getBody();
1201c1057afSEugene Zelenko   else if (const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
1216f2e6522SChandler Carruth     return FunTmpl->getTemplatedDecl()->getBody();
1226f2e6522SChandler Carruth 
1236f2e6522SChandler Carruth   llvm_unreachable("unknown code decl");
1246f2e6522SChandler Carruth }
1256f2e6522SChandler Carruth 
getBody() const12600c69a59SAnna Zaks Stmt *AnalysisDeclContext::getBody() const {
12700c69a59SAnna Zaks   bool Tmp;
12800c69a59SAnna Zaks   return getBody(Tmp);
12900c69a59SAnna Zaks }
13000c69a59SAnna Zaks 
isBodyAutosynthesized() const13100c69a59SAnna Zaks bool AnalysisDeclContext::isBodyAutosynthesized() const {
13200c69a59SAnna Zaks   bool Tmp;
13300c69a59SAnna Zaks   getBody(Tmp);
13400c69a59SAnna Zaks   return Tmp;
13500c69a59SAnna Zaks }
13600c69a59SAnna Zaks 
isBodyAutosynthesizedFromModelFile() const137eeccb30bSTed Kremenek bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
138eeccb30bSTed Kremenek   bool Tmp;
139eeccb30bSTed Kremenek   Stmt *Body = getBody(Tmp);
140f2ceec48SStephen Kelly   return Tmp && Body->getBeginLoc().isValid();
141eeccb30bSTed Kremenek }
142eeccb30bSTed Kremenek 
143c289b74bSDevin Coughlin /// Returns true if \param VD is an Objective-C implicit 'self' parameter.
isSelfDecl(const VarDecl * VD)144c289b74bSDevin Coughlin static bool isSelfDecl(const VarDecl *VD) {
145c289b74bSDevin Coughlin   return isa<ImplicitParamDecl>(VD) && VD->getName() == "self";
146c289b74bSDevin Coughlin }
147eeccb30bSTed Kremenek 
getSelfDecl() const1486f2e6522SChandler Carruth const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
1491c1057afSEugene Zelenko   if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
1506f2e6522SChandler Carruth     return MD->getSelfDecl();
1511c1057afSEugene Zelenko   if (const auto *BD = dyn_cast<BlockDecl>(D)) {
152b39fcfaaSTed Kremenek     // See if 'self' was captured by the block.
1539371dd22SAaron Ballman     for (const auto &I : BD->captures()) {
1549371dd22SAaron Ballman       const VarDecl *VD = I.getVariable();
155c289b74bSDevin Coughlin       if (isSelfDecl(VD))
156b39fcfaaSTed Kremenek         return dyn_cast<ImplicitParamDecl>(VD);
157b39fcfaaSTed Kremenek     }
158b39fcfaaSTed Kremenek   }
1596f2e6522SChandler Carruth 
1601d405832SDevin Coughlin   auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
1611d405832SDevin Coughlin   if (!CXXMethod)
1621d405832SDevin Coughlin     return nullptr;
1631d405832SDevin Coughlin 
1641d405832SDevin Coughlin   const CXXRecordDecl *parent = CXXMethod->getParent();
1651d405832SDevin Coughlin   if (!parent->isLambda())
1661d405832SDevin Coughlin     return nullptr;
1671d405832SDevin Coughlin 
1681c1057afSEugene Zelenko   for (const auto &LC : parent->captures()) {
1691d405832SDevin Coughlin     if (!LC.capturesVariable())
1701d405832SDevin Coughlin       continue;
1711d405832SDevin Coughlin 
1721d405832SDevin Coughlin     VarDecl *VD = LC.getCapturedVar();
173c289b74bSDevin Coughlin     if (isSelfDecl(VD))
1741d405832SDevin Coughlin       return dyn_cast<ImplicitParamDecl>(VD);
1751d405832SDevin Coughlin   }
1761d405832SDevin Coughlin 
17725542943SCraig Topper   return nullptr;
1786f2e6522SChandler Carruth }
1796f2e6522SChandler Carruth 
registerForcedBlockExpression(const Stmt * stmt)1806f2e6522SChandler Carruth void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
1816f2e6522SChandler Carruth   if (!forcedBlkExprs)
1826f2e6522SChandler Carruth     forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
1836f2e6522SChandler Carruth   // Default construct an entry for 'stmt'.
1841c1057afSEugene Zelenko   if (const auto *e = dyn_cast<Expr>(stmt))
1856f2e6522SChandler Carruth     stmt = e->IgnoreParens();
1866f2e6522SChandler Carruth   (void) (*forcedBlkExprs)[stmt];
1876f2e6522SChandler Carruth }
1886f2e6522SChandler Carruth 
1896f2e6522SChandler Carruth const CFGBlock *
getBlockForRegisteredExpression(const Stmt * stmt)1906f2e6522SChandler Carruth AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
1916f2e6522SChandler Carruth   assert(forcedBlkExprs);
1921c1057afSEugene Zelenko   if (const auto *e = dyn_cast<Expr>(stmt))
1936f2e6522SChandler Carruth     stmt = e->IgnoreParens();
1946f2e6522SChandler Carruth   CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
1956f2e6522SChandler Carruth     forcedBlkExprs->find(stmt);
1966f2e6522SChandler Carruth   assert(itr != forcedBlkExprs->end());
1976f2e6522SChandler Carruth   return itr->second;
1986f2e6522SChandler Carruth }
1996f2e6522SChandler Carruth 
200cf10ea8cSJordan Rose /// Add each synthetic statement in the CFG to the parent map, using the
201cf10ea8cSJordan Rose /// source statement's parent.
addParentsForSyntheticStmts(const CFG * TheCFG,ParentMap & PM)202cf10ea8cSJordan Rose static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) {
203cf10ea8cSJordan Rose   if (!TheCFG)
204cf10ea8cSJordan Rose     return;
205cf10ea8cSJordan Rose 
206cf10ea8cSJordan Rose   for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(),
207cf10ea8cSJordan Rose                                     E = TheCFG->synthetic_stmt_end();
208cf10ea8cSJordan Rose        I != E; ++I) {
209cf10ea8cSJordan Rose     PM.setParent(I->first, PM.getParent(I->second));
210cf10ea8cSJordan Rose   }
211cf10ea8cSJordan Rose }
212cf10ea8cSJordan Rose 
getCFG()2136f2e6522SChandler Carruth CFG *AnalysisDeclContext::getCFG() {
2146f2e6522SChandler Carruth   if (!cfgBuildOptions.PruneTriviallyFalseEdges)
2156f2e6522SChandler Carruth     return getUnoptimizedCFG();
2166f2e6522SChandler Carruth 
2176f2e6522SChandler Carruth   if (!builtCFG) {
218e90195c0SDavid Blaikie     cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
2196f2e6522SChandler Carruth     // Even when the cfg is not successfully built, we don't
2206f2e6522SChandler Carruth     // want to try building it again.
2216f2e6522SChandler Carruth     builtCFG = true;
222cf10ea8cSJordan Rose 
223cf10ea8cSJordan Rose     if (PM)
224cf10ea8cSJordan Rose       addParentsForSyntheticStmts(cfg.get(), *PM);
225e9fa266cSRichard Trieu 
226e729d9b5SRichard Trieu     // The Observer should only observe one build of the CFG.
22725542943SCraig Topper     getCFGBuildOptions().Observer = nullptr;
2286f2e6522SChandler Carruth   }
2296f2e6522SChandler Carruth   return cfg.get();
2306f2e6522SChandler Carruth }
2316f2e6522SChandler Carruth 
getUnoptimizedCFG()2326f2e6522SChandler Carruth CFG *AnalysisDeclContext::getUnoptimizedCFG() {
2336f2e6522SChandler Carruth   if (!builtCompleteCFG) {
2346f2e6522SChandler Carruth     SaveAndRestore<bool> NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges,
2356f2e6522SChandler Carruth                                   false);
236e90195c0SDavid Blaikie     completeCFG =
237e90195c0SDavid Blaikie         CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
2386f2e6522SChandler Carruth     // Even when the cfg is not successfully built, we don't
2396f2e6522SChandler Carruth     // want to try building it again.
2406f2e6522SChandler Carruth     builtCompleteCFG = true;
241cf10ea8cSJordan Rose 
242cf10ea8cSJordan Rose     if (PM)
243cf10ea8cSJordan Rose       addParentsForSyntheticStmts(completeCFG.get(), *PM);
244e9fa266cSRichard Trieu 
245e729d9b5SRichard Trieu     // The Observer should only observe one build of the CFG.
24625542943SCraig Topper     getCFGBuildOptions().Observer = nullptr;
2476f2e6522SChandler Carruth   }
2486f2e6522SChandler Carruth   return completeCFG.get();
2496f2e6522SChandler Carruth }
2506f2e6522SChandler Carruth 
getCFGStmtMap()2516f2e6522SChandler Carruth CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
2526f2e6522SChandler Carruth   if (cfgStmtMap)
2536f2e6522SChandler Carruth     return cfgStmtMap.get();
2546f2e6522SChandler Carruth 
2556f2e6522SChandler Carruth   if (CFG *c = getCFG()) {
2566f2e6522SChandler Carruth     cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
2576f2e6522SChandler Carruth     return cfgStmtMap.get();
2586f2e6522SChandler Carruth   }
2596f2e6522SChandler Carruth 
26025542943SCraig Topper   return nullptr;
2616f2e6522SChandler Carruth }
2626f2e6522SChandler Carruth 
getCFGReachablityAnalysis()2636f2e6522SChandler Carruth CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
2646f2e6522SChandler Carruth   if (CFA)
2656f2e6522SChandler Carruth     return CFA.get();
2666f2e6522SChandler Carruth 
2676f2e6522SChandler Carruth   if (CFG *c = getCFG()) {
2686f2e6522SChandler Carruth     CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
2696f2e6522SChandler Carruth     return CFA.get();
2706f2e6522SChandler Carruth   }
2716f2e6522SChandler Carruth 
27225542943SCraig Topper   return nullptr;
2736f2e6522SChandler Carruth }
2746f2e6522SChandler Carruth 
dumpCFG(bool ShowColors)27572be32afSTed Kremenek void AnalysisDeclContext::dumpCFG(bool ShowColors) {
276bbafb8a7SDavid Blaikie   getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
2776f2e6522SChandler Carruth }
2786f2e6522SChandler Carruth 
getParentMap()279433b0f54SJordan Rose ParentMap &AnalysisDeclContext::getParentMap() {
280433b0f54SJordan Rose   if (!PM) {
281433b0f54SJordan Rose     PM.reset(new ParentMap(getBody()));
2821c1057afSEugene Zelenko     if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
2830ad78303SAaron Ballman       for (const auto *I : C->inits()) {
2840ad78303SAaron Ballman         PM->addStmt(I->getInit());
28525bc20f8SJordan Rose       }
28625bc20f8SJordan Rose     }
287cf10ea8cSJordan Rose     if (builtCFG)
288cf10ea8cSJordan Rose       addParentsForSyntheticStmts(getCFG(), *PM);
289cf10ea8cSJordan Rose     if (builtCompleteCFG)
290cf10ea8cSJordan Rose       addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);
29125bc20f8SJordan Rose   }
2926f2e6522SChandler Carruth   return *PM;
2936f2e6522SChandler Carruth }
2946f2e6522SChandler Carruth 
getContext(const Decl * D)2954f8198e7SJordy Rose AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
2961c1057afSEugene Zelenko   if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
2973d0ec38cSTed Kremenek     // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
2983d0ec38cSTed Kremenek     // that has the body.
29914f779c4STed Kremenek     FD->hasBody(FD);
30014f779c4STed Kremenek     D = FD;
30114f779c4STed Kremenek   }
30214f779c4STed Kremenek 
3035cb35e16SJustin Lebar   std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
3046f2e6522SChandler Carruth   if (!AC)
3052b3d49b6SJonas Devlieghere     AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions);
3065cb35e16SJustin Lebar   return AC.get();
3076f2e6522SChandler Carruth }
3086f2e6522SChandler Carruth 
getBodyFarm()309ed017b63SGeorge Karpenkov BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
3103d64d6eeSGeorge Karpenkov 
3116f2e6522SChandler Carruth const StackFrameContext *
getStackFrame(const LocationContext * ParentLC,const Stmt * S,const CFGBlock * Blk,unsigned BlockCount,unsigned Index)3127e1a6ca9SCharusso AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC,
3137e1a6ca9SCharusso                                    const Stmt *S, const CFGBlock *Blk,
3147e1a6ca9SCharusso                                    unsigned BlockCount, unsigned Index) {
3157e1a6ca9SCharusso   return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk,
3167e1a6ca9SCharusso                                                    BlockCount, Index);
3176f2e6522SChandler Carruth }
3186f2e6522SChandler Carruth 
getBlockInvocationContext(const LocationContext * ParentLC,const BlockDecl * BD,const void * Data)3197e1a6ca9SCharusso const BlockInvocationContext *AnalysisDeclContext::getBlockInvocationContext(
3207e1a6ca9SCharusso     const LocationContext *ParentLC, const BlockDecl *BD, const void *Data) {
3217e1a6ca9SCharusso   return getLocationContextManager().getBlockInvocationContext(this, ParentLC,
3227e1a6ca9SCharusso                                                                BD, Data);
323c3da376fSTed Kremenek }
324c3da376fSTed Kremenek 
isInStdNamespace(const Decl * D)3259165df12SDevin Coughlin bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
3269165df12SDevin Coughlin   const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
3271c1057afSEugene Zelenko   const auto *ND = dyn_cast<NamespaceDecl>(DC);
3289165df12SDevin Coughlin   if (!ND)
3299165df12SDevin Coughlin     return false;
3309165df12SDevin Coughlin 
3319165df12SDevin Coughlin   while (const DeclContext *Parent = ND->getParent()) {
3329165df12SDevin Coughlin     if (!isa<NamespaceDecl>(Parent))
3339165df12SDevin Coughlin       break;
3349165df12SDevin Coughlin     ND = cast<NamespaceDecl>(Parent);
3359165df12SDevin Coughlin   }
3369165df12SDevin Coughlin 
3379165df12SDevin Coughlin   return ND->isStdNamespace();
3389165df12SDevin Coughlin }
3399165df12SDevin Coughlin 
getFunctionName(const Decl * D)340d3e14fafSBalazs Benics std::string AnalysisDeclContext::getFunctionName(const Decl *D) {
341d3e14fafSBalazs Benics   std::string Str;
342d3e14fafSBalazs Benics   llvm::raw_string_ostream OS(Str);
343d3e14fafSBalazs Benics   const ASTContext &Ctx = D->getASTContext();
344d3e14fafSBalazs Benics 
345d3e14fafSBalazs Benics   if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
346d3e14fafSBalazs Benics     OS << FD->getQualifiedNameAsString();
347d3e14fafSBalazs Benics 
348d3e14fafSBalazs Benics     // In C++, there are overloads.
349d3e14fafSBalazs Benics 
350d3e14fafSBalazs Benics     if (Ctx.getLangOpts().CPlusPlus) {
351d3e14fafSBalazs Benics       OS << '(';
352d3e14fafSBalazs Benics       for (const auto &P : FD->parameters()) {
353d3e14fafSBalazs Benics         if (P != *FD->param_begin())
354d3e14fafSBalazs Benics           OS << ", ";
355*cfb81690SNathan James         OS << P->getType();
356d3e14fafSBalazs Benics       }
357d3e14fafSBalazs Benics       OS << ')';
358d3e14fafSBalazs Benics     }
359d3e14fafSBalazs Benics 
360d3e14fafSBalazs Benics   } else if (isa<BlockDecl>(D)) {
361d3e14fafSBalazs Benics     PresumedLoc Loc = Ctx.getSourceManager().getPresumedLoc(D->getLocation());
362d3e14fafSBalazs Benics 
363d3e14fafSBalazs Benics     if (Loc.isValid()) {
364d3e14fafSBalazs Benics       OS << "block (line: " << Loc.getLine() << ", col: " << Loc.getColumn()
365d3e14fafSBalazs Benics          << ')';
366d3e14fafSBalazs Benics     }
367d3e14fafSBalazs Benics 
368d3e14fafSBalazs Benics   } else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
369d3e14fafSBalazs Benics 
370d3e14fafSBalazs Benics     // FIXME: copy-pasted from CGDebugInfo.cpp.
371d3e14fafSBalazs Benics     OS << (OMD->isInstanceMethod() ? '-' : '+') << '[';
372d3e14fafSBalazs Benics     const DeclContext *DC = OMD->getDeclContext();
373d3e14fafSBalazs Benics     if (const auto *OID = dyn_cast<ObjCImplementationDecl>(DC)) {
374d3e14fafSBalazs Benics       OS << OID->getName();
375d3e14fafSBalazs Benics     } else if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) {
376d3e14fafSBalazs Benics       OS << OID->getName();
377d3e14fafSBalazs Benics     } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(DC)) {
378d3e14fafSBalazs Benics       if (OC->IsClassExtension()) {
379d3e14fafSBalazs Benics         OS << OC->getClassInterface()->getName();
380d3e14fafSBalazs Benics       } else {
381d3e14fafSBalazs Benics         OS << OC->getIdentifier()->getNameStart() << '('
382d3e14fafSBalazs Benics            << OC->getIdentifier()->getNameStart() << ')';
383d3e14fafSBalazs Benics       }
384d3e14fafSBalazs Benics     } else if (const auto *OCD = dyn_cast<ObjCCategoryImplDecl>(DC)) {
385d3e14fafSBalazs Benics       OS << OCD->getClassInterface()->getName() << '(' << OCD->getName() << ')';
386d3e14fafSBalazs Benics     }
387d3e14fafSBalazs Benics     OS << ' ' << OMD->getSelector().getAsString() << ']';
388d3e14fafSBalazs Benics   }
389d3e14fafSBalazs Benics 
390715c72b4SLogan Smith   return Str;
391d3e14fafSBalazs Benics }
392d3e14fafSBalazs Benics 
getLocationContextManager()3936f2e6522SChandler Carruth LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
3947e1a6ca9SCharusso   assert(
3957e1a6ca9SCharusso       ADCMgr &&
3966f2e6522SChandler Carruth       "Cannot create LocationContexts without an AnalysisDeclContextManager!");
3977e1a6ca9SCharusso   return ADCMgr->getLocationContextManager();
3986f2e6522SChandler Carruth }
3996f2e6522SChandler Carruth 
4006f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
4016f2e6522SChandler Carruth // FoldingSet profiling.
4026f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
4036f2e6522SChandler Carruth 
ProfileCommon(llvm::FoldingSetNodeID & ID,ContextKind ck,AnalysisDeclContext * ctx,const LocationContext * parent,const void * data)4046f2e6522SChandler Carruth void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
4056f2e6522SChandler Carruth                                     ContextKind ck,
4066f2e6522SChandler Carruth                                     AnalysisDeclContext *ctx,
4076f2e6522SChandler Carruth                                     const LocationContext *parent,
4086f2e6522SChandler Carruth                                     const void *data) {
4096f2e6522SChandler Carruth   ID.AddInteger(ck);
4106f2e6522SChandler Carruth   ID.AddPointer(ctx);
4116f2e6522SChandler Carruth   ID.AddPointer(parent);
4126f2e6522SChandler Carruth   ID.AddPointer(data);
4136f2e6522SChandler Carruth }
4146f2e6522SChandler Carruth 
Profile(llvm::FoldingSetNodeID & ID)4156f2e6522SChandler Carruth void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
4167740c6d6SCsaba Dabis   Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block,
4177740c6d6SCsaba Dabis           BlockCount, Index);
4186f2e6522SChandler Carruth }
4196f2e6522SChandler Carruth 
Profile(llvm::FoldingSetNodeID & ID)4206f2e6522SChandler Carruth void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
4217e1a6ca9SCharusso   Profile(ID, getAnalysisDeclContext(), getParent(), BD, Data);
4226f2e6522SChandler Carruth }
4236f2e6522SChandler Carruth 
4246f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
4256f2e6522SChandler Carruth // LocationContext creation.
4266f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
4276f2e6522SChandler Carruth 
getStackFrame(AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s,const CFGBlock * blk,unsigned blockCount,unsigned idx)4287740c6d6SCsaba Dabis const StackFrameContext *LocationContextManager::getStackFrame(
4297740c6d6SCsaba Dabis     AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
4307740c6d6SCsaba Dabis     const CFGBlock *blk, unsigned blockCount, unsigned idx) {
4316f2e6522SChandler Carruth   llvm::FoldingSetNodeID ID;
4327740c6d6SCsaba Dabis   StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx);
4336f2e6522SChandler Carruth   void *InsertPos;
4341c1057afSEugene Zelenko   auto *L =
4356f2e6522SChandler Carruth    cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
4366f2e6522SChandler Carruth   if (!L) {
4377740c6d6SCsaba Dabis     L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
4386f2e6522SChandler Carruth     Contexts.InsertNode(L, InsertPos);
4396f2e6522SChandler Carruth   }
4406f2e6522SChandler Carruth   return L;
4416f2e6522SChandler Carruth }
4426f2e6522SChandler Carruth 
getBlockInvocationContext(AnalysisDeclContext * ADC,const LocationContext * ParentLC,const BlockDecl * BD,const void * Data)4437e1a6ca9SCharusso const BlockInvocationContext *LocationContextManager::getBlockInvocationContext(
4447e1a6ca9SCharusso     AnalysisDeclContext *ADC, const LocationContext *ParentLC,
4457e1a6ca9SCharusso     const BlockDecl *BD, const void *Data) {
446c3da376fSTed Kremenek   llvm::FoldingSetNodeID ID;
4477e1a6ca9SCharusso   BlockInvocationContext::Profile(ID, ADC, ParentLC, BD, Data);
448c3da376fSTed Kremenek   void *InsertPos;
4491c1057afSEugene Zelenko   auto *L =
450c3da376fSTed Kremenek     cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
451c3da376fSTed Kremenek                                                                     InsertPos));
452c3da376fSTed Kremenek   if (!L) {
4537e1a6ca9SCharusso     L = new BlockInvocationContext(ADC, ParentLC, BD, Data, ++NewID);
454c3da376fSTed Kremenek     Contexts.InsertNode(L, InsertPos);
455c3da376fSTed Kremenek   }
456c3da376fSTed Kremenek   return L;
457c3da376fSTed Kremenek }
458c3da376fSTed Kremenek 
4596f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
4606f2e6522SChandler Carruth // LocationContext methods.
4616f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
4626f2e6522SChandler Carruth 
getStackFrame() const463dd18b11bSGeorge Karpenkov const StackFrameContext *LocationContext::getStackFrame() const {
4646f2e6522SChandler Carruth   const LocationContext *LC = this;
4656f2e6522SChandler Carruth   while (LC) {
4661c1057afSEugene Zelenko     if (const auto *SFC = dyn_cast<StackFrameContext>(LC))
4676f2e6522SChandler Carruth       return SFC;
4686f2e6522SChandler Carruth     LC = LC->getParent();
4696f2e6522SChandler Carruth   }
47025542943SCraig Topper   return nullptr;
4716f2e6522SChandler Carruth }
4726f2e6522SChandler Carruth 
inTopFrame() const47344dc91b4SAnna Zaks bool LocationContext::inTopFrame() const {
474dd18b11bSGeorge Karpenkov   return getStackFrame()->inTopFrame();
47544dc91b4SAnna Zaks }
47644dc91b4SAnna Zaks 
isParentOf(const LocationContext * LC) const4776f2e6522SChandler Carruth bool LocationContext::isParentOf(const LocationContext *LC) const {
4786f2e6522SChandler Carruth   do {
4796f2e6522SChandler Carruth     const LocationContext *Parent = LC->getParent();
4806f2e6522SChandler Carruth     if (Parent == this)
4816f2e6522SChandler Carruth       return true;
4826f2e6522SChandler Carruth     else
4836f2e6522SChandler Carruth       LC = Parent;
4846f2e6522SChandler Carruth   } while (LC);
4856f2e6522SChandler Carruth 
4866f2e6522SChandler Carruth   return false;
4876f2e6522SChandler Carruth }
4886f2e6522SChandler Carruth 
printLocation(raw_ostream & Out,const SourceManager & SM,SourceLocation Loc)4899ce37466SCsaba Dabis static void printLocation(raw_ostream &Out, const SourceManager &SM,
4909ce37466SCsaba Dabis                           SourceLocation Loc) {
4919ce37466SCsaba Dabis   if (Loc.isFileID() && SM.isInMainFile(Loc))
4929ce37466SCsaba Dabis     Out << SM.getExpansionLineNumber(Loc);
493be073035SArtem Dergachev   else
4949ce37466SCsaba Dabis     Loc.print(Out, SM);
495be073035SArtem Dergachev }
496be073035SArtem Dergachev 
dumpStack(raw_ostream & Out) const4977e1a6ca9SCharusso void LocationContext::dumpStack(raw_ostream &Out) const {
4986fdef11cSJordan Rose   ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
4996fdef11cSJordan Rose   PrintingPolicy PP(Ctx.getLangOpts());
5006fdef11cSJordan Rose   PP.TerseOutput = 1;
5016fdef11cSJordan Rose 
502be073035SArtem Dergachev   const SourceManager &SM =
503be073035SArtem Dergachev       getAnalysisDeclContext()->getASTContext().getSourceManager();
504be073035SArtem Dergachev 
5056fdef11cSJordan Rose   unsigned Frame = 0;
5066fdef11cSJordan Rose   for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
5076fdef11cSJordan Rose     switch (LCtx->getKind()) {
5086fdef11cSJordan Rose     case StackFrame:
5099ce37466SCsaba Dabis       Out << "\t#" << Frame << ' ';
510be073035SArtem Dergachev       ++Frame;
5111c1057afSEugene Zelenko       if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
512d3e14fafSBalazs Benics         Out << "Calling " << AnalysisDeclContext::getFunctionName(D);
513be073035SArtem Dergachev       else
5149ce37466SCsaba Dabis         Out << "Calling anonymous code";
515be073035SArtem Dergachev       if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
5169ce37466SCsaba Dabis         Out << " at line ";
5179ce37466SCsaba Dabis         printLocation(Out, SM, S->getBeginLoc());
518be073035SArtem Dergachev       }
5196fdef11cSJordan Rose       break;
5206fdef11cSJordan Rose     case Block:
5219ce37466SCsaba Dabis       Out << "Invoking block";
522be073035SArtem Dergachev       if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
5239ce37466SCsaba Dabis         Out << " defined at line ";
5249ce37466SCsaba Dabis         printLocation(Out, SM, D->getBeginLoc());
525be073035SArtem Dergachev       }
5266fdef11cSJordan Rose       break;
5276fdef11cSJordan Rose     }
5287e1a6ca9SCharusso     Out << '\n';
5296fdef11cSJordan Rose   }
5306fdef11cSJordan Rose }
5316fdef11cSJordan Rose 
printJson(raw_ostream & Out,const char * NL,unsigned int Space,bool IsDot,std::function<void (const LocationContext *)> printMoreInfoPerContext) const5329ce37466SCsaba Dabis void LocationContext::printJson(raw_ostream &Out, const char *NL,
5339ce37466SCsaba Dabis                                 unsigned int Space, bool IsDot,
5349ce37466SCsaba Dabis                                 std::function<void(const LocationContext *)>
5359ce37466SCsaba Dabis                                     printMoreInfoPerContext) const {
5369ce37466SCsaba Dabis   ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
5379ce37466SCsaba Dabis   PrintingPolicy PP(Ctx.getLangOpts());
5389ce37466SCsaba Dabis   PP.TerseOutput = 1;
5399ce37466SCsaba Dabis 
5409ce37466SCsaba Dabis   const SourceManager &SM =
5419ce37466SCsaba Dabis       getAnalysisDeclContext()->getASTContext().getSourceManager();
5429ce37466SCsaba Dabis 
5439ce37466SCsaba Dabis   unsigned Frame = 0;
5449ce37466SCsaba Dabis   for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
545f9f6cdb1SArtem Dergachev     Indent(Out, Space, IsDot)
546f9f6cdb1SArtem Dergachev         << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";
5479ce37466SCsaba Dabis     switch (LCtx->getKind()) {
5489ce37466SCsaba Dabis     case StackFrame:
5499ce37466SCsaba Dabis       Out << '#' << Frame << " Call\", \"calling\": \"";
5509ce37466SCsaba Dabis       ++Frame;
5519ce37466SCsaba Dabis       if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
5529ce37466SCsaba Dabis         Out << D->getQualifiedNameAsString();
5539ce37466SCsaba Dabis       else
5549ce37466SCsaba Dabis         Out << "anonymous code";
5559ce37466SCsaba Dabis 
556ed035ff8SArtem Dergachev       Out << "\", \"location\": ";
5579ce37466SCsaba Dabis       if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
558ed035ff8SArtem Dergachev         printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
5599ce37466SCsaba Dabis       } else {
5609ce37466SCsaba Dabis         Out << "null";
561e9c57229SJordan Rose       }
562e9c57229SJordan Rose 
5639ce37466SCsaba Dabis       Out << ", \"items\": ";
5649ce37466SCsaba Dabis       break;
5659ce37466SCsaba Dabis     case Block:
5669ce37466SCsaba Dabis       Out << "Invoking block\" ";
5679ce37466SCsaba Dabis       if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
568ed035ff8SArtem Dergachev         Out << ", \"location\": ";
569ed035ff8SArtem Dergachev         printSourceLocationAsJson(Out, D->getBeginLoc(), SM);
5709ce37466SCsaba Dabis         Out << ' ';
5719ce37466SCsaba Dabis       }
5729ce37466SCsaba Dabis       break;
5739ce37466SCsaba Dabis     }
5749ce37466SCsaba Dabis 
5759ce37466SCsaba Dabis     printMoreInfoPerContext(LCtx);
5769ce37466SCsaba Dabis 
5779ce37466SCsaba Dabis     Out << '}';
5789ce37466SCsaba Dabis     if (LCtx->getParent())
5799ce37466SCsaba Dabis       Out << ',';
5809ce37466SCsaba Dabis     Out << NL;
5819ce37466SCsaba Dabis   }
5829ce37466SCsaba Dabis }
5839ce37466SCsaba Dabis 
dump() const5849ce37466SCsaba Dabis LLVM_DUMP_METHOD void LocationContext::dump() const { printJson(llvm::errs()); }
5859ce37466SCsaba Dabis 
5866f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
5876f2e6522SChandler Carruth // Lazily generated map to query the external variables referenced by a Block.
5886f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
5896f2e6522SChandler Carruth 
5906f2e6522SChandler Carruth namespace {
5911c1057afSEugene Zelenko 
5926f2e6522SChandler Carruth class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
5936f2e6522SChandler Carruth   BumpVector<const VarDecl *> &BEVals;
5946f2e6522SChandler Carruth   BumpVectorContext &BC;
595616f8022SBenjamin Kramer   llvm::SmallPtrSet<const VarDecl *, 4> Visited;
596616f8022SBenjamin Kramer   llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
5971c1057afSEugene Zelenko 
5986f2e6522SChandler Carruth public:
FindBlockDeclRefExprsVals(BumpVector<const VarDecl * > & bevals,BumpVectorContext & bc)5996f2e6522SChandler Carruth   FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
6006f2e6522SChandler Carruth                             BumpVectorContext &bc)
6016f2e6522SChandler Carruth       : BEVals(bevals), BC(bc) {}
6026f2e6522SChandler Carruth 
VisitStmt(Stmt * S)6036f2e6522SChandler Carruth   void VisitStmt(Stmt *S) {
6041c1057afSEugene Zelenko     for (auto *Child : S->children())
605642f173aSBenjamin Kramer       if (Child)
606642f173aSBenjamin Kramer         Visit(Child);
6076f2e6522SChandler Carruth   }
6086f2e6522SChandler Carruth 
VisitDeclRefExpr(DeclRefExpr * DR)609299cfb7aSTed Kremenek   void VisitDeclRefExpr(DeclRefExpr *DR) {
6106f2e6522SChandler Carruth     // Non-local variables are also directly modified.
6111c1057afSEugene Zelenko     if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
6126f2e6522SChandler Carruth       if (!VD->hasLocalStorage()) {
61382e95a3cSDavid Blaikie         if (Visited.insert(VD).second)
6146f2e6522SChandler Carruth           BEVals.push_back(VD, BC);
6156f2e6522SChandler Carruth       }
6166f2e6522SChandler Carruth     }
6176f2e6522SChandler Carruth   }
6186f2e6522SChandler Carruth 
VisitBlockExpr(BlockExpr * BR)6196f2e6522SChandler Carruth   void VisitBlockExpr(BlockExpr *BR) {
6206f2e6522SChandler Carruth     // Blocks containing blocks can transitively capture more variables.
6216f2e6522SChandler Carruth     IgnoredContexts.insert(BR->getBlockDecl());
6226f2e6522SChandler Carruth     Visit(BR->getBlockDecl()->getBody());
6236f2e6522SChandler Carruth   }
624299cfb7aSTed Kremenek 
VisitPseudoObjectExpr(PseudoObjectExpr * PE)625299cfb7aSTed Kremenek   void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
626299cfb7aSTed Kremenek     for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
627299cfb7aSTed Kremenek          et = PE->semantics_end(); it != et; ++it) {
628299cfb7aSTed Kremenek       Expr *Semantic = *it;
6291c1057afSEugene Zelenko       if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
630299cfb7aSTed Kremenek         Semantic = OVE->getSourceExpr();
631299cfb7aSTed Kremenek       Visit(Semantic);
632299cfb7aSTed Kremenek     }
633299cfb7aSTed Kremenek   }
6346f2e6522SChandler Carruth };
6356f2e6522SChandler Carruth 
6361c1057afSEugene Zelenko } // namespace
6371c1057afSEugene Zelenko 
6381c1057afSEugene Zelenko using DeclVec = BumpVector<const VarDecl *>;
6396f2e6522SChandler Carruth 
LazyInitializeReferencedDecls(const BlockDecl * BD,void * & Vec,llvm::BumpPtrAllocator & A)6406f2e6522SChandler Carruth static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
6416f2e6522SChandler Carruth                                               void *&Vec,
6426f2e6522SChandler Carruth                                               llvm::BumpPtrAllocator &A) {
6436f2e6522SChandler Carruth   if (Vec)
6446f2e6522SChandler Carruth     return (DeclVec*) Vec;
6456f2e6522SChandler Carruth 
6466f2e6522SChandler Carruth   BumpVectorContext BC(A);
6476f2e6522SChandler Carruth   DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
6486f2e6522SChandler Carruth   new (BV) DeclVec(BC, 10);
6496f2e6522SChandler Carruth 
6503e871d8cSTed Kremenek   // Go through the capture list.
6519371dd22SAaron Ballman   for (const auto &CI : BD->captures()) {
6529371dd22SAaron Ballman     BV->push_back(CI.getVariable(), BC);
6533e871d8cSTed Kremenek   }
6543e871d8cSTed Kremenek 
6553e871d8cSTed Kremenek   // Find the referenced global/static variables.
6566f2e6522SChandler Carruth   FindBlockDeclRefExprsVals F(*BV, BC);
6576f2e6522SChandler Carruth   F.Visit(BD->getBody());
6586f2e6522SChandler Carruth 
6596f2e6522SChandler Carruth   Vec = BV;
6606f2e6522SChandler Carruth   return BV;
6616f2e6522SChandler Carruth }
6626f2e6522SChandler Carruth 
663b4ef6683SBenjamin Kramer llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl * BD)6646f2e6522SChandler Carruth AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
6656f2e6522SChandler Carruth   if (!ReferencedBlockVars)
6666f2e6522SChandler Carruth     ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
6676f2e6522SChandler Carruth 
668b4ef6683SBenjamin Kramer   const DeclVec *V =
669b4ef6683SBenjamin Kramer       LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
670b4ef6683SBenjamin Kramer   return llvm::make_range(V->begin(), V->end());
6716f2e6522SChandler Carruth }
6726f2e6522SChandler Carruth 
getAnalysisImpl(const void * tag)673e265f92bSDavid Blaikie std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(const void *tag) {
6746f2e6522SChandler Carruth   if (!ManagedAnalyses)
6756f2e6522SChandler Carruth     ManagedAnalyses = new ManagedAnalysisMap();
6766f2e6522SChandler Carruth   ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
6776f2e6522SChandler Carruth   return (*M)[tag];
6786f2e6522SChandler Carruth }
6796f2e6522SChandler Carruth 
6806f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
6816f2e6522SChandler Carruth // Cleanup.
6826f2e6522SChandler Carruth //===----------------------------------------------------------------------===//
6836f2e6522SChandler Carruth 
6841c1057afSEugene Zelenko ManagedAnalysis::~ManagedAnalysis() = default;
6856f2e6522SChandler Carruth 
~AnalysisDeclContext()6866f2e6522SChandler Carruth AnalysisDeclContext::~AnalysisDeclContext() {
6876f2e6522SChandler Carruth   delete forcedBlkExprs;
6886f2e6522SChandler Carruth   delete ReferencedBlockVars;
689e265f92bSDavid Blaikie   delete (ManagedAnalysisMap*) ManagedAnalyses;
6906f2e6522SChandler Carruth }
6916f2e6522SChandler Carruth 
6921c1057afSEugene Zelenko LocationContext::~LocationContext() = default;
6936f2e6522SChandler Carruth 
~LocationContextManager()6946f2e6522SChandler Carruth LocationContextManager::~LocationContextManager() {
6956f2e6522SChandler Carruth   clear();
6966f2e6522SChandler Carruth }
6976f2e6522SChandler Carruth 
clear()6986f2e6522SChandler Carruth void LocationContextManager::clear() {
6996f2e6522SChandler Carruth   for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
7006f2e6522SChandler Carruth        E = Contexts.end(); I != E; ) {
7016f2e6522SChandler Carruth     LocationContext *LC = &*I;
7026f2e6522SChandler Carruth     ++I;
7036f2e6522SChandler Carruth     delete LC;
7046f2e6522SChandler Carruth   }
7056f2e6522SChandler Carruth   Contexts.clear();
7066f2e6522SChandler Carruth }
707