CheckerManager.cpp revision 18c66fdc3c4008d335885695fe36fb5353c5f672
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (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.
76d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)//
86d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)//===----------------------------------------------------------------------===//
9868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)//
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Defines the Static Analyzer Checker Manager.
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//===----------------------------------------------------------------------===//
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerManager.h"
154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
16010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "clang/StaticAnalyzer/Core/Checker.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "clang/Analysis/ProgramPoint.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "clang/AST/DeclBase.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)using namespace clang;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using namespace ento;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CheckerManager::hasPathSensitiveCheckers() const {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !StmtCheckers.empty()              ||
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !PreObjCMessageCheckers.empty()    ||
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !PostObjCMessageCheckers.empty()   ||
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !LocationCheckers.empty()          ||
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !BindCheckers.empty()              ||
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         !EndAnalysisCheckers.empty()       ||
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         !EndPathCheckers.empty()           ||
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         !BranchConditionCheckers.empty()   ||
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         !LiveSymbolsCheckers.empty()       ||
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         !DeadSymbolsCheckers.empty()       ||
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         !RegionChangesCheckers.empty()     ||
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         !EvalAssumeCheckers.empty()        ||
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)         !EvalCallCheckers.empty();
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::finishedCheckerRegistration() {
41116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#ifndef NDEBUG
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure that for every event that has listeners, there is at least
43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  // one dispatcher registered for it.
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (llvm::DenseMap<EventTag, EventInfo>::iterator
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         I = Events.begin(), E = Events.end(); I != E; ++I)
461320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    assert(I->second.HasDispatcher && "No dispatcher registered for an event");
47a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)//===----------------------------------------------------------------------===//
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Functions for running checkers for AST traversing..
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          BugReporter &BR) {
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(D);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned DeclKind = D->getKind();
599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  CachedDeclCheckers *checkers = 0;
60c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (CCI != CachedDeclCheckersMap.end()) {
62f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    checkers = &(CCI->second);
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Find the checkers that should run for this Decl and cache them.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    checkers = &CachedDeclCheckersMap[DeclKind];
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      DeclCheckerInfo &info = DeclCheckers[i];
68a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch      if (info.IsForDeclFn(D))
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        checkers->push_back(info.CheckFn);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
73c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  assert(checkers);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (CachedDeclCheckers::iterator
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         I = checkers->begin(), E = checkers->end(); I != E; ++I)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (*I)(D, mgr, BR);
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          BugReporter &BR) {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  assert(D && D->hasBody());
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
83eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch  for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    BodyCheckers[i](D, mgr, BR);
85116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
8746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//===----------------------------------------------------------------------===//
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Functions for running checkers for path-sensitive checking.
8946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)//===----------------------------------------------------------------------===//
90a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)template <typename CHECK_CTX>
92a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)static void expandGraphWithCheckers(CHECK_CTX checkCtx,
93116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                    ExplodedNodeSet &Dst,
9423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)                                    const ExplodedNodeSet &Src) {
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typename CHECK_CTX::CheckersTy::const_iterator
97116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (I == E) {
99ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    Dst.insert(Src);
100ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch    return;
101ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch  }
102ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ExplodedNodeSet Tmp1, Tmp2;
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const ExplodedNodeSet *PrevSet = &Src;
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  for (; I != E; ++I) {
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExplodedNodeSet *CurrSet = 0;
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (I+1 == E)
10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CurrSet = &Dst;
11046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    else {
11146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
11246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)      CurrSet->clear();
1136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    }
11446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
1155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
1161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci         NI != NE; ++NI)
1176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      checkCtx.runChecker(*I, *CurrSet, *NI);
11846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
11946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    // Update which NodeSet is the current one.
12090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    PrevSet = CurrSet;
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
12490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)namespace {
12590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  struct CheckStmtContext {
12623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)    typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    bool IsPreVisit;
12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const CheckersTy &Checkers;
12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    const Stmt *S;
1300f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    ExprEngine &Eng;
1310f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
1340f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
135f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)                     const Stmt *s, ExprEngine &eng)
1370f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }
1380f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
1391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    void runChecker(CheckerManager::CheckStmtFunc checkFn,
1400f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // FIXME: Remove respondsToCallback from CheckerContext;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       IsPreVisit ? ProgramPoint::PreStmtKind :
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                    ProgramPoint::PostStmtKind, 0, S);
14558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      checkFn(S, C);
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
149424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
15046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)/// \brief Run checkers for visiting Stmts.
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)void CheckerManager::runCheckersForStmt(bool isPreVisit,
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        ExplodedNodeSet &Dst,
1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                        const ExplodedNodeSet &Src,
154116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                        const Stmt *S,
155c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                        ExprEngine &Eng) {
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                     S, Eng);
1586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  expandGraphWithCheckers(C, Dst, Src);
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochnamespace {
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct CheckObjCMessageContext {
1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
1646e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    bool IsPreVisit;
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    const CheckersTy &Checkers;
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const ObjCMessage &Msg;
1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    ExprEngine &Eng;
1689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            const ObjCMessage &msg, ExprEngine &eng)
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
1775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
178116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       IsPreVisit ? ProgramPoint::PreStmtKind :
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                    ProgramPoint::PostStmtKind, 0,
181a3f7b4e666c476898878fa745f637129375cd889Ben Murdoch                       Msg.getOriginExpr());
182116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      checkFn(Msg, C);
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// \brief Run checkers for visiting obj-c messages.
1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
1890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                               ExplodedNodeSet &Dst,
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const ExplodedNodeSet &Src,
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               const ObjCMessage &msg,
1920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                               ExprEngine &Eng) {
1930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  CheckObjCMessageContext C(isPreVisit,
1946d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)                            isPreVisit ? PreObjCMessageCheckers
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       : PostObjCMessageCheckers,
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            msg, Eng);
1970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  expandGraphWithCheckers(C, Dst, Src);
1980f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
2010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  struct CheckLocationContext {
2020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
2034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    const CheckersTy &Checkers;
2044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    SVal Loc;
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool IsLoad;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Stmt *S;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExprEngine &Eng;
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CheckLocationContext(const CheckersTy &checkers,
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         SVal loc, bool isLoad, const Stmt *s, ExprEngine &eng)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s), Eng(eng) { }
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void runChecker(CheckerManager::CheckLocationFunc checkFn,
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       IsLoad ? ProgramPoint::PreLoadKind :
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       ProgramPoint::PreStoreKind, 0, S);
221bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch      checkFn(Loc, IsLoad, C);
222bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch    }
223bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  };
224bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci/// \brief Run checkers for load/store of a location.
2271320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
2281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            const ExplodedNodeSet &Src,
2291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                            SVal location, bool isLoad,
2305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)                                            const Stmt *S, ExprEngine &Eng) {
2311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  CheckLocationContext C(LocationCheckers, location, isLoad, S, Eng);
232bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch  expandGraphWithCheckers(C, Dst, Src);
233bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch}
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct CheckBindContext {
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CheckersTy &Checkers;
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SVal Loc;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SVal Val;
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const Stmt *S;
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ExprEngine &Eng;
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
2475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CheckBindContext(const CheckersTy &checkers,
2480f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng)
2495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng) { }
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void runChecker(CheckerManager::CheckBindFunc checkFn,
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                       ProgramPoint::PreStmtKind, 0, S);
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      checkFn(Loc, Val, C);
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
25746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  };
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch/// \brief Run checkers for binding of a value to a location.
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
262a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                        const ExplodedNodeSet &Src,
2630f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                        SVal location, SVal val,
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const Stmt *S, ExprEngine &Eng) {
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckBindContext C(BindCheckers, location, val, S, Eng);
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  expandGraphWithCheckers(C, Dst, Src);
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2680f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
2690f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               BugReporter &BR,
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               ExprEngine &Eng) {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EndAnalysisCheckers[i](G, BR, Eng);
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for end of path.
27734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)void CheckerManager::runCheckersForEndPath(EndOfFunctionNodeBuilder &B,
27834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)                                           ExprEngine &Eng) {
27934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)  for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
28034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles)    CheckEndPathFunc fn = EndPathCheckers[i];
2815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    EndOfFunctionNodeBuilder specialB = B.withCheckerTag(fn.Checker);
2825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    fn(specialB, Eng);
283a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2860f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)/// \brief Run checkers for branch condition.
2870f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::runCheckersForBranchCondition(const Stmt *condition,
2880f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                   BranchNodeBuilder &B,
2890f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                   ExprEngine &Eng) {
2900f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  for (unsigned i = 0, e = BranchConditionCheckers.size(); i != e; ++i) {
2910f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    CheckBranchConditionFunc fn = BranchConditionCheckers[i];
2920f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    fn(condition, B, Eng);
2930f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/// \brief Run checkers for live symbols.
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::runCheckersForLiveSymbols(const ProgramState *state,
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               SymbolReaper &SymReaper) {
2991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LiveSymbolsCheckers[i](state, SymReaper);
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3021320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3031320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccinamespace {
304d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)  struct CheckDeadSymbolsContext {
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
306d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    const CheckersTy &Checkers;
307d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)    SymbolReaper &SR;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Stmt *S;
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ExprEngine &Eng;
310cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
3136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            const Stmt *s, ExprEngine &eng)
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : Checkers(checkers), SR(sr), S(s), Eng(eng) { }
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
32068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
321cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                       ProgramPoint::PostPurgeDeadSymbolsKind, 0, S);
322116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      checkFn(SR, C);
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
324ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  };
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// \brief Run checkers for dead symbols.
328a3f7b4e666c476898878fa745f637129375cd889Ben Murdochvoid CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
329116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               const ExplodedNodeSet &Src,
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               SymbolReaper &SymReaper,
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                               const Stmt *S,
332116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                               ExprEngine &Eng) {
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng);
334424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  expandGraphWithCheckers(C, Dst, Src);
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
336116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// \brief True if at least one checker wants to check region changes.
3385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)bool CheckerManager::wantsRegionChangeUpdate(const ProgramState *state) {
3396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
340868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (RegionChangesCheckers[i].WantUpdateFn(state))
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return true;
3425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// \brief Run checkers for region changes.
3475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuconst ProgramState *
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CheckerManager::runCheckersForRegionChanges(const ProgramState *state,
3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                            const StoreManager::InvalidatedSymbols *invalidated,
3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                            const MemRegion * const *Begin,
3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)                                            const MemRegion * const *End) {
3526d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
353c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    // If any checker declares the state infeasible (or if it starts that way),
3544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    // bail out.
3550f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)    if (!state)
3560f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)      return NULL;
3575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    state = RegionChangesCheckers[i].CheckFn(state, invalidated, Begin, End);
3580f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  }
3595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  return state;
3605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
3615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
3625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/// \brief Run checkers for handling assumptions on symbolic values.
3631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciconst ProgramState *
3645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)CheckerManager::runCheckersForEvalAssume(const ProgramState *state,
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         SVal Cond, bool Assumption) {
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
3677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // If any checker declares the state infeasible (or if it starts that way),
3687dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // bail out.
369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (!state)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return NULL;
3717dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    state = EvalAssumeCheckers[i](state, Cond, Assumption);
372116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
37323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)  return state;
3747dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
3757dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch/// \brief Run checkers for evaluating a call.
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/// Only one checker will evaluate the call.
3787dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
379116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            const ExplodedNodeSet &Src,
380a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                            const CallExpr *CE,
381116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch                                            ExprEngine &Eng,
3827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                            GraphExpander *defaultEval) {
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (EvalCallCheckers.empty() && defaultEval == 0) {
3847dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    Dst.insert(Src);
3857dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    return;
3867dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
387a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
3887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  for (ExplodedNodeSet::iterator
389a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)         NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
3907dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
3917dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    ExplodedNode *Pred = *NI;
392c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    bool anyEvaluated = false;
3937dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    for (std::vector<EvalCallFunc>::iterator
3947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch           EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
3957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch         EI != EE; ++EI) {
3967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      ExplodedNodeSet checkDst;
3977dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      CheckerContext C(checkDst, Eng.getBuilder(), Eng, Pred, EI->Checker,
3987dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                       ProgramPoint::PostStmtKind, 0, CE);
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool evaluated = (*EI)(CE, C);
4007dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      assert(!(evaluated && anyEvaluated)
4017dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch             && "There are more than one checkers evaluating the call");
4025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      if (evaluated) {
403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)        anyEvaluated = true;
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Dst.insert(checkDst);
405ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#ifdef NDEBUG
406ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch        break; // on release don't check that no other checker also evals.
407ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#endif
408ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch      }
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4107dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!anyEvaluated) {
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (defaultEval)
41368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        defaultEval->expandGraph(Dst, Pred);
4145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      else
41568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        Dst.insert(Pred);
41646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)    }
41746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)  }
41846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}
4196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
42068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)/// \brief Run checkers for the entire Translation Unit.
4210f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::runCheckersOnEndOfTranslationUnit(
4220f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                  const TranslationUnitDecl *TU,
4230f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                  AnalysisManager &mgr,
4240f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                                  BugReporter &BR) {
4250f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    EndOfTranslationUnitCheckers[i](TU, mgr, BR);
427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)//===----------------------------------------------------------------------===//
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Internal registration functions for AST traversing.
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//===----------------------------------------------------------------------===//
4320f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
4330f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
434c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch                                      HandlesDeclFunc isForDeclFn) {
435c2db58bd994c04d98e4ee2cd7565b71548655fe3Ben Murdoch  DeclCheckerInfo info = { checkfn, isForDeclFn };
4361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  DeclCheckers.push_back(info);
4371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
4401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  BodyCheckers.push_back(checkfn);
4411320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
44323730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)//===----------------------------------------------------------------------===//
44423730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)// Internal registration functions for path-sensitive checking.
44523730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)//===----------------------------------------------------------------------===//
44623730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                         HandlesStmtFunc isForStmtFn) {
449f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
4500f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  StmtCheckers.push_back(info);
4510f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
4520f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
4530f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)                                          HandlesStmtFunc isForStmtFn) {
4547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
4557dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  StmtCheckers.push_back(info);
4566d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)}
4577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
4591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  PreObjCMessageCheckers.push_back(checkfn);
4603240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch}
4611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccivoid CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
4623240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch  PostObjCMessageCheckers.push_back(checkfn);
4631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
4645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
4657dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
4667dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  LocationCheckers.push_back(checkfn);
4677dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void CheckerManager::_registerForBind(CheckBindFunc checkfn) {
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BindCheckers.push_back(checkfn);
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4737dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EndAnalysisCheckers.push_back(checkfn);
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
47858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  EndPathCheckers.push_back(checkfn);
4795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
48046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)
48168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)void CheckerManager::_registerForBranchCondition(
4827dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                             CheckBranchConditionFunc checkfn) {
4837dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  BranchConditionCheckers.push_back(checkfn);
4845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
485a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
48658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)void CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
487c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  LiveSymbolsCheckers.push_back(checkfn);
4887dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
4897dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeadSymbolsCheckers.push_back(checkfn);
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
4947dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
4957dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch                                     WantsRegionChangeUpdateFunc wantUpdateFn) {
4967dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
4970f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  RegionChangesCheckers.push_back(info);
4985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
4990f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)void CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
5010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)  EvalAssumeCheckers.push_back(checkfn);
5020f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)}
5030f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EvalCallCheckers.push_back(checkfn);
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void CheckerManager::_registerForEndOfTranslationUnit(
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                            CheckEndOfTranslationUnit checkfn) {
5105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  EndOfTranslationUnitCheckers.push_back(checkfn);
511c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)}
512bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
513bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//===----------------------------------------------------------------------===//
514bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Implementation details.
515bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch//===----------------------------------------------------------------------===//
516bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
517bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochCheckerManager::CachedStmtCheckers *
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  assert(S);
5207dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5217dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
5229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  CachedStmtCheckers *checkers = 0;
5239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
5249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  if (CCI != CachedStmtCheckersMap.end()) {
5259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch    checkers = &(CCI->second);
5267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  } else {
5277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    // Find the checkers that should run for this Stmt and cache them.
5285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    checkers = &CachedStmtCheckersMap[key];
5295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
5305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      StmtCheckerInfo &info = StmtCheckers[i];
5315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
5327dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch        checkers->push_back(info.CheckFn);
5337dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    }
5347dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  }
5359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch
5369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch  assert(checkers);
5377dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  return checkers;
5387dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch}
5397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CheckerManager::~CheckerManager() {
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CheckerDtors[i]();
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Anchor for the vtable.
546bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochCheckerProvider::~CheckerProvider() { }
547bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch
548bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben Murdoch// Anchor for the vtable.
549bb1529ce867d8845a77ec7cdf3e3003ef1771a40Ben MurdochGraphExpander::~GraphExpander() { }
5506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)