17330f729Sjoerg //===- AnalysisDeclContext.cpp - Analysis context for Path Sens analysis --===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file defines AnalysisDeclContext, a class that manages the analysis
107330f729Sjoerg // context data for path sensitive analysis.
117330f729Sjoerg //
127330f729Sjoerg //===----------------------------------------------------------------------===//
137330f729Sjoerg
147330f729Sjoerg #include "clang/Analysis/AnalysisDeclContext.h"
157330f729Sjoerg #include "clang/AST/ASTContext.h"
167330f729Sjoerg #include "clang/AST/Decl.h"
177330f729Sjoerg #include "clang/AST/DeclBase.h"
187330f729Sjoerg #include "clang/AST/DeclCXX.h"
197330f729Sjoerg #include "clang/AST/DeclObjC.h"
207330f729Sjoerg #include "clang/AST/DeclTemplate.h"
217330f729Sjoerg #include "clang/AST/Expr.h"
227330f729Sjoerg #include "clang/AST/LambdaCapture.h"
237330f729Sjoerg #include "clang/AST/ParentMap.h"
247330f729Sjoerg #include "clang/AST/PrettyPrinter.h"
257330f729Sjoerg #include "clang/AST/Stmt.h"
267330f729Sjoerg #include "clang/AST/StmtCXX.h"
277330f729Sjoerg #include "clang/AST/StmtVisitor.h"
287330f729Sjoerg #include "clang/Analysis/Analyses/CFGReachabilityAnalysis.h"
297330f729Sjoerg #include "clang/Analysis/BodyFarm.h"
307330f729Sjoerg #include "clang/Analysis/CFG.h"
317330f729Sjoerg #include "clang/Analysis/CFGStmtMap.h"
327330f729Sjoerg #include "clang/Analysis/Support/BumpVector.h"
337330f729Sjoerg #include "clang/Basic/JsonSupport.h"
347330f729Sjoerg #include "clang/Basic/LLVM.h"
357330f729Sjoerg #include "clang/Basic/SourceLocation.h"
367330f729Sjoerg #include "clang/Basic/SourceManager.h"
377330f729Sjoerg #include "llvm/ADT/DenseMap.h"
387330f729Sjoerg #include "llvm/ADT/FoldingSet.h"
397330f729Sjoerg #include "llvm/ADT/STLExtras.h"
407330f729Sjoerg #include "llvm/ADT/SmallPtrSet.h"
417330f729Sjoerg #include "llvm/ADT/iterator_range.h"
427330f729Sjoerg #include "llvm/Support/Allocator.h"
437330f729Sjoerg #include "llvm/Support/Casting.h"
447330f729Sjoerg #include "llvm/Support/Compiler.h"
457330f729Sjoerg #include "llvm/Support/ErrorHandling.h"
467330f729Sjoerg #include "llvm/Support/SaveAndRestore.h"
477330f729Sjoerg #include "llvm/Support/raw_ostream.h"
487330f729Sjoerg #include <cassert>
497330f729Sjoerg #include <memory>
507330f729Sjoerg
517330f729Sjoerg using namespace clang;
527330f729Sjoerg
53*e038c9c4Sjoerg using ManagedAnalysisMap = llvm::DenseMap<const void *, std::unique_ptr<ManagedAnalysis>>;
547330f729Sjoerg
AnalysisDeclContext(AnalysisDeclContextManager * ADCMgr,const Decl * D,const CFG::BuildOptions & Options)55*e038c9c4Sjoerg AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
56*e038c9c4Sjoerg const Decl *D,
57*e038c9c4Sjoerg const CFG::BuildOptions &Options)
58*e038c9c4Sjoerg : ADCMgr(ADCMgr), D(D), cfgBuildOptions(Options) {
597330f729Sjoerg cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
607330f729Sjoerg }
617330f729Sjoerg
AnalysisDeclContext(AnalysisDeclContextManager * ADCMgr,const Decl * D)62*e038c9c4Sjoerg AnalysisDeclContext::AnalysisDeclContext(AnalysisDeclContextManager *ADCMgr,
63*e038c9c4Sjoerg const Decl *D)
64*e038c9c4Sjoerg : ADCMgr(ADCMgr), D(D) {
657330f729Sjoerg cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
667330f729Sjoerg }
677330f729Sjoerg
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)687330f729Sjoerg AnalysisDeclContextManager::AnalysisDeclContextManager(
697330f729Sjoerg ASTContext &ASTCtx, bool useUnoptimizedCFG, bool addImplicitDtors,
707330f729Sjoerg bool addInitializers, bool addTemporaryDtors, bool addLifetime,
717330f729Sjoerg bool addLoopExit, bool addScopes, bool synthesizeBodies,
727330f729Sjoerg bool addStaticInitBranch, bool addCXXNewAllocator,
737330f729Sjoerg bool addRichCXXConstructors, bool markElidedCXXConstructors,
747330f729Sjoerg bool addVirtualBaseBranches, CodeInjector *injector)
757330f729Sjoerg : Injector(injector), FunctionBodyFarm(ASTCtx, injector),
767330f729Sjoerg SynthesizeBodies(synthesizeBodies) {
777330f729Sjoerg cfgBuildOptions.PruneTriviallyFalseEdges = !useUnoptimizedCFG;
787330f729Sjoerg cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
797330f729Sjoerg cfgBuildOptions.AddInitializers = addInitializers;
807330f729Sjoerg cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
817330f729Sjoerg cfgBuildOptions.AddLifetime = addLifetime;
827330f729Sjoerg cfgBuildOptions.AddLoopExit = addLoopExit;
837330f729Sjoerg cfgBuildOptions.AddScopes = addScopes;
847330f729Sjoerg cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
857330f729Sjoerg cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
867330f729Sjoerg cfgBuildOptions.AddRichCXXConstructors = addRichCXXConstructors;
877330f729Sjoerg cfgBuildOptions.MarkElidedCXXConstructors = markElidedCXXConstructors;
887330f729Sjoerg cfgBuildOptions.AddVirtualBaseBranches = addVirtualBaseBranches;
897330f729Sjoerg }
907330f729Sjoerg
clear()917330f729Sjoerg void AnalysisDeclContextManager::clear() { Contexts.clear(); }
927330f729Sjoerg
getBody(bool & IsAutosynthesized) const937330f729Sjoerg Stmt *AnalysisDeclContext::getBody(bool &IsAutosynthesized) const {
947330f729Sjoerg IsAutosynthesized = false;
957330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
967330f729Sjoerg Stmt *Body = FD->getBody();
977330f729Sjoerg if (auto *CoroBody = dyn_cast_or_null<CoroutineBodyStmt>(Body))
987330f729Sjoerg Body = CoroBody->getBody();
99*e038c9c4Sjoerg if (ADCMgr && ADCMgr->synthesizeBodies()) {
100*e038c9c4Sjoerg Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(FD);
1017330f729Sjoerg if (SynthesizedBody) {
1027330f729Sjoerg Body = SynthesizedBody;
1037330f729Sjoerg IsAutosynthesized = true;
1047330f729Sjoerg }
1057330f729Sjoerg }
1067330f729Sjoerg return Body;
1077330f729Sjoerg }
1087330f729Sjoerg else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
1097330f729Sjoerg Stmt *Body = MD->getBody();
110*e038c9c4Sjoerg if (ADCMgr && ADCMgr->synthesizeBodies()) {
111*e038c9c4Sjoerg Stmt *SynthesizedBody = ADCMgr->getBodyFarm().getBody(MD);
1127330f729Sjoerg if (SynthesizedBody) {
1137330f729Sjoerg Body = SynthesizedBody;
1147330f729Sjoerg IsAutosynthesized = true;
1157330f729Sjoerg }
1167330f729Sjoerg }
1177330f729Sjoerg return Body;
1187330f729Sjoerg } else if (const auto *BD = dyn_cast<BlockDecl>(D))
1197330f729Sjoerg return BD->getBody();
1207330f729Sjoerg else if (const auto *FunTmpl = dyn_cast_or_null<FunctionTemplateDecl>(D))
1217330f729Sjoerg return FunTmpl->getTemplatedDecl()->getBody();
1227330f729Sjoerg
1237330f729Sjoerg llvm_unreachable("unknown code decl");
1247330f729Sjoerg }
1257330f729Sjoerg
getBody() const1267330f729Sjoerg Stmt *AnalysisDeclContext::getBody() const {
1277330f729Sjoerg bool Tmp;
1287330f729Sjoerg return getBody(Tmp);
1297330f729Sjoerg }
1307330f729Sjoerg
isBodyAutosynthesized() const1317330f729Sjoerg bool AnalysisDeclContext::isBodyAutosynthesized() const {
1327330f729Sjoerg bool Tmp;
1337330f729Sjoerg getBody(Tmp);
1347330f729Sjoerg return Tmp;
1357330f729Sjoerg }
1367330f729Sjoerg
isBodyAutosynthesizedFromModelFile() const1377330f729Sjoerg bool AnalysisDeclContext::isBodyAutosynthesizedFromModelFile() const {
1387330f729Sjoerg bool Tmp;
1397330f729Sjoerg Stmt *Body = getBody(Tmp);
1407330f729Sjoerg return Tmp && Body->getBeginLoc().isValid();
1417330f729Sjoerg }
1427330f729Sjoerg
1437330f729Sjoerg /// Returns true if \param VD is an Objective-C implicit 'self' parameter.
isSelfDecl(const VarDecl * VD)1447330f729Sjoerg static bool isSelfDecl(const VarDecl *VD) {
1457330f729Sjoerg return isa<ImplicitParamDecl>(VD) && VD->getName() == "self";
1467330f729Sjoerg }
1477330f729Sjoerg
getSelfDecl() const1487330f729Sjoerg const ImplicitParamDecl *AnalysisDeclContext::getSelfDecl() const {
1497330f729Sjoerg if (const auto *MD = dyn_cast<ObjCMethodDecl>(D))
1507330f729Sjoerg return MD->getSelfDecl();
1517330f729Sjoerg if (const auto *BD = dyn_cast<BlockDecl>(D)) {
1527330f729Sjoerg // See if 'self' was captured by the block.
1537330f729Sjoerg for (const auto &I : BD->captures()) {
1547330f729Sjoerg const VarDecl *VD = I.getVariable();
1557330f729Sjoerg if (isSelfDecl(VD))
1567330f729Sjoerg return dyn_cast<ImplicitParamDecl>(VD);
1577330f729Sjoerg }
1587330f729Sjoerg }
1597330f729Sjoerg
1607330f729Sjoerg auto *CXXMethod = dyn_cast<CXXMethodDecl>(D);
1617330f729Sjoerg if (!CXXMethod)
1627330f729Sjoerg return nullptr;
1637330f729Sjoerg
1647330f729Sjoerg const CXXRecordDecl *parent = CXXMethod->getParent();
1657330f729Sjoerg if (!parent->isLambda())
1667330f729Sjoerg return nullptr;
1677330f729Sjoerg
1687330f729Sjoerg for (const auto &LC : parent->captures()) {
1697330f729Sjoerg if (!LC.capturesVariable())
1707330f729Sjoerg continue;
1717330f729Sjoerg
1727330f729Sjoerg VarDecl *VD = LC.getCapturedVar();
1737330f729Sjoerg if (isSelfDecl(VD))
1747330f729Sjoerg return dyn_cast<ImplicitParamDecl>(VD);
1757330f729Sjoerg }
1767330f729Sjoerg
1777330f729Sjoerg return nullptr;
1787330f729Sjoerg }
1797330f729Sjoerg
registerForcedBlockExpression(const Stmt * stmt)1807330f729Sjoerg void AnalysisDeclContext::registerForcedBlockExpression(const Stmt *stmt) {
1817330f729Sjoerg if (!forcedBlkExprs)
1827330f729Sjoerg forcedBlkExprs = new CFG::BuildOptions::ForcedBlkExprs();
1837330f729Sjoerg // Default construct an entry for 'stmt'.
1847330f729Sjoerg if (const auto *e = dyn_cast<Expr>(stmt))
1857330f729Sjoerg stmt = e->IgnoreParens();
1867330f729Sjoerg (void) (*forcedBlkExprs)[stmt];
1877330f729Sjoerg }
1887330f729Sjoerg
1897330f729Sjoerg const CFGBlock *
getBlockForRegisteredExpression(const Stmt * stmt)1907330f729Sjoerg AnalysisDeclContext::getBlockForRegisteredExpression(const Stmt *stmt) {
1917330f729Sjoerg assert(forcedBlkExprs);
1927330f729Sjoerg if (const auto *e = dyn_cast<Expr>(stmt))
1937330f729Sjoerg stmt = e->IgnoreParens();
1947330f729Sjoerg CFG::BuildOptions::ForcedBlkExprs::const_iterator itr =
1957330f729Sjoerg forcedBlkExprs->find(stmt);
1967330f729Sjoerg assert(itr != forcedBlkExprs->end());
1977330f729Sjoerg return itr->second;
1987330f729Sjoerg }
1997330f729Sjoerg
2007330f729Sjoerg /// Add each synthetic statement in the CFG to the parent map, using the
2017330f729Sjoerg /// source statement's parent.
addParentsForSyntheticStmts(const CFG * TheCFG,ParentMap & PM)2027330f729Sjoerg static void addParentsForSyntheticStmts(const CFG *TheCFG, ParentMap &PM) {
2037330f729Sjoerg if (!TheCFG)
2047330f729Sjoerg return;
2057330f729Sjoerg
2067330f729Sjoerg for (CFG::synthetic_stmt_iterator I = TheCFG->synthetic_stmt_begin(),
2077330f729Sjoerg E = TheCFG->synthetic_stmt_end();
2087330f729Sjoerg I != E; ++I) {
2097330f729Sjoerg PM.setParent(I->first, PM.getParent(I->second));
2107330f729Sjoerg }
2117330f729Sjoerg }
2127330f729Sjoerg
getCFG()2137330f729Sjoerg CFG *AnalysisDeclContext::getCFG() {
2147330f729Sjoerg if (!cfgBuildOptions.PruneTriviallyFalseEdges)
2157330f729Sjoerg return getUnoptimizedCFG();
2167330f729Sjoerg
2177330f729Sjoerg if (!builtCFG) {
2187330f729Sjoerg cfg = CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
2197330f729Sjoerg // Even when the cfg is not successfully built, we don't
2207330f729Sjoerg // want to try building it again.
2217330f729Sjoerg builtCFG = true;
2227330f729Sjoerg
2237330f729Sjoerg if (PM)
2247330f729Sjoerg addParentsForSyntheticStmts(cfg.get(), *PM);
2257330f729Sjoerg
2267330f729Sjoerg // The Observer should only observe one build of the CFG.
2277330f729Sjoerg getCFGBuildOptions().Observer = nullptr;
2287330f729Sjoerg }
2297330f729Sjoerg return cfg.get();
2307330f729Sjoerg }
2317330f729Sjoerg
getUnoptimizedCFG()2327330f729Sjoerg CFG *AnalysisDeclContext::getUnoptimizedCFG() {
2337330f729Sjoerg if (!builtCompleteCFG) {
2347330f729Sjoerg SaveAndRestore<bool> NotPrune(cfgBuildOptions.PruneTriviallyFalseEdges,
2357330f729Sjoerg false);
2367330f729Sjoerg completeCFG =
2377330f729Sjoerg CFG::buildCFG(D, getBody(), &D->getASTContext(), cfgBuildOptions);
2387330f729Sjoerg // Even when the cfg is not successfully built, we don't
2397330f729Sjoerg // want to try building it again.
2407330f729Sjoerg builtCompleteCFG = true;
2417330f729Sjoerg
2427330f729Sjoerg if (PM)
2437330f729Sjoerg addParentsForSyntheticStmts(completeCFG.get(), *PM);
2447330f729Sjoerg
2457330f729Sjoerg // The Observer should only observe one build of the CFG.
2467330f729Sjoerg getCFGBuildOptions().Observer = nullptr;
2477330f729Sjoerg }
2487330f729Sjoerg return completeCFG.get();
2497330f729Sjoerg }
2507330f729Sjoerg
getCFGStmtMap()2517330f729Sjoerg CFGStmtMap *AnalysisDeclContext::getCFGStmtMap() {
2527330f729Sjoerg if (cfgStmtMap)
2537330f729Sjoerg return cfgStmtMap.get();
2547330f729Sjoerg
2557330f729Sjoerg if (CFG *c = getCFG()) {
2567330f729Sjoerg cfgStmtMap.reset(CFGStmtMap::Build(c, &getParentMap()));
2577330f729Sjoerg return cfgStmtMap.get();
2587330f729Sjoerg }
2597330f729Sjoerg
2607330f729Sjoerg return nullptr;
2617330f729Sjoerg }
2627330f729Sjoerg
getCFGReachablityAnalysis()2637330f729Sjoerg CFGReverseBlockReachabilityAnalysis *AnalysisDeclContext::getCFGReachablityAnalysis() {
2647330f729Sjoerg if (CFA)
2657330f729Sjoerg return CFA.get();
2667330f729Sjoerg
2677330f729Sjoerg if (CFG *c = getCFG()) {
2687330f729Sjoerg CFA.reset(new CFGReverseBlockReachabilityAnalysis(*c));
2697330f729Sjoerg return CFA.get();
2707330f729Sjoerg }
2717330f729Sjoerg
2727330f729Sjoerg return nullptr;
2737330f729Sjoerg }
2747330f729Sjoerg
dumpCFG(bool ShowColors)2757330f729Sjoerg void AnalysisDeclContext::dumpCFG(bool ShowColors) {
2767330f729Sjoerg getCFG()->dump(getASTContext().getLangOpts(), ShowColors);
2777330f729Sjoerg }
2787330f729Sjoerg
getParentMap()2797330f729Sjoerg ParentMap &AnalysisDeclContext::getParentMap() {
2807330f729Sjoerg if (!PM) {
2817330f729Sjoerg PM.reset(new ParentMap(getBody()));
2827330f729Sjoerg if (const auto *C = dyn_cast<CXXConstructorDecl>(getDecl())) {
2837330f729Sjoerg for (const auto *I : C->inits()) {
2847330f729Sjoerg PM->addStmt(I->getInit());
2857330f729Sjoerg }
2867330f729Sjoerg }
2877330f729Sjoerg if (builtCFG)
2887330f729Sjoerg addParentsForSyntheticStmts(getCFG(), *PM);
2897330f729Sjoerg if (builtCompleteCFG)
2907330f729Sjoerg addParentsForSyntheticStmts(getUnoptimizedCFG(), *PM);
2917330f729Sjoerg }
2927330f729Sjoerg return *PM;
2937330f729Sjoerg }
2947330f729Sjoerg
getContext(const Decl * D)2957330f729Sjoerg AnalysisDeclContext *AnalysisDeclContextManager::getContext(const Decl *D) {
2967330f729Sjoerg if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
2977330f729Sjoerg // Calling 'hasBody' replaces 'FD' in place with the FunctionDecl
2987330f729Sjoerg // that has the body.
2997330f729Sjoerg FD->hasBody(FD);
3007330f729Sjoerg D = FD;
3017330f729Sjoerg }
3027330f729Sjoerg
3037330f729Sjoerg std::unique_ptr<AnalysisDeclContext> &AC = Contexts[D];
3047330f729Sjoerg if (!AC)
3057330f729Sjoerg AC = std::make_unique<AnalysisDeclContext>(this, D, cfgBuildOptions);
3067330f729Sjoerg return AC.get();
3077330f729Sjoerg }
3087330f729Sjoerg
getBodyFarm()3097330f729Sjoerg BodyFarm &AnalysisDeclContextManager::getBodyFarm() { return FunctionBodyFarm; }
3107330f729Sjoerg
3117330f729Sjoerg const StackFrameContext *
getStackFrame(const LocationContext * ParentLC,const Stmt * S,const CFGBlock * Blk,unsigned BlockCount,unsigned Index)312*e038c9c4Sjoerg AnalysisDeclContext::getStackFrame(const LocationContext *ParentLC,
313*e038c9c4Sjoerg const Stmt *S, const CFGBlock *Blk,
314*e038c9c4Sjoerg unsigned BlockCount, unsigned Index) {
315*e038c9c4Sjoerg return getLocationContextManager().getStackFrame(this, ParentLC, S, Blk,
316*e038c9c4Sjoerg BlockCount, Index);
3177330f729Sjoerg }
3187330f729Sjoerg
getBlockInvocationContext(const LocationContext * ParentLC,const BlockDecl * BD,const void * Data)319*e038c9c4Sjoerg const BlockInvocationContext *AnalysisDeclContext::getBlockInvocationContext(
320*e038c9c4Sjoerg const LocationContext *ParentLC, const BlockDecl *BD, const void *Data) {
321*e038c9c4Sjoerg return getLocationContextManager().getBlockInvocationContext(this, ParentLC,
322*e038c9c4Sjoerg BD, Data);
3237330f729Sjoerg }
3247330f729Sjoerg
isInStdNamespace(const Decl * D)3257330f729Sjoerg bool AnalysisDeclContext::isInStdNamespace(const Decl *D) {
3267330f729Sjoerg const DeclContext *DC = D->getDeclContext()->getEnclosingNamespaceContext();
3277330f729Sjoerg const auto *ND = dyn_cast<NamespaceDecl>(DC);
3287330f729Sjoerg if (!ND)
3297330f729Sjoerg return false;
3307330f729Sjoerg
3317330f729Sjoerg while (const DeclContext *Parent = ND->getParent()) {
3327330f729Sjoerg if (!isa<NamespaceDecl>(Parent))
3337330f729Sjoerg break;
3347330f729Sjoerg ND = cast<NamespaceDecl>(Parent);
3357330f729Sjoerg }
3367330f729Sjoerg
3377330f729Sjoerg return ND->isStdNamespace();
3387330f729Sjoerg }
3397330f729Sjoerg
getLocationContextManager()3407330f729Sjoerg LocationContextManager &AnalysisDeclContext::getLocationContextManager() {
341*e038c9c4Sjoerg assert(
342*e038c9c4Sjoerg ADCMgr &&
3437330f729Sjoerg "Cannot create LocationContexts without an AnalysisDeclContextManager!");
344*e038c9c4Sjoerg return ADCMgr->getLocationContextManager();
3457330f729Sjoerg }
3467330f729Sjoerg
3477330f729Sjoerg //===----------------------------------------------------------------------===//
3487330f729Sjoerg // FoldingSet profiling.
3497330f729Sjoerg //===----------------------------------------------------------------------===//
3507330f729Sjoerg
ProfileCommon(llvm::FoldingSetNodeID & ID,ContextKind ck,AnalysisDeclContext * ctx,const LocationContext * parent,const void * data)3517330f729Sjoerg void LocationContext::ProfileCommon(llvm::FoldingSetNodeID &ID,
3527330f729Sjoerg ContextKind ck,
3537330f729Sjoerg AnalysisDeclContext *ctx,
3547330f729Sjoerg const LocationContext *parent,
3557330f729Sjoerg const void *data) {
3567330f729Sjoerg ID.AddInteger(ck);
3577330f729Sjoerg ID.AddPointer(ctx);
3587330f729Sjoerg ID.AddPointer(parent);
3597330f729Sjoerg ID.AddPointer(data);
3607330f729Sjoerg }
3617330f729Sjoerg
Profile(llvm::FoldingSetNodeID & ID)3627330f729Sjoerg void StackFrameContext::Profile(llvm::FoldingSetNodeID &ID) {
3637330f729Sjoerg Profile(ID, getAnalysisDeclContext(), getParent(), CallSite, Block,
3647330f729Sjoerg BlockCount, Index);
3657330f729Sjoerg }
3667330f729Sjoerg
Profile(llvm::FoldingSetNodeID & ID)3677330f729Sjoerg void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
368*e038c9c4Sjoerg Profile(ID, getAnalysisDeclContext(), getParent(), BD, Data);
3697330f729Sjoerg }
3707330f729Sjoerg
3717330f729Sjoerg //===----------------------------------------------------------------------===//
3727330f729Sjoerg // LocationContext creation.
3737330f729Sjoerg //===----------------------------------------------------------------------===//
3747330f729Sjoerg
getStackFrame(AnalysisDeclContext * ctx,const LocationContext * parent,const Stmt * s,const CFGBlock * blk,unsigned blockCount,unsigned idx)3757330f729Sjoerg const StackFrameContext *LocationContextManager::getStackFrame(
3767330f729Sjoerg AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s,
3777330f729Sjoerg const CFGBlock *blk, unsigned blockCount, unsigned idx) {
3787330f729Sjoerg llvm::FoldingSetNodeID ID;
3797330f729Sjoerg StackFrameContext::Profile(ID, ctx, parent, s, blk, blockCount, idx);
3807330f729Sjoerg void *InsertPos;
3817330f729Sjoerg auto *L =
3827330f729Sjoerg cast_or_null<StackFrameContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
3837330f729Sjoerg if (!L) {
3847330f729Sjoerg L = new StackFrameContext(ctx, parent, s, blk, blockCount, idx, ++NewID);
3857330f729Sjoerg Contexts.InsertNode(L, InsertPos);
3867330f729Sjoerg }
3877330f729Sjoerg return L;
3887330f729Sjoerg }
3897330f729Sjoerg
getBlockInvocationContext(AnalysisDeclContext * ADC,const LocationContext * ParentLC,const BlockDecl * BD,const void * Data)390*e038c9c4Sjoerg const BlockInvocationContext *LocationContextManager::getBlockInvocationContext(
391*e038c9c4Sjoerg AnalysisDeclContext *ADC, const LocationContext *ParentLC,
392*e038c9c4Sjoerg const BlockDecl *BD, const void *Data) {
3937330f729Sjoerg llvm::FoldingSetNodeID ID;
394*e038c9c4Sjoerg BlockInvocationContext::Profile(ID, ADC, ParentLC, BD, Data);
3957330f729Sjoerg void *InsertPos;
3967330f729Sjoerg auto *L =
3977330f729Sjoerg cast_or_null<BlockInvocationContext>(Contexts.FindNodeOrInsertPos(ID,
3987330f729Sjoerg InsertPos));
3997330f729Sjoerg if (!L) {
400*e038c9c4Sjoerg L = new BlockInvocationContext(ADC, ParentLC, BD, Data, ++NewID);
4017330f729Sjoerg Contexts.InsertNode(L, InsertPos);
4027330f729Sjoerg }
4037330f729Sjoerg return L;
4047330f729Sjoerg }
4057330f729Sjoerg
4067330f729Sjoerg //===----------------------------------------------------------------------===//
4077330f729Sjoerg // LocationContext methods.
4087330f729Sjoerg //===----------------------------------------------------------------------===//
4097330f729Sjoerg
getStackFrame() const4107330f729Sjoerg const StackFrameContext *LocationContext::getStackFrame() const {
4117330f729Sjoerg const LocationContext *LC = this;
4127330f729Sjoerg while (LC) {
4137330f729Sjoerg if (const auto *SFC = dyn_cast<StackFrameContext>(LC))
4147330f729Sjoerg return SFC;
4157330f729Sjoerg LC = LC->getParent();
4167330f729Sjoerg }
4177330f729Sjoerg return nullptr;
4187330f729Sjoerg }
4197330f729Sjoerg
inTopFrame() const4207330f729Sjoerg bool LocationContext::inTopFrame() const {
4217330f729Sjoerg return getStackFrame()->inTopFrame();
4227330f729Sjoerg }
4237330f729Sjoerg
isParentOf(const LocationContext * LC) const4247330f729Sjoerg bool LocationContext::isParentOf(const LocationContext *LC) const {
4257330f729Sjoerg do {
4267330f729Sjoerg const LocationContext *Parent = LC->getParent();
4277330f729Sjoerg if (Parent == this)
4287330f729Sjoerg return true;
4297330f729Sjoerg else
4307330f729Sjoerg LC = Parent;
4317330f729Sjoerg } while (LC);
4327330f729Sjoerg
4337330f729Sjoerg return false;
4347330f729Sjoerg }
4357330f729Sjoerg
printLocation(raw_ostream & Out,const SourceManager & SM,SourceLocation Loc)4367330f729Sjoerg static void printLocation(raw_ostream &Out, const SourceManager &SM,
4377330f729Sjoerg SourceLocation Loc) {
4387330f729Sjoerg if (Loc.isFileID() && SM.isInMainFile(Loc))
4397330f729Sjoerg Out << SM.getExpansionLineNumber(Loc);
4407330f729Sjoerg else
4417330f729Sjoerg Loc.print(Out, SM);
4427330f729Sjoerg }
4437330f729Sjoerg
dumpStack(raw_ostream & Out) const444*e038c9c4Sjoerg void LocationContext::dumpStack(raw_ostream &Out) const {
4457330f729Sjoerg ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
4467330f729Sjoerg PrintingPolicy PP(Ctx.getLangOpts());
4477330f729Sjoerg PP.TerseOutput = 1;
4487330f729Sjoerg
4497330f729Sjoerg const SourceManager &SM =
4507330f729Sjoerg getAnalysisDeclContext()->getASTContext().getSourceManager();
4517330f729Sjoerg
4527330f729Sjoerg unsigned Frame = 0;
4537330f729Sjoerg for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
4547330f729Sjoerg switch (LCtx->getKind()) {
4557330f729Sjoerg case StackFrame:
4567330f729Sjoerg Out << "\t#" << Frame << ' ';
4577330f729Sjoerg ++Frame;
4587330f729Sjoerg if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
4597330f729Sjoerg Out << "Calling " << D->getQualifiedNameAsString();
4607330f729Sjoerg else
4617330f729Sjoerg Out << "Calling anonymous code";
4627330f729Sjoerg if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
4637330f729Sjoerg Out << " at line ";
4647330f729Sjoerg printLocation(Out, SM, S->getBeginLoc());
4657330f729Sjoerg }
4667330f729Sjoerg break;
4677330f729Sjoerg case Block:
4687330f729Sjoerg Out << "Invoking block";
4697330f729Sjoerg if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
4707330f729Sjoerg Out << " defined at line ";
4717330f729Sjoerg printLocation(Out, SM, D->getBeginLoc());
4727330f729Sjoerg }
4737330f729Sjoerg break;
4747330f729Sjoerg }
475*e038c9c4Sjoerg Out << '\n';
4767330f729Sjoerg }
4777330f729Sjoerg }
4787330f729Sjoerg
printJson(raw_ostream & Out,const char * NL,unsigned int Space,bool IsDot,std::function<void (const LocationContext *)> printMoreInfoPerContext) const4797330f729Sjoerg void LocationContext::printJson(raw_ostream &Out, const char *NL,
4807330f729Sjoerg unsigned int Space, bool IsDot,
4817330f729Sjoerg std::function<void(const LocationContext *)>
4827330f729Sjoerg printMoreInfoPerContext) const {
4837330f729Sjoerg ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
4847330f729Sjoerg PrintingPolicy PP(Ctx.getLangOpts());
4857330f729Sjoerg PP.TerseOutput = 1;
4867330f729Sjoerg
4877330f729Sjoerg const SourceManager &SM =
4887330f729Sjoerg getAnalysisDeclContext()->getASTContext().getSourceManager();
4897330f729Sjoerg
4907330f729Sjoerg unsigned Frame = 0;
4917330f729Sjoerg for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
4927330f729Sjoerg Indent(Out, Space, IsDot)
4937330f729Sjoerg << "{ \"lctx_id\": " << LCtx->getID() << ", \"location_context\": \"";
4947330f729Sjoerg switch (LCtx->getKind()) {
4957330f729Sjoerg case StackFrame:
4967330f729Sjoerg Out << '#' << Frame << " Call\", \"calling\": \"";
4977330f729Sjoerg ++Frame;
4987330f729Sjoerg if (const auto *D = dyn_cast<NamedDecl>(LCtx->getDecl()))
4997330f729Sjoerg Out << D->getQualifiedNameAsString();
5007330f729Sjoerg else
5017330f729Sjoerg Out << "anonymous code";
5027330f729Sjoerg
5037330f729Sjoerg Out << "\", \"location\": ";
5047330f729Sjoerg if (const Stmt *S = cast<StackFrameContext>(LCtx)->getCallSite()) {
5057330f729Sjoerg printSourceLocationAsJson(Out, S->getBeginLoc(), SM);
5067330f729Sjoerg } else {
5077330f729Sjoerg Out << "null";
5087330f729Sjoerg }
5097330f729Sjoerg
5107330f729Sjoerg Out << ", \"items\": ";
5117330f729Sjoerg break;
5127330f729Sjoerg case Block:
5137330f729Sjoerg Out << "Invoking block\" ";
5147330f729Sjoerg if (const Decl *D = cast<BlockInvocationContext>(LCtx)->getDecl()) {
5157330f729Sjoerg Out << ", \"location\": ";
5167330f729Sjoerg printSourceLocationAsJson(Out, D->getBeginLoc(), SM);
5177330f729Sjoerg Out << ' ';
5187330f729Sjoerg }
5197330f729Sjoerg break;
5207330f729Sjoerg }
5217330f729Sjoerg
5227330f729Sjoerg printMoreInfoPerContext(LCtx);
5237330f729Sjoerg
5247330f729Sjoerg Out << '}';
5257330f729Sjoerg if (LCtx->getParent())
5267330f729Sjoerg Out << ',';
5277330f729Sjoerg Out << NL;
5287330f729Sjoerg }
5297330f729Sjoerg }
5307330f729Sjoerg
dump() const5317330f729Sjoerg LLVM_DUMP_METHOD void LocationContext::dump() const { printJson(llvm::errs()); }
5327330f729Sjoerg
5337330f729Sjoerg //===----------------------------------------------------------------------===//
5347330f729Sjoerg // Lazily generated map to query the external variables referenced by a Block.
5357330f729Sjoerg //===----------------------------------------------------------------------===//
5367330f729Sjoerg
5377330f729Sjoerg namespace {
5387330f729Sjoerg
5397330f729Sjoerg class FindBlockDeclRefExprsVals : public StmtVisitor<FindBlockDeclRefExprsVals>{
5407330f729Sjoerg BumpVector<const VarDecl *> &BEVals;
5417330f729Sjoerg BumpVectorContext &BC;
5427330f729Sjoerg llvm::SmallPtrSet<const VarDecl *, 4> Visited;
5437330f729Sjoerg llvm::SmallPtrSet<const DeclContext *, 4> IgnoredContexts;
5447330f729Sjoerg
5457330f729Sjoerg public:
FindBlockDeclRefExprsVals(BumpVector<const VarDecl * > & bevals,BumpVectorContext & bc)5467330f729Sjoerg FindBlockDeclRefExprsVals(BumpVector<const VarDecl*> &bevals,
5477330f729Sjoerg BumpVectorContext &bc)
5487330f729Sjoerg : BEVals(bevals), BC(bc) {}
5497330f729Sjoerg
VisitStmt(Stmt * S)5507330f729Sjoerg void VisitStmt(Stmt *S) {
5517330f729Sjoerg for (auto *Child : S->children())
5527330f729Sjoerg if (Child)
5537330f729Sjoerg Visit(Child);
5547330f729Sjoerg }
5557330f729Sjoerg
VisitDeclRefExpr(DeclRefExpr * DR)5567330f729Sjoerg void VisitDeclRefExpr(DeclRefExpr *DR) {
5577330f729Sjoerg // Non-local variables are also directly modified.
5587330f729Sjoerg if (const auto *VD = dyn_cast<VarDecl>(DR->getDecl())) {
5597330f729Sjoerg if (!VD->hasLocalStorage()) {
5607330f729Sjoerg if (Visited.insert(VD).second)
5617330f729Sjoerg BEVals.push_back(VD, BC);
5627330f729Sjoerg }
5637330f729Sjoerg }
5647330f729Sjoerg }
5657330f729Sjoerg
VisitBlockExpr(BlockExpr * BR)5667330f729Sjoerg void VisitBlockExpr(BlockExpr *BR) {
5677330f729Sjoerg // Blocks containing blocks can transitively capture more variables.
5687330f729Sjoerg IgnoredContexts.insert(BR->getBlockDecl());
5697330f729Sjoerg Visit(BR->getBlockDecl()->getBody());
5707330f729Sjoerg }
5717330f729Sjoerg
VisitPseudoObjectExpr(PseudoObjectExpr * PE)5727330f729Sjoerg void VisitPseudoObjectExpr(PseudoObjectExpr *PE) {
5737330f729Sjoerg for (PseudoObjectExpr::semantics_iterator it = PE->semantics_begin(),
5747330f729Sjoerg et = PE->semantics_end(); it != et; ++it) {
5757330f729Sjoerg Expr *Semantic = *it;
5767330f729Sjoerg if (auto *OVE = dyn_cast<OpaqueValueExpr>(Semantic))
5777330f729Sjoerg Semantic = OVE->getSourceExpr();
5787330f729Sjoerg Visit(Semantic);
5797330f729Sjoerg }
5807330f729Sjoerg }
5817330f729Sjoerg };
5827330f729Sjoerg
5837330f729Sjoerg } // namespace
5847330f729Sjoerg
5857330f729Sjoerg using DeclVec = BumpVector<const VarDecl *>;
5867330f729Sjoerg
LazyInitializeReferencedDecls(const BlockDecl * BD,void * & Vec,llvm::BumpPtrAllocator & A)5877330f729Sjoerg static DeclVec* LazyInitializeReferencedDecls(const BlockDecl *BD,
5887330f729Sjoerg void *&Vec,
5897330f729Sjoerg llvm::BumpPtrAllocator &A) {
5907330f729Sjoerg if (Vec)
5917330f729Sjoerg return (DeclVec*) Vec;
5927330f729Sjoerg
5937330f729Sjoerg BumpVectorContext BC(A);
5947330f729Sjoerg DeclVec *BV = (DeclVec*) A.Allocate<DeclVec>();
5957330f729Sjoerg new (BV) DeclVec(BC, 10);
5967330f729Sjoerg
5977330f729Sjoerg // Go through the capture list.
5987330f729Sjoerg for (const auto &CI : BD->captures()) {
5997330f729Sjoerg BV->push_back(CI.getVariable(), BC);
6007330f729Sjoerg }
6017330f729Sjoerg
6027330f729Sjoerg // Find the referenced global/static variables.
6037330f729Sjoerg FindBlockDeclRefExprsVals F(*BV, BC);
6047330f729Sjoerg F.Visit(BD->getBody());
6057330f729Sjoerg
6067330f729Sjoerg Vec = BV;
6077330f729Sjoerg return BV;
6087330f729Sjoerg }
6097330f729Sjoerg
6107330f729Sjoerg llvm::iterator_range<AnalysisDeclContext::referenced_decls_iterator>
getReferencedBlockVars(const BlockDecl * BD)6117330f729Sjoerg AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
6127330f729Sjoerg if (!ReferencedBlockVars)
6137330f729Sjoerg ReferencedBlockVars = new llvm::DenseMap<const BlockDecl*,void*>();
6147330f729Sjoerg
6157330f729Sjoerg const DeclVec *V =
6167330f729Sjoerg LazyInitializeReferencedDecls(BD, (*ReferencedBlockVars)[BD], A);
6177330f729Sjoerg return llvm::make_range(V->begin(), V->end());
6187330f729Sjoerg }
6197330f729Sjoerg
getAnalysisImpl(const void * tag)620*e038c9c4Sjoerg std::unique_ptr<ManagedAnalysis> &AnalysisDeclContext::getAnalysisImpl(const void *tag) {
6217330f729Sjoerg if (!ManagedAnalyses)
6227330f729Sjoerg ManagedAnalyses = new ManagedAnalysisMap();
6237330f729Sjoerg ManagedAnalysisMap *M = (ManagedAnalysisMap*) ManagedAnalyses;
6247330f729Sjoerg return (*M)[tag];
6257330f729Sjoerg }
6267330f729Sjoerg
6277330f729Sjoerg //===----------------------------------------------------------------------===//
6287330f729Sjoerg // Cleanup.
6297330f729Sjoerg //===----------------------------------------------------------------------===//
6307330f729Sjoerg
6317330f729Sjoerg ManagedAnalysis::~ManagedAnalysis() = default;
6327330f729Sjoerg
~AnalysisDeclContext()6337330f729Sjoerg AnalysisDeclContext::~AnalysisDeclContext() {
6347330f729Sjoerg delete forcedBlkExprs;
6357330f729Sjoerg delete ReferencedBlockVars;
636*e038c9c4Sjoerg delete (ManagedAnalysisMap*) ManagedAnalyses;
6377330f729Sjoerg }
6387330f729Sjoerg
6397330f729Sjoerg LocationContext::~LocationContext() = default;
6407330f729Sjoerg
~LocationContextManager()6417330f729Sjoerg LocationContextManager::~LocationContextManager() {
6427330f729Sjoerg clear();
6437330f729Sjoerg }
6447330f729Sjoerg
clear()6457330f729Sjoerg void LocationContextManager::clear() {
6467330f729Sjoerg for (llvm::FoldingSet<LocationContext>::iterator I = Contexts.begin(),
6477330f729Sjoerg E = Contexts.end(); I != E; ) {
6487330f729Sjoerg LocationContext *LC = &*I;
6497330f729Sjoerg ++I;
6507330f729Sjoerg delete LC;
6517330f729Sjoerg }
6527330f729Sjoerg Contexts.clear();
6537330f729Sjoerg }
654