1 //===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===// 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 // Defines the Static Analyzer Checker Manager. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 15 #include "clang/StaticAnalyzer/Core/Checker.h" 16 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 17 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 18 #include "clang/Analysis/ProgramPoint.h" 19 #include "clang/AST/DeclBase.h" 20 21 using namespace clang; 22 using namespace ento; 23 24 bool CheckerManager::hasPathSensitiveCheckers() const { 25 return !StmtCheckers.empty() || 26 !PreObjCMessageCheckers.empty() || 27 !PostObjCMessageCheckers.empty() || 28 !LocationCheckers.empty() || 29 !BindCheckers.empty() || 30 !EndAnalysisCheckers.empty() || 31 !EndPathCheckers.empty() || 32 !BranchConditionCheckers.empty() || 33 !LiveSymbolsCheckers.empty() || 34 !DeadSymbolsCheckers.empty() || 35 !RegionChangesCheckers.empty() || 36 !EvalAssumeCheckers.empty() || 37 !EvalCallCheckers.empty() || 38 !InlineCallCheckers.empty(); 39 } 40 41 void CheckerManager::finishedCheckerRegistration() { 42 #ifndef NDEBUG 43 // Make sure that for every event that has listeners, there is at least 44 // one dispatcher registered for it. 45 for (llvm::DenseMap<EventTag, EventInfo>::iterator 46 I = Events.begin(), E = Events.end(); I != E; ++I) 47 assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 48 #endif 49 } 50 51 //===----------------------------------------------------------------------===// 52 // Functions for running checkers for AST traversing.. 53 //===----------------------------------------------------------------------===// 54 55 void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 56 BugReporter &BR) { 57 assert(D); 58 59 unsigned DeclKind = D->getKind(); 60 CachedDeclCheckers *checkers = 0; 61 CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 62 if (CCI != CachedDeclCheckersMap.end()) { 63 checkers = &(CCI->second); 64 } else { 65 // Find the checkers that should run for this Decl and cache them. 66 checkers = &CachedDeclCheckersMap[DeclKind]; 67 for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 68 DeclCheckerInfo &info = DeclCheckers[i]; 69 if (info.IsForDeclFn(D)) 70 checkers->push_back(info.CheckFn); 71 } 72 } 73 74 assert(checkers); 75 for (CachedDeclCheckers::iterator 76 I = checkers->begin(), E = checkers->end(); I != E; ++I) 77 (*I)(D, mgr, BR); 78 } 79 80 void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 81 BugReporter &BR) { 82 assert(D && D->hasBody()); 83 84 for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 85 BodyCheckers[i](D, mgr, BR); 86 } 87 88 //===----------------------------------------------------------------------===// 89 // Functions for running checkers for path-sensitive checking. 90 //===----------------------------------------------------------------------===// 91 92 template <typename CHECK_CTX> 93 static void expandGraphWithCheckers(CHECK_CTX checkCtx, 94 ExplodedNodeSet &Dst, 95 const ExplodedNodeSet &Src) { 96 const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext(); 97 if (Src.empty()) 98 return; 99 100 typename CHECK_CTX::CheckersTy::const_iterator 101 I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 102 if (I == E) { 103 Dst.insert(Src); 104 return; 105 } 106 107 ExplodedNodeSet Tmp1, Tmp2; 108 const ExplodedNodeSet *PrevSet = &Src; 109 110 for (; I != E; ++I) { 111 ExplodedNodeSet *CurrSet = 0; 112 if (I+1 == E) 113 CurrSet = &Dst; 114 else { 115 CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 116 CurrSet->clear(); 117 } 118 119 NodeBuilder B(*PrevSet, *CurrSet, BldrCtx); 120 for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 121 NI != NE; ++NI) { 122 checkCtx.runChecker(*I, B, *NI); 123 } 124 125 // If all the produced transitions are sinks, stop. 126 if (CurrSet->empty()) 127 return; 128 129 // Update which NodeSet is the current one. 130 PrevSet = CurrSet; 131 } 132 } 133 134 namespace { 135 struct CheckStmtContext { 136 typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 137 bool IsPreVisit; 138 const CheckersTy &Checkers; 139 const Stmt *S; 140 ExprEngine &Eng; 141 142 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 143 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 144 145 CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 146 const Stmt *s, ExprEngine &eng) 147 : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { } 148 149 void runChecker(CheckerManager::CheckStmtFunc checkFn, 150 NodeBuilder &Bldr, ExplodedNode *Pred) { 151 // FIXME: Remove respondsToCallback from CheckerContext; 152 ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 153 ProgramPoint::PostStmtKind; 154 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 155 Pred->getLocationContext(), checkFn.Checker); 156 CheckerContext C(Bldr, Eng, Pred, L); 157 158 checkFn(S, C); 159 } 160 }; 161 } 162 163 /// \brief Run checkers for visiting Stmts. 164 void CheckerManager::runCheckersForStmt(bool isPreVisit, 165 ExplodedNodeSet &Dst, 166 const ExplodedNodeSet &Src, 167 const Stmt *S, 168 ExprEngine &Eng) { 169 CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 170 S, Eng); 171 expandGraphWithCheckers(C, Dst, Src); 172 } 173 174 namespace { 175 struct CheckObjCMessageContext { 176 typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 177 bool IsPreVisit; 178 const CheckersTy &Checkers; 179 const ObjCMessage &Msg; 180 ExprEngine &Eng; 181 182 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 183 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 184 185 CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 186 const ObjCMessage &msg, ExprEngine &eng) 187 : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 188 189 void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 190 NodeBuilder &Bldr, ExplodedNode *Pred) { 191 ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 192 ProgramPoint::PostStmtKind; 193 const ProgramPoint &L = 194 ProgramPoint::getProgramPoint(Msg.getMessageExpr(), 195 K, Pred->getLocationContext(), 196 checkFn.Checker); 197 CheckerContext C(Bldr, Eng, Pred, L); 198 199 checkFn(Msg, C); 200 } 201 }; 202 } 203 204 /// \brief Run checkers for visiting obj-c messages. 205 void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 206 ExplodedNodeSet &Dst, 207 const ExplodedNodeSet &Src, 208 const ObjCMessage &msg, 209 ExprEngine &Eng) { 210 CheckObjCMessageContext C(isPreVisit, 211 isPreVisit ? PreObjCMessageCheckers 212 : PostObjCMessageCheckers, 213 msg, Eng); 214 expandGraphWithCheckers(C, Dst, Src); 215 } 216 217 namespace { 218 struct CheckLocationContext { 219 typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 220 const CheckersTy &Checkers; 221 SVal Loc; 222 bool IsLoad; 223 const Stmt *S; 224 ExprEngine &Eng; 225 226 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 227 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 228 229 CheckLocationContext(const CheckersTy &checkers, 230 SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) 231 : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } 232 233 void runChecker(CheckerManager::CheckLocationFunc checkFn, 234 NodeBuilder &Bldr, ExplodedNode *Pred) { 235 ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind : 236 ProgramPoint::PreStoreKind; 237 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 238 Pred->getLocationContext(), checkFn.Checker); 239 CheckerContext C(Bldr, Eng, Pred, L); 240 241 checkFn(Loc, IsLoad, S, C); 242 } 243 }; 244 } 245 246 /// \brief Run checkers for load/store of a location. 247 248 void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 249 const ExplodedNodeSet &Src, 250 SVal location, bool isLoad, 251 const Stmt *S, ExprEngine &Eng) { 252 CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); 253 expandGraphWithCheckers(C, Dst, Src); 254 } 255 256 namespace { 257 struct CheckBindContext { 258 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 259 const CheckersTy &Checkers; 260 SVal Loc; 261 SVal Val; 262 const Stmt *S; 263 ExprEngine &Eng; 264 ProgramPoint::Kind PointKind; 265 266 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 267 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 268 269 CheckBindContext(const CheckersTy &checkers, 270 SVal loc, SVal val, const Stmt *s, ExprEngine &eng, 271 ProgramPoint::Kind PK) 272 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {} 273 274 void runChecker(CheckerManager::CheckBindFunc checkFn, 275 NodeBuilder &Bldr, ExplodedNode *Pred) { 276 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind, 277 Pred->getLocationContext(), checkFn.Checker); 278 CheckerContext C(Bldr, Eng, Pred, L); 279 280 checkFn(Loc, Val, S, C); 281 } 282 }; 283 } 284 285 /// \brief Run checkers for binding of a value to a location. 286 void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 287 const ExplodedNodeSet &Src, 288 SVal location, SVal val, 289 const Stmt *S, ExprEngine &Eng, 290 ProgramPoint::Kind PointKind) { 291 CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind); 292 expandGraphWithCheckers(C, Dst, Src); 293 } 294 295 void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 296 BugReporter &BR, 297 ExprEngine &Eng) { 298 for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 299 EndAnalysisCheckers[i](G, BR, Eng); 300 } 301 302 /// \brief Run checkers for end of path. 303 // Note, We do not chain the checker output (like in expandGraphWithCheckers) 304 // for this callback since end of path nodes are expected to be final. 305 void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC, 306 ExplodedNodeSet &Dst, 307 ExprEngine &Eng) { 308 ExplodedNode *Pred = BC.Pred; 309 310 // We define the builder outside of the loop bacause if at least one checkers 311 // creates a sucsessor for Pred, we do not need to generate an 312 // autotransition for it. 313 NodeBuilder Bldr(Pred, Dst, BC); 314 for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 315 CheckEndPathFunc checkFn = EndPathCheckers[i]; 316 317 const ProgramPoint &L = BlockEntrance(BC.Block, 318 Pred->getLocationContext(), 319 checkFn.Checker); 320 CheckerContext C(Bldr, Eng, Pred, L); 321 checkFn(C); 322 } 323 } 324 325 namespace { 326 struct CheckBranchConditionContext { 327 typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy; 328 const CheckersTy &Checkers; 329 const Stmt *Condition; 330 ExprEngine &Eng; 331 332 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 333 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 334 335 CheckBranchConditionContext(const CheckersTy &checkers, 336 const Stmt *Cond, ExprEngine &eng) 337 : Checkers(checkers), Condition(Cond), Eng(eng) {} 338 339 void runChecker(CheckerManager::CheckBranchConditionFunc checkFn, 340 NodeBuilder &Bldr, ExplodedNode *Pred) { 341 ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(), 342 checkFn.Checker); 343 CheckerContext C(Bldr, Eng, Pred, L); 344 checkFn(Condition, C); 345 } 346 }; 347 } 348 349 /// \brief Run checkers for branch condition. 350 void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition, 351 ExplodedNodeSet &Dst, 352 ExplodedNode *Pred, 353 ExprEngine &Eng) { 354 ExplodedNodeSet Src; 355 Src.insert(Pred); 356 CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng); 357 expandGraphWithCheckers(C, Dst, Src); 358 } 359 360 /// \brief Run checkers for live symbols. 361 void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state, 362 SymbolReaper &SymReaper) { 363 for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 364 LiveSymbolsCheckers[i](state, SymReaper); 365 } 366 367 namespace { 368 struct CheckDeadSymbolsContext { 369 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 370 const CheckersTy &Checkers; 371 SymbolReaper &SR; 372 const Stmt *S; 373 ExprEngine &Eng; 374 375 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 376 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 377 378 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 379 const Stmt *s, ExprEngine &eng) 380 : Checkers(checkers), SR(sr), S(s), Eng(eng) { } 381 382 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 383 NodeBuilder &Bldr, ExplodedNode *Pred) { 384 ProgramPoint::Kind K = ProgramPoint::PostPurgeDeadSymbolsKind; 385 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 386 Pred->getLocationContext(), checkFn.Checker); 387 CheckerContext C(Bldr, Eng, Pred, L); 388 389 checkFn(SR, C); 390 } 391 }; 392 } 393 394 /// \brief Run checkers for dead symbols. 395 void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 396 const ExplodedNodeSet &Src, 397 SymbolReaper &SymReaper, 398 const Stmt *S, 399 ExprEngine &Eng) { 400 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); 401 expandGraphWithCheckers(C, Dst, Src); 402 } 403 404 /// \brief True if at least one checker wants to check region changes. 405 bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) { 406 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 407 if (RegionChangesCheckers[i].WantUpdateFn(state)) 408 return true; 409 410 return false; 411 } 412 413 /// \brief Run checkers for region changes. 414 ProgramStateRef 415 CheckerManager::runCheckersForRegionChanges(ProgramStateRef state, 416 const StoreManager::InvalidatedSymbols *invalidated, 417 ArrayRef<const MemRegion *> ExplicitRegions, 418 ArrayRef<const MemRegion *> Regions, 419 const CallOrObjCMessage *Call) { 420 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 421 // If any checker declares the state infeasible (or if it starts that way), 422 // bail out. 423 if (!state) 424 return NULL; 425 state = RegionChangesCheckers[i].CheckFn(state, invalidated, 426 ExplicitRegions, Regions, Call); 427 } 428 return state; 429 } 430 431 /// \brief Run checkers for handling assumptions on symbolic values. 432 ProgramStateRef 433 CheckerManager::runCheckersForEvalAssume(ProgramStateRef state, 434 SVal Cond, bool Assumption) { 435 for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 436 // If any checker declares the state infeasible (or if it starts that way), 437 // bail out. 438 if (!state) 439 return NULL; 440 state = EvalAssumeCheckers[i](state, Cond, Assumption); 441 } 442 return state; 443 } 444 445 /// \brief Run checkers for evaluating a call. 446 /// Only one checker will evaluate the call. 447 void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 448 const ExplodedNodeSet &Src, 449 const CallExpr *CE, 450 ExprEngine &Eng, 451 GraphExpander *defaultEval) { 452 if (EvalCallCheckers.empty() && 453 InlineCallCheckers.empty() && 454 defaultEval == 0) { 455 Dst.insert(Src); 456 return; 457 } 458 459 for (ExplodedNodeSet::iterator 460 NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 461 462 ExplodedNode *Pred = *NI; 463 bool anyEvaluated = false; 464 465 // First, check if any of the InlineCall callbacks can evaluate the call. 466 assert(InlineCallCheckers.size() <= 1 && 467 "InlineCall is a special hacky callback to allow intrusive" 468 "evaluation of the call (which simulates inlining). It is " 469 "currently only used by OSAtomicChecker and should go away " 470 "at some point."); 471 for (std::vector<InlineCallFunc>::iterator 472 EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end(); 473 EI != EE; ++EI) { 474 ExplodedNodeSet checkDst; 475 bool evaluated = (*EI)(CE, Eng, Pred, checkDst); 476 assert(!(evaluated && anyEvaluated) 477 && "There are more than one checkers evaluating the call"); 478 if (evaluated) { 479 anyEvaluated = true; 480 Dst.insert(checkDst); 481 #ifdef NDEBUG 482 break; // on release don't check that no other checker also evals. 483 #endif 484 } 485 } 486 487 #ifdef NDEBUG // on release don't check that no other checker also evals. 488 if (anyEvaluated) { 489 break; 490 } 491 #endif 492 493 ExplodedNodeSet checkDst; 494 NodeBuilder B(Pred, checkDst, Eng.getBuilderContext()); 495 // Next, check if any of the EvalCall callbacks can evaluate the call. 496 for (std::vector<EvalCallFunc>::iterator 497 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 498 EI != EE; ++EI) { 499 ProgramPoint::Kind K = ProgramPoint::PostStmtKind; 500 const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K, 501 Pred->getLocationContext(), EI->Checker); 502 bool evaluated = false; 503 { // CheckerContext generates transitions(populates checkDest) on 504 // destruction, so introduce the scope to make sure it gets properly 505 // populated. 506 CheckerContext C(B, Eng, Pred, L); 507 evaluated = (*EI)(CE, C); 508 } 509 assert(!(evaluated && anyEvaluated) 510 && "There are more than one checkers evaluating the call"); 511 if (evaluated) { 512 anyEvaluated = true; 513 Dst.insert(checkDst); 514 #ifdef NDEBUG 515 break; // on release don't check that no other checker also evals. 516 #endif 517 } 518 } 519 520 // If none of the checkers evaluated the call, ask ExprEngine to handle it. 521 if (!anyEvaluated) { 522 if (defaultEval) 523 defaultEval->expandGraph(Dst, Pred); 524 else 525 Dst.insert(Pred); 526 } 527 } 528 } 529 530 /// \brief Run checkers for the entire Translation Unit. 531 void CheckerManager::runCheckersOnEndOfTranslationUnit( 532 const TranslationUnitDecl *TU, 533 AnalysisManager &mgr, 534 BugReporter &BR) { 535 for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 536 EndOfTranslationUnitCheckers[i](TU, mgr, BR); 537 } 538 539 void CheckerManager::runCheckersForPrintState(raw_ostream &Out, 540 ProgramStateRef State, 541 const char *NL, const char *Sep) { 542 for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator 543 I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I) 544 I->second->printState(Out, State, NL, Sep); 545 } 546 547 //===----------------------------------------------------------------------===// 548 // Internal registration functions for AST traversing. 549 //===----------------------------------------------------------------------===// 550 551 void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 552 HandlesDeclFunc isForDeclFn) { 553 DeclCheckerInfo info = { checkfn, isForDeclFn }; 554 DeclCheckers.push_back(info); 555 } 556 557 void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 558 BodyCheckers.push_back(checkfn); 559 } 560 561 //===----------------------------------------------------------------------===// 562 // Internal registration functions for path-sensitive checking. 563 //===----------------------------------------------------------------------===// 564 565 void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 566 HandlesStmtFunc isForStmtFn) { 567 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 568 StmtCheckers.push_back(info); 569 } 570 void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 571 HandlesStmtFunc isForStmtFn) { 572 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 573 StmtCheckers.push_back(info); 574 } 575 576 void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 577 PreObjCMessageCheckers.push_back(checkfn); 578 } 579 void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 580 PostObjCMessageCheckers.push_back(checkfn); 581 } 582 583 void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 584 LocationCheckers.push_back(checkfn); 585 } 586 587 void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 588 BindCheckers.push_back(checkfn); 589 } 590 591 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 592 EndAnalysisCheckers.push_back(checkfn); 593 } 594 595 void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 596 EndPathCheckers.push_back(checkfn); 597 } 598 599 void CheckerManager::_registerForBranchCondition( 600 CheckBranchConditionFunc checkfn) { 601 BranchConditionCheckers.push_back(checkfn); 602 } 603 604 void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 605 LiveSymbolsCheckers.push_back(checkfn); 606 } 607 608 void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 609 DeadSymbolsCheckers.push_back(checkfn); 610 } 611 612 void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 613 WantsRegionChangeUpdateFunc wantUpdateFn) { 614 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 615 RegionChangesCheckers.push_back(info); 616 } 617 618 void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 619 EvalAssumeCheckers.push_back(checkfn); 620 } 621 622 void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 623 EvalCallCheckers.push_back(checkfn); 624 } 625 626 void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) { 627 InlineCallCheckers.push_back(checkfn); 628 } 629 630 void CheckerManager::_registerForEndOfTranslationUnit( 631 CheckEndOfTranslationUnit checkfn) { 632 EndOfTranslationUnitCheckers.push_back(checkfn); 633 } 634 635 //===----------------------------------------------------------------------===// 636 // Implementation details. 637 //===----------------------------------------------------------------------===// 638 639 CheckerManager::CachedStmtCheckers * 640 CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 641 assert(S); 642 643 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 644 CachedStmtCheckers *checkers = 0; 645 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 646 if (CCI != CachedStmtCheckersMap.end()) { 647 checkers = &(CCI->second); 648 } else { 649 // Find the checkers that should run for this Stmt and cache them. 650 checkers = &CachedStmtCheckersMap[key]; 651 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 652 StmtCheckerInfo &info = StmtCheckers[i]; 653 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 654 checkers->push_back(info.CheckFn); 655 } 656 } 657 658 assert(checkers); 659 return checkers; 660 } 661 662 CheckerManager::~CheckerManager() { 663 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 664 CheckerDtors[i](); 665 } 666 667 // Anchor for the vtable. 668 GraphExpander::~GraphExpander() { } 669