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