CheckerManager.cpp revision 18c66fdc3c4008d335885695fe36fb5353c5f672
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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. 76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)// 86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)//===----------------------------------------------------------------------===// 9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Defines the Static Analyzer Checker Manager. 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerProvider.h" 16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/Analysis/ProgramPoint.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/DeclBase.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace clang; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CheckerManager::hasPathSensitiveCheckers() const { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !StmtCheckers.empty() || 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !PreObjCMessageCheckers.empty() || 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !PostObjCMessageCheckers.empty() || 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !LocationCheckers.empty() || 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !BindCheckers.empty() || 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !EndAnalysisCheckers.empty() || 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !EndPathCheckers.empty() || 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !BranchConditionCheckers.empty() || 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !LiveSymbolsCheckers.empty() || 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !DeadSymbolsCheckers.empty() || 35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) !RegionChangesCheckers.empty() || 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !EvalAssumeCheckers.empty() || 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) !EvalCallCheckers.empty(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::finishedCheckerRegistration() { 41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifndef NDEBUG 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that for every event that has listeners, there is at least 43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // one dispatcher registered for it. 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (llvm::DenseMap<EventTag, EventInfo>::iterator 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = Events.begin(), E = Events.end(); I != E; ++I) 461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//===----------------------------------------------------------------------===// 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions for running checkers for AST traversing.. 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR) { 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(D); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned DeclKind = D->getKind(); 599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CachedDeclCheckers *checkers = 0; 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (CCI != CachedDeclCheckersMap.end()) { 62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) checkers = &(CCI->second); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) // Find the checkers that should run for this Decl and cache them. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkers = &CachedDeclCheckersMap[DeclKind]; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeclCheckerInfo &info = DeclCheckers[i]; 68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (info.IsForDeclFn(D)) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkers->push_back(info.CheckFn); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) assert(checkers); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CachedDeclCheckers::iterator 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = checkers->begin(), E = checkers->end(); I != E; ++I) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*I)(D, mgr, BR); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(D && D->hasBody()); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) BodyCheckers[i](D, mgr, BR); 85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch} 861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//===----------------------------------------------------------------------===// 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Functions for running checkers for path-sensitive checking. 8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//===----------------------------------------------------------------------===// 90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template <typename CHECK_CTX> 92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void expandGraphWithCheckers(CHECK_CTX checkCtx, 93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ExplodedNodeSet &Dst, 9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) const ExplodedNodeSet &Src) { 955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename CHECK_CTX::CheckersTy::const_iterator 97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (I == E) { 99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch Dst.insert(Src); 100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch return; 101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet Tmp1, Tmp2; 1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ExplodedNodeSet *PrevSet = &Src; 1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) for (; I != E; ++I) { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet *CurrSet = 0; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (I+1 == E) 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CurrSet = &Dst; 11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) else { 11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CurrSet->clear(); 1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) } 11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci NI != NE; ++NI) 1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) checkCtx.runChecker(*I, *CurrSet, *NI); 11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Update which NodeSet is the current one. 12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) PrevSet = CurrSet; 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace { 12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct CheckStmtContext { 12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) bool IsPreVisit; 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const CheckersTy &Checkers; 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) const Stmt *S; 1300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExprEngine &Eng; 1310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 1340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const Stmt *s, ExprEngine &eng) 1370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { } 1380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci void runChecker(CheckerManager::CheckStmtFunc checkFn, 1400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNodeSet &Dst, ExplodedNode *Pred) { 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FIXME: Remove respondsToCallback from CheckerContext; 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsPreVisit ? ProgramPoint::PreStmtKind : 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ProgramPoint::PostStmtKind, 0, S); 14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) checkFn(S, C); 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 149424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) 15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/// \brief Run checkers for visiting Stmts. 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CheckerManager::runCheckersForStmt(bool isPreVisit, 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExplodedNodeSet &Dst, 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const ExplodedNodeSet &Src, 154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const Stmt *S, 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng) { 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) S, Eng); 1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace { 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) struct CheckObjCMessageContext { 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) bool IsPreVisit; 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) const CheckersTy &Checkers; 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ObjCMessage &Msg; 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExprEngine &Eng; 1689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const ObjCMessage &msg, ExprEngine &eng) 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ExplodedNodeSet &Dst, ExplodedNode *Pred) { 178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) IsPreVisit ? ProgramPoint::PreStmtKind : 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ProgramPoint::PostStmtKind, 0, 181a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch Msg.getOriginExpr()); 182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch checkFn(Msg, C); 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// \brief Run checkers for visiting obj-c messages. 1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 1890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExplodedNodeSet &Dst, 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExplodedNodeSet &Src, 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMessage &msg, 1920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExprEngine &Eng) { 1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CheckObjCMessageContext C(isPreVisit, 1946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) isPreVisit ? PreObjCMessageCheckers 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : PostObjCMessageCheckers, 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg, Eng); 1970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 1980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 2010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) struct CheckLocationContext { 2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const CheckersTy &Checkers; 2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) SVal Loc; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsLoad; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Stmt *S; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckLocationContext(const CheckersTy &checkers, 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void runChecker(CheckerManager::CheckLocationFunc checkFn, 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExplodedNodeSet &Dst, ExplodedNode *Pred) { 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsLoad ? ProgramPoint::PreLoadKind : 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ProgramPoint::PreStoreKind, 0, S); 221bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch checkFn(Loc, IsLoad, C); 222bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch } 223bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch }; 224bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/// \brief Run checkers for load/store of a location. 2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci const ExplodedNodeSet &Src, 2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci SVal location, bool isLoad, 2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) const Stmt *S, ExprEngine &Eng) { 2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); 232bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch expandGraphWithCheckers(C, Dst, Src); 233bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch} 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) struct CheckBindContext { 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CheckersTy &Checkers; 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SVal Loc; 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SVal Val; 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Stmt *S; 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExprEngine &Eng; 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CheckBindContext(const CheckersTy &checkers, 2480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) SVal loc, SVal val, const Stmt *s, ExprEngine &eng) 2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { } 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void runChecker(CheckerManager::CheckBindFunc checkFn, 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExplodedNodeSet &Dst, ExplodedNode *Pred) { 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ProgramPoint::PreStmtKind, 0, S); 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) checkFn(Loc, Val, C); 2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) }; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch/// \brief Run checkers for binding of a value to a location. 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ExplodedNodeSet &Src, 2630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) SVal location, SVal val, 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Stmt *S, ExprEngine &Eng) { 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckBindContext C(BindCheckers, location, val, S, Eng); 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 2690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EndAnalysisCheckers[i](G, BR, Eng); 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for end of path. 27734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B, 27834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) ExprEngine &Eng) { 27934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 28034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) CheckEndPathFunc fn = EndPathCheckers[i]; 2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker); 2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu fn(specialB, Eng); 283a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// \brief Run checkers for branch condition. 2870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::runCheckersForBranchCondition(const Stmt *condition, 2880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BranchNodeBuilder &B, 2890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ExprEngine &Eng) { 2900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) { 2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) CheckBranchConditionFunc fn = BranchConditionCheckers[i]; 2920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) fn(condition, B, Eng); 2930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for live symbols. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersForLiveSymbols(const ProgramState *state, 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SymbolReaper &SymReaper) { 2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) LiveSymbolsCheckers[i](state, SymReaper); 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace { 304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) struct CheckDeadSymbolsContext { 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const CheckersTy &Checkers; 307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) SymbolReaper &SR; 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Stmt *S; 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng; 310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *s, ExprEngine &eng) 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : Checkers(checkers), SR(sr), S(s), Eng(eng) { } 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExplodedNodeSet &Dst, ExplodedNode *Pred) { 32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) ProgramPoint::PostPurgeDeadSymbolsKind, 0, S); 322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch checkFn(SR, C); 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch }; 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// \brief Run checkers for dead symbols. 328a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ExplodedNodeSet &Src, 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SymbolReaper &SymReaper, 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Stmt *S, 332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ExprEngine &Eng) { 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); 334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// \brief True if at least one checker wants to check region changes. 3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CheckerManager::wantsRegionChangeUpdate(const ProgramState *state) { 3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (RegionChangesCheckers[i].WantUpdateFn(state)) 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// \brief Run checkers for region changes. 3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst ProgramState * 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckerManager::runCheckersForRegionChanges(const ProgramState *state, 3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const StoreManager::InvalidatedSymbols *invalidated, 3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const MemRegion * const *Begin, 3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const MemRegion * const *End) { 3526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // If any checker declares the state infeasible (or if it starts that way), 3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // bail out. 3550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) if (!state) 3560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) return NULL; 3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End); 3580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) } 3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return state; 3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/// \brief Run checkers for handling assumptions on symbolic values. 3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst ProgramState * 3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)CheckerManager::runCheckersForEvalAssume(const ProgramState *state, 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal Cond, bool Assumption) { 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // If any checker declares the state infeasible (or if it starts that way), 3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // bail out. 369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!state) 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NULL; 3717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch state = EvalAssumeCheckers[i](state, Cond, Assumption); 372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch } 37323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) return state; 3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// \brief Run checkers for evaluating a call. 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// Only one checker will evaluate the call. 3787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch const ExplodedNodeSet &Src, 380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const CallExpr *CE, 381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch ExprEngine &Eng, 3827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch GraphExpander *defaultEval) { 383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (EvalCallCheckers.empty() && defaultEval == 0) { 3847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch Dst.insert(Src); 3857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return; 3867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 387a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 3887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (ExplodedNodeSet::iterator 389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 3907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 3917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ExplodedNode *Pred = *NI; 392c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool anyEvaluated = false; 3937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch for (std::vector<EvalCallFunc>::iterator 3947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch EI != EE; ++EI) { 3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ExplodedNodeSet checkDst; 3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker, 3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch ProgramPoint::PostStmtKind, 0, CE); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool evaluated = (*EI)(CE, C); 4007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch assert(!(evaluated && anyEvaluated) 4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch && "There are more than one checkers evaluating the call"); 4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) if (evaluated) { 403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) anyEvaluated = true; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Dst.insert(checkDst); 405ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#ifdef NDEBUG 406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch break; // on release don't check that no other checker also evals. 407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif 408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch } 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!anyEvaluated) { 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (defaultEval) 41368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) defaultEval->expandGraph(Dst, Pred); 4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) else 41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Dst.insert(Pred); 41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 4196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/// \brief Run checkers for the entire Translation Unit. 4210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::runCheckersOnEndOfTranslationUnit( 4220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) const TranslationUnitDecl *TU, 4230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) AnalysisManager &mgr, 4240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) BugReporter &BR) { 4250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EndOfTranslationUnitCheckers[i](TU, mgr, BR); 427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//===----------------------------------------------------------------------===// 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Internal registration functions for AST traversing. 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===// 4320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 4330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 434c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch HandlesDeclFunc isForDeclFn) { 435c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch DeclCheckerInfo info = { checkfn, isForDeclFn }; 4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci DeclCheckers.push_back(info); 4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci BodyCheckers.push_back(checkfn); 4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 44323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)//===----------------------------------------------------------------------===// 44423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Internal registration functions for path-sensitive checking. 44523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)//===----------------------------------------------------------------------===// 44623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles) 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) HandlesStmtFunc isForStmtFn) { 449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 4500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) StmtCheckers.push_back(info); 4510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 4520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 4530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) HandlesStmtFunc isForStmtFn) { 4547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch StmtCheckers.push_back(info); 4566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci PreObjCMessageCheckers.push_back(checkfn); 4603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch} 4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 4623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch PostObjCMessageCheckers.push_back(checkfn); 4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci} 4645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu 4657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 4667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch LocationCheckers.push_back(checkfn); 4677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BindCheckers.push_back(checkfn); 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EndAnalysisCheckers.push_back(checkfn); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 47758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) EndPathCheckers.push_back(checkfn); 4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 48046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 48168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CheckerManager::_registerForBranchCondition( 4827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CheckBranchConditionFunc checkfn) { 4837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch BranchConditionCheckers.push_back(checkfn); 4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 48658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) LiveSymbolsCheckers.push_back(checkfn); 4887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeadSymbolsCheckers.push_back(checkfn); 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci 4947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 4957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch WantsRegionChangeUpdateFunc wantUpdateFn) { 4967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 4970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) RegionChangesCheckers.push_back(info); 4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 4990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 5000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 5010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) EvalAssumeCheckers.push_back(checkfn); 5020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)} 5030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) EvalCallCheckers.push_back(checkfn); 5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::_registerForEndOfTranslationUnit( 509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckEndOfTranslationUnit checkfn) { 5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EndOfTranslationUnitCheckers.push_back(checkfn); 511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 512bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 513bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//===----------------------------------------------------------------------===// 514bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Implementation details. 515bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//===----------------------------------------------------------------------===// 516bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 517bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochCheckerManager::CachedStmtCheckers * 5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) assert(S); 5207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 5229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CachedStmtCheckers *checkers = 0; 5239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 5249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (CCI != CachedStmtCheckersMap.end()) { 5259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkers = &(CCI->second); 5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } else { 5277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Find the checkers that should run for this Stmt and cache them. 5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) checkers = &CachedStmtCheckersMap[key]; 5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) StmtCheckerInfo &info = StmtCheckers[i]; 5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 5327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch checkers->push_back(info.CheckFn); 5337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch } 5359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch assert(checkers); 5377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch return checkers; 5387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch} 5397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch 5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CheckerManager::~CheckerManager() { 5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CheckerDtors[i](); 5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Anchor for the vtable. 546bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochCheckerProvider::~CheckerProvider() { } 547bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch 548bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Anchor for the vtable. 549bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochGraphExpander::~GraphExpander() { } 5506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)