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