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/CheckerProvider.h" 16 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 17 #include "clang/Analysis/ProgramPoint.h" 18 #include "clang/AST/DeclBase.h" 19 20 using namespace clang; 21 using namespace ento; 22 23 bool CheckerManager::hasPathSensitiveCheckers() const { 24 return !StmtCheckers.empty() || 25 !PreObjCMessageCheckers.empty() || 26 !PostObjCMessageCheckers.empty() || 27 !LocationCheckers.empty() || 28 !BindCheckers.empty() || 29 !EndAnalysisCheckers.empty() || 30 !EndPathCheckers.empty() || 31 !BranchConditionCheckers.empty() || 32 !LiveSymbolsCheckers.empty() || 33 !DeadSymbolsCheckers.empty() || 34 !RegionChangesCheckers.empty() || 35 !EvalAssumeCheckers.empty() || 36 !EvalCallCheckers.empty(); 37 } 38 39 void CheckerManager::finishedCheckerRegistration() { 40 #ifndef NDEBUG 41 // Make sure that for every event that has listeners, there is at least 42 // one dispatcher registered for it. 43 for (llvm::DenseMap<EventTag, EventInfo>::iterator 44 I = Events.begin(), E = Events.end(); I != E; ++I) 45 assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 46 #endif 47 } 48 49 //===----------------------------------------------------------------------===// 50 // Functions for running checkers for AST traversing.. 51 //===----------------------------------------------------------------------===// 52 53 void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 54 BugReporter &BR) { 55 assert(D); 56 57 unsigned DeclKind = D->getKind(); 58 CachedDeclCheckers *checkers = 0; 59 CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 60 if (CCI != CachedDeclCheckersMap.end()) { 61 checkers = &(CCI->second); 62 } else { 63 // Find the checkers that should run for this Decl and cache them. 64 checkers = &CachedDeclCheckersMap[DeclKind]; 65 for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 66 DeclCheckerInfo &info = DeclCheckers[i]; 67 if (info.IsForDeclFn(D)) 68 checkers->push_back(info.CheckFn); 69 } 70 } 71 72 assert(checkers); 73 for (CachedDeclCheckers::iterator 74 I = checkers->begin(), E = checkers->end(); I != E; ++I) 75 (*I)(D, mgr, BR); 76 } 77 78 void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 79 BugReporter &BR) { 80 assert(D && D->hasBody()); 81 82 for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 83 BodyCheckers[i](D, mgr, BR); 84 } 85 86 //===----------------------------------------------------------------------===// 87 // Functions for running checkers for path-sensitive checking. 88 //===----------------------------------------------------------------------===// 89 90 template <typename CHECK_CTX> 91 static void expandGraphWithCheckers(CHECK_CTX checkCtx, 92 ExplodedNodeSet &Dst, 93 const ExplodedNodeSet &Src) { 94 95 typename CHECK_CTX::CheckersTy::const_iterator 96 I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 97 if (I == E) { 98 Dst.insert(Src); 99 return; 100 } 101 102 ExplodedNodeSet Tmp1, Tmp2; 103 const ExplodedNodeSet *PrevSet = &Src; 104 105 for (; I != E; ++I) { 106 ExplodedNodeSet *CurrSet = 0; 107 if (I+1 == E) 108 CurrSet = &Dst; 109 else { 110 CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 111 CurrSet->clear(); 112 } 113 114 for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 115 NI != NE; ++NI) 116 checkCtx.runChecker(*I, *CurrSet, *NI); 117 118 // Update which NodeSet is the current one. 119 PrevSet = CurrSet; 120 } 121 } 122 123 namespace { 124 struct CheckStmtContext { 125 typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 126 bool IsPreVisit; 127 const CheckersTy &Checkers; 128 const Stmt *S; 129 ExprEngine &Eng; 130 131 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 132 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 133 134 CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 135 const Stmt *s, ExprEngine &eng) 136 : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { } 137 138 void runChecker(CheckerManager::CheckStmtFunc checkFn, 139 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 140 // FIXME: Remove respondsToCallback from CheckerContext; 141 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 142 IsPreVisit ? ProgramPoint::PreStmtKind : 143 ProgramPoint::PostStmtKind, 0, S); 144 checkFn(S, C); 145 } 146 }; 147 } 148 149 /// \brief Run checkers for visiting Stmts. 150 void CheckerManager::runCheckersForStmt(bool isPreVisit, 151 ExplodedNodeSet &Dst, 152 const ExplodedNodeSet &Src, 153 const Stmt *S, 154 ExprEngine &Eng) { 155 CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 156 S, Eng); 157 expandGraphWithCheckers(C, Dst, Src); 158 } 159 160 namespace { 161 struct CheckObjCMessageContext { 162 typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 163 bool IsPreVisit; 164 const CheckersTy &Checkers; 165 const ObjCMessage &Msg; 166 ExprEngine &Eng; 167 168 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 169 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 170 171 CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 172 const ObjCMessage &msg, ExprEngine &eng) 173 : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 174 175 void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 176 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 177 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 178 IsPreVisit ? ProgramPoint::PreStmtKind : 179 ProgramPoint::PostStmtKind, 0, 180 Msg.getOriginExpr()); 181 checkFn(Msg, C); 182 } 183 }; 184 } 185 186 /// \brief Run checkers for visiting obj-c messages. 187 void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 188 ExplodedNodeSet &Dst, 189 const ExplodedNodeSet &Src, 190 const ObjCMessage &msg, 191 ExprEngine &Eng) { 192 CheckObjCMessageContext C(isPreVisit, 193 isPreVisit ? PreObjCMessageCheckers 194 : PostObjCMessageCheckers, 195 msg, Eng); 196 expandGraphWithCheckers(C, Dst, Src); 197 } 198 199 namespace { 200 struct CheckLocationContext { 201 typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 202 const CheckersTy &Checkers; 203 SVal Loc; 204 bool IsLoad; 205 const Stmt *S; 206 ExprEngine &Eng; 207 208 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 209 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 210 211 CheckLocationContext(const CheckersTy &checkers, 212 SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) 213 : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } 214 215 void runChecker(CheckerManager::CheckLocationFunc checkFn, 216 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 217 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 218 IsLoad ? ProgramPoint::PreLoadKind : 219 ProgramPoint::PreStoreKind, 0, S); 220 checkFn(Loc, IsLoad, C); 221 } 222 }; 223 } 224 225 /// \brief Run checkers for load/store of a location. 226 void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 227 const ExplodedNodeSet &Src, 228 SVal location, bool isLoad, 229 const Stmt *S, ExprEngine &Eng) { 230 CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); 231 expandGraphWithCheckers(C, Dst, Src); 232 } 233 234 namespace { 235 struct CheckBindContext { 236 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 237 const CheckersTy &Checkers; 238 SVal Loc; 239 SVal Val; 240 const Stmt *S; 241 ExprEngine &Eng; 242 243 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 244 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 245 246 CheckBindContext(const CheckersTy &checkers, 247 SVal loc, SVal val, const Stmt *s, ExprEngine &eng) 248 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { } 249 250 void runChecker(CheckerManager::CheckBindFunc checkFn, 251 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 252 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 253 ProgramPoint::PreStmtKind, 0, S); 254 checkFn(Loc, Val, C); 255 } 256 }; 257 } 258 259 /// \brief Run checkers for binding of a value to a location. 260 void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 261 const ExplodedNodeSet &Src, 262 SVal location, SVal val, 263 const Stmt *S, ExprEngine &Eng) { 264 CheckBindContext C(BindCheckers, location, val, S, Eng); 265 expandGraphWithCheckers(C, Dst, Src); 266 } 267 268 void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 269 BugReporter &BR, 270 ExprEngine &Eng) { 271 for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 272 EndAnalysisCheckers[i](G, BR, Eng); 273 } 274 275 /// \brief Run checkers for end of path. 276 void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B, 277 ExprEngine &Eng) { 278 for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 279 CheckEndPathFunc fn = EndPathCheckers[i]; 280 EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker); 281 fn(specialB, Eng); 282 } 283 } 284 285 /// \brief Run checkers for branch condition. 286 void CheckerManager::runCheckersForBranchCondition(const Stmt *condition, 287 BranchNodeBuilder &B, 288 ExprEngine &Eng) { 289 for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) { 290 CheckBranchConditionFunc fn = BranchConditionCheckers[i]; 291 fn(condition, B, Eng); 292 } 293 } 294 295 /// \brief Run checkers for live symbols. 296 void CheckerManager::runCheckersForLiveSymbols(const GRState *state, 297 SymbolReaper &SymReaper) { 298 for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 299 LiveSymbolsCheckers[i](state, SymReaper); 300 } 301 302 namespace { 303 struct CheckDeadSymbolsContext { 304 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 305 const CheckersTy &Checkers; 306 SymbolReaper &SR; 307 const Stmt *S; 308 ExprEngine &Eng; 309 310 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 311 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 312 313 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 314 const Stmt *s, ExprEngine &eng) 315 : Checkers(checkers), SR(sr), S(s), Eng(eng) { } 316 317 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 318 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 319 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 320 ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); 321 checkFn(SR, C); 322 } 323 }; 324 } 325 326 /// \brief Run checkers for dead symbols. 327 void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 328 const ExplodedNodeSet &Src, 329 SymbolReaper &SymReaper, 330 const Stmt *S, 331 ExprEngine &Eng) { 332 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); 333 expandGraphWithCheckers(C, Dst, Src); 334 } 335 336 /// \brief True if at least one checker wants to check region changes. 337 bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) { 338 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 339 if (RegionChangesCheckers[i].WantUpdateFn(state)) 340 return true; 341 342 return false; 343 } 344 345 /// \brief Run checkers for region changes. 346 const GRState * 347 CheckerManager::runCheckersForRegionChanges(const GRState *state, 348 const StoreManager::InvalidatedSymbols *invalidated, 349 const MemRegion * const *Begin, 350 const MemRegion * const *End) { 351 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 352 // If any checker declares the state infeasible (or if it starts that way), 353 // bail out. 354 if (!state) 355 return NULL; 356 state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End); 357 } 358 return state; 359 } 360 361 /// \brief Run checkers for handling assumptions on symbolic values. 362 const GRState * 363 CheckerManager::runCheckersForEvalAssume(const GRState *state, 364 SVal Cond, bool Assumption) { 365 for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 366 // If any checker declares the state infeasible (or if it starts that way), 367 // bail out. 368 if (!state) 369 return NULL; 370 state = EvalAssumeCheckers[i](state, Cond, Assumption); 371 } 372 return state; 373 } 374 375 /// \brief Run checkers for evaluating a call. 376 /// Only one checker will evaluate the call. 377 void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 378 const ExplodedNodeSet &Src, 379 const CallExpr *CE, 380 ExprEngine &Eng, 381 GraphExpander *defaultEval) { 382 if (EvalCallCheckers.empty() && defaultEval == 0) { 383 Dst.insert(Src); 384 return; 385 } 386 387 for (ExplodedNodeSet::iterator 388 NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 389 390 ExplodedNode *Pred = *NI; 391 bool anyEvaluated = false; 392 for (std::vector<EvalCallFunc>::iterator 393 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 394 EI != EE; ++EI) { 395 ExplodedNodeSet checkDst; 396 CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker, 397 ProgramPoint::PostStmtKind, 0, CE); 398 bool evaluated = (*EI)(CE, C); 399 assert(!(evaluated && anyEvaluated) 400 && "There are more than one checkers evaluating the call"); 401 if (evaluated) { 402 anyEvaluated = true; 403 Dst.insert(checkDst); 404 #ifdef NDEBUG 405 break; // on release don't check that no other checker also evals. 406 #endif 407 } 408 } 409 410 if (!anyEvaluated) { 411 if (defaultEval) 412 defaultEval->expandGraph(Dst, Pred); 413 else 414 Dst.insert(Pred); 415 } 416 } 417 } 418 419 /// \brief Run checkers for the entire Translation Unit. 420 void CheckerManager::runCheckersOnEndOfTranslationUnit( 421 const TranslationUnitDecl *TU, 422 AnalysisManager &mgr, 423 BugReporter &BR) { 424 for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 425 EndOfTranslationUnitCheckers[i](TU, mgr, BR); 426 } 427 428 //===----------------------------------------------------------------------===// 429 // Internal registration functions for AST traversing. 430 //===----------------------------------------------------------------------===// 431 432 void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 433 HandlesDeclFunc isForDeclFn) { 434 DeclCheckerInfo info = { checkfn, isForDeclFn }; 435 DeclCheckers.push_back(info); 436 } 437 438 void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 439 BodyCheckers.push_back(checkfn); 440 } 441 442 //===----------------------------------------------------------------------===// 443 // Internal registration functions for path-sensitive checking. 444 //===----------------------------------------------------------------------===// 445 446 void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 447 HandlesStmtFunc isForStmtFn) { 448 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 449 StmtCheckers.push_back(info); 450 } 451 void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 452 HandlesStmtFunc isForStmtFn) { 453 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 454 StmtCheckers.push_back(info); 455 } 456 457 void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 458 PreObjCMessageCheckers.push_back(checkfn); 459 } 460 void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 461 PostObjCMessageCheckers.push_back(checkfn); 462 } 463 464 void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 465 LocationCheckers.push_back(checkfn); 466 } 467 468 void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 469 BindCheckers.push_back(checkfn); 470 } 471 472 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 473 EndAnalysisCheckers.push_back(checkfn); 474 } 475 476 void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 477 EndPathCheckers.push_back(checkfn); 478 } 479 480 void CheckerManager::_registerForBranchCondition( 481 CheckBranchConditionFunc checkfn) { 482 BranchConditionCheckers.push_back(checkfn); 483 } 484 485 void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 486 LiveSymbolsCheckers.push_back(checkfn); 487 } 488 489 void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 490 DeadSymbolsCheckers.push_back(checkfn); 491 } 492 493 void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 494 WantsRegionChangeUpdateFunc wantUpdateFn) { 495 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 496 RegionChangesCheckers.push_back(info); 497 } 498 499 void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 500 EvalAssumeCheckers.push_back(checkfn); 501 } 502 503 void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 504 EvalCallCheckers.push_back(checkfn); 505 } 506 507 void CheckerManager::_registerForEndOfTranslationUnit( 508 CheckEndOfTranslationUnit checkfn) { 509 EndOfTranslationUnitCheckers.push_back(checkfn); 510 } 511 512 //===----------------------------------------------------------------------===// 513 // Implementation details. 514 //===----------------------------------------------------------------------===// 515 516 CheckerManager::CachedStmtCheckers * 517 CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 518 assert(S); 519 520 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 521 CachedStmtCheckers *checkers = 0; 522 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 523 if (CCI != CachedStmtCheckersMap.end()) { 524 checkers = &(CCI->second); 525 } else { 526 // Find the checkers that should run for this Stmt and cache them. 527 checkers = &CachedStmtCheckersMap[key]; 528 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 529 StmtCheckerInfo &info = StmtCheckers[i]; 530 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 531 checkers->push_back(info.CheckFn); 532 } 533 } 534 535 assert(checkers); 536 return checkers; 537 } 538 539 CheckerManager::~CheckerManager() { 540 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 541 CheckerDtors[i](); 542 } 543 544 // Anchor for the vtable. 545 CheckerProvider::~CheckerProvider() { } 546 547 // Anchor for the vtable. 548 GraphExpander::~GraphExpander() { } 549