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