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