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