1 //===- AnalysisDeclContext.cpp - Analysis context for Path Sens analysis --===//
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
7 //===----------------------------------------------------------------------===//
9 // This file defines AnalysisDeclContext, a class that manages the analysis
10 // context data for path sensitive analysis.
12 //===----------------------------------------------------------------------===//
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"
51 using namespace clang;
53 using ManagedAnalysisMap = llvm::DenseMap<const void *, ManagedAnalysis *>;
55 AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
57 const CFG::BuildOptions &buildOptions)
58 : Manager(Mgr), D(d), cfgBuildOptions(buildOptions) {
59 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
62 AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *Mgr,
64 : Manager(Mgr), D(d) {
65 cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
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;
91 void AnalysisDeclContextManager::clear() { Contexts.clear(); }
93 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 (Manager && Manager->synthesizeBodies()) {
100 Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(FD);
101 if (SynthesizedBody) {
102 Body = SynthesizedBody;
103 IsAutosynthesized = true;
108 else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
109 Stmt *Body = MD->getBody();
110 if (Manager && Manager->synthesizeBodies()) {
111 Stmt *SynthesizedBody = Manager->getBodyFarm().getBody(MD);
112 if (SynthesizedBody) {
113 Body = SynthesizedBody;
114 IsAutosynthesized = true;
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();
123 llvm_unreachable("unknown code decl");
126 Stmt *AnalysisDeclContext::getBody() const {
131 bool AnalysisDeclContext::isBodyAutosynthesized() const {
137 bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
139 Stmt *Body = getBody(Tmp);
140 return Tmp && Body->getBeginLoc().isValid();
143 /// Returns true if \param VD is an Objective-C implicit 'self' parameter.
144 static bool isSelfDecl(const VarDecl *VD) {
145 return isa<ImplicitParamDecl>(VD) && VD->getName() == "self";
148 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();
156 return dyn_cast<ImplicitParamDecl>(VD);
160 auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
164 const CXXRecordDecl *parent = CXXMethod->getParent();
165 if (!parent->isLambda())
168 for (const auto &LC : parent->captures()) {
169 if (!LC.capturesVariable())
172 VarDecl *VD = LC.getCapturedVar();
174 return dyn_cast<ImplicitParamDecl>(VD);
180 void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
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];
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());
200 /// Add each synthetic statement in the CFG to the parent map, using the
201 /// source statement's parent.
202 static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) {
206 for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(),
207 E = TheCFG->synthetic_stmt_end();
209 PM.setParent(I->first, PM.getParent(I->second));
213 CFG *AnalysisDeclContext::getCFG() {
214 if (!cfgBuildOptions.PruneTriviallyFalseEdges)
215 return getUnoptimizedCFG();
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.
224 addParentsForSyntheticStmts(cfg.get(), *PM);
226 // The Observer should only observe one build of the CFG.
227 getCFGBuildOptions().Observer = nullptr;
232 CFG *AnalysisDeclContext::getUnoptimizedCFG() {
233 if (!builtCompleteCFG) {
234 SaveAndRestore<bool> NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges,
237 CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
238 // Even when the cfg is not successfully built, we don't
239 // want to try building it again.
240 builtCompleteCFG = true;
243 addParentsForSyntheticStmts(completeCFG.get(), *PM);
245 // The Observer should only observe one build of the CFG.
246 getCFGBuildOptions().Observer = nullptr;
248 return completeCFG.get();
251 CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
253 return cfgStmtMap.get();
255 if (CFG *c = getCFG()) {
256 cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
257 return cfgStmtMap.get();
263 CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
267 if (CFG *c = getCFG()) {
268 CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
275 void AnalysisDeclContext::dumpCFG(bool ShowColors) {
276 getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
279 ParentMap &AnalysisDeclContext::getParentMap() {
281 PM.reset(new ParentMap(getBody()));
282 if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
283 for (const auto *I : C->inits()) {
284 PM->addStmt(I->getInit());
288 addParentsForSyntheticStmts(getCFG(), *PM);
289 if (builtCompleteCFG)
290 addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);
295 AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
296 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
297 // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
298 // that has the body.
303 std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
305 AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions);
309 BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
311 const StackFrameContext *
312 AnalysisDeclContext::getStackFrame(LocationContext const *Parent, const Stmt *S,
313 const CFGBlock *Blk, unsigned BlockCount,
315 return getLocationContextManager().getStackFrame(this, Parent, S, Blk,
319 const BlockInvocationContext *
320 AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent,
322 const void *ContextData) {
323 return getLocationContextManager().getBlockInvocationContext(this, parent,
327 bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
328 const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
329 const auto *ND = dyn_cast<NamespaceDecl>(DC);
333 while (const DeclContext *Parent = ND->getParent()) {
334 if (!isa<NamespaceDecl>(Parent))
336 ND = cast<NamespaceDecl>(Parent);
339 return ND->isStdNamespace();
342 LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
344 "Cannot create LocationContexts without an AnalysisDeclContextManager!");
345 return Manager->getLocationContextManager();
348 //===----------------------------------------------------------------------===//
349 // FoldingSet profiling.
350 //===----------------------------------------------------------------------===//
352 void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
354 AnalysisDeclContext *ctx,
355 const LocationContext *parent,
359 ID.AddPointer(parent);
363 void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
364 Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block,
368 void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
369 Profile(ID, getAnalysisDeclContext(), getParent(), Enter);
372 void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
373 Profile(ID, getAnalysisDeclContext(), getParent(), BD, ContextData);
376 //===----------------------------------------------------------------------===//
377 // LocationContext creation.
378 //===----------------------------------------------------------------------===//
380 template <typename LOC, typename DATA>
382 LocationContextManager::getLocationContext(AnalysisDeclContext *ctx,
383 const LocationContext *parent,
385 llvm::FoldingSetNodeID ID;
386 LOC::Profile(ID, ctx, parent, d);
389 LOC *L = cast_or_null<LOC>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
392 L = new LOC(ctx, parent, d, ++NewID);
393 Contexts.InsertNode(L, InsertPos);
398 const StackFrameContext *LocationContextManager::getStackFrame(
399 AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
400 const CFGBlock *blk, unsigned blockCount, unsigned idx) {
401 llvm::FoldingSetNodeID ID;
402 StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx);
405 cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
407 L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
408 Contexts.InsertNode(L, InsertPos);
414 LocationContextManager::getScope(AnalysisDeclContext *ctx,
415 const LocationContext *parent,
417 return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
420 const BlockInvocationContext *
421 LocationContextManager::getBlockInvocationContext(AnalysisDeclContext *ctx,
422 const LocationContext *parent,
424 const void *ContextData) {
425 llvm::FoldingSetNodeID ID;
426 BlockInvocationContext::Profile(ID, ctx, parent, BD, ContextData);
429 cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
432 L = new BlockInvocationContext(ctx, parent, BD, ContextData, ++NewID);
433 Contexts.InsertNode(L, InsertPos);
438 //===----------------------------------------------------------------------===//
439 // LocationContext methods.
440 //===----------------------------------------------------------------------===//
442 const StackFrameContext *LocationContext::getStackFrame() const {
443 const LocationContext *LC = this;
445 if (const auto *SFC = dyn_cast<StackFrameContext>(LC))
447 LC = LC->getParent();
452 bool LocationContext::inTopFrame() const {
453 return getStackFrame()->inTopFrame();
456 bool LocationContext::isParentOf(const LocationContext *LC) const {
458 const LocationContext *Parent = LC->getParent();
468 static void printLocation(raw_ostream &Out, const SourceManager &SM,
469 SourceLocation Loc) {
470 if (Loc.isFileID() && SM.isInMainFile(Loc))
471 Out << SM.getExpansionLineNumber(Loc);
476 void LocationContext::dumpStack(raw_ostream &Out, const char *NL,
477 std::function<void(const LocationContext *)>
478 printMoreInfoPerContext) const {
479 ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
480 PrintingPolicy PP(Ctx.getLangOpts());
483 const SourceManager &SM =
484 getAnalysisDeclContext()->getASTContext().getSourceManager();
487 for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
488 switch (LCtx->getKind()) {
490 Out << "\t#" << Frame << ' ';
492 if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
493 Out << "Calling " << D->getQualifiedNameAsString();
495 Out << "Calling anonymous code";
496 if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
498 printLocation(Out, SM, S->getBeginLoc());
502 Out << "Entering scope";
505 Out << "Invoking block";
506 if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
507 Out << " defined at line ";
508 printLocation(Out, SM, D->getBeginLoc());
514 printMoreInfoPerContext(LCtx);
518 void LocationContext::printJson(raw_ostream &Out, const char *NL,
519 unsigned int Space, bool IsDot,
520 std::function<void(const LocationContext *)>
521 printMoreInfoPerContext) const {
522 ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
523 PrintingPolicy PP(Ctx.getLangOpts());
526 const SourceManager &SM =
527 getAnalysisDeclContext()->getASTContext().getSourceManager();
530 for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
531 Indent(Out, Space, IsDot)
532 << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";
533 switch (LCtx->getKind()) {
535 Out << '#' << Frame << " Call\", \"calling\": \"";
537 if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
538 Out << D->getQualifiedNameAsString();
540 Out << "anonymous code";
542 Out << "\", \"location\": ";
543 if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
544 printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
549 Out << ", \"items\": ";
552 Out << "Entering scope\" ";
555 Out << "Invoking block\" ";
556 if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
557 Out << ", \"location\": ";
558 printSourceLocationAsJson(Out, D->getBeginLoc(), SM);
564 printMoreInfoPerContext(LCtx);
567 if (LCtx->getParent())
573 LLVM_DUMP_METHOD void LocationContext::dump() const { printJson(llvm::errs()); }
575 //===----------------------------------------------------------------------===//
576 // Lazily generated map to query the external variables referenced by a Block.
577 //===----------------------------------------------------------------------===//
581 class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
582 BumpVector<const VarDecl *> &BEVals;
583 BumpVectorContext &BC;
584 llvm::SmallPtrSet<const VarDecl *, 4> Visited;
585 llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
588 FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
589 BumpVectorContext &bc)
590 : BEVals(bevals), BC(bc) {}
592 void VisitStmt(Stmt *S) {
593 for (auto *Child : S->children())
598 void VisitDeclRefExpr(DeclRefExpr *DR) {
599 // Non-local variables are also directly modified.
600 if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
601 if (!VD->hasLocalStorage()) {
602 if (Visited.insert(VD).second)
603 BEVals.push_back(VD, BC);
608 void VisitBlockExpr(BlockExpr *BR) {
609 // Blocks containing blocks can transitively capture more variables.
610 IgnoredContexts.insert(BR->getBlockDecl());
611 Visit(BR->getBlockDecl()->getBody());
614 void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
615 for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
616 et = PE->semantics_end(); it != et; ++it) {
617 Expr *Semantic = *it;
618 if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
619 Semantic = OVE->getSourceExpr();
627 using DeclVec = BumpVector<const VarDecl *>;
629 static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
631 llvm::BumpPtrAllocator &A) {
633 return (DeclVec*) Vec;
635 BumpVectorContext BC(A);
636 DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
637 new (BV) DeclVec(BC, 10);
639 // Go through the capture list.
640 for (const auto &CI : BD->captures()) {
641 BV->push_back(CI.getVariable(), BC);
644 // Find the referenced global/static variables.
645 FindBlockDeclRefExprsVals F(*BV, BC);
646 F.Visit(BD->getBody());
652 llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
653 AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
654 if (!ReferencedBlockVars)
655 ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
658 LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
659 return llvm::make_range(V->begin(), V->end());
662 ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) {
663 if (!ManagedAnalyses)
664 ManagedAnalyses = new ManagedAnalysisMap();
665 ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
669 //===----------------------------------------------------------------------===//
671 //===----------------------------------------------------------------------===//
673 ManagedAnalysis::~ManagedAnalysis() = default;
675 AnalysisDeclContext::~AnalysisDeclContext() {
676 delete forcedBlkExprs;
677 delete ReferencedBlockVars;
678 // Release the managed analyses.
679 if (ManagedAnalyses) {
680 ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
681 llvm::DeleteContainerSeconds(*M);
686 LocationContext::~LocationContext() = default;
688 LocationContextManager::~LocationContextManager() {
692 void LocationContextManager::clear() {
693 for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
694 E = Contexts.end(); I != E; ) {
695 LocationContext *LC = &*I;