CheckerManager.cpp revision 9be6e7ce5788e50c62d40c59b0bbc2ea423683f7
14186ad56cfe70ab065d3ca7aadcded814574fa42Chris Lattner//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===// 2fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman// 3b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// The LLVM Compiler Infrastructure 4b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell// 54ee451de366474b9c228b4e5fa573795a715216dChris Lattner// This file is distributed under the University of Illinois Open Source 64ee451de366474b9c228b4e5fa573795a715216dChris Lattner// License. See LICENSE.TXT for details. 7fd93908ae8b9684fe71c239e3c6cfe13ff6a2663Misha Brukman// 8b576c94c15af9a440f69d9d03c2afead7971118cJohn Criswell//===----------------------------------------------------------------------===// 9573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner// 104cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattner// Defines the Static Analyzer Checker Manager. 114cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattner// 12573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner//===----------------------------------------------------------------------===// 13c86b67742a3298c0a5a715b57a64f11107b8a3f2Gordon Henriksen 14c86b67742a3298c0a5a715b57a64f11107b8a3f2Gordon Henriksen#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner#include "clang/StaticAnalyzer/Core/CheckerProvider.h" 16c86b67742a3298c0a5a715b57a64f11107b8a3f2Gordon Henriksen#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 17c86b67742a3298c0a5a715b57a64f11107b8a3f2Gordon Henriksen#include "clang/Analysis/ProgramPoint.h" 184cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattner#include "clang/AST/DeclBase.h" 194cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattner 204cf4b69330f0b2a3ba325bcdb1ff41847c022260Chris Lattnerusing namespace clang; 21573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattnerusing namespace ento; 22573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner 23573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattnerbool CheckerManager::hasPathSensitiveCheckers() const { 24573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner return !StmtCheckers.empty() || 25d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth !PreObjCMessageCheckers.empty() || 26d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth !PostObjCMessageCheckers.empty() || 27d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth !LocationCheckers.empty() || 28be04929f7fd76a921540e9901f24563e51dc1219Chandler Carruth !BindCheckers.empty() || 290b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth !EndAnalysisCheckers.empty() || 3036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines !EndPathCheckers.empty() || 310b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth !BranchConditionCheckers.empty() || 320b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth !LiveSymbolsCheckers.empty() || 330b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth !DeadSymbolsCheckers.empty() || 340b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth !RegionChangesCheckers.empty() || 350b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth !EvalAssumeCheckers.empty() || 36573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner !EvalCallCheckers.empty(); 37d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth} 38d7456026629fc1760a45e6e955e9834246493147Chris Lattner 39d0fde30ce850b78371fd1386338350591f9ff494Brian Gaekevoid CheckerManager::finishedCheckerRegistration() { 40dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines#ifndef NDEBUG 41dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines // Make sure that for every event that has listeners, there is at least 420e5f499638c8d277b9dc4a4385712177c53b5681Chris Lattner // one dispatcher registered for it. 43a92f696b74a99325026ebbdbffd2a44317e0c10bChris Lattner for (llvm::DenseMap<EventTag, EventInfo>::iterator 440e5f499638c8d277b9dc4a4385712177c53b5681Chris Lattner I = Events.begin(), E = Events.end(); I != E; ++I) 4557e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 4657e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard#endif 4701d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard} 4801d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard 4957e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard//===----------------------------------------------------------------------===// 5036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines// Functions for running checkers for AST traversing.. 5101d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard//===----------------------------------------------------------------------===// 5236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 5357e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellardvoid CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 5457e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard BugReporter &BR) { 5557e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard assert(D); 56573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner 57573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner unsigned DeclKind = D->getKind(); 5801d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard CachedDeclCheckers *checkers = 0; 5901d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 6057e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard if (CCI != CachedDeclCheckersMap.end()) { 615f46c3c2e8d13c6ac8d3863d84e887f84c73f27aChandler Carruth checkers = &(CCI->second); 6201d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard } else { 6357e6b2d1f3de0bf459e96f7038e692d624f7e580Tom Stellard // Find the checkers that should run for this Decl and cache them. 64844731a7f1909f55935e3514c9e713a62d67662eDan Gohman checkers = &CachedDeclCheckersMap[DeclKind]; 65d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 6601d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard DeclCheckerInfo &info = DeclCheckers[i]; 6701d7203ef8316fdd71c3cec59f8e68fb869e0dbfTom Stellard if (info.IsForDeclFn(D)) 68573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner checkers->push_back(info.CheckFn); 69573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner } 70557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach } 711a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 72557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach assert(checkers); 731a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner for (CachedDeclCheckers::iterator 74a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem I = checkers->begin(), E = checkers->end(); I != E; ++I) 75dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines (*I)(D, mgr, BR); 76a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem} 771a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 781a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattnervoid CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 791a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner BugReporter &BR) { 80a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem assert(D && D->hasBody()); 811a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 821a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 83dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines BodyCheckers[i](D, mgr, BR); 84a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem} 851a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 861a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner//===----------------------------------------------------------------------===// 871a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner// Functions for running checkers for path-sensitive checking. 881a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner//===----------------------------------------------------------------------===// 891a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 901a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattnertemplate <typename CHECK_CTX> 91ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendlingstatic void expandGraphWithCheckers(CHECK_CTX checkCtx, 92ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling ExplodedNodeSet &Dst, 93ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling const ExplodedNodeSet &Src) { 94ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling 95ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling typename CHECK_CTX::CheckersTy::const_iterator 96ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 97ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling if (I == E) { 981a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner Dst.insert(Src); 991a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner return; 100ead138bc628b57bfd0a03f6f7644ceb10128bb52Bill Wendling } 1011a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 102dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines ExplodedNodeSet Tmp1, Tmp2; 1031a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner const ExplodedNodeSet *PrevSet = &Src; 1041a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 1051a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner for (; I != E; ++I) { 106a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem ExplodedNodeSet *CurrSet = 0; 1071a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner if (I+1 == E) 1081a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner CurrSet = &Dst; 109a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem else { 1101a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 1111a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner CurrSet->clear(); 1121a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner } 1131a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 114a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 1151a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner NI != NE; ++NI) 1161a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner checkCtx.runChecker(*I, *CurrSet, *NI); 1171a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 1181a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner // Update which NodeSet is the current one. 1191a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner PrevSet = CurrSet; 120a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem } 1211a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner} 1221a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 123dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesnamespace { 124ca704957972df96a86f4ef90ce992bce5a9b60e9Devang Patel struct CheckStmtContext { 125d8b4fb4aab4d6fedb2b14bed1b846451b17bde7cJay Foad typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 1263ecfc861b4365f341c5c969b40e1afccde676e6fJay Foad bool IsPreVisit; 1273ecfc861b4365f341c5c969b40e1afccde676e6fJay Foad const CheckersTy &Checkers; 1281a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner const Stmt *S; 129a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem ExprEngine &Eng; 130d8b4fb4aab4d6fedb2b14bed1b846451b17bde7cJay Foad 1311a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 1321a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 1331a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 134a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 1351a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner const Stmt *s, ExprEngine &eng) 1361a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { } 1371a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner 1381a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner void runChecker(CheckerManager::CheckStmtFunc checkFn, 1391a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner ExplodedNodeSet &Dst, ExplodedNode *Pred) { 1401a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner // FIXME: Remove respondsToCallback from CheckerContext; 1411a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 142a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem IsPreVisit ? ProgramPoint::PreStmtKind : 1431a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner ProgramPoint::PostStmtKind, 0, S); 1441a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner checkFn(S, C); 1451a0e7081c3e94ae69f2768465da34a3dceaaa5f6Chris Lattner } 146557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach }; 147b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner} 1485f46c3c2e8d13c6ac8d3863d84e887f84c73f27aChandler Carruth 14936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines/// \brief Run checkers for visiting Stmts. 150b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattnervoid CheckerManager::runCheckersForStmt(bool isPreVisit, 151573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner ExplodedNodeSet &Dst, 152573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner const ExplodedNodeSet &Src, 153573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner const Stmt *S, 154a94d6e87c4c49f2e81b01d66d8bfb591277f8f96Nadav Rotem ExprEngine &Eng) { 155e2c6d131d12c779a410740e0a90545def75e0f48Dan Gohman CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 156573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner S, Eng); 157e2c6d131d12c779a410740e0a90545def75e0f48Dan Gohman expandGraphWithCheckers(C, Dst, Src); 15836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines} 159573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner 160573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattnernamespace { 161573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner struct CheckObjCMessageContext { 162573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 163573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner bool IsPreVisit; 164573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner const CheckersTy &Checkers; 165573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner const ObjCMessage &Msg; 166573527bd5dc546a198a122cd6d1da62246d2d9beChris Lattner ExprEngine &Eng; 167b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner 168b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 169b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 170b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner 171b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 17236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines const ObjCMessage &msg, ExprEngine &eng) 17336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 17436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines 1755f46c3c2e8d13c6ac8d3863d84e887f84c73f27aChandler Carruth void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 17636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines ExplodedNodeSet &Dst, ExplodedNode *Pred) { 177dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 1784f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne IsPreVisit ? ProgramPoint::PreStmtKind : 179557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach ProgramPoint::PostStmtKind, 0, 18036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines Msg.getOriginExpr()); 18158e9ee85fda5083e2eea987917e8eab6ba31fe5eJakob Stoklund Olesen checkFn(Msg, C); 182b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner } 183b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner }; 184b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner} 185557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach 1864f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne/// \brief Run checkers for visiting obj-c messages. 187b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattnervoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 188557a20a23494c13fbcef90fcc8454f2c8aa33c22Jim Grosbach ExplodedNodeSet &Dst, 1894f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne const ExplodedNodeSet &Src, 1904f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne const ObjCMessage &msg, 191b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner ExprEngine &Eng) { 19258e9ee85fda5083e2eea987917e8eab6ba31fe5eJakob Stoklund Olesen CheckObjCMessageContext C(isPreVisit, 193b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner isPreVisit ? PreObjCMessageCheckers 19436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines : PostObjCMessageCheckers, 1954f96b7e1478be0b33cda589db40635a1e3a40c11Peter Collingbourne msg, Eng); 196b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner expandGraphWithCheckers(C, Dst, Src); 19758e9ee85fda5083e2eea987917e8eab6ba31fe5eJakob Stoklund Olesen} 198b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattner 199b42c8f71017f29d006741f0fa4ce8de227e7226fChris Lattnernamespace { 200 struct CheckLocationContext { 201 typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 202 const CheckersTy &Checkers; 203 SVal Loc; 204 bool IsLoad; 205 const Stmt *S; 206 ExprEngine &Eng; 207 208 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 209 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 210 211 CheckLocationContext(const CheckersTy &checkers, 212 SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) 213 : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } 214 215 void runChecker(CheckerManager::CheckLocationFunc checkFn, 216 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 217 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 218 IsLoad ? ProgramPoint::PreLoadKind : 219 ProgramPoint::PreStoreKind, 0, S); 220 checkFn(Loc, IsLoad, C); 221 } 222 }; 223} 224 225/// \brief Run checkers for load/store of a location. 226void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 227 const ExplodedNodeSet &Src, 228 SVal location, bool isLoad, 229 const Stmt *S, ExprEngine &Eng) { 230 CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); 231 expandGraphWithCheckers(C, Dst, Src); 232} 233 234namespace { 235 struct CheckBindContext { 236 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 237 const CheckersTy &Checkers; 238 SVal Loc; 239 SVal Val; 240 const Stmt *S; 241 ExprEngine &Eng; 242 243 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 244 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 245 246 CheckBindContext(const CheckersTy &checkers, 247 SVal loc, SVal val, const Stmt *s, ExprEngine &eng) 248 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { } 249 250 void runChecker(CheckerManager::CheckBindFunc checkFn, 251 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 252 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 253 ProgramPoint::PreStmtKind, 0, S); 254 checkFn(Loc, Val, C); 255 } 256 }; 257} 258 259/// \brief Run checkers for binding of a value to a location. 260void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 261 const ExplodedNodeSet &Src, 262 SVal location, SVal val, 263 const Stmt *S, ExprEngine &Eng) { 264 CheckBindContext C(BindCheckers, location, val, S, Eng); 265 expandGraphWithCheckers(C, Dst, Src); 266} 267 268void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 269 BugReporter &BR, 270 ExprEngine &Eng) { 271 for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 272 EndAnalysisCheckers[i](G, BR, Eng); 273} 274 275/// \brief Run checkers for end of path. 276void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B, 277 ExprEngine &Eng) { 278 for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 279 CheckEndPathFunc fn = EndPathCheckers[i]; 280 EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker); 281 fn(specialB, Eng); 282 } 283} 284 285/// \brief Run checkers for branch condition. 286void CheckerManager::runCheckersForBranchCondition(const Stmt *condition, 287 BranchNodeBuilder &B, 288 ExprEngine &Eng) { 289 for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) { 290 CheckBranchConditionFunc fn = BranchConditionCheckers[i]; 291 fn(condition, B, Eng); 292 } 293} 294 295/// \brief Run checkers for live symbols. 296void CheckerManager::runCheckersForLiveSymbols(const GRState *state, 297 SymbolReaper &SymReaper) { 298 for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 299 LiveSymbolsCheckers[i](state, SymReaper); 300} 301 302namespace { 303 struct CheckDeadSymbolsContext { 304 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 305 const CheckersTy &Checkers; 306 SymbolReaper &SR; 307 const Stmt *S; 308 ExprEngine &Eng; 309 310 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 311 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 312 313 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 314 const Stmt *s, ExprEngine &eng) 315 : Checkers(checkers), SR(sr), S(s), Eng(eng) { } 316 317 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 318 ExplodedNodeSet &Dst, ExplodedNode *Pred) { 319 CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 320 ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); 321 checkFn(SR, C); 322 } 323 }; 324} 325 326/// \brief Run checkers for dead symbols. 327void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 328 const ExplodedNodeSet &Src, 329 SymbolReaper &SymReaper, 330 const Stmt *S, 331 ExprEngine &Eng) { 332 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); 333 expandGraphWithCheckers(C, Dst, Src); 334} 335 336/// \brief True if at least one checker wants to check region changes. 337bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) { 338 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 339 if (RegionChangesCheckers[i].WantUpdateFn(state)) 340 return true; 341 342 return false; 343} 344 345/// \brief Run checkers for region changes. 346const GRState * 347CheckerManager::runCheckersForRegionChanges(const GRState *state, 348 const StoreManager::InvalidatedSymbols *invalidated, 349 const MemRegion * const *Begin, 350 const MemRegion * const *End) { 351 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 352 // If any checker declares the state infeasible (or if it starts that way), 353 // bail out. 354 if (!state) 355 return NULL; 356 state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End); 357 } 358 return state; 359} 360 361/// \brief Run checkers for handling assumptions on symbolic values. 362const GRState * 363CheckerManager::runCheckersForEvalAssume(const GRState *state, 364 SVal Cond, bool Assumption) { 365 for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 366 // If any checker declares the state infeasible (or if it starts that way), 367 // bail out. 368 if (!state) 369 return NULL; 370 state = EvalAssumeCheckers[i](state, Cond, Assumption); 371 } 372 return state; 373} 374 375/// \brief Run checkers for evaluating a call. 376/// Only one checker will evaluate the call. 377void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 378 const ExplodedNodeSet &Src, 379 const CallExpr *CE, 380 ExprEngine &Eng, 381 GraphExpander *defaultEval) { 382 if (EvalCallCheckers.empty() && defaultEval == 0) { 383 Dst.insert(Src); 384 return; 385 } 386 387 for (ExplodedNodeSet::iterator 388 NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 389 390 ExplodedNode *Pred = *NI; 391 bool anyEvaluated = false; 392 for (std::vector<EvalCallFunc>::iterator 393 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 394 EI != EE; ++EI) { 395 ExplodedNodeSet checkDst; 396 CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker, 397 ProgramPoint::PostStmtKind, 0, CE); 398 bool evaluated = (*EI)(CE, C); 399 assert(!(evaluated && anyEvaluated) 400 && "There are more than one checkers evaluating the call"); 401 if (evaluated) { 402 anyEvaluated = true; 403 Dst.insert(checkDst); 404#ifdef NDEBUG 405 break; // on release don't check that no other checker also evals. 406#endif 407 } 408 } 409 410 if (!anyEvaluated) { 411 if (defaultEval) 412 defaultEval->expandGraph(Dst, Pred); 413 else 414 Dst.insert(Pred); 415 } 416 } 417} 418 419/// \brief Run checkers for the entire Translation Unit. 420void CheckerManager::runCheckersOnEndOfTranslationUnit( 421 const TranslationUnitDecl *TU, 422 AnalysisManager &mgr, 423 BugReporter &BR) { 424 for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 425 EndOfTranslationUnitCheckers[i](TU, mgr, BR); 426} 427 428//===----------------------------------------------------------------------===// 429// Internal registration functions for AST traversing. 430//===----------------------------------------------------------------------===// 431 432void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 433 HandlesDeclFunc isForDeclFn) { 434 DeclCheckerInfo info = { checkfn, isForDeclFn }; 435 DeclCheckers.push_back(info); 436} 437 438void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 439 BodyCheckers.push_back(checkfn); 440} 441 442//===----------------------------------------------------------------------===// 443// Internal registration functions for path-sensitive checking. 444//===----------------------------------------------------------------------===// 445 446void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 447 HandlesStmtFunc isForStmtFn) { 448 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 449 StmtCheckers.push_back(info); 450} 451void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 452 HandlesStmtFunc isForStmtFn) { 453 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 454 StmtCheckers.push_back(info); 455} 456 457void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 458 PreObjCMessageCheckers.push_back(checkfn); 459} 460void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 461 PostObjCMessageCheckers.push_back(checkfn); 462} 463 464void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 465 LocationCheckers.push_back(checkfn); 466} 467 468void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 469 BindCheckers.push_back(checkfn); 470} 471 472void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 473 EndAnalysisCheckers.push_back(checkfn); 474} 475 476void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 477 EndPathCheckers.push_back(checkfn); 478} 479 480void CheckerManager::_registerForBranchCondition( 481 CheckBranchConditionFunc checkfn) { 482 BranchConditionCheckers.push_back(checkfn); 483} 484 485void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 486 LiveSymbolsCheckers.push_back(checkfn); 487} 488 489void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 490 DeadSymbolsCheckers.push_back(checkfn); 491} 492 493void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 494 WantsRegionChangeUpdateFunc wantUpdateFn) { 495 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 496 RegionChangesCheckers.push_back(info); 497} 498 499void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 500 EvalAssumeCheckers.push_back(checkfn); 501} 502 503void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 504 EvalCallCheckers.push_back(checkfn); 505} 506 507void CheckerManager::_registerForEndOfTranslationUnit( 508 CheckEndOfTranslationUnit checkfn) { 509 EndOfTranslationUnitCheckers.push_back(checkfn); 510} 511 512//===----------------------------------------------------------------------===// 513// Implementation details. 514//===----------------------------------------------------------------------===// 515 516CheckerManager::CachedStmtCheckers * 517CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 518 assert(S); 519 520 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 521 CachedStmtCheckers *checkers = 0; 522 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 523 if (CCI != CachedStmtCheckersMap.end()) { 524 checkers = &(CCI->second); 525 } else { 526 // Find the checkers that should run for this Stmt and cache them. 527 checkers = &CachedStmtCheckersMap[key]; 528 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 529 StmtCheckerInfo &info = StmtCheckers[i]; 530 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 531 checkers->push_back(info.CheckFn); 532 } 533 } 534 535 assert(checkers); 536 return checkers; 537} 538 539CheckerManager::~CheckerManager() { 540 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 541 CheckerDtors[i](); 542} 543 544// Anchor for the vtable. 545CheckerProvider::~CheckerProvider() { } 546 547// Anchor for the vtable. 548GraphExpander::~GraphExpander() { } 549