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