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