CheckerManager.cpp revision 96479da6ad9d921d875e7be29fe1bfa127be8069
143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===// 243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// 343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// The LLVM Compiler Infrastructure 443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// 543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source 643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// License. See LICENSE.TXT for details. 743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// 843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===----------------------------------------------------------------------===// 943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// 1043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// Defines the Static Analyzer Checker Manager. 1143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// 1243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===----------------------------------------------------------------------===// 1343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 1443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "clang/StaticAnalyzer/Core/Checker.h" 16769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 17de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" 18769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis#include "clang/Analysis/ProgramPoint.h" 199fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "clang/AST/DeclBase.h" 2043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 2143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace clang; 2243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace ento; 2343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 24d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidisbool CheckerManager::hasPathSensitiveCheckers() const { 25d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis return !StmtCheckers.empty() || 26d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !PreObjCMessageCheckers.empty() || 27d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !PostObjCMessageCheckers.empty() || 2896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose !PreCallCheckers.empty() || 2996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose !PostCallCheckers.empty() || 30d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !LocationCheckers.empty() || 31d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !BindCheckers.empty() || 32d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !EndAnalysisCheckers.empty() || 33d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !EndPathCheckers.empty() || 34d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !BranchConditionCheckers.empty() || 35d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !LiveSymbolsCheckers.empty() || 36d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !DeadSymbolsCheckers.empty() || 37d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !RegionChangesCheckers.empty() || 38d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis !EvalAssumeCheckers.empty() || 39dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks !EvalCallCheckers.empty() || 40dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks !InlineCallCheckers.empty(); 41d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis} 42d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis 43deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidisvoid CheckerManager::finishedCheckerRegistration() { 44deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis#ifndef NDEBUG 45deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis // Make sure that for every event that has listeners, there is at least 46deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis // one dispatcher registered for it. 47deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis for (llvm::DenseMap<EventTag, EventInfo>::iterator 48deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis I = Events.begin(), E = Events.end(); I != E; ++I) 49deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 50deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis#endif 51deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis} 52deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis 53769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 54769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for AST traversing.. 55769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 56769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 579fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 589fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis BugReporter &BR) { 599fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis assert(D); 609fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 619fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis unsigned DeclKind = D->getKind(); 629fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis CachedDeclCheckers *checkers = 0; 639fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 649fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis if (CCI != CachedDeclCheckersMap.end()) { 659fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis checkers = &(CCI->second); 669fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } else { 679fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis // Find the checkers that should run for this Decl and cache them. 689fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis checkers = &CachedDeclCheckersMap[DeclKind]; 699fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 709fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis DeclCheckerInfo &info = DeclCheckers[i]; 719fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis if (info.IsForDeclFn(D)) 72769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkers->push_back(info.CheckFn); 739fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } 749fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } 759fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 769fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis assert(checkers); 779fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis for (CachedDeclCheckers::iterator 78769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis I = checkers->begin(), E = checkers->end(); I != E; ++I) 79769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis (*I)(D, mgr, BR); 809fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 819fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 829fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 839fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis BugReporter &BR) { 849fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis assert(D && D->hasBody()); 859fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 86769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 87769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis BodyCheckers[i](D, mgr, BR); 88769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 89769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 90769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 91769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for path-sensitive checking. 92769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 93769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 94769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidistemplate <typename CHECK_CTX> 95c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidisstatic void expandGraphWithCheckers(CHECK_CTX checkCtx, 96c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis ExplodedNodeSet &Dst, 97cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet &Src) { 988ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext(); 998ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks if (Src.empty()) 1008ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks return; 101769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 102e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis typename CHECK_CTX::CheckersTy::const_iterator 103e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 104e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis if (I == E) { 105769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis Dst.insert(Src); 106769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis return; 107769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 108769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 109cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis ExplodedNodeSet Tmp1, Tmp2; 110cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet *PrevSet = &Src; 111769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 112e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis for (; I != E; ++I) { 113769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet *CurrSet = 0; 114769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis if (I+1 == E) 115769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CurrSet = &Dst; 116769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis else { 117cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 118769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CurrSet->clear(); 119769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 120769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 1218ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks NodeBuilder B(*PrevSet, *CurrSet, BldrCtx); 122769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 1238ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks NI != NE; ++NI) { 1248ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks checkCtx.runChecker(*I, B, *NI); 1258ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks } 1268ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks 1278ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks // If all the produced transitions are sinks, stop. 1288ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks if (CurrSet->empty()) 1298ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks return; 1308ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks 131769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis // Update which NodeSet is the current one. 132769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis PrevSet = CurrSet; 1339fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } 1349fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 1359fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 136769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace { 137769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis struct CheckStmtContext { 1385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 139769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis bool IsPreVisit; 140769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const CheckersTy &Checkers; 141769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const Stmt *S; 142769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng; 143514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek bool wasInlined; 144769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 145e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 146e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 147e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 148769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 149514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek const Stmt *s, ExprEngine &eng, bool wasInlined = false) 150514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng), 151514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek wasInlined(wasInlined) {} 152769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 153769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis void runChecker(CheckerManager::CheckStmtFunc checkFn, 1548ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks NodeBuilder &Bldr, ExplodedNode *Pred) { 155769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis // FIXME: Remove respondsToCallback from CheckerContext; 1563f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 1573f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks ProgramPoint::PostStmtKind; 1583f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 1593f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks Pred->getLocationContext(), checkFn.Checker); 160514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek CheckerContext C(Bldr, Eng, Pred, L, wasInlined); 161769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkFn(S, C); 162769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 163769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis }; 164769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 165769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 166769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting Stmts. 167769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForStmt(bool isPreVisit, 168769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet &Dst, 169cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet &Src, 170769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const Stmt *S, 171514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek ExprEngine &Eng, 172514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek bool wasInlined) { 173769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 174514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek S, Eng, wasInlined); 175c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis expandGraphWithCheckers(C, Dst, Src); 176769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 177769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 178769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace { 179769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis struct CheckObjCMessageContext { 180769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 181769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis bool IsPreVisit; 182769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const CheckersTy &Checkers; 183de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose const ObjCMethodCall &Msg; 184769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng; 185769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 186e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 187e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 188e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 189769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 190de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose const ObjCMethodCall &msg, ExprEngine &eng) 191769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 192769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 193769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 1948ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks NodeBuilder &Bldr, ExplodedNode *Pred) { 1953f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 1963f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks ProgramPoint::PostStmtKind; 197b673a41c92aa276f2e37164d0747be1cfb0c402bTed Kremenek const ProgramPoint &L = 198de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose ProgramPoint::getProgramPoint(Msg.getOriginExpr(), 199b673a41c92aa276f2e37164d0747be1cfb0c402bTed Kremenek K, Pred->getLocationContext(), 200b673a41c92aa276f2e37164d0747be1cfb0c402bTed Kremenek checkFn.Checker); 201063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks CheckerContext C(Bldr, Eng, Pred, L); 2023f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks 203769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkFn(Msg, C); 204769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 205769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis }; 206769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 207769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 208769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting obj-c messages. 209769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 210769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet &Dst, 211cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet &Src, 212de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose const ObjCMethodCall &msg, 213769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng) { 2143f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis CheckObjCMessageContext C(isPreVisit, 2153f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis isPreVisit ? PreObjCMessageCheckers 2163f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis : PostObjCMessageCheckers, 2173f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis msg, Eng); 218c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis expandGraphWithCheckers(C, Dst, Src); 219769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 220769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 221769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace { 22296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose // FIXME: This has all the same signatures as CheckObjCMessageContext. 22396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose // Is there a way we can merge the two? 22496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose struct CheckCallContext { 22596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose typedef std::vector<CheckerManager::CheckCallFunc> CheckersTy; 22696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose bool IsPreVisit; 22796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose const CheckersTy &Checkers; 22896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose const CallEvent &Call; 22996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ExprEngine &Eng; 23096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 23196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 23296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 23396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 23496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose CheckCallContext(bool isPreVisit, const CheckersTy &checkers, 23596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose const CallEvent &call, ExprEngine &eng) 23696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose : IsPreVisit(isPreVisit), Checkers(checkers), Call(call), Eng(eng) { } 23796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 23896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose void runChecker(CheckerManager::CheckCallFunc checkFn, 23996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose NodeBuilder &Bldr, ExplodedNode *Pred) { 24096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose // FIXME: This will be wrong as soon as we handle any calls without 24196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose // associated statements. 24296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind 24396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose : ProgramPoint::PostStmtKind; 24496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose assert(Call.getOriginExpr() && "Calls without stmts not yet handled"); 24596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose const ProgramPoint &L = 24696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ProgramPoint::getProgramPoint(Call.getOriginExpr(), 24796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose K, Pred->getLocationContext(), 24896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose checkFn.Checker); 24996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose CheckerContext C(Bldr, Eng, Pred, L); 25096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 25196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose checkFn(Call, C); 25296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose } 25396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose }; 25496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose} 25596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 25696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose/// \brief Run checkers for visiting an abstract call event. 25796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::runCheckersForCallEvent(bool isPreVisit, 25896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ExplodedNodeSet &Dst, 25996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose const ExplodedNodeSet &Src, 26096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose const CallEvent &Call, 26196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose ExprEngine &Eng) { 26296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose CheckCallContext C(isPreVisit, 26396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose isPreVisit ? PreCallCheckers 26496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose : PostCallCheckers, 26596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose Call, Eng); 26696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose expandGraphWithCheckers(C, Dst, Src); 26796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose} 26896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 26996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosenamespace { 270769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis struct CheckLocationContext { 271769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 272769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const CheckersTy &Checkers; 273769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis SVal Loc; 274769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis bool IsLoad; 275bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek const Stmt *NodeEx; /* Will become a CFGStmt */ 276bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek const Stmt *BoundEx; 277769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng; 278769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 279e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 280e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 281e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 282769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckLocationContext(const CheckersTy &checkers, 283bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek SVal loc, bool isLoad, const Stmt *NodeEx, 284bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek const Stmt *BoundEx, 285bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek ExprEngine &eng) 286bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx), 287bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek BoundEx(BoundEx), Eng(eng) {} 288769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 289769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis void runChecker(CheckerManager::CheckLocationFunc checkFn, 2908ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks NodeBuilder &Bldr, ExplodedNode *Pred) { 2913f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind : 2923f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks ProgramPoint::PreStoreKind; 293bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek const ProgramPoint &L = 294bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek ProgramPoint::getProgramPoint(NodeEx, K, 295bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek Pred->getLocationContext(), 296bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek checkFn.Checker); 297063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks CheckerContext C(Bldr, Eng, Pred, L); 298bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek checkFn(Loc, IsLoad, BoundEx, C); 299769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 300769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis }; 3019fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 3029fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 303769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for load/store of a location. 304ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks 305769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 306cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet &Src, 307769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis SVal location, bool isLoad, 308bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek const Stmt *NodeEx, 309bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek const Stmt *BoundEx, 310bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek ExprEngine &Eng) { 311bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx, 312bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek BoundEx, Eng); 313c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis expandGraphWithCheckers(C, Dst, Src); 3149fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 3159fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 316312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisnamespace { 317312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis struct CheckBindContext { 318312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 319312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis const CheckersTy &Checkers; 320312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis SVal Loc; 321312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis SVal Val; 322312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis const Stmt *S; 323312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis ExprEngine &Eng; 324ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks ProgramPoint::Kind PointKind; 325312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis 326312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 327312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 328312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis 329312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis CheckBindContext(const CheckersTy &checkers, 330ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks SVal loc, SVal val, const Stmt *s, ExprEngine &eng, 331ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks ProgramPoint::Kind PK) 332ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {} 333312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis 334312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis void runChecker(CheckerManager::CheckBindFunc checkFn, 3358ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks NodeBuilder &Bldr, ExplodedNode *Pred) { 336ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind, 3373f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks Pred->getLocationContext(), checkFn.Checker); 338063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks CheckerContext C(Bldr, Eng, Pred, L); 3393f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks 340390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks checkFn(Loc, Val, S, C); 341312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis } 342312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis }; 343312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis} 344312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis 345312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis/// \brief Run checkers for binding of a value to a location. 346312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 347312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis const ExplodedNodeSet &Src, 348312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis SVal location, SVal val, 349ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks const Stmt *S, ExprEngine &Eng, 350ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks ProgramPoint::Kind PointKind) { 351ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind); 352312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis expandGraphWithCheckers(C, Dst, Src); 353312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis} 354312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis 35530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 35630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis BugReporter &BR, 35730726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis ExprEngine &Eng) { 35830726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 35930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis EndAnalysisCheckers[i](G, BR, Eng); 36030726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis} 36130726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis 362af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis/// \brief Run checkers for end of path. 363af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks// Note, We do not chain the checker output (like in expandGraphWithCheckers) 364af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks// for this callback since end of path nodes are expected to be final. 365af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaksvoid CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC, 366af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks ExplodedNodeSet &Dst, 367af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis ExprEngine &Eng) { 368af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks ExplodedNode *Pred = BC.Pred; 369af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks 370af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks // We define the builder outside of the loop bacause if at least one checkers 371af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks // creates a sucsessor for Pred, we do not need to generate an 372af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks // autotransition for it. 373af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks NodeBuilder Bldr(Pred, Dst, BC); 374af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 375af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks CheckEndPathFunc checkFn = EndPathCheckers[i]; 376af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks 377af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks const ProgramPoint &L = BlockEntrance(BC.Block, 378af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks Pred->getLocationContext(), 379af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks checkFn.Checker); 380063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks CheckerContext C(Bldr, Eng, Pred, L); 381af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks checkFn(C); 382af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis } 383af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis} 384af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis 385f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaksnamespace { 386f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks struct CheckBranchConditionContext { 387f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy; 388f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks const CheckersTy &Checkers; 389f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks const Stmt *Condition; 390f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks ExprEngine &Eng; 391f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks 392f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 393f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 394f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks 395f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks CheckBranchConditionContext(const CheckersTy &checkers, 396f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks const Stmt *Cond, ExprEngine &eng) 397f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks : Checkers(checkers), Condition(Cond), Eng(eng) {} 398f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks 399f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks void runChecker(CheckerManager::CheckBranchConditionFunc checkFn, 400f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks NodeBuilder &Bldr, ExplodedNode *Pred) { 401f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(), 402f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks checkFn.Checker); 403063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks CheckerContext C(Bldr, Eng, Pred, L); 404f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks checkFn(Condition, C); 405f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks } 406f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks }; 407f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks} 408f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks 409cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis/// \brief Run checkers for branch condition. 410f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaksvoid CheckerManager::runCheckersForBranchCondition(const Stmt *Condition, 411f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks ExplodedNodeSet &Dst, 4124e82d3cf6fd4c907265e3fa3aac0a835c35dc759Anna Zaks ExplodedNode *Pred, 413cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis ExprEngine &Eng) { 414f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks ExplodedNodeSet Src; 415f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks Src.insert(Pred); 416f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng); 417f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks expandGraphWithCheckers(C, Dst, Src); 418cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis} 419cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis 420183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for live symbols. 4218bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekvoid CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state, 422183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SymbolReaper &SymReaper) { 423183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 424183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis LiveSymbolsCheckers[i](state, SymReaper); 425183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 426183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 427183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisnamespace { 428183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis struct CheckDeadSymbolsContext { 429183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 430183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const CheckersTy &Checkers; 431183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SymbolReaper &SR; 432183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Stmt *S; 433183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis ExprEngine &Eng; 4340b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks ProgramPoint::Kind ProgarmPointKind; 435183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 436183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 437183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 438183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 439183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 4400b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks const Stmt *s, ExprEngine &eng, 4410b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks ProgramPoint::Kind K) 4420b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { } 443183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 444183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 4458ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks NodeBuilder &Bldr, ExplodedNode *Pred) { 4460b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind, 4473f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks Pred->getLocationContext(), checkFn.Checker); 448063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks CheckerContext C(Bldr, Eng, Pred, L); 4493f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks 4500b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks // Note, do not pass the statement to the checkers without letting them 4510b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks // differentiate if we ran remove dead bindings before or after the 4520b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks // statement. 453183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis checkFn(SR, C); 454183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis } 455183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis }; 456183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 457183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 458183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for dead symbols. 459183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 460183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const ExplodedNodeSet &Src, 461183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis SymbolReaper &SymReaper, 462183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis const Stmt *S, 4630b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks ExprEngine &Eng, 4640b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks ProgramPoint::Kind K) { 4650b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K); 466183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis expandGraphWithCheckers(C, Dst, Src); 467183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 468183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 469183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief True if at least one checker wants to check region changes. 4708bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekbool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) { 471183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 472183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis if (RegionChangesCheckers[i].WantUpdateFn(state)) 473183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis return true; 474183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 475183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis return false; 476183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 477183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 478183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for region changes. 4798bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef 4808bef8238181a30e52dea380789a7e2d760eac532Ted KremenekCheckerManager::runCheckersForRegionChanges(ProgramStateRef state, 48135bdbf40624beba3fc00cb72ab444659939c1a6bTed Kremenek const StoreManager::InvalidatedSymbols *invalidated, 482537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose ArrayRef<const MemRegion *> ExplicitRegions, 48366c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks ArrayRef<const MemRegion *> Regions, 484740d490593e0de8732a697c9f77b90ddd463863bJordan Rose const CallEvent *Call) { 485183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 486183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis // If any checker declares the state infeasible (or if it starts that way), 487183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis // bail out. 488183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis if (!state) 489183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis return NULL; 490537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose state = RegionChangesCheckers[i].CheckFn(state, invalidated, 49166c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks ExplicitRegions, Regions, Call); 492183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis } 493183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis return state; 494183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 495183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 496312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis/// \brief Run checkers for handling assumptions on symbolic values. 4978bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef 4988bef8238181a30e52dea380789a7e2d760eac532Ted KremenekCheckerManager::runCheckersForEvalAssume(ProgramStateRef state, 499312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis SVal Cond, bool Assumption) { 500312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 501312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis // If any checker declares the state infeasible (or if it starts that way), 502312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis // bail out. 503312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis if (!state) 504312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis return NULL; 505312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis state = EvalAssumeCheckers[i](state, Cond, Assumption); 506312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis } 507312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis return state; 508312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis} 509312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis 510e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis/// \brief Run checkers for evaluating a call. 511e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis/// Only one checker will evaluate the call. 512e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 513e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis const ExplodedNodeSet &Src, 51469f87c956b3ac2b80124fd9604af012e1061473aJordan Rose const SimpleCall &Call, 51569f87c956b3ac2b80124fd9604af012e1061473aJordan Rose ExprEngine &Eng) { 51669f87c956b3ac2b80124fd9604af012e1061473aJordan Rose const CallExpr *CE = Call.getOriginExpr(); 517e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis for (ExplodedNodeSet::iterator 518e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 519e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 520e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis ExplodedNode *Pred = *NI; 521e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis bool anyEvaluated = false; 522dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks 523dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks // First, check if any of the InlineCall callbacks can evaluate the call. 524dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks assert(InlineCallCheckers.size() <= 1 && 525dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks "InlineCall is a special hacky callback to allow intrusive" 526dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks "evaluation of the call (which simulates inlining). It is " 527dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks "currently only used by OSAtomicChecker and should go away " 528dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks "at some point."); 529dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks for (std::vector<InlineCallFunc>::iterator 530dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end(); 531dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks EI != EE; ++EI) { 532dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks ExplodedNodeSet checkDst; 533dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks bool evaluated = (*EI)(CE, Eng, Pred, checkDst); 534dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks assert(!(evaluated && anyEvaluated) 535dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks && "There are more than one checkers evaluating the call"); 536dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks if (evaluated) { 537dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks anyEvaluated = true; 538dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks Dst.insert(checkDst); 539dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks#ifdef NDEBUG 540dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks break; // on release don't check that no other checker also evals. 541dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks#endif 542dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks } 543dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks } 544dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks 545dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks#ifdef NDEBUG // on release don't check that no other checker also evals. 546dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks if (anyEvaluated) { 547dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks break; 548dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks } 549dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks#endif 550dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks 5518ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks ExplodedNodeSet checkDst; 5528ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks NodeBuilder B(Pred, checkDst, Eng.getBuilderContext()); 553dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks // Next, check if any of the EvalCall callbacks can evaluate the call. 554e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis for (std::vector<EvalCallFunc>::iterator 555e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 556e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis EI != EE; ++EI) { 5573f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks ProgramPoint::Kind K = ProgramPoint::PostStmtKind; 5583f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K, 5593f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks Pred->getLocationContext(), EI->Checker); 560b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks bool evaluated = false; 561b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks { // CheckerContext generates transitions(populates checkDest) on 562b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks // destruction, so introduce the scope to make sure it gets properly 563b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks // populated. 564063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks CheckerContext C(B, Eng, Pred, L); 565b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks evaluated = (*EI)(CE, C); 566b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks } 567e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis assert(!(evaluated && anyEvaluated) 568e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis && "There are more than one checkers evaluating the call"); 569e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis if (evaluated) { 570e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis anyEvaluated = true; 571e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis Dst.insert(checkDst); 572e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis#ifdef NDEBUG 573e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis break; // on release don't check that no other checker also evals. 574e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis#endif 575e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis } 576e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis } 577e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 578dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks // If none of the checkers evaluated the call, ask ExprEngine to handle it. 57969f87c956b3ac2b80124fd9604af012e1061473aJordan Rose if (!anyEvaluated) 58069f87c956b3ac2b80124fd9604af012e1061473aJordan Rose Eng.defaultEvalCall(Dst, Pred, Call); 581e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis } 582e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis} 583e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 5849be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek/// \brief Run checkers for the entire Translation Unit. 5859be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenekvoid CheckerManager::runCheckersOnEndOfTranslationUnit( 5869be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek const TranslationUnitDecl *TU, 5879be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek AnalysisManager &mgr, 5889be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek BugReporter &BR) { 5899be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 5909be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek EndOfTranslationUnitCheckers[i](TU, mgr, BR); 5919be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek} 5929be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek 593dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rosevoid CheckerManager::runCheckersForPrintState(raw_ostream &Out, 5948bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek ProgramStateRef State, 595dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose const char *NL, const char *Sep) { 596dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator 597dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I) 598dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose I->second->printState(Out, State, NL, Sep); 599dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose} 600dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose 601769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 602769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for AST traversing. 603769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 604769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 605769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 606769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis HandlesDeclFunc isForDeclFn) { 607769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis DeclCheckerInfo info = { checkfn, isForDeclFn }; 608769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis DeclCheckers.push_back(info); 609769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 610769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 611769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 612769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis BodyCheckers.push_back(checkfn); 613769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 614769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 615769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 616769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for path-sensitive checking. 617769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 618769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 619769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 620769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis HandlesStmtFunc isForStmtFn) { 621769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 622769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckers.push_back(info); 623769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 624769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 625769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis HandlesStmtFunc isForStmtFn) { 626769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 627769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckers.push_back(info); 628769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 629769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 630769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 631769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis PreObjCMessageCheckers.push_back(checkfn); 632769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 633769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 634769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis PostObjCMessageCheckers.push_back(checkfn); 635769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 636769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 63796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::_registerForPreCall(CheckCallFunc checkfn) { 63896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose PreCallCheckers.push_back(checkfn); 63996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose} 64096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::_registerForPostCall(CheckCallFunc checkfn) { 64196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose PostCallCheckers.push_back(checkfn); 64296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose} 64396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose 644769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 645769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis LocationCheckers.push_back(checkfn); 646769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 647769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 648312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::_registerForBind(CheckBindFunc checkfn) { 649312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis BindCheckers.push_back(checkfn); 650312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis} 651312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis 65230726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 65330726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis EndAnalysisCheckers.push_back(checkfn); 65430726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis} 65530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis 656af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidisvoid CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 657af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis EndPathCheckers.push_back(checkfn); 658af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis} 659af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis 660cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidisvoid CheckerManager::_registerForBranchCondition( 661cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis CheckBranchConditionFunc checkfn) { 662cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis BranchConditionCheckers.push_back(checkfn); 663cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis} 664cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis 665183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 666183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis LiveSymbolsCheckers.push_back(checkfn); 667183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 668183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 669183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 670183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis DeadSymbolsCheckers.push_back(checkfn); 671183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 672183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 673183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 674183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis WantsRegionChangeUpdateFunc wantUpdateFn) { 675183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 676183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis RegionChangesCheckers.push_back(info); 677183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis} 678183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis 679312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 680312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis EvalAssumeCheckers.push_back(checkfn); 681312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis} 682312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis 683e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 684e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis EvalCallCheckers.push_back(checkfn); 685e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis} 686e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 687dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaksvoid CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) { 688dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks InlineCallCheckers.push_back(checkfn); 689dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks} 690dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks 6919be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenekvoid CheckerManager::_registerForEndOfTranslationUnit( 6929be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek CheckEndOfTranslationUnit checkfn) { 6939be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek EndOfTranslationUnitCheckers.push_back(checkfn); 6949be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek} 6959be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek 696769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 697769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Implementation details. 698769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 699769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 700769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::CachedStmtCheckers * 701769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 702769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis assert(S); 703769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 704769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 705769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CachedStmtCheckers *checkers = 0; 706769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 707769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis if (CCI != CachedStmtCheckersMap.end()) { 708769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkers = &(CCI->second); 709769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } else { 710769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis // Find the checkers that should run for this Stmt and cache them. 711769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkers = &CachedStmtCheckersMap[key]; 712769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 713769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckerInfo &info = StmtCheckers[i]; 714769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 715769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkers->push_back(info.CheckFn); 716769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 7179fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } 718769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 719769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis assert(checkers); 720769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis return checkers; 721769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 722769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 723769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::~CheckerManager() { 724769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 725769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckerDtors[i](); 7269fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 727