xref: /openbsd-src/gnu/llvm/clang/lib/Analysis/AnalysisDeclContext.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
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