CheckerManager.cpp revision e81ce256b62717dd846bd19aecc4115a0dcd4995
1c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===// 2c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 3c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// The LLVM Compiler Infrastructure 4c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// This file is distributed under the University of Illinois Open Source 6c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// License. See LICENSE.TXT for details. 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// 10c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Defines the Static Analyzer Checker Manager. 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)// 12c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 13c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 14868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h" 15c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h" 16c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h" 18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/Analysis/ProgramPoint.h" 19c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "clang/AST/DeclBase.h" 207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) 21c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace clang; 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)using namespace ento; 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool CheckerManager::hasPathSensitiveCheckers() const { 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return !StmtCheckers.empty() || 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !PreObjCMessageCheckers.empty() || 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !PostObjCMessageCheckers.empty() || 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !PreCallCheckers.empty() || 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !PostCallCheckers.empty() || 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !LocationCheckers.empty() || 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !BindCheckers.empty() || 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !EndAnalysisCheckers.empty() || 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !EndPathCheckers.empty() || 34c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !BranchConditionCheckers.empty() || 35c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !LiveSymbolsCheckers.empty() || 36868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) !DeadSymbolsCheckers.empty() || 377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) !RegionChangesCheckers.empty() || 38c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !EvalAssumeCheckers.empty() || 39c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !EvalCallCheckers.empty() || 40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) !InlineCallCheckers.empty(); 41c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 42c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 43c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::finishedCheckerRegistration() { 44558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#ifndef NDEBUG 45558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Make sure that for every event that has listeners, there is at least 46558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // one dispatcher registered for it. 47558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch for (llvm::DenseMap<EventTag, EventInfo>::iterator 48558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch I = Events.begin(), E = Events.end(); I != E; ++I) 49558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch assert(I->second.HasDispatcher && "No dispatcher registered for an event"); 50558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#endif 51558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 52c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 53c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 54c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Functions for running checkers for AST traversing.. 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BugReporter &BR) { 59c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) assert(D); 60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 61c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) unsigned DeclKind = D->getKind(); 62c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CachedDeclCheckers *checkers = 0; 63c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind); 64c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (CCI != CachedDeclCheckersMap.end()) { 65c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkers = &(CCI->second); 66c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } else { 67c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Find the checkers that should run for this Decl and cache them. 68c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkers = &CachedDeclCheckersMap[DeclKind]; 69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) { 70c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) DeclCheckerInfo &info = DeclCheckers[i]; 71c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (info.IsForDeclFn(D)) 72c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkers->push_back(info.CheckFn); 73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 74c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 75c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 76c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) assert(checkers); 77c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (CachedDeclCheckers::iterator 78c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) I = checkers->begin(), E = checkers->end(); I != E; ++I) 79c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) (*I)(D, mgr, BR); 80c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 81c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, 83c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BugReporter &BR) { 84c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) assert(D && D->hasBody()); 85c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 86c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i) 87c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BodyCheckers[i](D, mgr, BR); 88c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 89c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 90c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 91c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Functions for running checkers for path-sensitive checking. 92c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)//===----------------------------------------------------------------------===// 93c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 94c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)template <typename CHECK_CTX> 95c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)static void expandGraphWithCheckers(CHECK_CTX checkCtx, 96c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExplodedNodeSet &Dst, 97c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ExplodedNodeSet &Src) { 98c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext(); 99c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (Src.empty()) 100c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 101c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) typename CHECK_CTX::CheckersTy::const_iterator 103c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) I = checkCtx.checkers_begin(), E = checkCtx.checkers_end(); 104c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (I == E) { 105c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Dst.insert(Src); 106c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 107c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 108c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 109c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExplodedNodeSet Tmp1, Tmp2; 110c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ExplodedNodeSet *PrevSet = &Src; 111c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (; I != E; ++I) { 113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExplodedNodeSet *CurrSet = 0; 114c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (I+1 == E) 115c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CurrSet = &Dst; 116c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) else { 117c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1; 118c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CurrSet->clear(); 119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 120c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 121c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NodeBuilder B(*PrevSet, *CurrSet, BldrCtx); 122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end(); 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) NI != NE; ++NI) { 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) checkCtx.runChecker(*I, B, *NI); 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) } 126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 127c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // If all the produced transitions are sinks, stop. 128c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (CurrSet->empty()) 129c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return; 130c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 131c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Update which NodeSet is the current one. 132c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) PrevSet = CurrSet; 133c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 134c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 135c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 136c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct CheckStmtContext { 138c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy; 139c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool IsPreVisit; 140c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CheckersTy &Checkers; 141c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *S; 142c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng; 1437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) bool wasInlined; 144c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 145c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 148c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckStmtContext(bool isPreVisit, const CheckersTy &checkers, 149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *s, ExprEngine &eng, bool wasInlined = false) 150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng), 151c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) wasInlined(wasInlined) {} 152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void runChecker(CheckerManager::CheckStmtFunc checkFn, 154c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NodeBuilder &Bldr, ExplodedNode *Pred) { 155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // FIXME: Remove respondsToCallback from CheckerContext; 1567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 157c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::PostStmtKind; 158c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K, 159c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Pred->getLocationContext(), checkFn.Checker); 160c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext C(Bldr, Eng, Pred, L, wasInlined); 161c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn(S, C); 162c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 163c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 164c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 166c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// \brief Run checkers for visiting Stmts. 167c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::runCheckersForStmt(bool isPreVisit, 168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExplodedNodeSet &Dst, 169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ExplodedNodeSet &Src, 170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *S, 171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng, 172c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool wasInlined) { 1737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit), 174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) S, Eng, wasInlined); 175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 178c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 179c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct CheckObjCMessageContext { 180c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy; 181c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool IsPreVisit; 182c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CheckersTy &Checkers; 183c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ObjCMethodCall &Msg; 184c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng; 185c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 186c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 187c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 188c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 189c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers, 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ObjCMethodCall &msg, ExprEngine &eng) 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { } 192c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void runChecker(CheckerManager::CheckObjCMessageFunc checkFn, 194c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NodeBuilder &Bldr, ExplodedNode *Pred) { 195c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind : 196c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::PostStmtKind; 197c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ProgramPoint &L = 198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::getProgramPoint(Msg.getOriginExpr(), 199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) K, Pred->getLocationContext(), 200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn.Checker); 201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext C(Bldr, Eng, Pred, L); 202c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn(Msg, C); 204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 208c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// \brief Run checkers for visiting obj-c messages. 2093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)void CheckerManager::runCheckersForObjCMessage(bool isPreVisit, 2103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) ExplodedNodeSet &Dst, 2113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const ExplodedNodeSet &Src, 212c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ObjCMethodCall &msg, 213c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng) { 214c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckObjCMessageContext C(isPreVisit, 215c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) isPreVisit ? PreObjCMessageCheckers 216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : PostObjCMessageCheckers, 217c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) msg, Eng); 218c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 220c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 221c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 222c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // FIXME: This has all the same signatures as CheckObjCMessageContext. 223c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Is there a way we can merge the two? 224c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct CheckCallContext { 225c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) typedef std::vector<CheckerManager::CheckCallFunc> CheckersTy; 226c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool IsPreVisit; 227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CheckersTy &Checkers; 228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CallEvent &Call; 229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng; 230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 231c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckCallContext(bool isPreVisit, const CheckersTy &checkers, 235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CallEvent &call, ExprEngine &eng) 236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : IsPreVisit(isPreVisit), Checkers(checkers), Call(call), Eng(eng) { } 237c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 238c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void runChecker(CheckerManager::CheckCallFunc checkFn, 239c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NodeBuilder &Bldr, ExplodedNode *Pred) { 240c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ProgramPoint &L = Call.getProgramPoint(IsPreVisit, checkFn.Checker); 241c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext C(Bldr, Eng, Pred, L); 242c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 243c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn(Call, C); 244c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 245c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 246c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 247c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 248c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// \brief Run checkers for visiting an abstract call event. 249c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::runCheckersForCallEvent(bool isPreVisit, 250c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExplodedNodeSet &Dst, 251c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ExplodedNodeSet &Src, 252c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CallEvent &Call, 253c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng) { 254c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckCallContext C(isPreVisit, 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) isPreVisit ? PreCallCheckers 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : PostCallCheckers, 257c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Call, Eng); 258c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 259c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 260c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 261c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct CheckLocationContext { 263c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy; 264c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CheckersTy &Checkers; 265c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal Loc; 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) bool IsLoad; 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *NodeEx; /* Will become a CFGStmt */ 268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *BoundEx; 269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng; 270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 271c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckLocationContext(const CheckersTy &checkers, 275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal loc, bool isLoad, const Stmt *NodeEx, 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *BoundEx, 277c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &eng) 278c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx), 279c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BoundEx(BoundEx), Eng(eng) {} 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void runChecker(CheckerManager::CheckLocationFunc checkFn, 282c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NodeBuilder &Bldr, ExplodedNode *Pred) { 283c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::Kind K = IsLoad ? ProgramPoint::PreLoadKind : 284c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::PreStoreKind; 285c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ProgramPoint &L = 286c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::getProgramPoint(NodeEx, K, 287c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Pred->getLocationContext(), 288c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn.Checker); 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext C(Bldr, Eng, Pred, L); 290c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn(Loc, IsLoad, BoundEx, C); 291c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 295c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// \brief Run checkers for load/store of a location. 296c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 297c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst, 298c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ExplodedNodeSet &Src, 299c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal location, bool isLoad, 300c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *NodeEx, 301c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *BoundEx, 302c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng) { 303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx, 304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BoundEx, Eng); 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct CheckBindContext { 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy; 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CheckersTy &Checkers; 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal Loc; 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal Val; 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *S; 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng; 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::Kind PointKind; 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 319c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckBindContext(const CheckersTy &checkers, 322c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal loc, SVal val, const Stmt *s, ExprEngine &eng, 323c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::Kind PK) 324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {} 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 326c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) void runChecker(CheckerManager::CheckBindFunc checkFn, 327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NodeBuilder &Bldr, ExplodedNode *Pred) { 328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind, 329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Pred->getLocationContext(), checkFn.Checker); 330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext C(Bldr, Eng, Pred, L); 331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 332c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn(Loc, Val, S, C); 333c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 334c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) }; 335c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 336c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 337c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// \brief Run checkers for binding of a value to a location. 338c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst, 339c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ExplodedNodeSet &Src, 340c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SVal location, SVal val, 341c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *S, ExprEngine &Eng, 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ProgramPoint::Kind PointKind) { 343c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind); 344c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) expandGraphWithCheckers(C, Dst, Src); 345c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 347c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G, 348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) BugReporter &BR, 349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng) { 350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i) 351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) EndAnalysisCheckers[i](G, BR, Eng); 352558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 353558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 354c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)/// \brief Run checkers for end of path. 355c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Note, We do not chain the checker output (like in expandGraphWithCheckers) 356c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// for this callback since end of path nodes are expected to be final. 357c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC, 358c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExplodedNodeSet &Dst, 359c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExprEngine &Eng) { 360c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) ExplodedNode *Pred = BC.Pred; 361c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 362c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // We define the builder outside of the loop bacause if at least one checkers 363c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // creates a sucsessor for Pred, we do not need to generate an 364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // autotransition for it. 365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) NodeBuilder Bldr(Pred, Dst, BC); 366c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) { 367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckEndPathFunc checkFn = EndPathCheckers[i]; 368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const ProgramPoint &L = BlockEntrance(BC.Block, 370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Pred->getLocationContext(), 371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn.Checker); 372c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) CheckerContext C(Bldr, Eng, Pred, L); 373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) checkFn(C); 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 376c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) struct CheckBranchConditionContext { 379868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy; 380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const CheckersTy &Checkers; 381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const Stmt *Condition; 382 ExprEngine &Eng; 383 384 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 385 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 386 387 CheckBranchConditionContext(const CheckersTy &checkers, 388 const Stmt *Cond, ExprEngine &eng) 389 : Checkers(checkers), Condition(Cond), Eng(eng) {} 390 391 void runChecker(CheckerManager::CheckBranchConditionFunc checkFn, 392 NodeBuilder &Bldr, ExplodedNode *Pred) { 393 ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(), 394 checkFn.Checker); 395 CheckerContext C(Bldr, Eng, Pred, L); 396 checkFn(Condition, C); 397 } 398 }; 399} 400 401/// \brief Run checkers for branch condition. 402void CheckerManager::runCheckersForBranchCondition(const Stmt *Condition, 403 ExplodedNodeSet &Dst, 404 ExplodedNode *Pred, 405 ExprEngine &Eng) { 406 ExplodedNodeSet Src; 407 Src.insert(Pred); 408 CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng); 409 expandGraphWithCheckers(C, Dst, Src); 410} 411 412/// \brief Run checkers for live symbols. 413void CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state, 414 SymbolReaper &SymReaper) { 415 for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i) 416 LiveSymbolsCheckers[i](state, SymReaper); 417} 418 419namespace { 420 struct CheckDeadSymbolsContext { 421 typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy; 422 const CheckersTy &Checkers; 423 SymbolReaper &SR; 424 const Stmt *S; 425 ExprEngine &Eng; 426 ProgramPoint::Kind ProgarmPointKind; 427 428 CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); } 429 CheckersTy::const_iterator checkers_end() { return Checkers.end(); } 430 431 CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr, 432 const Stmt *s, ExprEngine &eng, 433 ProgramPoint::Kind K) 434 : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { } 435 436 void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn, 437 NodeBuilder &Bldr, ExplodedNode *Pred) { 438 const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind, 439 Pred->getLocationContext(), checkFn.Checker); 440 CheckerContext C(Bldr, Eng, Pred, L); 441 442 // Note, do not pass the statement to the checkers without letting them 443 // differentiate if we ran remove dead bindings before or after the 444 // statement. 445 checkFn(SR, C); 446 } 447 }; 448} 449 450/// \brief Run checkers for dead symbols. 451void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst, 452 const ExplodedNodeSet &Src, 453 SymbolReaper &SymReaper, 454 const Stmt *S, 455 ExprEngine &Eng, 456 ProgramPoint::Kind K) { 457 CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K); 458 expandGraphWithCheckers(C, Dst, Src); 459} 460 461/// \brief True if at least one checker wants to check region changes. 462bool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) { 463 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) 464 if (RegionChangesCheckers[i].WantUpdateFn(state)) 465 return true; 466 467 return false; 468} 469 470/// \brief Run checkers for region changes. 471ProgramStateRef 472CheckerManager::runCheckersForRegionChanges(ProgramStateRef state, 473 const StoreManager::InvalidatedSymbols *invalidated, 474 ArrayRef<const MemRegion *> ExplicitRegions, 475 ArrayRef<const MemRegion *> Regions, 476 const CallEvent *Call) { 477 for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) { 478 // If any checker declares the state infeasible (or if it starts that way), 479 // bail out. 480 if (!state) 481 return NULL; 482 state = RegionChangesCheckers[i].CheckFn(state, invalidated, 483 ExplicitRegions, Regions, Call); 484 } 485 return state; 486} 487 488/// \brief Run checkers for handling assumptions on symbolic values. 489ProgramStateRef 490CheckerManager::runCheckersForEvalAssume(ProgramStateRef state, 491 SVal Cond, bool Assumption) { 492 for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) { 493 // If any checker declares the state infeasible (or if it starts that way), 494 // bail out. 495 if (!state) 496 return NULL; 497 state = EvalAssumeCheckers[i](state, Cond, Assumption); 498 } 499 return state; 500} 501 502/// \brief Run checkers for evaluating a call. 503/// Only one checker will evaluate the call. 504void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst, 505 const ExplodedNodeSet &Src, 506 const SimpleCall &Call, 507 ExprEngine &Eng) { 508 const CallExpr *CE = Call.getOriginExpr(); 509 for (ExplodedNodeSet::iterator 510 NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) { 511 512 ExplodedNode *Pred = *NI; 513 bool anyEvaluated = false; 514 515 // First, check if any of the InlineCall callbacks can evaluate the call. 516 assert(InlineCallCheckers.size() <= 1 && 517 "InlineCall is a special hacky callback to allow intrusive" 518 "evaluation of the call (which simulates inlining). It is " 519 "currently only used by OSAtomicChecker and should go away " 520 "at some point."); 521 for (std::vector<InlineCallFunc>::iterator 522 EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end(); 523 EI != EE; ++EI) { 524 ExplodedNodeSet checkDst; 525 bool evaluated = (*EI)(CE, Eng, Pred, checkDst); 526 assert(!(evaluated && anyEvaluated) 527 && "There are more than one checkers evaluating the call"); 528 if (evaluated) { 529 anyEvaluated = true; 530 Dst.insert(checkDst); 531#ifdef NDEBUG 532 break; // on release don't check that no other checker also evals. 533#endif 534 } 535 } 536 537#ifdef NDEBUG // on release don't check that no other checker also evals. 538 if (anyEvaluated) { 539 break; 540 } 541#endif 542 543 ExplodedNodeSet checkDst; 544 NodeBuilder B(Pred, checkDst, Eng.getBuilderContext()); 545 // Next, check if any of the EvalCall callbacks can evaluate the call. 546 for (std::vector<EvalCallFunc>::iterator 547 EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end(); 548 EI != EE; ++EI) { 549 ProgramPoint::Kind K = ProgramPoint::PostStmtKind; 550 const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K, 551 Pred->getLocationContext(), EI->Checker); 552 bool evaluated = false; 553 { // CheckerContext generates transitions(populates checkDest) on 554 // destruction, so introduce the scope to make sure it gets properly 555 // populated. 556 CheckerContext C(B, Eng, Pred, L); 557 evaluated = (*EI)(CE, C); 558 } 559 assert(!(evaluated && anyEvaluated) 560 && "There are more than one checkers evaluating the call"); 561 if (evaluated) { 562 anyEvaluated = true; 563 Dst.insert(checkDst); 564#ifdef NDEBUG 565 break; // on release don't check that no other checker also evals. 566#endif 567 } 568 } 569 570 // If none of the checkers evaluated the call, ask ExprEngine to handle it. 571 if (!anyEvaluated) { 572 NodeBuilder B(Pred, Dst, Eng.getBuilderContext()); 573 Eng.defaultEvalCall(B, Pred, Call); 574 } 575 } 576} 577 578/// \brief Run checkers for the entire Translation Unit. 579void CheckerManager::runCheckersOnEndOfTranslationUnit( 580 const TranslationUnitDecl *TU, 581 AnalysisManager &mgr, 582 BugReporter &BR) { 583 for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i) 584 EndOfTranslationUnitCheckers[i](TU, mgr, BR); 585} 586 587void CheckerManager::runCheckersForPrintState(raw_ostream &Out, 588 ProgramStateRef State, 589 const char *NL, const char *Sep) { 590 for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator 591 I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I) 592 I->second->printState(Out, State, NL, Sep); 593} 594 595//===----------------------------------------------------------------------===// 596// Internal registration functions for AST traversing. 597//===----------------------------------------------------------------------===// 598 599void CheckerManager::_registerForDecl(CheckDeclFunc checkfn, 600 HandlesDeclFunc isForDeclFn) { 601 DeclCheckerInfo info = { checkfn, isForDeclFn }; 602 DeclCheckers.push_back(info); 603} 604 605void CheckerManager::_registerForBody(CheckDeclFunc checkfn) { 606 BodyCheckers.push_back(checkfn); 607} 608 609//===----------------------------------------------------------------------===// 610// Internal registration functions for path-sensitive checking. 611//===----------------------------------------------------------------------===// 612 613void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn, 614 HandlesStmtFunc isForStmtFn) { 615 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true }; 616 StmtCheckers.push_back(info); 617} 618void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn, 619 HandlesStmtFunc isForStmtFn) { 620 StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false }; 621 StmtCheckers.push_back(info); 622} 623 624void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) { 625 PreObjCMessageCheckers.push_back(checkfn); 626} 627void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) { 628 PostObjCMessageCheckers.push_back(checkfn); 629} 630 631void CheckerManager::_registerForPreCall(CheckCallFunc checkfn) { 632 PreCallCheckers.push_back(checkfn); 633} 634void CheckerManager::_registerForPostCall(CheckCallFunc checkfn) { 635 PostCallCheckers.push_back(checkfn); 636} 637 638void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) { 639 LocationCheckers.push_back(checkfn); 640} 641 642void CheckerManager::_registerForBind(CheckBindFunc checkfn) { 643 BindCheckers.push_back(checkfn); 644} 645 646void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) { 647 EndAnalysisCheckers.push_back(checkfn); 648} 649 650void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) { 651 EndPathCheckers.push_back(checkfn); 652} 653 654void CheckerManager::_registerForBranchCondition( 655 CheckBranchConditionFunc checkfn) { 656 BranchConditionCheckers.push_back(checkfn); 657} 658 659void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) { 660 LiveSymbolsCheckers.push_back(checkfn); 661} 662 663void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) { 664 DeadSymbolsCheckers.push_back(checkfn); 665} 666 667void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn, 668 WantsRegionChangeUpdateFunc wantUpdateFn) { 669 RegionChangesCheckerInfo info = {checkfn, wantUpdateFn}; 670 RegionChangesCheckers.push_back(info); 671} 672 673void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) { 674 EvalAssumeCheckers.push_back(checkfn); 675} 676 677void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) { 678 EvalCallCheckers.push_back(checkfn); 679} 680 681void CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) { 682 InlineCallCheckers.push_back(checkfn); 683} 684 685void CheckerManager::_registerForEndOfTranslationUnit( 686 CheckEndOfTranslationUnit checkfn) { 687 EndOfTranslationUnitCheckers.push_back(checkfn); 688} 689 690//===----------------------------------------------------------------------===// 691// Implementation details. 692//===----------------------------------------------------------------------===// 693 694CheckerManager::CachedStmtCheckers * 695CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) { 696 assert(S); 697 698 CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit); 699 CachedStmtCheckers *checkers = 0; 700 CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key); 701 if (CCI != CachedStmtCheckersMap.end()) { 702 checkers = &(CCI->second); 703 } else { 704 // Find the checkers that should run for this Stmt and cache them. 705 checkers = &CachedStmtCheckersMap[key]; 706 for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) { 707 StmtCheckerInfo &info = StmtCheckers[i]; 708 if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S)) 709 checkers->push_back(info.CheckFn); 710 } 711 } 712 713 assert(checkers); 714 return checkers; 715} 716 717CheckerManager::~CheckerManager() { 718 for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i) 719 CheckerDtors[i](); 720} 721