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