CheckerManager.cpp revision deb6447d0029bdb122397fafb5fa2a4e76f2e555
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     The LLVM Compiler Infrastructure
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is distributed under the University of Illinois Open Source
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// License. See LICENSE.TXT for details.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
89ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch//===----------------------------------------------------------------------===//
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Defines the Static Analyzer Checker Manager.
119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/Analysis/ProgramPoint.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/DeclBase.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace clang;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::finishedCheckerRegistration() {
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef NDEBUG
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that for every event that has listeners, there is at least
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // one dispatcher registered for it.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (llvm::DenseMap<EventTag, EventInfo>::iterator
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         I = Events.begin(), E = Events.end(); I != E; ++I)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    assert(I->second.HasDispatcher && "No dispatcher registered for an event");
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions for running checkers for AST traversing..
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
38010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                          BugReporter &BR) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(D);
407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  unsigned DeclKind = D->getKind();
427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CachedDeclCheckers *checkers = 0;
437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  if (CCI != CachedDeclCheckersMap.end()) {
457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    checkers = &(CCI->second);
467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  } else {
477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    // Find the checkers that should run for this Decl and cache them.
487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    checkers = &CachedDeclCheckersMap[DeclKind];
497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      DeclCheckerInfo &info = DeclCheckers[i];
517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (info.IsForDeclFn(D))
527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        checkers->push_back(info.CheckFn);
537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  }
557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)
567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  assert(checkers);
577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (CachedDeclCheckers::iterator
587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)         I = checkers->begin(), E = checkers->end(); I != E; ++I)
597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    (*I)(D, mgr, BR);
607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)}
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                          BugReporter &BR) {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(D && D->hasBody());
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    BodyCheckers[i](D, mgr, BR);
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)//===----------------------------------------------------------------------===//
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions for running checkers for path-sensitive checking.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)template <typename CHECK_CTX>
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static void expandGraphWithCheckers(CHECK_CTX checkCtx,
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    ExplodedNodeSet &Dst,
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    const ExplodedNodeSet &Src) {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typename CHECK_CTX::CheckersTy::const_iterator
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (I == E) {
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Dst.insert(Src);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExplodedNodeSet Tmp1, Tmp2;
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const ExplodedNodeSet *PrevSet = &Src;
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (; I != E; ++I) {
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExplodedNodeSet *CurrSet = 0;
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (I+1 == E)
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CurrSet = &Dst;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    else {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CurrSet->clear();
965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         NI != NE; ++NI)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checkCtx.runChecker(*I, *CurrSet, *NI);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
102c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // Update which NodeSet is the current one.
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PrevSet = CurrSet;
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1087d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  struct CheckStmtContext {
1097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
1107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    bool IsPreVisit;
111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const CheckersTy &Checkers;
112010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    const Stmt *S;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExprEngine &Eng;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     const Stmt *s, ExprEngine &eng)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void runChecker(CheckerManager::CheckStmtFunc checkFn,
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // FIXME: Remove respondsToCallback from CheckerContext;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       IsPreVisit ? ProgramPoint::PreStmtKind :
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    ProgramPoint::PostStmtKind, 0, S);
128010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      checkFn(S, C);
129010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    }
130010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  };
131010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
132010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for visiting Stmts.
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersForStmt(bool isPreVisit,
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        ExplodedNodeSet &Dst,
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        const ExplodedNodeSet &Src,
137c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        const Stmt *S,
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        ExprEngine &Eng) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     S, Eng);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expandGraphWithCheckers(C, Dst, Src);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct CheckObjCMessageContext {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool IsPreVisit;
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CheckersTy &Checkers;
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const ObjCMessage &Msg;
150010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    ExprEngine &Eng;
151010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
155010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            const ObjCMessage &msg, ExprEngine &eng)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       IsPreVisit ? ProgramPoint::PreStmtKind :
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    ProgramPoint::PostStmtKind, 0,
1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                       Msg.getOriginExpr());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      checkFn(Msg, C);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
168010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
169010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
170010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)/// \brief Run checkers for visiting obj-c messages.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
172010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                               ExplodedNodeSet &Dst,
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const ExplodedNodeSet &Src,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const ObjCMessage &msg,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               ExprEngine &Eng) {
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckObjCMessageContext C(isPreVisit,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            isPreVisit ? PreObjCMessageCheckers
1787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                       : PostObjCMessageCheckers,
1797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                            msg, Eng);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expandGraphWithCheckers(C, Dst, Src);
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
182010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)
183010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)namespace {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct CheckLocationContext {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CheckersTy &Checkers;
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SVal Loc;
188010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    bool IsLoad;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Stmt *S;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExprEngine &Eng;
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    CheckLocationContext(const CheckersTy &checkers,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng)
197010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { }
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    void runChecker(CheckerManager::CheckLocationFunc checkFn,
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
202010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                       IsLoad ? ProgramPoint::PreLoadKind :
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       ProgramPoint::PreStoreKind, 0, S);
204010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)      checkFn(Loc, IsLoad, C);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
206010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  };
207010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)}
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for load/store of a location.
210010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
211010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                            const ExplodedNodeSet &Src,
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            SVal location, bool isLoad,
213010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                            const Stmt *S, ExprEngine &Eng) {
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng);
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  expandGraphWithCheckers(C, Dst, Src);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
217
218namespace {
219  struct CheckBindContext {
220    typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
221    const CheckersTy &Checkers;
222    SVal Loc;
223    SVal Val;
224    const Stmt *S;
225    ExprEngine &Eng;
226
227    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
228    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
229
230    CheckBindContext(const CheckersTy &checkers,
231                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng)
232      : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { }
233
234    void runChecker(CheckerManager::CheckBindFunc checkFn,
235                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
236      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
237                       ProgramPoint::PreStmtKind, 0, S);
238      checkFn(Loc, Val, C);
239    }
240  };
241}
242
243/// \brief Run checkers for binding of a value to a location.
244void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
245                                        const ExplodedNodeSet &Src,
246                                        SVal location, SVal val,
247                                        const Stmt *S, ExprEngine &Eng) {
248  CheckBindContext C(BindCheckers, location, val, S, Eng);
249  expandGraphWithCheckers(C, Dst, Src);
250}
251
252void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
253                                               BugReporter &BR,
254                                               ExprEngine &Eng) {
255  for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
256    EndAnalysisCheckers[i](G, BR, Eng);
257}
258
259/// \brief Run checkers for end of path.
260void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B,
261                                           ExprEngine &Eng) {
262  for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
263    CheckEndPathFunc fn = EndPathCheckers[i];
264    EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker);
265    fn(specialB, Eng);
266  }
267}
268
269/// \brief Run checkers for branch condition.
270void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
271                                                   BranchNodeBuilder &B,
272                                                   ExprEngine &Eng) {
273  for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) {
274    CheckBranchConditionFunc fn = BranchConditionCheckers[i];
275    fn(condition, B, Eng);
276  }
277}
278
279/// \brief Run checkers for live symbols.
280void CheckerManager::runCheckersForLiveSymbols(const GRState *state,
281                                               SymbolReaper &SymReaper) {
282  for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
283    LiveSymbolsCheckers[i](state, SymReaper);
284}
285
286namespace {
287  struct CheckDeadSymbolsContext {
288    typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
289    const CheckersTy &Checkers;
290    SymbolReaper &SR;
291    const Stmt *S;
292    ExprEngine &Eng;
293
294    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
295    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
296
297    CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
298                            const Stmt *s, ExprEngine &eng)
299      : Checkers(checkers), SR(sr), S(s), Eng(eng) { }
300
301    void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
302                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
303      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
304                       ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
305      checkFn(SR, C);
306    }
307  };
308}
309
310/// \brief Run checkers for dead symbols.
311void CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
312                                               const ExplodedNodeSet &Src,
313                                               SymbolReaper &SymReaper,
314                                               const Stmt *S,
315                                               ExprEngine &Eng) {
316  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng);
317  expandGraphWithCheckers(C, Dst, Src);
318}
319
320/// \brief True if at least one checker wants to check region changes.
321bool CheckerManager::wantsRegionChangeUpdate(const GRState *state) {
322  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
323    if (RegionChangesCheckers[i].WantUpdateFn(state))
324      return true;
325
326  return false;
327}
328
329/// \brief Run checkers for region changes.
330const GRState *
331CheckerManager::runCheckersForRegionChanges(const GRState *state,
332                                            const MemRegion * const *Begin,
333                                            const MemRegion * const *End) {
334  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
335    // If any checker declares the state infeasible (or if it starts that way),
336    // bail out.
337    if (!state)
338      return NULL;
339    state = RegionChangesCheckers[i].CheckFn(state, Begin, End);
340  }
341  return state;
342}
343
344/// \brief Run checkers for handling assumptions on symbolic values.
345const GRState *
346CheckerManager::runCheckersForEvalAssume(const GRState *state,
347                                         SVal Cond, bool Assumption) {
348  for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
349    // If any checker declares the state infeasible (or if it starts that way),
350    // bail out.
351    if (!state)
352      return NULL;
353    state = EvalAssumeCheckers[i](state, Cond, Assumption);
354  }
355  return state;
356}
357
358/// \brief Run checkers for evaluating a call.
359/// Only one checker will evaluate the call.
360void CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
361                                            const ExplodedNodeSet &Src,
362                                            const CallExpr *CE,
363                                            ExprEngine &Eng,
364                                            GraphExpander *defaultEval) {
365  if (EvalCallCheckers.empty() && defaultEval == 0) {
366    Dst.insert(Src);
367    return;
368  }
369
370  for (ExplodedNodeSet::iterator
371         NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
372
373    ExplodedNode *Pred = *NI;
374    bool anyEvaluated = false;
375    for (std::vector<EvalCallFunc>::iterator
376           EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
377         EI != EE; ++EI) {
378      ExplodedNodeSet checkDst;
379      CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker,
380                       ProgramPoint::PostStmtKind, 0, CE);
381      bool evaluated = (*EI)(CE, C);
382      assert(!(evaluated && anyEvaluated)
383             && "There are more than one checkers evaluating the call");
384      if (evaluated) {
385        anyEvaluated = true;
386        Dst.insert(checkDst);
387#ifdef NDEBUG
388        break; // on release don't check that no other checker also evals.
389#endif
390      }
391    }
392
393    if (!anyEvaluated) {
394      if (defaultEval)
395        defaultEval->expandGraph(Dst, Pred);
396      else
397        Dst.insert(Pred);
398    }
399  }
400}
401
402//===----------------------------------------------------------------------===//
403// Internal registration functions for AST traversing.
404//===----------------------------------------------------------------------===//
405
406void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
407                                      HandlesDeclFunc isForDeclFn) {
408  DeclCheckerInfo info = { checkfn, isForDeclFn };
409  DeclCheckers.push_back(info);
410}
411
412void CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
413  BodyCheckers.push_back(checkfn);
414}
415
416//===----------------------------------------------------------------------===//
417// Internal registration functions for path-sensitive checking.
418//===----------------------------------------------------------------------===//
419
420void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
421                                         HandlesStmtFunc isForStmtFn) {
422  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
423  StmtCheckers.push_back(info);
424}
425void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
426                                          HandlesStmtFunc isForStmtFn) {
427  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
428  StmtCheckers.push_back(info);
429}
430
431void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
432  PreObjCMessageCheckers.push_back(checkfn);
433}
434void CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
435  PostObjCMessageCheckers.push_back(checkfn);
436}
437
438void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
439  LocationCheckers.push_back(checkfn);
440}
441
442void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
443  BindCheckers.push_back(checkfn);
444}
445
446void CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
447  EndAnalysisCheckers.push_back(checkfn);
448}
449
450void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
451  EndPathCheckers.push_back(checkfn);
452}
453
454void CheckerManager::_registerForBranchCondition(
455                                             CheckBranchConditionFunc checkfn) {
456  BranchConditionCheckers.push_back(checkfn);
457}
458
459void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
460  LiveSymbolsCheckers.push_back(checkfn);
461}
462
463void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
464  DeadSymbolsCheckers.push_back(checkfn);
465}
466
467void CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
468                                     WantsRegionChangeUpdateFunc wantUpdateFn) {
469  RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
470  RegionChangesCheckers.push_back(info);
471}
472
473void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
474  EvalAssumeCheckers.push_back(checkfn);
475}
476
477void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
478  EvalCallCheckers.push_back(checkfn);
479}
480
481//===----------------------------------------------------------------------===//
482// Implementation details.
483//===----------------------------------------------------------------------===//
484
485CheckerManager::CachedStmtCheckers *
486CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
487  assert(S);
488
489  CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
490  CachedStmtCheckers *checkers = 0;
491  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
492  if (CCI != CachedStmtCheckersMap.end()) {
493    checkers = &(CCI->second);
494  } else {
495    // Find the checkers that should run for this Stmt and cache them.
496    checkers = &CachedStmtCheckersMap[key];
497    for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
498      StmtCheckerInfo &info = StmtCheckers[i];
499      if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
500        checkers->push_back(info.CheckFn);
501    }
502  }
503
504  assert(checkers);
505  return checkers;
506}
507
508CheckerManager::~CheckerManager() {
509  for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
510    CheckerDtors[i]();
511}
512
513// Anchor for the vtable.
514CheckerProvider::~CheckerProvider() { }
515
516// Anchor for the vtable.
517GraphExpander::~GraphExpander() { }
518