CheckerManager.cpp revision cd50e136ad7dc721822f5e6350769a37c216612d
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" 1543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerProvider.h" 16769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 17769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis#include "clang/Analysis/ProgramPoint.h" 189fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "clang/AST/DeclBase.h" 1943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 2043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace clang; 2143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace ento; 2243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 23769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 24769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for AST traversing.. 25769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 26769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 279fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 289fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis BugReporter &BR) { 299fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis assert(D); 309fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 319fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis unsigned DeclKind = D->getKind(); 329fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis CachedDeclCheckers *checkers = 0; 339fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 349fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis if (CCI != CachedDeclCheckersMap.end()) { 359fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis checkers = &(CCI->second); 369fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } else { 379fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis // Find the checkers that should run for this Decl and cache them. 389fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis checkers = &CachedDeclCheckersMap[DeclKind]; 399fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 409fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis DeclCheckerInfo &info = DeclCheckers[i]; 419fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis if (info.IsForDeclFn(D)) 42769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkers->push_back(info.CheckFn); 439fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } 449fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } 459fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 469fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis assert(checkers); 479fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis for (CachedDeclCheckers::iterator 48769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis I = checkers->begin(), E = checkers->end(); I != E; ++I) 49769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis (*I)(D, mgr, BR); 509fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 519fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 529fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 539fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis BugReporter &BR) { 549fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis assert(D && D->hasBody()); 559fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 56769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 57769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis BodyCheckers[i](D, mgr, BR); 58769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 59769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 60769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 61769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for path-sensitive checking. 62769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 63769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 64769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidistemplate <typename CHECK_CTX> 65c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidisstatic void expandGraphWithCheckers(CHECK_CTX checkCtx, 66c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis ExplodedNodeSet &Dst, 67cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet &Src) { 68769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 69e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis typename CHECK_CTX::CheckersTy::const_iterator 70e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 71e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis if (I == E) { 72769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis Dst.insert(Src); 73769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis return; 74769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 75769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 76cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis ExplodedNodeSet Tmp1, Tmp2; 77cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet *PrevSet = &Src; 78769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 79e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis for (; I != E; ++I) { 80769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet *CurrSet = 0; 81769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis if (I+1 == E) 82769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CurrSet = &Dst; 83769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis else { 84cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 85769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CurrSet->clear(); 86769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 87769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 88769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 89769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis NI != NE; ++NI) 90769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkCtx.runChecker(*I, *CurrSet, *NI); 91769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 92769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis // Update which NodeSet is the current one. 93769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis PrevSet = CurrSet; 949fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } 959fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 969fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 97769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace { 98769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis struct CheckStmtContext { 99769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 100769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis bool IsPreVisit; 101769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const CheckersTy &Checkers; 102769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const Stmt *S; 103769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng; 104769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 105e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 106e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 107e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 108769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 109769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const Stmt *s, ExprEngine &eng) 110769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { } 111769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 112769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis void runChecker(CheckerManager::CheckStmtFunc checkFn, 113769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet &Dst, ExplodedNode *Pred) { 114769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis // FIXME: Remove respondsToCallback from CheckerContext; 115769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 116769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis IsPreVisit ? ProgramPoint::PreStmtKind : 117769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ProgramPoint::PostStmtKind, 0, S); 118769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkFn(S, C); 119769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 120769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis }; 121769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 122769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 123769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting Stmts. 124769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForStmt(bool isPreVisit, 125769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet &Dst, 126cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet &Src, 127769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const Stmt *S, 128769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng) { 129769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 130769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis S, Eng); 131c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis expandGraphWithCheckers(C, Dst, Src); 132769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 133769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 134769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace { 135769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis struct CheckObjCMessageContext { 136769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 137769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis bool IsPreVisit; 138769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const CheckersTy &Checkers; 139769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const ObjCMessage &Msg; 140769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng; 141769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 142e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 143e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 144e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 145769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 146769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const ObjCMessage &msg, ExprEngine &eng) 147769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 148769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 149769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 150769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet &Dst, ExplodedNode *Pred) { 151769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 152769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis IsPreVisit ? ProgramPoint::PreStmtKind : 153769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ProgramPoint::PostStmtKind, 0, 154769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis Msg.getOriginExpr()); 155769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkFn(Msg, C); 156769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 157769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis }; 158769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 159769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 160769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting obj-c messages. 161769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 162769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet &Dst, 163cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet &Src, 164769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const ObjCMessage &msg, 165769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng) { 1663f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis CheckObjCMessageContext C(isPreVisit, 1673f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis isPreVisit ? PreObjCMessageCheckers 1683f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis : PostObjCMessageCheckers, 1693f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis msg, Eng); 170c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis expandGraphWithCheckers(C, Dst, Src); 171769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 172769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 173769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace { 174769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis struct CheckLocationContext { 175769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 176769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const CheckersTy &Checkers; 177769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis SVal Loc; 178769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis bool IsLoad; 179769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const Stmt *S; 180769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const GRState *State; 181769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng; 182769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 183e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 184e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 185e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 186769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckLocationContext(const CheckersTy &checkers, 187769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis SVal loc, bool isLoad, const Stmt *s, 188769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const GRState *state, ExprEngine &eng) 189769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), 190769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis State(state), Eng(eng) { } 191769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 192769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis void runChecker(CheckerManager::CheckLocationFunc checkFn, 193769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExplodedNodeSet &Dst, ExplodedNode *Pred) { 194769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker, 195769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis IsLoad ? ProgramPoint::PreLoadKind : 196769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ProgramPoint::PreStoreKind, 0, S, State); 197769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkFn(Loc, IsLoad, C); 198769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 199769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis }; 2009fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 2019fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 202769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for load/store of a location. 203769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 204cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis const ExplodedNodeSet &Src, 205769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis SVal location, bool isLoad, 206769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const Stmt *S, 207769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis const GRState *state, 208769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis ExprEngine &Eng) { 209769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckLocationContext C(LocationCheckers, location, isLoad, S, state, Eng); 210c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis expandGraphWithCheckers(C, Dst, Src); 2119fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 2129fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 21330726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 21430726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis BugReporter &BR, 21530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis ExprEngine &Eng) { 21630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 21730726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis EndAnalysisCheckers[i](G, BR, Eng); 21830726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis} 21930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis 220e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis/// \brief Run checkers for evaluating a call. 221e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis/// Only one checker will evaluate the call. 222e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 223e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis const ExplodedNodeSet &Src, 224e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis const CallExpr *CE, 225e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis ExprEngine &Eng, 226e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis GraphExpander *defaultEval) { 227e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis if (EvalCallCheckers.empty() && defaultEval == 0) { 228e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis Dst.insert(Src); 229e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis return; 230e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis } 231e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 232e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis for (ExplodedNodeSet::iterator 233e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 234e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 235e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis ExplodedNode *Pred = *NI; 236e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis bool anyEvaluated = false; 237e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis for (std::vector<EvalCallFunc>::iterator 238e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 239e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis EI != EE; ++EI) { 240e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis ExplodedNodeSet checkDst; 241e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker, 242e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis ProgramPoint::PostStmtKind, 0, CE); 243e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis bool evaluated = (*EI)(CE, C); 244e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis assert(!(evaluated && anyEvaluated) 245e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis && "There are more than one checkers evaluating the call"); 246e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis if (evaluated) { 247e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis anyEvaluated = true; 248e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis Dst.insert(checkDst); 249e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis#ifdef NDEBUG 250e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis break; // on release don't check that no other checker also evals. 251e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis#endif 252e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis } 253e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis } 254e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 255e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis if (!anyEvaluated) { 256e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis if (defaultEval) 257e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis defaultEval->expandGraph(Dst, Pred); 258e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis else 259e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis Dst.insert(Pred); 260e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis } 261e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis } 262e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis} 263e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 26443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisvoid CheckerManager::registerCheckersToEngine(ExprEngine &eng) { 26543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis for (unsigned i = 0, e = Funcs.size(); i != e; ++i) 26643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis Funcs[i](eng); 26743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis} 26843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis 269769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 270769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for AST traversing. 271769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 272769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 273769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 274769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis HandlesDeclFunc isForDeclFn) { 275769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis DeclCheckerInfo info = { checkfn, isForDeclFn }; 276769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis DeclCheckers.push_back(info); 277769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 278769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 279769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 280769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis BodyCheckers.push_back(checkfn); 281769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 282769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 283769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 284769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for path-sensitive checking. 285769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 286769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 287769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 288769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis HandlesStmtFunc isForStmtFn) { 289769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 290769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckers.push_back(info); 291769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 292769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 293769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis HandlesStmtFunc isForStmtFn) { 294769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 295769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckers.push_back(info); 296769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 297769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 298769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 299769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis PreObjCMessageCheckers.push_back(checkfn); 300769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 301769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 302769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis PostObjCMessageCheckers.push_back(checkfn); 303769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 304769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 305769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 306769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis LocationCheckers.push_back(checkfn); 307769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 308769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 30930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 31030726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis EndAnalysisCheckers.push_back(checkfn); 31130726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis} 31230726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis 313e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 314e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis EvalCallCheckers.push_back(checkfn); 315e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis} 316e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 317769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 318769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Implementation details. 319769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===// 320769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 321769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::CachedStmtCheckers * 322769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 323769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis assert(S); 324769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 325769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 326769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CachedStmtCheckers *checkers = 0; 327769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 328769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis if (CCI != CachedStmtCheckersMap.end()) { 329769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkers = &(CCI->second); 330769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } else { 331769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis // Find the checkers that should run for this Stmt and cache them. 332769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkers = &CachedStmtCheckersMap[key]; 333769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 334769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis StmtCheckerInfo &info = StmtCheckers[i]; 335769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 336769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis checkers->push_back(info.CheckFn); 337769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis } 3389fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis } 339769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 340769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis assert(checkers); 341769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis return checkers; 342769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis} 343769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis 344769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::~CheckerManager() { 345769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 346769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis CheckerDtors[i](); 3479fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis} 3489fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis 34943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// Anchor for the vtable. 35043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios KyrtzidisCheckerProvider::~CheckerProvider() { } 351e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis 352e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis// Anchor for the vtable. 353e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios KyrtzidisGraphExpander::~GraphExpander() { } 354