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