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