CheckerManager.cpp revision 9be6e7ce5788e50c62d40c59b0bbc2ea423683f7
1436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===// 2436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// 3436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// The LLVM Compiler Infrastructure 4436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// 5436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// This file is distributed under the University of Illinois Open Source 6436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// License. See LICENSE.TXT for details. 7436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// 8436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 9436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// 10436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Defines the Static Analyzer Checker Manager. 11436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// 12436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 13436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 14436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "clang/StaticAnalyzer/Core/CheckerProvider.h" 16436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 17436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "clang/Analysis/ProgramPoint.h" 18436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#include "clang/AST/DeclBase.h" 19436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 20436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovusing namespace clang; 21436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovusing namespace ento; 22436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 23436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovbool CheckerManager::hasPathSensitiveCheckers() const { 24436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return !StmtCheckers.empty() || 25436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !PreObjCMessageCheckers.empty() || 26436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !PostObjCMessageCheckers.empty() || 27436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !LocationCheckers.empty() || 28436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !BindCheckers.empty() || 29436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !EndAnalysisCheckers.empty() || 30436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !EndPathCheckers.empty() || 31436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !BranchConditionCheckers.empty() || 32436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !LiveSymbolsCheckers.empty() || 33436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !DeadSymbolsCheckers.empty() || 34436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !RegionChangesCheckers.empty() || 35436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !EvalAssumeCheckers.empty() || 36436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov !EvalCallCheckers.empty(); 37436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 38436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 39436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::finishedCheckerRegistration() { 40436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#ifndef NDEBUG 41436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Make sure that for every event that has listeners, there is at least 42436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // one dispatcher registered for it. 43436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (llvm::DenseMap<EventTag, EventInfo>::iterator 44436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov I = Events.begin(), E = Events.end(); I != E; ++I) 45436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 46436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif 47436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 48436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 49436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 50436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Functions for running checkers for AST traversing.. 51436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 52436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 53436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 54436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BugReporter &BR) { 55436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(D); 56436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 57436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov unsigned DeclKind = D->getKind(); 58436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CachedDeclCheckers *checkers = 0; 59436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 60436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (CCI != CachedDeclCheckersMap.end()) { 61436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkers = &(CCI->second); 62436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 63436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Find the checkers that should run for this Decl and cache them. 64436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkers = &CachedDeclCheckersMap[DeclKind]; 65436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 66436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DeclCheckerInfo &info = DeclCheckers[i]; 67436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (info.IsForDeclFn(D)) 68436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkers->push_back(info.CheckFn); 69436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 70436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 71436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 72436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(checkers); 73436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (CachedDeclCheckers::iterator 74436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov I = checkers->begin(), E = checkers->end(); I != E; ++I) 75436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov (*I)(D, mgr, BR); 76436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 77436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 78436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 79436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BugReporter &BR) { 80436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(D && D->hasBody()); 81436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 82436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 83436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BodyCheckers[i](D, mgr, BR); 84436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 85436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 86436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 87436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Functions for running checkers for path-sensitive checking. 88436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 89436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 90436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovtemplate <typename CHECK_CTX> 91436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovstatic void expandGraphWithCheckers(CHECK_CTX checkCtx, 92436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet &Dst, 93436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ExplodedNodeSet &Src) { 94436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 95436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov typename CHECK_CTX::CheckersTy::const_iterator 96436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 97436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (I == E) { 98436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Dst.insert(Src); 99436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 100436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 101436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 102436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet Tmp1, Tmp2; 103436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ExplodedNodeSet *PrevSet = &Src; 104436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 105436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (; I != E; ++I) { 106436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet *CurrSet = 0; 107436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (I+1 == E) 108436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CurrSet = &Dst; 109436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else { 110436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 111436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CurrSet->clear(); 112436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 113436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 114436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 115436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov NI != NE; ++NI) 116436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkCtx.runChecker(*I, *CurrSet, *NI); 117436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 118436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Update which NodeSet is the current one. 119436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov PrevSet = CurrSet; 120436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 121436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 122436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 123436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovnamespace { 124436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct CheckStmtContext { 125436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 126436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov bool IsPreVisit; 127436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const CheckersTy &Checkers; 128436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *S; 129436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng; 130436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 131436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 132436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 133436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 134436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 135436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *s, ExprEngine &eng) 136436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { } 137436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 138436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov void runChecker(CheckerManager::CheckStmtFunc checkFn, 139436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet &Dst, ExplodedNode *Pred) { 140436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // FIXME: Remove respondsToCallback from CheckerContext; 141436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 142436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IsPreVisit ? ProgramPoint::PreStmtKind : 143436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ProgramPoint::PostStmtKind, 0, S); 144436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkFn(S, C); 145436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 146436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov }; 147436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 148436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 149436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for visiting Stmts. 150436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForStmt(bool isPreVisit, 151436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet &Dst, 152436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ExplodedNodeSet &Src, 153436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *S, 154436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng) { 155436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 156436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov S, Eng); 157436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov expandGraphWithCheckers(C, Dst, Src); 158436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 159436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 160436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovnamespace { 161436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct CheckObjCMessageContext { 162436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 163436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov bool IsPreVisit; 164436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const CheckersTy &Checkers; 165436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ObjCMessage &Msg; 166436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng; 167436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 168436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 169436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 170436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 171436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 172436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ObjCMessage &msg, ExprEngine &eng) 173436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 174436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 175436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 176436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet &Dst, ExplodedNode *Pred) { 177436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 178436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IsPreVisit ? ProgramPoint::PreStmtKind : 179436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ProgramPoint::PostStmtKind, 0, 180436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Msg.getOriginExpr()); 181436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkFn(Msg, C); 182436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 183436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov }; 184436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 185436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 186436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for visiting obj-c messages. 187436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 188436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet &Dst, 189436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ExplodedNodeSet &Src, 190436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ObjCMessage &msg, 191436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng) { 192436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckObjCMessageContext C(isPreVisit, 193436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov isPreVisit ? PreObjCMessageCheckers 194436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : PostObjCMessageCheckers, 195436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov msg, Eng); 196436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov expandGraphWithCheckers(C, Dst, Src); 197436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 198436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 199436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovnamespace { 200436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct CheckLocationContext { 201436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 202436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const CheckersTy &Checkers; 203436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SVal Loc; 204436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov bool IsLoad; 205436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *S; 206436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng; 207436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 208436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 209436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 210436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 211436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckLocationContext(const CheckersTy &checkers, 212436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) 213436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } 214436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 215436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov void runChecker(CheckerManager::CheckLocationFunc checkFn, 216436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet &Dst, ExplodedNode *Pred) { 217436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 218436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov IsLoad ? ProgramPoint::PreLoadKind : 219436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ProgramPoint::PreStoreKind, 0, S); 220436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkFn(Loc, IsLoad, C); 221436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 222436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov }; 223436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 224436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 225436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for load/store of a location. 226436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 227436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ExplodedNodeSet &Src, 228436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SVal location, bool isLoad, 229436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *S, ExprEngine &Eng) { 230436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); 231436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov expandGraphWithCheckers(C, Dst, Src); 232436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 233436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 234436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovnamespace { 235436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct CheckBindContext { 236436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 237436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const CheckersTy &Checkers; 238436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SVal Loc; 239436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SVal Val; 240436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *S; 241436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng; 242436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 243436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 244436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 245436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 246436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckBindContext(const CheckersTy &checkers, 247436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SVal loc, SVal val, const Stmt *s, ExprEngine &eng) 248436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { } 249436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 250436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov void runChecker(CheckerManager::CheckBindFunc checkFn, 251436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet &Dst, ExplodedNode *Pred) { 252436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 253436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ProgramPoint::PreStmtKind, 0, S); 254436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkFn(Loc, Val, C); 255436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 256436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov }; 257436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 258436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 259436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for binding of a value to a location. 260436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 261436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ExplodedNodeSet &Src, 262436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SVal location, SVal val, 263436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *S, ExprEngine &Eng) { 264436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckBindContext C(BindCheckers, location, val, S, Eng); 265436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov expandGraphWithCheckers(C, Dst, Src); 266436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 267436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 268436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 269436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BugReporter &BR, 270436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng) { 271436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 272436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EndAnalysisCheckers[i](G, BR, Eng); 273436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 274436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 275436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for end of path. 276436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B, 277436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng) { 278436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 279436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckEndPathFunc fn = EndPathCheckers[i]; 280436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker); 281436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fn(specialB, Eng); 282436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 283436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 284436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 285436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for branch condition. 286436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForBranchCondition(const Stmt *condition, 287436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BranchNodeBuilder &B, 288436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng) { 289436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) { 290436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckBranchConditionFunc fn = BranchConditionCheckers[i]; 291436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov fn(condition, B, Eng); 292436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 293436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 294436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 295436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for live symbols. 296436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForLiveSymbols(const GRState *state, 297436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SymbolReaper &SymReaper) { 298436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 299436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov LiveSymbolsCheckers[i](state, SymReaper); 300436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 301436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 302436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovnamespace { 303436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov struct CheckDeadSymbolsContext { 304436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 305436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const CheckersTy &Checkers; 306436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SymbolReaper &SR; 307436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *S; 308436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng; 309436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 310436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 311436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 312436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 313436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 314436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *s, ExprEngine &eng) 315436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov : Checkers(checkers), SR(sr), S(s), Eng(eng) { } 316436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 317436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 318436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet &Dst, ExplodedNode *Pred) { 319436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 320436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); 321436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkFn(SR, C); 322436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 323436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov }; 324436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 325436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 326436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for dead symbols. 327436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 328436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ExplodedNodeSet &Src, 329436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SymbolReaper &SymReaper, 330436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const Stmt *S, 331436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng) { 332436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); 333436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov expandGraphWithCheckers(C, Dst, Src); 334436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 335436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 336436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief True if at least one checker wants to check region changes. 337436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovbool CheckerManager::wantsRegionChangeUpdate(const GRState *state) { 338436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 339436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (RegionChangesCheckers[i].WantUpdateFn(state)) 340436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return true; 341436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 342436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return false; 343436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 344436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 345436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for region changes. 346436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovconst GRState * 347436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovCheckerManager::runCheckersForRegionChanges(const GRState *state, 348436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const StoreManager::InvalidatedSymbols *invalidated, 349436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const MemRegion * const *Begin, 350436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const MemRegion * const *End) { 351436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 352436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // If any checker declares the state infeasible (or if it starts that way), 353436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // bail out. 354436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!state) 355436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 356436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End); 357436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 358436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return state; 359436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 360436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 361436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for handling assumptions on symbolic values. 362436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovconst GRState * 363436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovCheckerManager::runCheckersForEvalAssume(const GRState *state, 364436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov SVal Cond, bool Assumption) { 365436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 366436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // If any checker declares the state infeasible (or if it starts that way), 367436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // bail out. 368436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!state) 369436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return NULL; 370436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov state = EvalAssumeCheckers[i](state, Cond, Assumption); 371436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 372436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return state; 373436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 374436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 375436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for evaluating a call. 376436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// Only one checker will evaluate the call. 377436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 378436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const ExplodedNodeSet &Src, 379436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const CallExpr *CE, 380436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExprEngine &Eng, 381436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov GraphExpander *defaultEval) { 382436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (EvalCallCheckers.empty() && defaultEval == 0) { 383436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Dst.insert(Src); 384436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return; 385436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 386436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 387436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (ExplodedNodeSet::iterator 388436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 389436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 390436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNode *Pred = *NI; 391436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov bool anyEvaluated = false; 392436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (std::vector<EvalCallFunc>::iterator 393436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 394436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EI != EE; ++EI) { 395436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ExplodedNodeSet checkDst; 396436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker, 397436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov ProgramPoint::PostStmtKind, 0, CE); 398436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov bool evaluated = (*EI)(CE, C); 399436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(!(evaluated && anyEvaluated) 400436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov && "There are more than one checkers evaluating the call"); 401436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (evaluated) { 402436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov anyEvaluated = true; 403436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Dst.insert(checkDst); 404436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#ifdef NDEBUG 405436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov break; // on release don't check that no other checker also evals. 406436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov#endif 407436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 408436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 409436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 410436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (!anyEvaluated) { 411436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (defaultEval) 412436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov defaultEval->expandGraph(Dst, Pred); 413436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov else 414436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov Dst.insert(Pred); 415436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 416436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 417436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 418436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 419436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov/// \brief Run checkers for the entire Translation Unit. 420436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::runCheckersOnEndOfTranslationUnit( 421436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov const TranslationUnitDecl *TU, 422436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov AnalysisManager &mgr, 423436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BugReporter &BR) { 424436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 425436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EndOfTranslationUnitCheckers[i](TU, mgr, BR); 426436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 427436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 428436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 429436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Internal registration functions for AST traversing. 430436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 431436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 432436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 433436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HandlesDeclFunc isForDeclFn) { 434436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DeclCheckerInfo info = { checkfn, isForDeclFn }; 435436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DeclCheckers.push_back(info); 436436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 437436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 438436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 439436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BodyCheckers.push_back(checkfn); 440436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 441436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 442436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 443436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Internal registration functions for path-sensitive checking. 444436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 445436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 446436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 447436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HandlesStmtFunc isForStmtFn) { 448436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 449436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov StmtCheckers.push_back(info); 450436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 451436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 452436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov HandlesStmtFunc isForStmtFn) { 453436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 454436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov StmtCheckers.push_back(info); 455436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 456436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 457436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 458436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov PreObjCMessageCheckers.push_back(checkfn); 459436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 460436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 461436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov PostObjCMessageCheckers.push_back(checkfn); 462436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 463436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 464436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 465436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov LocationCheckers.push_back(checkfn); 466436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 467436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 468436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForBind(CheckBindFunc checkfn) { 469436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BindCheckers.push_back(checkfn); 470436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 471436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 472436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 473436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EndAnalysisCheckers.push_back(checkfn); 474436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 475436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 476436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 477436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EndPathCheckers.push_back(checkfn); 478436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 479436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 480436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForBranchCondition( 481436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckBranchConditionFunc checkfn) { 482436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov BranchConditionCheckers.push_back(checkfn); 483436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 484436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 485436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 486436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov LiveSymbolsCheckers.push_back(checkfn); 487436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 488436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 489436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 490436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov DeadSymbolsCheckers.push_back(checkfn); 491436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 492436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 493436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 494436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov WantsRegionChangeUpdateFunc wantUpdateFn) { 495436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 496436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov RegionChangesCheckers.push_back(info); 497436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 498436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 499436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 500436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EvalAssumeCheckers.push_back(checkfn); 501436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 502436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 503436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 504436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EvalCallCheckers.push_back(checkfn); 505436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 506436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 507436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanovvoid CheckerManager::_registerForEndOfTranslationUnit( 508436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckEndOfTranslationUnit checkfn) { 509436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov EndOfTranslationUnitCheckers.push_back(checkfn); 510436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 511436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 512436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 513436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Implementation details. 514436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov//===----------------------------------------------------------------------===// 515436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 516436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovCheckerManager::CachedStmtCheckers * 517436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovCheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 518436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(S); 519436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 520436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 521436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CachedStmtCheckers *checkers = 0; 522436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 523436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (CCI != CachedStmtCheckersMap.end()) { 524436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkers = &(CCI->second); 525436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } else { 526436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov // Find the checkers that should run for this Stmt and cache them. 527436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkers = &CachedStmtCheckersMap[key]; 528436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 529436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov StmtCheckerInfo &info = StmtCheckers[i]; 530436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 531436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov checkers->push_back(info.CheckFn); 532436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 533436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov } 534436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 535436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov assert(checkers); 536436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov return checkers; 537436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 538436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 539436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovCheckerManager::~CheckerManager() { 540436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 541436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov CheckerDtors[i](); 542436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov} 543436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 544436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Anchor for the vtable. 545436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovCheckerProvider::~CheckerProvider() { } 546436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov 547436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov// Anchor for the vtable. 548436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy IvanovGraphExpander::~GraphExpander() { } 549436e89c602e787e7a27dd6624b09beed41a0da8aDmitriy Ivanov