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