CheckerManager.cpp revision 514f2c9dcb9e04b52929c5b141a6fe88bd68b33f
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===// 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The LLVM Compiler Infrastructure 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 5a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details. 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Defines the Static Analyzer Checker Manager. 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 13a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 14a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/ObjCMessage.h" 18a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "clang/Analysis/ProgramPoint.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/DeclBase.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang; 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento; 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CheckerManager::hasPathSensitiveCheckers() const { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !StmtCheckers.empty() || 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !PreObjCMessageCheckers.empty() || 27a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !PostObjCMessageCheckers.empty() || 28a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !LocationCheckers.empty() || 29a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !BindCheckers.empty() || 30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !EndAnalysisCheckers.empty() || 31a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !EndPathCheckers.empty() || 32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch !BranchConditionCheckers.empty() || 33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch !LiveSymbolsCheckers.empty() || 34a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch !DeadSymbolsCheckers.empty() || 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !RegionChangesCheckers.empty() || 36a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !EvalAssumeCheckers.empty() || 37a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !EvalCallCheckers.empty() || 38a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) !InlineCallCheckers.empty(); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::finishedCheckerRegistration() { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that for every event that has listeners, there is at least 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // one dispatcher registered for it. 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (llvm::DenseMap<EventTag, EventInfo>::iterator 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = Events.begin(), E = Events.end(); I != E; ++I) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions for running checkers for AST traversing.. 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR) { 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(D); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned DeclKind = D->getKind(); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CachedDeclCheckers *checkers = 0; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CCI != CachedDeclCheckersMap.end()) { 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkers = &(CCI->second); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find the checkers that should run for this Decl and cache them. 66a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) checkers = &CachedDeclCheckersMap[DeclKind]; 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DeclCheckerInfo &info = DeclCheckers[i]; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (info.IsForDeclFn(D)) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkers->push_back(info.CheckFn); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 74a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) assert(checkers); 75a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for (CachedDeclCheckers::iterator 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = checkers->begin(), E = checkers->end(); I != E; ++I) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (*I)(D, mgr, BR); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BugReporter &BR) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert(D && D->hasBody()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) BodyCheckers[i](D, mgr, BR); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions for running checkers for path-sensitive checking. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===// 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename CHECK_CTX> 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void expandGraphWithCheckers(CHECK_CTX checkCtx, 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &Dst, 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExplodedNodeSet &Src) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext(); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (Src.empty()) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) typename CHECK_CTX::CheckersTy::const_iterator 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (I == E) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Dst.insert(Src); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 105a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 106a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet Tmp1, Tmp2; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExplodedNodeSet *PrevSet = &Src; 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (; I != E; ++I) { 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet *CurrSet = 0; 112a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if (I+1 == E) 113a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CurrSet = &Dst; 1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else { 115a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 1165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CurrSet->clear(); 1175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 118a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NodeBuilder B(*PrevSet, *CurrSet, BldrCtx); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NI != NE; ++NI) { 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkCtx.runChecker(*I, B, *NI); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If all the produced transitions are sinks, stop. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (CurrSet->empty()) 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Update which NodeSet is the current one. 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrevSet = CurrSet; 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 134a02191e04bc25c4935f804f2c080ae28663d096dBen Murdochnamespace { 135a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch struct CheckStmtContext { 136a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 137a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool IsPreVisit; 138a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const CheckersTy &Checkers; 139a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const Stmt *S; 140a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ExprEngine &Eng; 141a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch bool wasInlined; 142a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 146a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 147a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch const Stmt *s, ExprEngine &eng, bool wasInlined = false) 148a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng), 149a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch wasInlined(wasInlined) {} 150a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 151a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch void runChecker(CheckerManager::CheckStmtFunc checkFn, 152a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch NodeBuilder &Bldr, ExplodedNode *Pred) { 153a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch // FIXME: Remove respondsToCallback from CheckerContext; 154a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 155a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ProgramPoint::PostStmtKind; 156a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 157a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) Pred->getLocationContext(), checkFn.Checker); 158a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CheckerContext C(Bldr, Eng, Pred, L, wasInlined); 159a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) checkFn(S, C); 160a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch } 161a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch }; 162a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch} 163a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 164a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch/// \brief Run checkers for visiting Stmts. 165a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)void CheckerManager::runCheckersForStmt(bool isPreVisit, 166a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch ExplodedNodeSet &Dst, 167a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ExplodedNodeSet &Src, 168a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const Stmt *S, 169a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ExprEngine &Eng, 170a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool wasInlined) { 171a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 172a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) S, Eng, wasInlined); 173a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 174a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 175a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 176a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)namespace { 177a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) struct CheckObjCMessageContext { 178a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 179a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) bool IsPreVisit; 180a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const CheckersTy &Checkers; 181a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const ObjCMessage &Msg; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ExprEngine &Eng; 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMessage &msg, ExprEngine &eng) 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NodeBuilder &Bldr, ExplodedNode *Pred) { 193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramPoint::PostStmtKind; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ProgramPoint &L = 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ProgramPoint::getProgramPoint(Msg.getMessageExpr(), 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) K, Pred->getLocationContext(), 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkFn.Checker); 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckerContext C(Bldr, Eng, Pred, L); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) checkFn(Msg, C); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for visiting obj-c messages. 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExplodedNodeSet &Dst, 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ExplodedNodeSet &Src, 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const ObjCMessage &msg, 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng) { 212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CheckObjCMessageContext C(isPreVisit, 213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) isPreVisit ? PreObjCMessageCheckers 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : PostObjCMessageCheckers, 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) msg, Eng); 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) struct CheckLocationContext { 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const CheckersTy &Checkers; 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal Loc; 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool IsLoad; 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const Stmt *S; 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExprEngine &Eng; 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CheckLocationContext(const CheckersTy &checkers, 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng) 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { } 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235 void runChecker(CheckerManager::CheckLocationFunc checkFn, 236 NodeBuilder &Bldr, ExplodedNode *Pred) { 237 ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind : 238 ProgramPoint::PreStoreKind; 239 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 240 Pred->getLocationContext(), checkFn.Checker); 241 CheckerContext C(Bldr, Eng, Pred, L); 242 243 checkFn(Loc, IsLoad, S, C); 244 } 245 }; 246} 247 248/// \brief Run checkers for load/store of a location. 249 250void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 251 const ExplodedNodeSet &Src, 252 SVal location, bool isLoad, 253 const Stmt *S, ExprEngine &Eng) { 254 CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng); 255 expandGraphWithCheckers(C, Dst, Src); 256} 257 258namespace { 259 struct CheckBindContext { 260 typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 261 const CheckersTy &Checkers; 262 SVal Loc; 263 SVal Val; 264 const Stmt *S; 265 ExprEngine &Eng; 266 ProgramPoint::Kind PointKind; 267 268 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 269 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 270 271 CheckBindContext(const CheckersTy &checkers, 272 SVal loc, SVal val, const Stmt *s, ExprEngine &eng, 273 ProgramPoint::Kind PK) 274 : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {} 275 276 void runChecker(CheckerManager::CheckBindFunc checkFn, 277 NodeBuilder &Bldr, ExplodedNode *Pred) { 278 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind, 279 Pred->getLocationContext(), checkFn.Checker); 280 CheckerContext C(Bldr, Eng, Pred, L); 281 282 checkFn(Loc, Val, S, C); 283 } 284 }; 285} 286 287/// \brief Run checkers for binding of a value to a location. 288void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 289 const ExplodedNodeSet &Src, 290 SVal location, SVal val, 291 const Stmt *S, ExprEngine &Eng, 292 ProgramPoint::Kind PointKind) { 293 CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind); 294 expandGraphWithCheckers(C, Dst, Src); 295} 296 297void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 298 BugReporter &BR, 299 ExprEngine &Eng) { 300 for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 301 EndAnalysisCheckers[i](G, BR, Eng); 302} 303 304/// \brief Run checkers for end of path. 305// Note, We do not chain the checker output (like in expandGraphWithCheckers) 306// for this callback since end of path nodes are expected to be final. 307void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC, 308 ExplodedNodeSet &Dst, 309 ExprEngine &Eng) { 310 ExplodedNode *Pred = BC.Pred; 311 312 // We define the builder outside of the loop bacause if at least one checkers 313 // creates a sucsessor for Pred, we do not need to generate an 314 // autotransition for it. 315 NodeBuilder Bldr(Pred, Dst, BC); 316 for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 317 CheckEndPathFunc checkFn = EndPathCheckers[i]; 318 319 const ProgramPoint &L = BlockEntrance(BC.Block, 320 Pred->getLocationContext(), 321 checkFn.Checker); 322 CheckerContext C(Bldr, Eng, Pred, L); 323 checkFn(C); 324 } 325} 326 327namespace { 328 struct CheckBranchConditionContext { 329 typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy; 330 const CheckersTy &Checkers; 331 const Stmt *Condition; 332 ExprEngine &Eng; 333 334 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 335 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 336 337 CheckBranchConditionContext(const CheckersTy &checkers, 338 const Stmt *Cond, ExprEngine &eng) 339 : Checkers(checkers), Condition(Cond), Eng(eng) {} 340 341 void runChecker(CheckerManager::CheckBranchConditionFunc checkFn, 342 NodeBuilder &Bldr, ExplodedNode *Pred) { 343 ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(), 344 checkFn.Checker); 345 CheckerContext C(Bldr, Eng, Pred, L); 346 checkFn(Condition, C); 347 } 348 }; 349} 350 351/// \brief Run checkers for branch condition. 352void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition, 353 ExplodedNodeSet &Dst, 354 ExplodedNode *Pred, 355 ExprEngine &Eng) { 356 ExplodedNodeSet Src; 357 Src.insert(Pred); 358 CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng); 359 expandGraphWithCheckers(C, Dst, Src); 360} 361 362/// \brief Run checkers for live symbols. 363void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state, 364 SymbolReaper &SymReaper) { 365 for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 366 LiveSymbolsCheckers[i](state, SymReaper); 367} 368 369namespace { 370 struct CheckDeadSymbolsContext { 371 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 372 const CheckersTy &Checkers; 373 SymbolReaper &SR; 374 const Stmt *S; 375 ExprEngine &Eng; 376 377 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 378 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 379 380 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 381 const Stmt *s, ExprEngine &eng) 382 : Checkers(checkers), SR(sr), S(s), Eng(eng) { } 383 384 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 385 NodeBuilder &Bldr, ExplodedNode *Pred) { 386 ProgramPoint::Kind K = ProgramPoint::PostPurgeDeadSymbolsKind; 387 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 388 Pred->getLocationContext(), checkFn.Checker); 389 CheckerContext C(Bldr, Eng, Pred, L); 390 391 checkFn(SR, C); 392 } 393 }; 394} 395 396/// \brief Run checkers for dead symbols. 397void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 398 const ExplodedNodeSet &Src, 399 SymbolReaper &SymReaper, 400 const Stmt *S, 401 ExprEngine &Eng) { 402 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng); 403 expandGraphWithCheckers(C, Dst, Src); 404} 405 406/// \brief True if at least one checker wants to check region changes. 407bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) { 408 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 409 if (RegionChangesCheckers[i].WantUpdateFn(state)) 410 return true; 411 412 return false; 413} 414 415/// \brief Run checkers for region changes. 416ProgramStateRef 417CheckerManager::runCheckersForRegionChanges(ProgramStateRef state, 418 const StoreManager::InvalidatedSymbols *invalidated, 419 ArrayRef<const MemRegion *> ExplicitRegions, 420 ArrayRef<const MemRegion *> Regions, 421 const CallOrObjCMessage *Call) { 422 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 423 // If any checker declares the state infeasible (or if it starts that way), 424 // bail out. 425 if (!state) 426 return NULL; 427 state = RegionChangesCheckers[i].CheckFn(state, invalidated, 428 ExplicitRegions, Regions, Call); 429 } 430 return state; 431} 432 433/// \brief Run checkers for handling assumptions on symbolic values. 434ProgramStateRef 435CheckerManager::runCheckersForEvalAssume(ProgramStateRef state, 436 SVal Cond, bool Assumption) { 437 for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 438 // If any checker declares the state infeasible (or if it starts that way), 439 // bail out. 440 if (!state) 441 return NULL; 442 state = EvalAssumeCheckers[i](state, Cond, Assumption); 443 } 444 return state; 445} 446 447/// \brief Run checkers for evaluating a call. 448/// Only one checker will evaluate the call. 449void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 450 const ExplodedNodeSet &Src, 451 const CallExpr *CE, 452 ExprEngine &Eng, 453 GraphExpander *defaultEval) { 454 if (EvalCallCheckers.empty() && 455 InlineCallCheckers.empty() && 456 defaultEval == 0) { 457 Dst.insert(Src); 458 return; 459 } 460 461 for (ExplodedNodeSet::iterator 462 NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 463 464 ExplodedNode *Pred = *NI; 465 bool anyEvaluated = false; 466 467 // First, check if any of the InlineCall callbacks can evaluate the call. 468 assert(InlineCallCheckers.size() <= 1 && 469 "InlineCall is a special hacky callback to allow intrusive" 470 "evaluation of the call (which simulates inlining). It is " 471 "currently only used by OSAtomicChecker and should go away " 472 "at some point."); 473 for (std::vector<InlineCallFunc>::iterator 474 EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end(); 475 EI != EE; ++EI) { 476 ExplodedNodeSet checkDst; 477 bool evaluated = (*EI)(CE, Eng, Pred, checkDst); 478 assert(!(evaluated && anyEvaluated) 479 && "There are more than one checkers evaluating the call"); 480 if (evaluated) { 481 anyEvaluated = true; 482 Dst.insert(checkDst); 483#ifdef NDEBUG 484 break; // on release don't check that no other checker also evals. 485#endif 486 } 487 } 488 489#ifdef NDEBUG // on release don't check that no other checker also evals. 490 if (anyEvaluated) { 491 break; 492 } 493#endif 494 495 ExplodedNodeSet checkDst; 496 NodeBuilder B(Pred, checkDst, Eng.getBuilderContext()); 497 // Next, check if any of the EvalCall callbacks can evaluate the call. 498 for (std::vector<EvalCallFunc>::iterator 499 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 500 EI != EE; ++EI) { 501 ProgramPoint::Kind K = ProgramPoint::PostStmtKind; 502 const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K, 503 Pred->getLocationContext(), EI->Checker); 504 bool evaluated = false; 505 { // CheckerContext generates transitions(populates checkDest) on 506 // destruction, so introduce the scope to make sure it gets properly 507 // populated. 508 CheckerContext C(B, Eng, Pred, L); 509 evaluated = (*EI)(CE, C); 510 } 511 assert(!(evaluated && anyEvaluated) 512 && "There are more than one checkers evaluating the call"); 513 if (evaluated) { 514 anyEvaluated = true; 515 Dst.insert(checkDst); 516#ifdef NDEBUG 517 break; // on release don't check that no other checker also evals. 518#endif 519 } 520 } 521 522 // If none of the checkers evaluated the call, ask ExprEngine to handle it. 523 if (!anyEvaluated) { 524 if (defaultEval) 525 defaultEval->expandGraph(Dst, Pred); 526 else 527 Dst.insert(Pred); 528 } 529 } 530} 531 532/// \brief Run checkers for the entire Translation Unit. 533void CheckerManager::runCheckersOnEndOfTranslationUnit( 534 const TranslationUnitDecl *TU, 535 AnalysisManager &mgr, 536 BugReporter &BR) { 537 for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 538 EndOfTranslationUnitCheckers[i](TU, mgr, BR); 539} 540 541void CheckerManager::runCheckersForPrintState(raw_ostream &Out, 542 ProgramStateRef State, 543 const char *NL, const char *Sep) { 544 for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator 545 I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I) 546 I->second->printState(Out, State, NL, Sep); 547} 548 549//===----------------------------------------------------------------------===// 550// Internal registration functions for AST traversing. 551//===----------------------------------------------------------------------===// 552 553void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 554 HandlesDeclFunc isForDeclFn) { 555 DeclCheckerInfo info = { checkfn, isForDeclFn }; 556 DeclCheckers.push_back(info); 557} 558 559void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 560 BodyCheckers.push_back(checkfn); 561} 562 563//===----------------------------------------------------------------------===// 564// Internal registration functions for path-sensitive checking. 565//===----------------------------------------------------------------------===// 566 567void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 568 HandlesStmtFunc isForStmtFn) { 569 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 570 StmtCheckers.push_back(info); 571} 572void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 573 HandlesStmtFunc isForStmtFn) { 574 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 575 StmtCheckers.push_back(info); 576} 577 578void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 579 PreObjCMessageCheckers.push_back(checkfn); 580} 581void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 582 PostObjCMessageCheckers.push_back(checkfn); 583} 584 585void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 586 LocationCheckers.push_back(checkfn); 587} 588 589void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 590 BindCheckers.push_back(checkfn); 591} 592 593void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 594 EndAnalysisCheckers.push_back(checkfn); 595} 596 597void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 598 EndPathCheckers.push_back(checkfn); 599} 600 601void CheckerManager::_registerForBranchCondition( 602 CheckBranchConditionFunc checkfn) { 603 BranchConditionCheckers.push_back(checkfn); 604} 605 606void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 607 LiveSymbolsCheckers.push_back(checkfn); 608} 609 610void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 611 DeadSymbolsCheckers.push_back(checkfn); 612} 613 614void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 615 WantsRegionChangeUpdateFunc wantUpdateFn) { 616 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 617 RegionChangesCheckers.push_back(info); 618} 619 620void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 621 EvalAssumeCheckers.push_back(checkfn); 622} 623 624void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 625 EvalCallCheckers.push_back(checkfn); 626} 627 628void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) { 629 InlineCallCheckers.push_back(checkfn); 630} 631 632void CheckerManager::_registerForEndOfTranslationUnit( 633 CheckEndOfTranslationUnit checkfn) { 634 EndOfTranslationUnitCheckers.push_back(checkfn); 635} 636 637//===----------------------------------------------------------------------===// 638// Implementation details. 639//===----------------------------------------------------------------------===// 640 641CheckerManager::CachedStmtCheckers * 642CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 643 assert(S); 644 645 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 646 CachedStmtCheckers *checkers = 0; 647 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 648 if (CCI != CachedStmtCheckersMap.end()) { 649 checkers = &(CCI->second); 650 } else { 651 // Find the checkers that should run for this Stmt and cache them. 652 checkers = &CachedStmtCheckersMap[key]; 653 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 654 StmtCheckerInfo &info = StmtCheckers[i]; 655 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 656 checkers->push_back(info.CheckFn); 657 } 658 } 659 660 assert(checkers); 661 return checkers; 662} 663 664CheckerManager::~CheckerManager() { 665 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 666 CheckerDtors[i](); 667} 668 669// Anchor for the vtable. 670GraphExpander::~GraphExpander() { } 671