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