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