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