clang API Documentation
00001 //===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // Defines the Static Analyzer Checker Manager. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/StaticAnalyzer/Core/CheckerManager.h" 00015 #include "clang/StaticAnalyzer/Core/Checker.h" 00016 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 00017 #include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 00018 #include "clang/Analysis/ProgramPoint.h" 00019 #include "clang/AST/DeclBase.h" 00020 00021 using namespace clang; 00022 using namespace ento; 00023 00024 bool CheckerManager::hasPathSensitiveCheckers() const { 00025 return !StmtCheckers.empty() || 00026 !PreObjCMessageCheckers.empty() || 00027 !PostObjCMessageCheckers.empty() || 00028 !LocationCheckers.empty() || 00029 !BindCheckers.empty() || 00030 !EndAnalysisCheckers.empty() || 00031 !EndPathCheckers.empty() || 00032 !BranchConditionCheckers.empty() || 00033 !LiveSymbolsCheckers.empty() || 00034 !DeadSymbolsCheckers.empty() || 00035 !RegionChangesCheckers.empty() || 00036 !EvalAssumeCheckers.empty() || 00037 !EvalCallCheckers.empty() || 00038 !InlineCallCheckers.empty(); 00039 } 00040 00041 void CheckerManager::finishedCheckerRegistration() { 00042 #ifndef NDEBUG 00043 // Make sure that for every event that has listeners, there is at least 00044 // one dispatcher registered for it. 00045 for (llvm::DenseMap<EventTag, EventInfo>::iterator 00046 I = Events.begin(), E = Events.end(); I != E; ++I) 00047 assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 00048 #endif 00049 } 00050 00051 //===----------------------------------------------------------------------===// 00052 // Functions for running checkers for AST traversing.. 00053 //===----------------------------------------------------------------------===// 00054 00055 void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 00056 BugReporter &BR) { 00057 assert(D); 00058 00059 unsigned DeclKind = D->getKind(); 00060 CachedDeclCheckers *checkers = 0; 00061 CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 00062 if (CCI != CachedDeclCheckersMap.end()) { 00063 checkers = &(CCI->second); 00064 } else { 00065 // Find the checkers that should run for this Decl and cache them. 00066 checkers = &CachedDeclCheckersMap[DeclKind]; 00067 for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 00068 DeclCheckerInfo &info = DeclCheckers[i]; 00069 if (info.IsForDeclFn(D)) 00070 checkers->push_back(info.CheckFn); 00071 } 00072 } 00073 00074 assert(checkers); 00075 for (CachedDeclCheckers::iterator 00076 I = checkers->begin(), E = checkers->end(); I != E; ++I) 00077 (*I)(D, mgr, BR); 00078 } 00079 00080 void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 00081 BugReporter &BR) { 00082 assert(D && D->hasBody()); 00083 00084 for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 00085 BodyCheckers[i](D, mgr, BR); 00086 } 00087 00088 //===----------------------------------------------------------------------===// 00089 // Functions for running checkers for path-sensitive checking. 00090 //===----------------------------------------------------------------------===// 00091 00092 template <typename CHECK_CTX> 00093 static void expandGraphWithCheckers(CHECK_CTX checkCtx, 00094 ExplodedNodeSet &Dst, 00095 const ExplodedNodeSet &Src) { 00096 const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext(); 00097 if (Src.empty()) 00098 return; 00099 00100 typename CHECK_CTX::CheckersTy::const_iterator 00101 I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 00102 if (I == E) { 00103 Dst.insert(Src); 00104 return; 00105 } 00106 00107 ExplodedNodeSet Tmp1, Tmp2; 00108 const ExplodedNodeSet *PrevSet = &Src; 00109 00110 for (; I != E; ++I) { 00111 ExplodedNodeSet *CurrSet = 0; 00112 if (I+1 == E) 00113 CurrSet = &Dst; 00114 else { 00115 CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 00116 CurrSet->clear(); 00117 } 00118 00119 NodeBuilder B(*PrevSet, *CurrSet, BldrCtx); 00120 for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 00121 NI != NE; ++NI) { 00122 checkCtx.runChecker(*I, B, *NI); 00123 } 00124 00125 // If all the produced transitions are sinks, stop. 00126 if (CurrSet->empty()) 00127 return; 00128 00129 // Update which NodeSet is the current one. 00130 PrevSet = CurrSet; 00131 } 00132 } 00133 00134 namespace { 00135 struct CheckStmtContext { 00136 typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 00137 bool IsPreVisit; 00138 const CheckersTy &Checkers; 00139 const Stmt *S; 00140 ExprEngine &Eng; 00141 bool wasInlined; 00142 00143 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 00144 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 00145 00146 CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 00147 const Stmt *s, ExprEngine &eng, bool wasInlined = false) 00148 : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng), 00149 wasInlined(wasInlined) {} 00150 00151 void runChecker(CheckerManager::CheckStmtFunc checkFn, 00152 NodeBuilder &Bldr, ExplodedNode *Pred) { 00153 // FIXME: Remove respondsToCallback from CheckerContext; 00154 ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 00155 ProgramPoint::PostStmtKind; 00156 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 00157 Pred->getLocationContext(), checkFn.Checker); 00158 CheckerContext C(Bldr, Eng, Pred, L, wasInlined); 00159 checkFn(S, C); 00160 } 00161 }; 00162 } 00163 00164 /// \brief Run checkers for visiting Stmts. 00165 void CheckerManager::runCheckersForStmt(bool isPreVisit, 00166 ExplodedNodeSet &Dst, 00167 const ExplodedNodeSet &Src, 00168 const Stmt *S, 00169 ExprEngine &Eng, 00170 bool wasInlined) { 00171 CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 00172 S, Eng, wasInlined); 00173 expandGraphWithCheckers(C, Dst, Src); 00174 } 00175 00176 namespace { 00177 struct CheckObjCMessageContext { 00178 typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 00179 bool IsPreVisit; 00180 const CheckersTy &Checkers; 00181 const ObjCMessage &Msg; 00182 ExprEngine &Eng; 00183 00184 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 00185 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 00186 00187 CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 00188 const ObjCMessage &msg, ExprEngine &eng) 00189 : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 00190 00191 void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 00192 NodeBuilder &Bldr, ExplodedNode *Pred) { 00193 ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 00194 ProgramPoint::PostStmtKind; 00195 const ProgramPoint &L = 00196 ProgramPoint::getProgramPoint(Msg.getMessageExpr(), 00197 K, Pred->getLocationContext(), 00198 checkFn.Checker); 00199 CheckerContext C(Bldr, Eng, Pred, L); 00200 00201 checkFn(Msg, C); 00202 } 00203 }; 00204 } 00205 00206 /// \brief Run checkers for visiting obj-c messages. 00207 void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 00208 ExplodedNodeSet &Dst, 00209 const ExplodedNodeSet &Src, 00210 const ObjCMessage &msg, 00211 ExprEngine &Eng) { 00212 CheckObjCMessageContext C(isPreVisit, 00213 isPreVisit ? PreObjCMessageCheckers 00214 : PostObjCMessageCheckers, 00215 msg, Eng); 00216 expandGraphWithCheckers(C, Dst, Src); 00217 } 00218 00219 namespace { 00220 struct CheckLocationContext { 00221 typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 00222 const CheckersTy &Checkers; 00223 SVal Loc; 00224 bool IsLoad; 00225 const Stmt *NodeEx; /* Will become a CFGStmt */ 00226 const Stmt *BoundEx; 00227 ExprEngine &Eng; 00228 00229 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 00230 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 00231 00232 CheckLocationContext(const CheckersTy &checkers, 00233 SVal loc, bool isLoad, const Stmt *NodeEx, 00234 const Stmt *BoundEx, 00235 ExprEngine &eng) 00236 : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx), 00237 BoundEx(BoundEx), Eng(eng) {} 00238 00239 void runChecker(CheckerManager::CheckLocationFunc checkFn, 00240 NodeBuilder &Bldr, ExplodedNode *Pred) { 00241 ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind : 00242 ProgramPoint::PreStoreKind; 00243 const ProgramPoint &L = 00244 ProgramPoint::getProgramPoint(NodeEx, K, 00245 Pred->getLocationContext(), 00246 checkFn.Checker); 00247 CheckerContext C(Bldr, Eng, Pred, L); 00248 checkFn(Loc, IsLoad, BoundEx, C); 00249 } 00250 }; 00251 } 00252 00253 /// \brief Run checkers for load/store of a location. 00254 00255 void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 00256 const ExplodedNodeSet &Src, 00257 SVal location, bool isLoad, 00258 const Stmt *NodeEx, 00259 const Stmt *BoundEx, 00260 ExprEngine &Eng) { 00261 CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx, 00262 BoundEx, Eng); 00263 expandGraphWithCheckers(C, Dst, Src); 00264 } 00265 00266 namespace { 00267 struct CheckBindContext { 00268 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 00269 const CheckersTy &Checkers; 00270 SVal Loc; 00271 SVal Val; 00272 const Stmt *S; 00273 ExprEngine &Eng; 00274 ProgramPoint::Kind PointKind; 00275 00276 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 00277 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 00278 00279 CheckBindContext(const CheckersTy &checkers, 00280 SVal loc, SVal val, const Stmt *s, ExprEngine &eng, 00281 ProgramPoint::Kind PK) 00282 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {} 00283 00284 void runChecker(CheckerManager::CheckBindFunc checkFn, 00285 NodeBuilder &Bldr, ExplodedNode *Pred) { 00286 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind, 00287 Pred->getLocationContext(), checkFn.Checker); 00288 CheckerContext C(Bldr, Eng, Pred, L); 00289 00290 checkFn(Loc, Val, S, C); 00291 } 00292 }; 00293 } 00294 00295 /// \brief Run checkers for binding of a value to a location. 00296 void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 00297 const ExplodedNodeSet &Src, 00298 SVal location, SVal val, 00299 const Stmt *S, ExprEngine &Eng, 00300 ProgramPoint::Kind PointKind) { 00301 CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind); 00302 expandGraphWithCheckers(C, Dst, Src); 00303 } 00304 00305 void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 00306 BugReporter &BR, 00307 ExprEngine &Eng) { 00308 for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 00309 EndAnalysisCheckers[i](G, BR, Eng); 00310 } 00311 00312 /// \brief Run checkers for end of path. 00313 // Note, We do not chain the checker output (like in expandGraphWithCheckers) 00314 // for this callback since end of path nodes are expected to be final. 00315 void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC, 00316 ExplodedNodeSet &Dst, 00317 ExprEngine &Eng) { 00318 ExplodedNode *Pred = BC.Pred; 00319 00320 // We define the builder outside of the loop bacause if at least one checkers 00321 // creates a sucsessor for Pred, we do not need to generate an 00322 // autotransition for it. 00323 NodeBuilder Bldr(Pred, Dst, BC); 00324 for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 00325 CheckEndPathFunc checkFn = EndPathCheckers[i]; 00326 00327 const ProgramPoint &L = BlockEntrance(BC.Block, 00328 Pred->getLocationContext(), 00329 checkFn.Checker); 00330 CheckerContext C(Bldr, Eng, Pred, L); 00331 checkFn(C); 00332 } 00333 } 00334 00335 namespace { 00336 struct CheckBranchConditionContext { 00337 typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy; 00338 const CheckersTy &Checkers; 00339 const Stmt *Condition; 00340 ExprEngine &Eng; 00341 00342 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 00343 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 00344 00345 CheckBranchConditionContext(const CheckersTy &checkers, 00346 const Stmt *Cond, ExprEngine &eng) 00347 : Checkers(checkers), Condition(Cond), Eng(eng) {} 00348 00349 void runChecker(CheckerManager::CheckBranchConditionFunc checkFn, 00350 NodeBuilder &Bldr, ExplodedNode *Pred) { 00351 ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(), 00352 checkFn.Checker); 00353 CheckerContext C(Bldr, Eng, Pred, L); 00354 checkFn(Condition, C); 00355 } 00356 }; 00357 } 00358 00359 /// \brief Run checkers for branch condition. 00360 void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition, 00361 ExplodedNodeSet &Dst, 00362 ExplodedNode *Pred, 00363 ExprEngine &Eng) { 00364 ExplodedNodeSet Src; 00365 Src.insert(Pred); 00366 CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng); 00367 expandGraphWithCheckers(C, Dst, Src); 00368 } 00369 00370 /// \brief Run checkers for live symbols. 00371 void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state, 00372 SymbolReaper &SymReaper) { 00373 for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 00374 LiveSymbolsCheckers[i](state, SymReaper); 00375 } 00376 00377 namespace { 00378 struct CheckDeadSymbolsContext { 00379 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 00380 const CheckersTy &Checkers; 00381 SymbolReaper &SR; 00382 const Stmt *S; 00383 ExprEngine &Eng; 00384 ProgramPoint::Kind ProgarmPointKind; 00385 00386 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 00387 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 00388 00389 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 00390 const Stmt *s, ExprEngine &eng, 00391 ProgramPoint::Kind K) 00392 : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { } 00393 00394 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 00395 NodeBuilder &Bldr, ExplodedNode *Pred) { 00396 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind, 00397 Pred->getLocationContext(), checkFn.Checker); 00398 CheckerContext C(Bldr, Eng, Pred, L); 00399 00400 // Note, do not pass the statement to the checkers without letting them 00401 // differentiate if we ran remove dead bindings before or after the 00402 // statement. 00403 checkFn(SR, C); 00404 } 00405 }; 00406 } 00407 00408 /// \brief Run checkers for dead symbols. 00409 void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 00410 const ExplodedNodeSet &Src, 00411 SymbolReaper &SymReaper, 00412 const Stmt *S, 00413 ExprEngine &Eng, 00414 ProgramPoint::Kind K) { 00415 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K); 00416 expandGraphWithCheckers(C, Dst, Src); 00417 } 00418 00419 /// \brief True if at least one checker wants to check region changes. 00420 bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) { 00421 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 00422 if (RegionChangesCheckers[i].WantUpdateFn(state)) 00423 return true; 00424 00425 return false; 00426 } 00427 00428 /// \brief Run checkers for region changes. 00429 ProgramStateRef 00430 CheckerManager::runCheckersForRegionChanges(ProgramStateRef state, 00431 const StoreManager::InvalidatedSymbols *invalidated, 00432 ArrayRef<const MemRegion *> ExplicitRegions, 00433 ArrayRef<const MemRegion *> Regions, 00434 const CallOrObjCMessage *Call) { 00435 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 00436 // If any checker declares the state infeasible (or if it starts that way), 00437 // bail out. 00438 if (!state) 00439 return NULL; 00440 state = RegionChangesCheckers[i].CheckFn(state, invalidated, 00441 ExplicitRegions, Regions, Call); 00442 } 00443 return state; 00444 } 00445 00446 /// \brief Run checkers for handling assumptions on symbolic values. 00447 ProgramStateRef 00448 CheckerManager::runCheckersForEvalAssume(ProgramStateRef state, 00449 SVal Cond, bool Assumption) { 00450 for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 00451 // If any checker declares the state infeasible (or if it starts that way), 00452 // bail out. 00453 if (!state) 00454 return NULL; 00455 state = EvalAssumeCheckers[i](state, Cond, Assumption); 00456 } 00457 return state; 00458 } 00459 00460 /// \brief Run checkers for evaluating a call. 00461 /// Only one checker will evaluate the call. 00462 void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 00463 const ExplodedNodeSet &Src, 00464 const CallExpr *CE, 00465 ExprEngine &Eng, 00466 GraphExpander *defaultEval) { 00467 if (EvalCallCheckers.empty() && 00468 InlineCallCheckers.empty() && 00469 defaultEval == 0) { 00470 Dst.insert(Src); 00471 return; 00472 } 00473 00474 for (ExplodedNodeSet::iterator 00475 NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 00476 00477 ExplodedNode *Pred = *NI; 00478 bool anyEvaluated = false; 00479 00480 // First, check if any of the InlineCall callbacks can evaluate the call. 00481 assert(InlineCallCheckers.size() <= 1 && 00482 "InlineCall is a special hacky callback to allow intrusive" 00483 "evaluation of the call (which simulates inlining). It is " 00484 "currently only used by OSAtomicChecker and should go away " 00485 "at some point."); 00486 for (std::vector<InlineCallFunc>::iterator 00487 EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end(); 00488 EI != EE; ++EI) { 00489 ExplodedNodeSet checkDst; 00490 bool evaluated = (*EI)(CE, Eng, Pred, checkDst); 00491 assert(!(evaluated && anyEvaluated) 00492 && "There are more than one checkers evaluating the call"); 00493 if (evaluated) { 00494 anyEvaluated = true; 00495 Dst.insert(checkDst); 00496 #ifdef NDEBUG 00497 break; // on release don't check that no other checker also evals. 00498 #endif 00499 } 00500 } 00501 00502 #ifdef NDEBUG // on release don't check that no other checker also evals. 00503 if (anyEvaluated) { 00504 break; 00505 } 00506 #endif 00507 00508 ExplodedNodeSet checkDst; 00509 NodeBuilder B(Pred, checkDst, Eng.getBuilderContext()); 00510 // Next, check if any of the EvalCall callbacks can evaluate the call. 00511 for (std::vector<EvalCallFunc>::iterator 00512 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 00513 EI != EE; ++EI) { 00514 ProgramPoint::Kind K = ProgramPoint::PostStmtKind; 00515 const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K, 00516 Pred->getLocationContext(), EI->Checker); 00517 bool evaluated = false; 00518 { // CheckerContext generates transitions(populates checkDest) on 00519 // destruction, so introduce the scope to make sure it gets properly 00520 // populated. 00521 CheckerContext C(B, Eng, Pred, L); 00522 evaluated = (*EI)(CE, C); 00523 } 00524 assert(!(evaluated && anyEvaluated) 00525 && "There are more than one checkers evaluating the call"); 00526 if (evaluated) { 00527 anyEvaluated = true; 00528 Dst.insert(checkDst); 00529 #ifdef NDEBUG 00530 break; // on release don't check that no other checker also evals. 00531 #endif 00532 } 00533 } 00534 00535 // If none of the checkers evaluated the call, ask ExprEngine to handle it. 00536 if (!anyEvaluated) { 00537 if (defaultEval) 00538 defaultEval->expandGraph(Dst, Pred); 00539 else 00540 Dst.insert(Pred); 00541 } 00542 } 00543 } 00544 00545 /// \brief Run checkers for the entire Translation Unit. 00546 void CheckerManager::runCheckersOnEndOfTranslationUnit( 00547 const TranslationUnitDecl *TU, 00548 AnalysisManager &mgr, 00549 BugReporter &BR) { 00550 for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 00551 EndOfTranslationUnitCheckers[i](TU, mgr, BR); 00552 } 00553 00554 void CheckerManager::runCheckersForPrintState(raw_ostream &Out, 00555 ProgramStateRef State, 00556 const char *NL, const char *Sep) { 00557 for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator 00558 I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I) 00559 I->second->printState(Out, State, NL, Sep); 00560 } 00561 00562 //===----------------------------------------------------------------------===// 00563 // Internal registration functions for AST traversing. 00564 //===----------------------------------------------------------------------===// 00565 00566 void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 00567 HandlesDeclFunc isForDeclFn) { 00568 DeclCheckerInfo info = { checkfn, isForDeclFn }; 00569 DeclCheckers.push_back(info); 00570 } 00571 00572 void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 00573 BodyCheckers.push_back(checkfn); 00574 } 00575 00576 //===----------------------------------------------------------------------===// 00577 // Internal registration functions for path-sensitive checking. 00578 //===----------------------------------------------------------------------===// 00579 00580 void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 00581 HandlesStmtFunc isForStmtFn) { 00582 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 00583 StmtCheckers.push_back(info); 00584 } 00585 void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 00586 HandlesStmtFunc isForStmtFn) { 00587 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 00588 StmtCheckers.push_back(info); 00589 } 00590 00591 void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 00592 PreObjCMessageCheckers.push_back(checkfn); 00593 } 00594 void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 00595 PostObjCMessageCheckers.push_back(checkfn); 00596 } 00597 00598 void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 00599 LocationCheckers.push_back(checkfn); 00600 } 00601 00602 void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 00603 BindCheckers.push_back(checkfn); 00604 } 00605 00606 void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 00607 EndAnalysisCheckers.push_back(checkfn); 00608 } 00609 00610 void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 00611 EndPathCheckers.push_back(checkfn); 00612 } 00613 00614 void CheckerManager::_registerForBranchCondition( 00615 CheckBranchConditionFunc checkfn) { 00616 BranchConditionCheckers.push_back(checkfn); 00617 } 00618 00619 void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 00620 LiveSymbolsCheckers.push_back(checkfn); 00621 } 00622 00623 void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 00624 DeadSymbolsCheckers.push_back(checkfn); 00625 } 00626 00627 void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 00628 WantsRegionChangeUpdateFunc wantUpdateFn) { 00629 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 00630 RegionChangesCheckers.push_back(info); 00631 } 00632 00633 void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 00634 EvalAssumeCheckers.push_back(checkfn); 00635 } 00636 00637 void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 00638 EvalCallCheckers.push_back(checkfn); 00639 } 00640 00641 void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) { 00642 InlineCallCheckers.push_back(checkfn); 00643 } 00644 00645 void CheckerManager::_registerForEndOfTranslationUnit( 00646 CheckEndOfTranslationUnit checkfn) { 00647 EndOfTranslationUnitCheckers.push_back(checkfn); 00648 } 00649 00650 //===----------------------------------------------------------------------===// 00651 // Implementation details. 00652 //===----------------------------------------------------------------------===// 00653 00654 CheckerManager::CachedStmtCheckers * 00655 CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 00656 assert(S); 00657 00658 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 00659 CachedStmtCheckers *checkers = 0; 00660 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 00661 if (CCI != CachedStmtCheckersMap.end()) { 00662 checkers = &(CCI->second); 00663 } else { 00664 // Find the checkers that should run for this Stmt and cache them. 00665 checkers = &CachedStmtCheckersMap[key]; 00666 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 00667 StmtCheckerInfo &info = StmtCheckers[i]; 00668 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 00669 checkers->push_back(info.CheckFn); 00670 } 00671 } 00672 00673 assert(checkers); 00674 return checkers; 00675 } 00676 00677 CheckerManager::~CheckerManager() { 00678 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 00679 CheckerDtors[i](); 00680 } 00681 00682 // Anchor for the vtable. 00683 GraphExpander::~GraphExpander() { }