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