CheckerManager.cpp revision 66c40400e7d6272b0cd675ada18dd62c1f0362c7
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 21using namespace clang; 22using namespace ento; 23 24bool 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 41void 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 55void 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 80void 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 92template <typename CHECK_CTX> 93static 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 134namespace { 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. 164void 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 174namespace { 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 = ProgramPoint::getProgramPoint(Msg.getOriginExpr(), 194 K, Pred->getLocationContext(), checkFn.Checker); 195 CheckerContext C(Bldr, Eng, Pred, L); 196 197 checkFn(Msg, C); 198 } 199 }; 200} 201 202/// \brief Run checkers for visiting obj-c messages. 203void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 204 ExplodedNodeSet &Dst, 205 const ExplodedNodeSet &Src, 206 const ObjCMessage &msg, 207 ExprEngine &Eng) { 208 CheckObjCMessageContext C(isPreVisit, 209 isPreVisit ? PreObjCMessageCheckers 210 : PostObjCMessageCheckers, 211 msg, Eng); 212 expandGraphWithCheckers(C, Dst, Src); 213} 214 215namespace { 216 struct CheckLocationContext { 217 typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 218 const CheckersTy &Checkers; 219 SVal Loc; 220 bool IsLoad; 221 const Stmt *S; 222 ExprEngine &Eng; 223 224 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 225 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 226 227 CheckLocationContext(const CheckersTy &checkers, 228 SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) 229 : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } 230 231 void runChecker(CheckerManager::CheckLocationFunc checkFn, 232 NodeBuilder &Bldr, ExplodedNode *Pred) { 233 ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind : 234 ProgramPoint::PreStoreKind; 235 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 236 Pred->getLocationContext(), checkFn.Checker); 237 CheckerContext C(Bldr, Eng, Pred, L); 238 239 checkFn(Loc, IsLoad, S, C); 240 } 241 }; 242} 243 244/// \brief Run checkers for load/store of a location. 245 246void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 247 const ExplodedNodeSet &Src, 248 SVal location, bool isLoad, 249 const Stmt *S, ExprEngine &Eng) { 250 CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); 251 expandGraphWithCheckers(C, Dst, Src); 252} 253 254namespace { 255 struct CheckBindContext { 256 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 257 const CheckersTy &Checkers; 258 SVal Loc; 259 SVal Val; 260 const Stmt *S; 261 ExprEngine &Eng; 262 ProgramPoint::Kind PointKind; 263 264 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 265 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 266 267 CheckBindContext(const CheckersTy &checkers, 268 SVal loc, SVal val, const Stmt *s, ExprEngine &eng, 269 ProgramPoint::Kind PK) 270 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {} 271 272 void runChecker(CheckerManager::CheckBindFunc checkFn, 273 NodeBuilder &Bldr, ExplodedNode *Pred) { 274 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind, 275 Pred->getLocationContext(), checkFn.Checker); 276 CheckerContext C(Bldr, Eng, Pred, L); 277 278 checkFn(Loc, Val, S, C); 279 } 280 }; 281} 282 283/// \brief Run checkers for binding of a value to a location. 284void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 285 const ExplodedNodeSet &Src, 286 SVal location, SVal val, 287 const Stmt *S, ExprEngine &Eng, 288 ProgramPoint::Kind PointKind) { 289 CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind); 290 expandGraphWithCheckers(C, Dst, Src); 291} 292 293void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 294 BugReporter &BR, 295 ExprEngine &Eng) { 296 for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 297 EndAnalysisCheckers[i](G, BR, Eng); 298} 299 300/// \brief Run checkers for end of path. 301// Note, We do not chain the checker output (like in expandGraphWithCheckers) 302// for this callback since end of path nodes are expected to be final. 303void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC, 304 ExplodedNodeSet &Dst, 305 ExprEngine &Eng) { 306 ExplodedNode *Pred = BC.Pred; 307 308 // We define the builder outside of the loop bacause if at least one checkers 309 // creates a sucsessor for Pred, we do not need to generate an 310 // autotransition for it. 311 NodeBuilder Bldr(Pred, Dst, BC); 312 for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 313 CheckEndPathFunc checkFn = EndPathCheckers[i]; 314 315 const ProgramPoint &L = BlockEntrance(BC.Block, 316 Pred->getLocationContext(), 317 checkFn.Checker); 318 CheckerContext C(Bldr, Eng, Pred, L); 319 checkFn(C); 320 } 321} 322 323namespace { 324 struct CheckBranchConditionContext { 325 typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy; 326 const CheckersTy &Checkers; 327 const Stmt *Condition; 328 ExprEngine &Eng; 329 330 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 331 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 332 333 CheckBranchConditionContext(const CheckersTy &checkers, 334 const Stmt *Cond, ExprEngine &eng) 335 : Checkers(checkers), Condition(Cond), Eng(eng) {} 336 337 void runChecker(CheckerManager::CheckBranchConditionFunc checkFn, 338 NodeBuilder &Bldr, ExplodedNode *Pred) { 339 ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(), 340 checkFn.Checker); 341 CheckerContext C(Bldr, Eng, Pred, L); 342 checkFn(Condition, C); 343 } 344 }; 345} 346 347/// \brief Run checkers for branch condition. 348void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition, 349 ExplodedNodeSet &Dst, 350 ExplodedNode *Pred, 351 ExprEngine &Eng) { 352 ExplodedNodeSet Src; 353 Src.insert(Pred); 354 CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng); 355 expandGraphWithCheckers(C, Dst, Src); 356} 357 358/// \brief Run checkers for live symbols. 359void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state, 360 SymbolReaper &SymReaper) { 361 for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 362 LiveSymbolsCheckers[i](state, SymReaper); 363} 364 365namespace { 366 struct CheckDeadSymbolsContext { 367 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 368 const CheckersTy &Checkers; 369 SymbolReaper &SR; 370 const Stmt *S; 371 ExprEngine &Eng; 372 373 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 374 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 375 376 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 377 const Stmt *s, ExprEngine &eng) 378 : Checkers(checkers), SR(sr), S(s), Eng(eng) { } 379 380 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 381 NodeBuilder &Bldr, ExplodedNode *Pred) { 382 ProgramPoint::Kind K = ProgramPoint::PostPurgeDeadSymbolsKind; 383 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 384 Pred->getLocationContext(), checkFn.Checker); 385 CheckerContext C(Bldr, Eng, Pred, L); 386 387 checkFn(SR, C); 388 } 389 }; 390} 391 392/// \brief Run checkers for dead symbols. 393void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 394 const ExplodedNodeSet &Src, 395 SymbolReaper &SymReaper, 396 const Stmt *S, 397 ExprEngine &Eng) { 398 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); 399 expandGraphWithCheckers(C, Dst, Src); 400} 401 402/// \brief True if at least one checker wants to check region changes. 403bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) { 404 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 405 if (RegionChangesCheckers[i].WantUpdateFn(state)) 406 return true; 407 408 return false; 409} 410 411/// \brief Run checkers for region changes. 412ProgramStateRef 413CheckerManager::runCheckersForRegionChanges(ProgramStateRef state, 414 const StoreManager::InvalidatedSymbols *invalidated, 415 ArrayRef<const MemRegion *> ExplicitRegions, 416 ArrayRef<const MemRegion *> Regions, 417 const CallOrObjCMessage *Call) { 418 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 419 // If any checker declares the state infeasible (or if it starts that way), 420 // bail out. 421 if (!state) 422 return NULL; 423 state = RegionChangesCheckers[i].CheckFn(state, invalidated, 424 ExplicitRegions, Regions, Call); 425 } 426 return state; 427} 428 429/// \brief Run checkers for handling assumptions on symbolic values. 430ProgramStateRef 431CheckerManager::runCheckersForEvalAssume(ProgramStateRef state, 432 SVal Cond, bool Assumption) { 433 for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 434 // If any checker declares the state infeasible (or if it starts that way), 435 // bail out. 436 if (!state) 437 return NULL; 438 state = EvalAssumeCheckers[i](state, Cond, Assumption); 439 } 440 return state; 441} 442 443/// \brief Run checkers for evaluating a call. 444/// Only one checker will evaluate the call. 445void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 446 const ExplodedNodeSet &Src, 447 const CallExpr *CE, 448 ExprEngine &Eng, 449 GraphExpander *defaultEval) { 450 if (EvalCallCheckers.empty() && 451 InlineCallCheckers.empty() && 452 defaultEval == 0) { 453 Dst.insert(Src); 454 return; 455 } 456 457 for (ExplodedNodeSet::iterator 458 NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 459 460 ExplodedNode *Pred = *NI; 461 bool anyEvaluated = false; 462 463 // First, check if any of the InlineCall callbacks can evaluate the call. 464 assert(InlineCallCheckers.size() <= 1 && 465 "InlineCall is a special hacky callback to allow intrusive" 466 "evaluation of the call (which simulates inlining). It is " 467 "currently only used by OSAtomicChecker and should go away " 468 "at some point."); 469 for (std::vector<InlineCallFunc>::iterator 470 EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end(); 471 EI != EE; ++EI) { 472 ExplodedNodeSet checkDst; 473 bool evaluated = (*EI)(CE, Eng, Pred, checkDst); 474 assert(!(evaluated && anyEvaluated) 475 && "There are more than one checkers evaluating the call"); 476 if (evaluated) { 477 anyEvaluated = true; 478 Dst.insert(checkDst); 479#ifdef NDEBUG 480 break; // on release don't check that no other checker also evals. 481#endif 482 } 483 } 484 485#ifdef NDEBUG // on release don't check that no other checker also evals. 486 if (anyEvaluated) { 487 break; 488 } 489#endif 490 491 ExplodedNodeSet checkDst; 492 NodeBuilder B(Pred, checkDst, Eng.getBuilderContext()); 493 // Next, check if any of the EvalCall callbacks can evaluate the call. 494 for (std::vector<EvalCallFunc>::iterator 495 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 496 EI != EE; ++EI) { 497 ProgramPoint::Kind K = ProgramPoint::PostStmtKind; 498 const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K, 499 Pred->getLocationContext(), EI->Checker); 500 bool evaluated = false; 501 { // CheckerContext generates transitions(populates checkDest) on 502 // destruction, so introduce the scope to make sure it gets properly 503 // populated. 504 CheckerContext C(B, Eng, Pred, L); 505 evaluated = (*EI)(CE, C); 506 } 507 assert(!(evaluated && anyEvaluated) 508 && "There are more than one checkers evaluating the call"); 509 if (evaluated) { 510 anyEvaluated = true; 511 Dst.insert(checkDst); 512#ifdef NDEBUG 513 break; // on release don't check that no other checker also evals. 514#endif 515 } 516 } 517 518 // If none of the checkers evaluated the call, ask ExprEngine to handle it. 519 if (!anyEvaluated) { 520 if (defaultEval) 521 defaultEval->expandGraph(Dst, Pred); 522 else 523 Dst.insert(Pred); 524 } 525 } 526} 527 528/// \brief Run checkers for the entire Translation Unit. 529void CheckerManager::runCheckersOnEndOfTranslationUnit( 530 const TranslationUnitDecl *TU, 531 AnalysisManager &mgr, 532 BugReporter &BR) { 533 for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 534 EndOfTranslationUnitCheckers[i](TU, mgr, BR); 535} 536 537void CheckerManager::runCheckersForPrintState(raw_ostream &Out, 538 ProgramStateRef State, 539 const char *NL, const char *Sep) { 540 for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator 541 I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I) 542 I->second->printState(Out, State, NL, Sep); 543} 544 545//===----------------------------------------------------------------------===// 546// Internal registration functions for AST traversing. 547//===----------------------------------------------------------------------===// 548 549void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 550 HandlesDeclFunc isForDeclFn) { 551 DeclCheckerInfo info = { checkfn, isForDeclFn }; 552 DeclCheckers.push_back(info); 553} 554 555void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 556 BodyCheckers.push_back(checkfn); 557} 558 559//===----------------------------------------------------------------------===// 560// Internal registration functions for path-sensitive checking. 561//===----------------------------------------------------------------------===// 562 563void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 564 HandlesStmtFunc isForStmtFn) { 565 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 566 StmtCheckers.push_back(info); 567} 568void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 569 HandlesStmtFunc isForStmtFn) { 570 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 571 StmtCheckers.push_back(info); 572} 573 574void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 575 PreObjCMessageCheckers.push_back(checkfn); 576} 577void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 578 PostObjCMessageCheckers.push_back(checkfn); 579} 580 581void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 582 LocationCheckers.push_back(checkfn); 583} 584 585void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 586 BindCheckers.push_back(checkfn); 587} 588 589void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 590 EndAnalysisCheckers.push_back(checkfn); 591} 592 593void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 594 EndPathCheckers.push_back(checkfn); 595} 596 597void CheckerManager::_registerForBranchCondition( 598 CheckBranchConditionFunc checkfn) { 599 BranchConditionCheckers.push_back(checkfn); 600} 601 602void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 603 LiveSymbolsCheckers.push_back(checkfn); 604} 605 606void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 607 DeadSymbolsCheckers.push_back(checkfn); 608} 609 610void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 611 WantsRegionChangeUpdateFunc wantUpdateFn) { 612 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 613 RegionChangesCheckers.push_back(info); 614} 615 616void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 617 EvalAssumeCheckers.push_back(checkfn); 618} 619 620void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 621 EvalCallCheckers.push_back(checkfn); 622} 623 624void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) { 625 InlineCallCheckers.push_back(checkfn); 626} 627 628void CheckerManager::_registerForEndOfTranslationUnit( 629 CheckEndOfTranslationUnit checkfn) { 630 EndOfTranslationUnitCheckers.push_back(checkfn); 631} 632 633//===----------------------------------------------------------------------===// 634// Implementation details. 635//===----------------------------------------------------------------------===// 636 637CheckerManager::CachedStmtCheckers * 638CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 639 assert(S); 640 641 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 642 CachedStmtCheckers *checkers = 0; 643 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 644 if (CCI != CachedStmtCheckersMap.end()) { 645 checkers = &(CCI->second); 646 } else { 647 // Find the checkers that should run for this Stmt and cache them. 648 checkers = &CachedStmtCheckersMap[key]; 649 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 650 StmtCheckerInfo &info = StmtCheckers[i]; 651 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 652 checkers->push_back(info.CheckFn); 653 } 654 } 655 656 assert(checkers); 657 return checkers; 658} 659 660CheckerManager::~CheckerManager() { 661 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 662 CheckerDtors[i](); 663} 664 665// Anchor for the vtable. 666GraphExpander::~GraphExpander() { } 667