CheckerManager.cpp revision deb6447d0029bdb122397fafb5fa2a4e76f2e555
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch//===----------------------------------------------------------------------===// 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Defines the Static Analyzer Checker Manager. 119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerProvider.h" 169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Analysis/ProgramPoint.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/DeclBase.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::finishedCheckerRegistration() { 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that for every event that has listeners, there is at least 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one dispatcher registered for it. 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (llvm::DenseMap<EventTag, EventInfo>::iterator 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = Events.begin(), E = Events.end(); I != E; ++I) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions for running checkers for AST traversing.. 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) BugReporter &BR) { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(D); 407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) unsigned DeclKind = D->getKind(); 427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CachedDeclCheckers *checkers = 0; 437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (CCI != CachedDeclCheckersMap.end()) { 457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) checkers = &(CCI->second); 467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // Find the checkers that should run for this Decl and cache them. 487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) checkers = &CachedDeclCheckersMap[DeclKind]; 497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DeclCheckerInfo &info = DeclCheckers[i]; 517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (info.IsForDeclFn(D)) 527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) checkers->push_back(info.CheckFn); 537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) assert(checkers); 577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (CachedDeclCheckers::iterator 587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) I = checkers->begin(), E = checkers->end(); I != E; ++I) 597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) (*I)(D, mgr, BR); 607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)} 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BugReporter &BR) { 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(D && D->hasBody()); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BodyCheckers[i](D, mgr, BR); 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//===----------------------------------------------------------------------===// 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions for running checkers for path-sensitive checking. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename CHECK_CTX> 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void expandGraphWithCheckers(CHECK_CTX checkCtx, 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &Dst, 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExplodedNodeSet &Src) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename CHECK_CTX::CheckersTy::const_iterator 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (I == E) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Dst.insert(Src); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet Tmp1, Tmp2; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExplodedNodeSet *PrevSet = &Src; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; I != E; ++I) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet *CurrSet = 0; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (I+1 == E) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CurrSet = &Dst; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else { 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CurrSet->clear(); 965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NI != NE; ++NI) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkCtx.runChecker(*I, *CurrSet, *NI); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Update which NodeSet is the current one. 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrevSet = CurrSet; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) struct CheckStmtContext { 1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool IsPreVisit; 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const CheckersTy &Checkers; 112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Stmt *S; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Stmt *s, ExprEngine &eng) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { } 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void runChecker(CheckerManager::CheckStmtFunc checkFn, 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &Dst, ExplodedNode *Pred) { 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: Remove respondsToCallback from CheckerContext; 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsPreVisit ? ProgramPoint::PreStmtKind : 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramPoint::PostStmtKind, 0, S); 128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) checkFn(S, C); 129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) } 130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) }; 131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for visiting Stmts. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersForStmt(bool isPreVisit, 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &Dst, 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExplodedNodeSet &Src, 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *S, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng) { 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) S, Eng); 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct CheckObjCMessageContext { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsPreVisit; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CheckersTy &Checkers; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMessage &Msg; 150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ExprEngine &Eng; 151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMessage &msg, ExprEngine &eng) 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &Dst, ExplodedNode *Pred) { 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsPreVisit ? ProgramPoint::PreStmtKind : 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramPoint::PostStmtKind, 0, 1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) Msg.getOriginExpr()); 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkFn(Msg, C); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)/// \brief Run checkers for visiting obj-c messages. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) ExplodedNodeSet &Dst, 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExplodedNodeSet &Src, 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMessage &msg, 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng) { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckObjCMessageContext C(isPreVisit, 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) isPreVisit ? PreObjCMessageCheckers 1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) : PostObjCMessageCheckers, 1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) msg, Eng); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace { 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct CheckLocationContext { 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CheckersTy &Checkers; 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal Loc; 188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) bool IsLoad; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Stmt *S; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) CheckLocationContext(const CheckersTy &checkers, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) 197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void runChecker(CheckerManager::CheckLocationFunc checkFn, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &Dst, ExplodedNode *Pred) { 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) IsLoad ? ProgramPoint::PreLoadKind : 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramPoint::PreStoreKind, 0, S); 204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) checkFn(Loc, IsLoad, C); 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) }; 207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)} 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for load/store of a location. 210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const ExplodedNodeSet &Src, 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal location, bool isLoad, 213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) const Stmt *S, ExprEngine &Eng) { 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 217 218namespace { 219 struct CheckBindContext { 220 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 221 const CheckersTy &Checkers; 222 SVal Loc; 223 SVal Val; 224 const Stmt *S; 225 ExprEngine &Eng; 226 227 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 228 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 229 230 CheckBindContext(const CheckersTy &checkers, 231 SVal loc, SVal val, const Stmt *s, ExprEngine &eng) 232 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { } 233 234 void runChecker(CheckerManager::CheckBindFunc checkFn, 235 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 236 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 237 ProgramPoint::PreStmtKind, 0, S); 238 checkFn(Loc, Val, C); 239 } 240 }; 241} 242 243/// \brief Run checkers for binding of a value to a location. 244void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 245 const ExplodedNodeSet &Src, 246 SVal location, SVal val, 247 const Stmt *S, ExprEngine &Eng) { 248 CheckBindContext C(BindCheckers, location, val, S, Eng); 249 expandGraphWithCheckers(C, Dst, Src); 250} 251 252void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 253 BugReporter &BR, 254 ExprEngine &Eng) { 255 for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 256 EndAnalysisCheckers[i](G, BR, Eng); 257} 258 259/// \brief Run checkers for end of path. 260void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B, 261 ExprEngine &Eng) { 262 for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 263 CheckEndPathFunc fn = EndPathCheckers[i]; 264 EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker); 265 fn(specialB, Eng); 266 } 267} 268 269/// \brief Run checkers for branch condition. 270void CheckerManager::runCheckersForBranchCondition(const Stmt *condition, 271 BranchNodeBuilder &B, 272 ExprEngine &Eng) { 273 for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) { 274 CheckBranchConditionFunc fn = BranchConditionCheckers[i]; 275 fn(condition, B, Eng); 276 } 277} 278 279/// \brief Run checkers for live symbols. 280void CheckerManager::runCheckersForLiveSymbols(const GRState *state, 281 SymbolReaper &SymReaper) { 282 for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 283 LiveSymbolsCheckers[i](state, SymReaper); 284} 285 286namespace { 287 struct CheckDeadSymbolsContext { 288 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 289 const CheckersTy &Checkers; 290 SymbolReaper &SR; 291 const Stmt *S; 292 ExprEngine &Eng; 293 294 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 295 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 296 297 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 298 const Stmt *s, ExprEngine &eng) 299 : Checkers(checkers), SR(sr), S(s), Eng(eng) { } 300 301 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 302 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 303 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 304 ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); 305 checkFn(SR, C); 306 } 307 }; 308} 309 310/// \brief Run checkers for dead symbols. 311void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 312 const ExplodedNodeSet &Src, 313 SymbolReaper &SymReaper, 314 const Stmt *S, 315 ExprEngine &Eng) { 316 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); 317 expandGraphWithCheckers(C, Dst, Src); 318} 319 320/// \brief True if at least one checker wants to check region changes. 321bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) { 322 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 323 if (RegionChangesCheckers[i].WantUpdateFn(state)) 324 return true; 325 326 return false; 327} 328 329/// \brief Run checkers for region changes. 330const GRState * 331CheckerManager::runCheckersForRegionChanges(const GRState *state, 332 const MemRegion * const *Begin, 333 const MemRegion * const *End) { 334 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 335 // If any checker declares the state infeasible (or if it starts that way), 336 // bail out. 337 if (!state) 338 return NULL; 339 state = RegionChangesCheckers[i].CheckFn(state, Begin, End); 340 } 341 return state; 342} 343 344/// \brief Run checkers for handling assumptions on symbolic values. 345const GRState * 346CheckerManager::runCheckersForEvalAssume(const GRState *state, 347 SVal Cond, bool Assumption) { 348 for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 349 // If any checker declares the state infeasible (or if it starts that way), 350 // bail out. 351 if (!state) 352 return NULL; 353 state = EvalAssumeCheckers[i](state, Cond, Assumption); 354 } 355 return state; 356} 357 358/// \brief Run checkers for evaluating a call. 359/// Only one checker will evaluate the call. 360void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 361 const ExplodedNodeSet &Src, 362 const CallExpr *CE, 363 ExprEngine &Eng, 364 GraphExpander *defaultEval) { 365 if (EvalCallCheckers.empty() && defaultEval == 0) { 366 Dst.insert(Src); 367 return; 368 } 369 370 for (ExplodedNodeSet::iterator 371 NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 372 373 ExplodedNode *Pred = *NI; 374 bool anyEvaluated = false; 375 for (std::vector<EvalCallFunc>::iterator 376 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 377 EI != EE; ++EI) { 378 ExplodedNodeSet checkDst; 379 CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker, 380 ProgramPoint::PostStmtKind, 0, CE); 381 bool evaluated = (*EI)(CE, C); 382 assert(!(evaluated && anyEvaluated) 383 && "There are more than one checkers evaluating the call"); 384 if (evaluated) { 385 anyEvaluated = true; 386 Dst.insert(checkDst); 387#ifdef NDEBUG 388 break; // on release don't check that no other checker also evals. 389#endif 390 } 391 } 392 393 if (!anyEvaluated) { 394 if (defaultEval) 395 defaultEval->expandGraph(Dst, Pred); 396 else 397 Dst.insert(Pred); 398 } 399 } 400} 401 402//===----------------------------------------------------------------------===// 403// Internal registration functions for AST traversing. 404//===----------------------------------------------------------------------===// 405 406void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 407 HandlesDeclFunc isForDeclFn) { 408 DeclCheckerInfo info = { checkfn, isForDeclFn }; 409 DeclCheckers.push_back(info); 410} 411 412void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 413 BodyCheckers.push_back(checkfn); 414} 415 416//===----------------------------------------------------------------------===// 417// Internal registration functions for path-sensitive checking. 418//===----------------------------------------------------------------------===// 419 420void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 421 HandlesStmtFunc isForStmtFn) { 422 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 423 StmtCheckers.push_back(info); 424} 425void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 426 HandlesStmtFunc isForStmtFn) { 427 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 428 StmtCheckers.push_back(info); 429} 430 431void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 432 PreObjCMessageCheckers.push_back(checkfn); 433} 434void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 435 PostObjCMessageCheckers.push_back(checkfn); 436} 437 438void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 439 LocationCheckers.push_back(checkfn); 440} 441 442void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 443 BindCheckers.push_back(checkfn); 444} 445 446void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 447 EndAnalysisCheckers.push_back(checkfn); 448} 449 450void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 451 EndPathCheckers.push_back(checkfn); 452} 453 454void CheckerManager::_registerForBranchCondition( 455 CheckBranchConditionFunc checkfn) { 456 BranchConditionCheckers.push_back(checkfn); 457} 458 459void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 460 LiveSymbolsCheckers.push_back(checkfn); 461} 462 463void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 464 DeadSymbolsCheckers.push_back(checkfn); 465} 466 467void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 468 WantsRegionChangeUpdateFunc wantUpdateFn) { 469 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 470 RegionChangesCheckers.push_back(info); 471} 472 473void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 474 EvalAssumeCheckers.push_back(checkfn); 475} 476 477void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 478 EvalCallCheckers.push_back(checkfn); 479} 480 481//===----------------------------------------------------------------------===// 482// Implementation details. 483//===----------------------------------------------------------------------===// 484 485CheckerManager::CachedStmtCheckers * 486CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 487 assert(S); 488 489 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 490 CachedStmtCheckers *checkers = 0; 491 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 492 if (CCI != CachedStmtCheckersMap.end()) { 493 checkers = &(CCI->second); 494 } else { 495 // Find the checkers that should run for this Stmt and cache them. 496 checkers = &CachedStmtCheckersMap[key]; 497 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 498 StmtCheckerInfo &info = StmtCheckers[i]; 499 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 500 checkers->push_back(info.CheckFn); 501 } 502 } 503 504 assert(checkers); 505 return checkers; 506} 507 508CheckerManager::~CheckerManager() { 509 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 510 CheckerDtors[i](); 511} 512 513// Anchor for the vtable. 514CheckerProvider::~CheckerProvider() { } 515 516// Anchor for the vtable. 517GraphExpander::~GraphExpander() { } 518