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 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; 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. 209 void 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 221 namespace { 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 const ProgramPoint &L = Call.getProgramPoint(IsPreVisit, checkFn.Checker); 241 CheckerContext C(Bldr, Eng, Pred, L); 242 243 checkFn(Call, 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 CheckCallContext C(isPreVisit, 255 isPreVisit ? PreCallCheckers 256 : PostCallCheckers, 257 Call, Eng); 258 expandGraphWithCheckers(C, Dst, Src); 259 } 260 261 namespace { 262 struct CheckLocationContext { 263 typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 264 const CheckersTy &Checkers; 265 SVal Loc; 266 bool IsLoad; 267 const Stmt *NodeEx; /* Will become a CFGStmt */ 268 const Stmt *BoundEx; 269 ExprEngine &Eng; 270 271 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 272 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 273 274 CheckLocationContext(const CheckersTy &checkers, 275 SVal loc, bool isLoad, const Stmt *NodeEx, 276 const Stmt *BoundEx, 277 ExprEngine &eng) 278 : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx), 279 BoundEx(BoundEx), Eng(eng) {} 280 281 void runChecker(CheckerManager::CheckLocationFunc checkFn, 282 NodeBuilder &Bldr, ExplodedNode *Pred) { 283 ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind : 284 ProgramPoint::PreStoreKind; 285 const ProgramPoint &L = 286 ProgramPoint::getProgramPoint(NodeEx, K, 287 Pred->getLocationContext(), 288 checkFn.Checker); 289 CheckerContext C(Bldr, Eng, Pred, L); 290 checkFn(Loc, IsLoad, BoundEx, C); 291 } 292 }; 293 } 294 295 /// \brief Run checkers for load/store of a location. 296 297 void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 298 const ExplodedNodeSet &Src, 299 SVal location, bool isLoad, 300 const Stmt *NodeEx, 301 const Stmt *BoundEx, 302 ExprEngine &Eng) { 303 CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx, 304 BoundEx, Eng); 305 expandGraphWithCheckers(C, Dst, Src); 306 } 307 308 namespace { 309 struct CheckBindContext { 310 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 311 const CheckersTy &Checkers; 312 SVal Loc; 313 SVal Val; 314 const Stmt *S; 315 ExprEngine &Eng; 316 ProgramPoint::Kind PointKind; 317 318 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 319 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 320 321 CheckBindContext(const CheckersTy &checkers, 322 SVal loc, SVal val, const Stmt *s, ExprEngine &eng, 323 ProgramPoint::Kind PK) 324 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {} 325 326 void runChecker(CheckerManager::CheckBindFunc checkFn, 327 NodeBuilder &Bldr, ExplodedNode *Pred) { 328 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind, 329 Pred->getLocationContext(), 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 ProgramPoint::Kind PointKind) { 343 CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind); 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 SimpleCall &Call, 507 ExprEngine &Eng) { 508 const CallExpr *CE = 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 Eng.defaultEvalCall(Dst, Pred, Call); 573 } 574 } 575 576 /// \brief Run checkers for the entire Translation Unit. 577 void CheckerManager::runCheckersOnEndOfTranslationUnit( 578 const TranslationUnitDecl *TU, 579 AnalysisManager &mgr, 580 BugReporter &BR) { 581 for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 582 EndOfTranslationUnitCheckers[i](TU, mgr, BR); 583 } 584 585 void CheckerManager::runCheckersForPrintState(raw_ostream &Out, 586 ProgramStateRef State, 587 const char *NL, const char *Sep) { 588 for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator 589 I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I) 590 I->second->printState(Out, State, NL, Sep); 591 } 592 593 //===----------------------------------------------------------------------===// 594 // Internal registration functions for AST traversing. 595 //===----------------------------------------------------------------------===// 596 597 void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 598 HandlesDeclFunc isForDeclFn) { 599 DeclCheckerInfo info = { checkfn, isForDeclFn }; 600 DeclCheckers.push_back(info); 601 } 602 603 void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 604 BodyCheckers.push_back(checkfn); 605 } 606 607 //===----------------------------------------------------------------------===// 608 // Internal registration functions for path-sensitive checking. 609 //===----------------------------------------------------------------------===// 610 611 void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 612 HandlesStmtFunc isForStmtFn) { 613 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 614 StmtCheckers.push_back(info); 615 } 616 void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 617 HandlesStmtFunc isForStmtFn) { 618 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 619 StmtCheckers.push_back(info); 620 } 621 622 void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 623 PreObjCMessageCheckers.push_back(checkfn); 624 } 625 void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 626 PostObjCMessageCheckers.push_back(checkfn); 627 } 628 629 void CheckerManager::_registerForPreCall(CheckCallFunc checkfn) { 630 PreCallCheckers.push_back(checkfn); 631 } 632 void CheckerManager::_registerForPostCall(CheckCallFunc checkfn) { 633 PostCallCheckers.push_back(checkfn); 634 } 635 636 void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 637 LocationCheckers.push_back(checkfn); 638 } 639 640 void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 641 BindCheckers.push_back(checkfn); 642 } 643 644 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 645 EndAnalysisCheckers.push_back(checkfn); 646 } 647 648 void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 649 EndPathCheckers.push_back(checkfn); 650 } 651 652 void CheckerManager::_registerForBranchCondition( 653 CheckBranchConditionFunc checkfn) { 654 BranchConditionCheckers.push_back(checkfn); 655 } 656 657 void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 658 LiveSymbolsCheckers.push_back(checkfn); 659 } 660 661 void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 662 DeadSymbolsCheckers.push_back(checkfn); 663 } 664 665 void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 666 WantsRegionChangeUpdateFunc wantUpdateFn) { 667 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 668 RegionChangesCheckers.push_back(info); 669 } 670 671 void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 672 EvalAssumeCheckers.push_back(checkfn); 673 } 674 675 void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 676 EvalCallCheckers.push_back(checkfn); 677 } 678 679 void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) { 680 InlineCallCheckers.push_back(checkfn); 681 } 682 683 void CheckerManager::_registerForEndOfTranslationUnit( 684 CheckEndOfTranslationUnit checkfn) { 685 EndOfTranslationUnitCheckers.push_back(checkfn); 686 } 687 688 //===----------------------------------------------------------------------===// 689 // Implementation details. 690 //===----------------------------------------------------------------------===// 691 692 CheckerManager::CachedStmtCheckers * 693 CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 694 assert(S); 695 696 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 697 CachedStmtCheckers *checkers = 0; 698 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 699 if (CCI != CachedStmtCheckersMap.end()) { 700 checkers = &(CCI->second); 701 } else { 702 // Find the checkers that should run for this Stmt and cache them. 703 checkers = &CachedStmtCheckersMap[key]; 704 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 705 StmtCheckerInfo &info = StmtCheckers[i]; 706 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 707 checkers->push_back(info.CheckFn); 708 } 709 } 710 711 assert(checkers); 712 return checkers; 713 } 714 715 CheckerManager::~CheckerManager() { 716 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 717 CheckerDtors[i](); 718 } 719