CheckerManager.cpp revision e9a906b99286b44dcf5eb896f17df74d588e4ce9
143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===--- CheckerManager.cpp - Static Analyzer Checker Manager -------------===//
243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//                     The LLVM Compiler Infrastructure
443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// This file is distributed under the University of Illinois Open Source
643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// License. See LICENSE.TXT for details.
743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
843dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
1043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// Defines the Static Analyzer Checker Manager.
1143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//
1243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis//===----------------------------------------------------------------------===//
1343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
1443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerManager.h"
1555fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/AST/DeclBase.h"
1655fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/Analysis/ProgramPoint.h"
17ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "clang/StaticAnalyzer/Core/Checker.h"
18f540c54701e3eeb34cb619a3a4eb18f1ac70ef2dJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
1955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
2043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
2143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace clang;
2243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace ento;
2343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
24d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidisbool CheckerManager::hasPathSensitiveCheckers() const {
25d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis  return !StmtCheckers.empty()              ||
26d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !PreObjCMessageCheckers.empty()    ||
27d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !PostObjCMessageCheckers.empty()   ||
2896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose         !PreCallCheckers.empty()    ||
2996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose         !PostCallCheckers.empty()   ||
30d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !LocationCheckers.empty()          ||
31d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !BindCheckers.empty()              ||
32d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !EndAnalysisCheckers.empty()       ||
33344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks         !EndFunctionCheckers.empty()           ||
34d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !BranchConditionCheckers.empty()   ||
35d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !LiveSymbolsCheckers.empty()       ||
36d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !DeadSymbolsCheckers.empty()       ||
37d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !RegionChangesCheckers.empty()     ||
38d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !EvalAssumeCheckers.empty()        ||
3942e95acef35f4633119be1c1381e88878c966502Jordan Rose         !EvalCallCheckers.empty();
40d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis}
41d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis
42deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidisvoid CheckerManager::finishedCheckerRegistration() {
43deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis#ifndef NDEBUG
44deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  // Make sure that for every event that has listeners, there is at least
45deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  // one dispatcher registered for it.
46deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  for (llvm::DenseMap<EventTag, EventInfo>::iterator
47deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis         I = Events.begin(), E = Events.end(); I != E; ++I)
48deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis    assert(I->second.HasDispatcher && "No dispatcher registered for an event");
49deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis#endif
50deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis}
51deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis
52769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
53769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for AST traversing..
54769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
55769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
569fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
579fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                                          BugReporter &BR) {
589fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(D);
599fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
609fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  unsigned DeclKind = D->getKind();
619fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  CachedDeclCheckers *checkers = 0;
629fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
639fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  if (CCI != CachedDeclCheckersMap.end()) {
649fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    checkers = &(CCI->second);
659fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  } else {
669fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    // Find the checkers that should run for this Decl and cache them.
679fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    checkers = &CachedDeclCheckersMap[DeclKind];
689fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
699fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      DeclCheckerInfo &info = DeclCheckers[i];
709fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      if (info.IsForDeclFn(D))
71769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis        checkers->push_back(info.CheckFn);
729fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    }
739fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
749fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
759fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(checkers);
769fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  for (CachedDeclCheckers::iterator
77769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis         I = checkers->begin(), E = checkers->end(); I != E; ++I)
78769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    (*I)(D, mgr, BR);
799fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
809fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
819fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
829fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                                          BugReporter &BR) {
839fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(D && D->hasBody());
849fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
85769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
86769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    BodyCheckers[i](D, mgr, BR);
87769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
88769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
89769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
90769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for path-sensitive checking.
91769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
92769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
93769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidistemplate <typename CHECK_CTX>
94c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidisstatic void expandGraphWithCheckers(CHECK_CTX checkCtx,
95c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis                                    ExplodedNodeSet &Dst,
96cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis                                    const ExplodedNodeSet &Src) {
978ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
988ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks  if (Src.empty())
998ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    return;
100769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
101e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  typename CHECK_CTX::CheckersTy::const_iterator
102e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
103e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  if (I == E) {
104769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    Dst.insert(Src);
105769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    return;
106769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  }
107769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
108cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis  ExplodedNodeSet Tmp1, Tmp2;
109cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis  const ExplodedNodeSet *PrevSet = &Src;
110769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
111e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  for (; I != E; ++I) {
112769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExplodedNodeSet *CurrSet = 0;
113769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    if (I+1 == E)
114769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CurrSet = &Dst;
115769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    else {
116cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis      CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
117769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CurrSet->clear();
118769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
119769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
1208ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
121769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
1228ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks         NI != NE; ++NI) {
1238ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks      checkCtx.runChecker(*I, B, *NI);
1248ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    }
1258ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks
1268ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    // If all the produced transitions are sinks, stop.
1278ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    if (CurrSet->empty())
1288ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks      return;
1298ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks
130769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    // Update which NodeSet is the current one.
131769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    PrevSet = CurrSet;
1329fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
1339fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
1349fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
135769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
136769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckStmtContext {
1375f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
138769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    bool IsPreVisit;
139769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
140769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const Stmt *S;
141769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
14257c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose    bool WasInlined;
143769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
144e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
145e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
146e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
147769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
148514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek                     const Stmt *s, ExprEngine &eng, bool wasInlined = false)
149514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
15057c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose        WasInlined(wasInlined) {}
151769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
152769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckStmtFunc checkFn,
1538ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
154769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      // FIXME: Remove respondsToCallback from CheckerContext;
1553f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
1563f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                           ProgramPoint::PostStmtKind;
1573f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
1583f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                Pred->getLocationContext(), checkFn.Checker);
15957c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
160769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      checkFn(S, C);
161769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
162769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
163769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
164769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
165769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting Stmts.
166769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForStmt(bool isPreVisit,
167769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                        ExplodedNodeSet &Dst,
168cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis                                        const ExplodedNodeSet &Src,
169769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                        const Stmt *S,
170514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek                                        ExprEngine &Eng,
17157c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                                        bool WasInlined) {
172e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer  CheckStmtContext C(isPreVisit, getCachedStmtCheckersFor(S, isPreVisit),
17357c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                     S, Eng, WasInlined);
174c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
175769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
176769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
177769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
178769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckObjCMessageContext {
179769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
18057c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose    bool IsPreVisit, WasInlined;
181769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
182de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose    const ObjCMethodCall &Msg;
183769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
184769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
185e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
186e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
187e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
188769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
18957c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                            const ObjCMethodCall &msg, ExprEngine &eng,
19057c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                            bool wasInlined)
19157c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose      : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
19257c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose        Msg(msg), Eng(eng) { }
193769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
194769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
1958ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
196d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose      const ProgramPoint &L = Msg.getProgramPoint(IsPreVisit,checkFn.Checker);
19757c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
1983f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks
199d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose      checkFn(*Msg.cloneWithState<ObjCMethodCall>(Pred->getState()), C);
200769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
201769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
202769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
203769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
204769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting obj-c messages.
205769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
206769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                               ExplodedNodeSet &Dst,
207cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis                                               const ExplodedNodeSet &Src,
208de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose                                               const ObjCMethodCall &msg,
20957c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                                               ExprEngine &Eng,
21057c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                                               bool WasInlined) {
2113f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis  CheckObjCMessageContext C(isPreVisit,
2123f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis                            isPreVisit ? PreObjCMessageCheckers
2133f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis                                       : PostObjCMessageCheckers,
21457c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                            msg, Eng, WasInlined);
215c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
216769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
217769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
218769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
21996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  // FIXME: This has all the same signatures as CheckObjCMessageContext.
22096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  // Is there a way we can merge the two?
22196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  struct CheckCallContext {
22296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    typedef std::vector<CheckerManager::CheckCallFunc> CheckersTy;
22357c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose    bool IsPreVisit, WasInlined;
22496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    const CheckersTy &Checkers;
22596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    const CallEvent &Call;
22696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    ExprEngine &Eng;
22796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
22896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
22996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
23096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
23196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
23257c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                     const CallEvent &call, ExprEngine &eng,
23357c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                     bool wasInlined)
23457c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose    : IsPreVisit(isPreVisit), WasInlined(wasInlined), Checkers(checkers),
23557c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose      Call(call), Eng(eng) { }
23696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
23796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    void runChecker(CheckerManager::CheckCallFunc checkFn,
23896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                    NodeBuilder &Bldr, ExplodedNode *Pred) {
239d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose      const ProgramPoint &L = Call.getProgramPoint(IsPreVisit,checkFn.Checker);
24057c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose      CheckerContext C(Bldr, Eng, Pred, L, WasInlined);
24196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
242d563d3fb73879df7147b8a5302c3bf0e1402ba18Jordan Rose      checkFn(*Call.cloneWithState(Pred->getState()), C);
24396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    }
24496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  };
24596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
24696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
24796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose/// \brief Run checkers for visiting an abstract call event.
24896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::runCheckersForCallEvent(bool isPreVisit,
24996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                             ExplodedNodeSet &Dst,
25096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                             const ExplodedNodeSet &Src,
25196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                             const CallEvent &Call,
25257c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                                             ExprEngine &Eng,
25357c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                                             bool WasInlined) {
25496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  CheckCallContext C(isPreVisit,
25596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                     isPreVisit ? PreCallCheckers
25696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                : PostCallCheckers,
25757c033621dacd8720ac9ff65a09025f14f70e22fJordan Rose                     Call, Eng, WasInlined);
25896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  expandGraphWithCheckers(C, Dst, Src);
25996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
26096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
26196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosenamespace {
262769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckLocationContext {
263769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
264769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
265769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    SVal Loc;
266769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    bool IsLoad;
267bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek    const Stmt *NodeEx; /* Will become a CFGStmt */
268bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek    const Stmt *BoundEx;
269769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
270769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
271e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
272e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
273e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
274769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckLocationContext(const CheckersTy &checkers,
275bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                         SVal loc, bool isLoad, const Stmt *NodeEx,
276bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                         const Stmt *BoundEx,
277bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                         ExprEngine &eng)
278bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek      : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
279bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek        BoundEx(BoundEx), Eng(eng) {}
280769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
281769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckLocationFunc checkFn,
2828ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
2833f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      ProgramPoint::Kind K =  IsLoad ? ProgramPoint::PreLoadKind :
2843f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                       ProgramPoint::PreStoreKind;
285bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek      const ProgramPoint &L =
286bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek        ProgramPoint::getProgramPoint(NodeEx, K,
287bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                      Pred->getLocationContext(),
288bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                      checkFn.Checker);
289063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
290bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek      checkFn(Loc, IsLoad, BoundEx, C);
291769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
292769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
2939fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
2949fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
295769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for load/store of a location.
296ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks
297769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
298cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis                                            const ExplodedNodeSet &Src,
299769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                            SVal location, bool isLoad,
300bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                            const Stmt *NodeEx,
301bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                            const Stmt *BoundEx,
302bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                            ExprEngine &Eng) {
303bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek  CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
304bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                         BoundEx, Eng);
305c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
3069fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
3079fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
308312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisnamespace {
309312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  struct CheckBindContext {
310312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
311312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    const CheckersTy &Checkers;
312312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    SVal Loc;
313312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    SVal Val;
314312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    const Stmt *S;
315312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    ExprEngine &Eng;
3163682f1ea9c7fddc7dcbc590891158ba40f7fca16Jordan Rose    const ProgramPoint &PP;
317312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
318312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
319312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
320312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
321312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    CheckBindContext(const CheckersTy &checkers,
322ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
3233682f1ea9c7fddc7dcbc590891158ba40f7fca16Jordan Rose                     const ProgramPoint &pp)
3243682f1ea9c7fddc7dcbc590891158ba40f7fca16Jordan Rose      : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PP(pp) {}
325312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
326312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckBindFunc checkFn,
3278ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
3283682f1ea9c7fddc7dcbc590891158ba40f7fca16Jordan Rose      const ProgramPoint &L = PP.withTag(checkFn.Checker);
329063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
3303f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks
331390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks      checkFn(Loc, Val, S, C);
332312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    }
333312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  };
334312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
335312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
336312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis/// \brief Run checkers for binding of a value to a location.
337312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
338312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                        const ExplodedNodeSet &Src,
339312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                        SVal location, SVal val,
340ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks                                        const Stmt *S, ExprEngine &Eng,
3413682f1ea9c7fddc7dcbc590891158ba40f7fca16Jordan Rose                                        const ProgramPoint &PP) {
3423682f1ea9c7fddc7dcbc590891158ba40f7fca16Jordan Rose  CheckBindContext C(BindCheckers, location, val, S, Eng, PP);
343312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
344312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
345312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
34630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
34730726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis                                               BugReporter &BR,
34830726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis                                               ExprEngine &Eng) {
34930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis  for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
35030726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    EndAnalysisCheckers[i](G, BR, Eng);
35130726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis}
35230726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis
353af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis/// \brief Run checkers for end of path.
354af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks// Note, We do not chain the checker output (like in expandGraphWithCheckers)
355af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks// for this callback since end of path nodes are expected to be final.
356344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaksvoid CheckerManager::runCheckersForEndFunction(NodeBuilderContext &BC,
357344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks                                               ExplodedNodeSet &Dst,
358344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks                                               ExplodedNode *Pred,
359344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks                                               ExprEngine &Eng) {
360af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks
361af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  // We define the builder outside of the loop bacause if at least one checkers
362af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  // creates a sucsessor for Pred, we do not need to generate an
363af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  // autotransition for it.
364af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  NodeBuilder Bldr(Pred, Dst, BC);
365344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks  for (unsigned i = 0, e = EndFunctionCheckers.size(); i != e; ++i) {
366344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks    CheckEndFunctionFunc checkFn = EndFunctionCheckers[i];
367af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks
368af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks    const ProgramPoint &L = BlockEntrance(BC.Block,
369af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks                                          Pred->getLocationContext(),
370af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks                                          checkFn.Checker);
371063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks    CheckerContext C(Bldr, Eng, Pred, L);
372af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks    checkFn(C);
373af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis  }
374af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis}
375af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis
376f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaksnamespace {
377f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  struct CheckBranchConditionContext {
378f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy;
379f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    const CheckersTy &Checkers;
380f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    const Stmt *Condition;
381f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    ExprEngine &Eng;
382f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks
383f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
384f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
385f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks
386f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    CheckBranchConditionContext(const CheckersTy &checkers,
387f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks                                const Stmt *Cond, ExprEngine &eng)
388f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks      : Checkers(checkers), Condition(Cond), Eng(eng) {}
389f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks
390f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
391f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
392f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks      ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
393f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks                                     checkFn.Checker);
394063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
395f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks      checkFn(Condition, C);
396f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    }
397f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  };
398f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks}
399f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks
400cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis/// \brief Run checkers for branch condition.
401f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaksvoid CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
402f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks                                                   ExplodedNodeSet &Dst,
4034e82d3cf6fd4c907265e3fa3aac0a835c35dc759Anna Zaks                                                   ExplodedNode *Pred,
404cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis                                                   ExprEngine &Eng) {
405f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  ExplodedNodeSet Src;
406f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  Src.insert(Pred);
407f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
408f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  expandGraphWithCheckers(C, Dst, Src);
409cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis}
410cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis
411183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for live symbols.
4128bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekvoid CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
413183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                               SymbolReaper &SymReaper) {
414183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
415183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    LiveSymbolsCheckers[i](state, SymReaper);
416183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
417183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
418183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisnamespace {
419183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  struct CheckDeadSymbolsContext {
420183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
421183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    const CheckersTy &Checkers;
422183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    SymbolReaper &SR;
423183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    const Stmt *S;
424183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    ExprEngine &Eng;
4250b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    ProgramPoint::Kind ProgarmPointKind;
426183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
427183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
428183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
429183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
430183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
4310b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                            const Stmt *s, ExprEngine &eng,
4320b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                            ProgramPoint::Kind K)
4330b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { }
434183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
435183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
4368ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
4370b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
4383f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                Pred->getLocationContext(), checkFn.Checker);
439063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
4403f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks
4410b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      // Note, do not pass the statement to the checkers without letting them
4420b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      // differentiate if we ran remove dead bindings before or after the
4430b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      // statement.
444183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      checkFn(SR, C);
445183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    }
446183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  };
447183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
448183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
449183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for dead symbols.
450183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
451183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                               const ExplodedNodeSet &Src,
452183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                               SymbolReaper &SymReaper,
453183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                               const Stmt *S,
4540b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                                               ExprEngine &Eng,
4550b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                                               ProgramPoint::Kind K) {
4560b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
457183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
458183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
459183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
460183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief True if at least one checker wants to check region changes.
4618bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekbool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) {
462183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
463183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    if (RegionChangesCheckers[i].WantUpdateFn(state))
464183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      return true;
465183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
466183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  return false;
467183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
468183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
469183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for region changes.
4708bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef
4718bef8238181a30e52dea380789a7e2d760eac532Ted KremenekCheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
472bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks                                    const InvalidatedSymbols *invalidated,
473537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose                                    ArrayRef<const MemRegion *> ExplicitRegions,
474bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks                                    ArrayRef<const MemRegion *> Regions,
475bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks                                    const CallEvent *Call) {
476183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
477183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    // If any checker declares the state infeasible (or if it starts that way),
478183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    // bail out.
479183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    if (!state)
480183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      return NULL;
481537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose    state = RegionChangesCheckers[i].CheckFn(state, invalidated,
48266c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks                                             ExplicitRegions, Regions, Call);
483183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  }
484183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  return state;
485183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
486183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
487bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks/// \brief Run checkers to process symbol escape event.
488bf53dfac8195835028bd6347433f7dbebcc29fc1Anna ZaksProgramStateRef
489bf53dfac8195835028bd6347433f7dbebcc29fc1Anna ZaksCheckerManager::runCheckersForPointerEscape(ProgramStateRef State,
490bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks                                           const InvalidatedSymbols &Escaped,
491233e26acc0ff2a1098f4c813f69286fce840a422Anna Zaks                                           const CallEvent *Call,
49241988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks                                           PointerEscapeKind Kind,
49341988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks                                           bool IsConst) {
494233e26acc0ff2a1098f4c813f69286fce840a422Anna Zaks  assert((Call != NULL ||
495233e26acc0ff2a1098f4c813f69286fce840a422Anna Zaks          (Kind != PSK_DirectEscapeOnCall &&
496233e26acc0ff2a1098f4c813f69286fce840a422Anna Zaks           Kind != PSK_IndirectEscapeOnCall)) &&
497233e26acc0ff2a1098f4c813f69286fce840a422Anna Zaks         "Call must not be NULL when escaping on call");
49841988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks    for (unsigned i = 0, e = PointerEscapeCheckers.size(); i != e; ++i) {
49941988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks      // If any checker declares the state infeasible (or if it starts that
50041988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks      //  way), bail out.
50141988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks      if (!State)
50241988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks        return NULL;
50341988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks      State = PointerEscapeCheckers[i](State, Escaped, Call, Kind, IsConst);
50441988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks    }
505bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks  return State;
506bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks}
507bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks
508312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis/// \brief Run checkers for handling assumptions on symbolic values.
5098bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef
5108bef8238181a30e52dea380789a7e2d760eac532Ted KremenekCheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
511312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                         SVal Cond, bool Assumption) {
512312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
513312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    // If any checker declares the state infeasible (or if it starts that way),
514312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    // bail out.
515312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    if (!state)
516312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis      return NULL;
517312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    state = EvalAssumeCheckers[i](state, Cond, Assumption);
518312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  }
519312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  return state;
520312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
521312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
522e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis/// \brief Run checkers for evaluating a call.
523e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis/// Only one checker will evaluate the call.
524e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
525e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis                                            const ExplodedNodeSet &Src,
526645baeed6800f952e9ad1d5666e01080385531a2Jordan Rose                                            const CallEvent &Call,
52769f87c956b3ac2b80124fd9604af012e1061473aJordan Rose                                            ExprEngine &Eng) {
528645baeed6800f952e9ad1d5666e01080385531a2Jordan Rose  const CallExpr *CE = cast<CallExpr>(Call.getOriginExpr());
529e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  for (ExplodedNodeSet::iterator
530e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis         NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
531e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    ExplodedNode *Pred = *NI;
532e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    bool anyEvaluated = false;
533dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks
5348ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    ExplodedNodeSet checkDst;
5358ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
53642e95acef35f4633119be1c1381e88878c966502Jordan Rose
53742e95acef35f4633119be1c1381e88878c966502Jordan Rose    // Check if any of the EvalCall callbacks can evaluate the call.
538e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    for (std::vector<EvalCallFunc>::iterator
539e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis           EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
540e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis         EI != EE; ++EI) {
5413f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      ProgramPoint::Kind K = ProgramPoint::PostStmtKind;
5423f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K,
5433f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                Pred->getLocationContext(), EI->Checker);
544b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks      bool evaluated = false;
545b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks      { // CheckerContext generates transitions(populates checkDest) on
546b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks        // destruction, so introduce the scope to make sure it gets properly
547b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks        // populated.
548063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks        CheckerContext C(B, Eng, Pred, L);
549b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks        evaluated = (*EI)(CE, C);
550b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks      }
551e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      assert(!(evaluated && anyEvaluated)
552e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis             && "There are more than one checkers evaluating the call");
553e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      if (evaluated) {
554e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis        anyEvaluated = true;
555e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis        Dst.insert(checkDst);
556e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis#ifdef NDEBUG
557e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis        break; // on release don't check that no other checker also evals.
558e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis#endif
559e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      }
560e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    }
561e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
562dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    // If none of the checkers evaluated the call, ask ExprEngine to handle it.
563e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks    if (!anyEvaluated) {
564e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks      NodeBuilder B(Pred, Dst, Eng.getBuilderContext());
565e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks      Eng.defaultEvalCall(B, Pred, Call);
566e81ce256b62717dd846bd19aecc4115a0dcd4995Anna Zaks    }
567e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  }
568e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis}
569e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
5709be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek/// \brief Run checkers for the entire Translation Unit.
5719be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenekvoid CheckerManager::runCheckersOnEndOfTranslationUnit(
5729be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                                  const TranslationUnitDecl *TU,
5739be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                                  AnalysisManager &mgr,
5749be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                                  BugReporter &BR) {
5759be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
5769be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek    EndOfTranslationUnitCheckers[i](TU, mgr, BR);
5779be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek}
5789be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
579dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rosevoid CheckerManager::runCheckersForPrintState(raw_ostream &Out,
5808bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek                                              ProgramStateRef State,
581dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose                                              const char *NL, const char *Sep) {
582dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose  for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
583dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose        I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
584dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose    I->second->printState(Out, State, NL, Sep);
585dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose}
586dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose
587769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
588769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for AST traversing.
589769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
590769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
591769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
592769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                      HandlesDeclFunc isForDeclFn) {
593769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  DeclCheckerInfo info = { checkfn, isForDeclFn };
594769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  DeclCheckers.push_back(info);
595769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
596769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
597769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
598769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  BodyCheckers.push_back(checkfn);
599769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
600769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
601769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
602769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for path-sensitive checking.
603769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
604769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
605769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
606769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                         HandlesStmtFunc isForStmtFn) {
607769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
608769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckers.push_back(info);
609769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
610769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
611769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                          HandlesStmtFunc isForStmtFn) {
612769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
613769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckers.push_back(info);
614769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
615769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
616769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
617769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  PreObjCMessageCheckers.push_back(checkfn);
618769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
619769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
620769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  PostObjCMessageCheckers.push_back(checkfn);
621769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
622769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
62396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::_registerForPreCall(CheckCallFunc checkfn) {
62496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  PreCallCheckers.push_back(checkfn);
62596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
62696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::_registerForPostCall(CheckCallFunc checkfn) {
62796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  PostCallCheckers.push_back(checkfn);
62896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
62996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
630769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
631769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  LocationCheckers.push_back(checkfn);
632769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
633769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
634312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::_registerForBind(CheckBindFunc checkfn) {
635312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  BindCheckers.push_back(checkfn);
636312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
637312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
63830726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
63930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis  EndAnalysisCheckers.push_back(checkfn);
64030726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis}
64130726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis
642344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaksvoid CheckerManager::_registerForEndFunction(CheckEndFunctionFunc checkfn) {
643344c77aac25e5d960aced3f45fbaa09853383f6dAnna Zaks  EndFunctionCheckers.push_back(checkfn);
644af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis}
645af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis
646cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidisvoid CheckerManager::_registerForBranchCondition(
647cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis                                             CheckBranchConditionFunc checkfn) {
648cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis  BranchConditionCheckers.push_back(checkfn);
649cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis}
650cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis
651183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
652183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  LiveSymbolsCheckers.push_back(checkfn);
653183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
654183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
655183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
656183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  DeadSymbolsCheckers.push_back(checkfn);
657183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
658183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
659183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
660183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                     WantsRegionChangeUpdateFunc wantUpdateFn) {
661183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
662183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  RegionChangesCheckers.push_back(info);
663183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
664183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
665bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaksvoid CheckerManager::_registerForPointerEscape(CheckPointerEscapeFunc checkfn){
666bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks  PointerEscapeCheckers.push_back(checkfn);
667bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks}
668bf53dfac8195835028bd6347433f7dbebcc29fc1Anna Zaks
66941988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaksvoid CheckerManager::_registerForConstPointerEscape(
67041988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks                                          CheckPointerEscapeFunc checkfn) {
67141988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks  PointerEscapeCheckers.push_back(checkfn);
67241988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks}
67341988f331a74a72cf243a2a68ffb56418e9a174eAnna Zaks
674312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
675312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  EvalAssumeCheckers.push_back(checkfn);
676312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
677312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
678e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
679e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  EvalCallCheckers.push_back(checkfn);
680e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis}
681e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
6829be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenekvoid CheckerManager::_registerForEndOfTranslationUnit(
6839be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                            CheckEndOfTranslationUnit checkfn) {
6849be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  EndOfTranslationUnitCheckers.push_back(checkfn);
6859be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek}
6869be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
687769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
688769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Implementation details.
689769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
690769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
691e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramerconst CheckerManager::CachedStmtCheckers &
692769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
693769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  assert(S);
694769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
695e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer  unsigned Key = (S->getStmtClass() << 1) | unsigned(isPreVisit);
696e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(Key);
697e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer  if (CCI != CachedStmtCheckersMap.end())
698e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer    return CCI->second;
699e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer
700e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer  // Find the checkers that should run for this Stmt and cache them.
701e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer  CachedStmtCheckers &Checkers = CachedStmtCheckersMap[Key];
702e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer  for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
703e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer    StmtCheckerInfo &Info = StmtCheckers[i];
704e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer    if (Info.IsPreVisit == isPreVisit && Info.IsForStmtFn(S))
705e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer      Checkers.push_back(Info.CheckFn);
7069fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
707e9a906b99286b44dcf5eb896f17df74d588e4ce9Benjamin Kramer  return Checkers;
708769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
709769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
710769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::~CheckerManager() {
711769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
712769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckerDtors[i]();
7139fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
714