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