CheckerManager.cpp revision 96479da6ad9d921d875e7be29fe1bfa127be8069
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"
15ca804539d908d3a0e8c72a0df5f1f571d29490bbTed Kremenek#include "clang/StaticAnalyzer/Core/Checker.h"
16769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
17de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose#include "clang/StaticAnalyzer/Core/PathSensitive/Calls.h"
18769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis#include "clang/Analysis/ProgramPoint.h"
199fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "clang/AST/DeclBase.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()       ||
33d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !EndPathCheckers.empty()           ||
34d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !BranchConditionCheckers.empty()   ||
35d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !LiveSymbolsCheckers.empty()       ||
36d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !DeadSymbolsCheckers.empty()       ||
37d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !RegionChangesCheckers.empty()     ||
38d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis         !EvalAssumeCheckers.empty()        ||
39dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks         !EvalCallCheckers.empty()          ||
40dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks         !InlineCallCheckers.empty();
41d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis}
42d655ab28fdf7c940d3f79f8f287954d7f76e0977Argyrios Kyrtzidis
43deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidisvoid CheckerManager::finishedCheckerRegistration() {
44deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis#ifndef NDEBUG
45deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  // Make sure that for every event that has listeners, there is at least
46deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  // one dispatcher registered for it.
47deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis  for (llvm::DenseMap<EventTag, EventInfo>::iterator
48deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis         I = Events.begin(), E = Events.end(); I != E; ++I)
49deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis    assert(I->second.HasDispatcher && "No dispatcher registered for an event");
50deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis#endif
51deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis}
52deb6447d0029bdb122397fafb5fa2a4e76f2e555Argyrios Kyrtzidis
53769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
54769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for AST traversing..
55769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
56769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
579fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
589fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                                          BugReporter &BR) {
599fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(D);
609fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
619fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  unsigned DeclKind = D->getKind();
629fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  CachedDeclCheckers *checkers = 0;
639fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
649fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  if (CCI != CachedDeclCheckersMap.end()) {
659fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    checkers = &(CCI->second);
669fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  } else {
679fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    // Find the checkers that should run for this Decl and cache them.
689fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    checkers = &CachedDeclCheckersMap[DeclKind];
699fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
709fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      DeclCheckerInfo &info = DeclCheckers[i];
719fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      if (info.IsForDeclFn(D))
72769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis        checkers->push_back(info.CheckFn);
739fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    }
749fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
759fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
769fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(checkers);
779fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  for (CachedDeclCheckers::iterator
78769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis         I = checkers->begin(), E = checkers->end(); I != E; ++I)
79769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    (*I)(D, mgr, BR);
809fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
819fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
829fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
839fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                                          BugReporter &BR) {
849fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(D && D->hasBody());
859fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
86769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
87769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    BodyCheckers[i](D, mgr, BR);
88769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
89769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
90769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
91769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for path-sensitive checking.
92769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
93769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
94769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidistemplate <typename CHECK_CTX>
95c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidisstatic void expandGraphWithCheckers(CHECK_CTX checkCtx,
96c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis                                    ExplodedNodeSet &Dst,
97cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis                                    const ExplodedNodeSet &Src) {
988ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks  const NodeBuilderContext &BldrCtx = checkCtx.Eng.getBuilderContext();
998ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks  if (Src.empty())
1008ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    return;
101769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
102e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  typename CHECK_CTX::CheckersTy::const_iterator
103e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      I = checkCtx.checkers_begin(), E = checkCtx.checkers_end();
104e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  if (I == E) {
105769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    Dst.insert(Src);
106769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    return;
107769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  }
108769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
109cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis  ExplodedNodeSet Tmp1, Tmp2;
110cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis  const ExplodedNodeSet *PrevSet = &Src;
111769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
112e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  for (; I != E; ++I) {
113769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExplodedNodeSet *CurrSet = 0;
114769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    if (I+1 == E)
115769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CurrSet = &Dst;
116769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    else {
117cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis      CurrSet = (PrevSet == &Tmp1) ? &Tmp2 : &Tmp1;
118769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CurrSet->clear();
119769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
120769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
1218ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    NodeBuilder B(*PrevSet, *CurrSet, BldrCtx);
122769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
1238ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks         NI != NE; ++NI) {
1248ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks      checkCtx.runChecker(*I, B, *NI);
1258ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    }
1268ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks
1278ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    // If all the produced transitions are sinks, stop.
1288ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    if (CurrSet->empty())
1298ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks      return;
1308ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks
131769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    // Update which NodeSet is the current one.
132769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    PrevSet = CurrSet;
1339fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
1349fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
1359fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
136769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
137769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckStmtContext {
1385f9e272e632e951b1efe824cd16acb4d96077930Chris Lattner    typedef SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
139769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    bool IsPreVisit;
140769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
141769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const Stmt *S;
142769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
143514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek    bool wasInlined;
144769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
145e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
146e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
147e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
148769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
149514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek                     const Stmt *s, ExprEngine &eng, bool wasInlined = false)
150514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng),
151514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek        wasInlined(wasInlined) {}
152769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
153769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckStmtFunc checkFn,
1548ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
155769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      // FIXME: Remove respondsToCallback from CheckerContext;
1563f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
1573f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                           ProgramPoint::PostStmtKind;
1583f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, K,
1593f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                Pred->getLocationContext(), checkFn.Checker);
160514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek      CheckerContext C(Bldr, Eng, Pred, L, wasInlined);
161769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      checkFn(S, C);
162769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
163769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
164769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
165769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
166769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting Stmts.
167769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForStmt(bool isPreVisit,
168769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                        ExplodedNodeSet &Dst,
169cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis                                        const ExplodedNodeSet &Src,
170769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                        const Stmt *S,
171514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek                                        ExprEngine &Eng,
172514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek                                        bool wasInlined) {
173769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
174514f2c9dcb9e04b52929c5b141a6fe88bd68b33fTed Kremenek                     S, Eng, wasInlined);
175c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
176769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
177769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
178769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
179769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckObjCMessageContext {
180769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
181769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    bool IsPreVisit;
182769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
183de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose    const ObjCMethodCall &Msg;
184769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
185769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
186e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
187e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
188e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
189769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
190de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose                            const ObjCMethodCall &msg, ExprEngine &eng)
191769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
192769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
193769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
1948ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
1953f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      ProgramPoint::Kind K =  IsPreVisit ? ProgramPoint::PreStmtKind :
1963f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                           ProgramPoint::PostStmtKind;
197b673a41c92aa276f2e37164d0747be1cfb0c402bTed Kremenek      const ProgramPoint &L =
198de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose        ProgramPoint::getProgramPoint(Msg.getOriginExpr(),
199b673a41c92aa276f2e37164d0747be1cfb0c402bTed Kremenek                                      K, Pred->getLocationContext(),
200b673a41c92aa276f2e37164d0747be1cfb0c402bTed Kremenek                                      checkFn.Checker);
201063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
2023f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks
203769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      checkFn(Msg, C);
204769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
205769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
206769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
207769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
208769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting obj-c messages.
209769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
210769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                               ExplodedNodeSet &Dst,
211cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis                                               const ExplodedNodeSet &Src,
212de507eaf3cb54d3cb234dc14499c10ab3373d15fJordan Rose                                               const ObjCMethodCall &msg,
213769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                               ExprEngine &Eng) {
2143f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis  CheckObjCMessageContext C(isPreVisit,
2153f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis                            isPreVisit ? PreObjCMessageCheckers
2163f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis                                       : PostObjCMessageCheckers,
2173f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis                            msg, Eng);
218c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
219769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
220769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
221769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
22296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  // FIXME: This has all the same signatures as CheckObjCMessageContext.
22396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  // Is there a way we can merge the two?
22496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  struct CheckCallContext {
22596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    typedef std::vector<CheckerManager::CheckCallFunc> CheckersTy;
22696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    bool IsPreVisit;
22796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    const CheckersTy &Checkers;
22896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    const CallEvent &Call;
22996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    ExprEngine &Eng;
23096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
23196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
23296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
23396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
23496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    CheckCallContext(bool isPreVisit, const CheckersTy &checkers,
23596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                     const CallEvent &call, ExprEngine &eng)
23696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    : IsPreVisit(isPreVisit), Checkers(checkers), Call(call), Eng(eng) { }
23796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
23896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    void runChecker(CheckerManager::CheckCallFunc checkFn,
23996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                    NodeBuilder &Bldr, ExplodedNode *Pred) {
24096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      // FIXME: This will be wrong as soon as we handle any calls without
24196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      // associated statements.
24296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      ProgramPoint::Kind K = IsPreVisit ? ProgramPoint::PreStmtKind
24396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                        : ProgramPoint::PostStmtKind;
24496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      assert(Call.getOriginExpr() && "Calls without stmts not yet handled");
24596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      const ProgramPoint &L =
24696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose        ProgramPoint::getProgramPoint(Call.getOriginExpr(),
24796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                      K, Pred->getLocationContext(),
24896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                      checkFn.Checker);
24996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      CheckerContext C(Bldr, Eng, Pred, L);
25096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
25196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose      checkFn(Call, C);
25296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose    }
25396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  };
25496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
25596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
25696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose/// \brief Run checkers for visiting an abstract call event.
25796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::runCheckersForCallEvent(bool isPreVisit,
25896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                             ExplodedNodeSet &Dst,
25996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                             const ExplodedNodeSet &Src,
26096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                             const CallEvent &Call,
26196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                             ExprEngine &Eng) {
26296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  CheckCallContext C(isPreVisit,
26396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                     isPreVisit ? PreCallCheckers
26496479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                                : PostCallCheckers,
26596479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose                     Call, Eng);
26696479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  expandGraphWithCheckers(C, Dst, Src);
26796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
26896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
26996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosenamespace {
270769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckLocationContext {
271769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
272769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
273769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    SVal Loc;
274769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    bool IsLoad;
275bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek    const Stmt *NodeEx; /* Will become a CFGStmt */
276bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek    const Stmt *BoundEx;
277769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
278769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
279e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
280e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
281e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
282769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckLocationContext(const CheckersTy &checkers,
283bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                         SVal loc, bool isLoad, const Stmt *NodeEx,
284bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                         const Stmt *BoundEx,
285bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                         ExprEngine &eng)
286bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek      : Checkers(checkers), Loc(loc), IsLoad(isLoad), NodeEx(NodeEx),
287bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek        BoundEx(BoundEx), Eng(eng) {}
288769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
289769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckLocationFunc checkFn,
2908ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
2913f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      ProgramPoint::Kind K =  IsLoad ? ProgramPoint::PreLoadKind :
2923f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                       ProgramPoint::PreStoreKind;
293bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek      const ProgramPoint &L =
294bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek        ProgramPoint::getProgramPoint(NodeEx, K,
295bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                      Pred->getLocationContext(),
296bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                      checkFn.Checker);
297063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
298bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek      checkFn(Loc, IsLoad, BoundEx, C);
299769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
300769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
3019fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
3029fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
303769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for load/store of a location.
304ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks
305769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
306cd50e136ad7dc721822f5e6350769a37c216612dArgyrios Kyrtzidis                                            const ExplodedNodeSet &Src,
307769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                            SVal location, bool isLoad,
308bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                            const Stmt *NodeEx,
309bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                            const Stmt *BoundEx,
310bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                                            ExprEngine &Eng) {
311bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek  CheckLocationContext C(LocationCheckers, location, isLoad, NodeEx,
312bd613137499b1d4c3b63dccd0aa21f6add243f4fTed Kremenek                         BoundEx, Eng);
313c2e0db82139c70c0eac9d5c165b6bf3250af5bedArgyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
3149fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
3159fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
316312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisnamespace {
317312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  struct CheckBindContext {
318312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckBindFunc> CheckersTy;
319312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    const CheckersTy &Checkers;
320312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    SVal Loc;
321312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    SVal Val;
322312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    const Stmt *S;
323312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    ExprEngine &Eng;
324ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks    ProgramPoint::Kind PointKind;
325312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
326312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
327312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
328312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
329312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    CheckBindContext(const CheckersTy &checkers,
330ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks                     SVal loc, SVal val, const Stmt *s, ExprEngine &eng,
331ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks                     ProgramPoint::Kind PK)
332ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks      : Checkers(checkers), Loc(loc), Val(val), S(s), Eng(eng), PointKind(PK) {}
333312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
334312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckBindFunc checkFn,
3358ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
336ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, PointKind,
3373f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                Pred->getLocationContext(), checkFn.Checker);
338063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
3393f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks
340390909c89c98ab1807e15e033a72e975f866fb23Anna Zaks      checkFn(Loc, Val, S, C);
341312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    }
342312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  };
343312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
344312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
345312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis/// \brief Run checkers for binding of a value to a location.
346312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::runCheckersForBind(ExplodedNodeSet &Dst,
347312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                        const ExplodedNodeSet &Src,
348312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                        SVal location, SVal val,
349ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks                                        const Stmt *S, ExprEngine &Eng,
350ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks                                        ProgramPoint::Kind PointKind) {
351ebae6d0209e1ec3d5ea14f9e63bd0d740218ed14Anna Zaks  CheckBindContext C(BindCheckers, location, val, S, Eng, PointKind);
352312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
353312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
354312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
35530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid CheckerManager::runCheckersForEndAnalysis(ExplodedGraph &G,
35630726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis                                               BugReporter &BR,
35730726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis                                               ExprEngine &Eng) {
35830726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis  for (unsigned i = 0, e = EndAnalysisCheckers.size(); i != e; ++i)
35930726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis    EndAnalysisCheckers[i](G, BR, Eng);
36030726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis}
36130726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis
362af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis/// \brief Run checkers for end of path.
363af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks// Note, We do not chain the checker output (like in expandGraphWithCheckers)
364af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks// for this callback since end of path nodes are expected to be final.
365af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaksvoid CheckerManager::runCheckersForEndPath(NodeBuilderContext &BC,
366af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks                                           ExplodedNodeSet &Dst,
367af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis                                           ExprEngine &Eng) {
368af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  ExplodedNode *Pred = BC.Pred;
369af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks
370af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  // We define the builder outside of the loop bacause if at least one checkers
371af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  // creates a sucsessor for Pred, we do not need to generate an
372af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  // autotransition for it.
373af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks  NodeBuilder Bldr(Pred, Dst, BC);
374af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis  for (unsigned i = 0, e = EndPathCheckers.size(); i != e; ++i) {
375af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks    CheckEndPathFunc checkFn = EndPathCheckers[i];
376af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks
377af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks    const ProgramPoint &L = BlockEntrance(BC.Block,
378af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks                                          Pred->getLocationContext(),
379af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks                                          checkFn.Checker);
380063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks    CheckerContext C(Bldr, Eng, Pred, L);
381af498a28797c075c48d7e943df5f5a8e78ed8eb0Anna Zaks    checkFn(C);
382af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis  }
383af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis}
384af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis
385f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaksnamespace {
386f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  struct CheckBranchConditionContext {
387f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    typedef std::vector<CheckerManager::CheckBranchConditionFunc> CheckersTy;
388f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    const CheckersTy &Checkers;
389f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    const Stmt *Condition;
390f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    ExprEngine &Eng;
391f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks
392f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
393f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
394f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks
395f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    CheckBranchConditionContext(const CheckersTy &checkers,
396f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks                                const Stmt *Cond, ExprEngine &eng)
397f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks      : Checkers(checkers), Condition(Cond), Eng(eng) {}
398f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks
399f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    void runChecker(CheckerManager::CheckBranchConditionFunc checkFn,
400f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
401f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks      ProgramPoint L = PostCondition(Condition, Pred->getLocationContext(),
402f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks                                     checkFn.Checker);
403063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
404f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks      checkFn(Condition, C);
405f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks    }
406f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  };
407f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks}
408f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks
409cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis/// \brief Run checkers for branch condition.
410f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaksvoid CheckerManager::runCheckersForBranchCondition(const Stmt *Condition,
411f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks                                                   ExplodedNodeSet &Dst,
4124e82d3cf6fd4c907265e3fa3aac0a835c35dc759Anna Zaks                                                   ExplodedNode *Pred,
413cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis                                                   ExprEngine &Eng) {
414f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  ExplodedNodeSet Src;
415f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  Src.insert(Pred);
416f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  CheckBranchConditionContext C(BranchConditionCheckers, Condition, Eng);
417f236b6503a4dbc44c1fccb8756bd57c9d0efdf05Anna Zaks  expandGraphWithCheckers(C, Dst, Src);
418cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis}
419cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis
420183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for live symbols.
4218bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekvoid CheckerManager::runCheckersForLiveSymbols(ProgramStateRef state,
422183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                               SymbolReaper &SymReaper) {
423183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  for (unsigned i = 0, e = LiveSymbolsCheckers.size(); i != e; ++i)
424183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    LiveSymbolsCheckers[i](state, SymReaper);
425183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
426183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
427183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisnamespace {
428183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  struct CheckDeadSymbolsContext {
429183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckDeadSymbolsFunc> CheckersTy;
430183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    const CheckersTy &Checkers;
431183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    SymbolReaper &SR;
432183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    const Stmt *S;
433183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    ExprEngine &Eng;
4340b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks    ProgramPoint::Kind ProgarmPointKind;
435183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
436183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
437183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
438183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
439183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    CheckDeadSymbolsContext(const CheckersTy &checkers, SymbolReaper &sr,
4400b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                            const Stmt *s, ExprEngine &eng,
4410b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                            ProgramPoint::Kind K)
4420b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      : Checkers(checkers), SR(sr), S(s), Eng(eng), ProgarmPointKind(K) { }
443183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
444183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckDeadSymbolsFunc checkFn,
4458ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks                    NodeBuilder &Bldr, ExplodedNode *Pred) {
4460b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      const ProgramPoint &L = ProgramPoint::getProgramPoint(S, ProgarmPointKind,
4473f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                Pred->getLocationContext(), checkFn.Checker);
448063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks      CheckerContext C(Bldr, Eng, Pred, L);
4493f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks
4500b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      // Note, do not pass the statement to the checkers without letting them
4510b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      // differentiate if we ran remove dead bindings before or after the
4520b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks      // statement.
453183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      checkFn(SR, C);
454183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    }
455183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  };
456183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
457183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
458183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for dead symbols.
459183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
460183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                               const ExplodedNodeSet &Src,
461183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                               SymbolReaper &SymReaper,
462183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                               const Stmt *S,
4630b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                                               ExprEngine &Eng,
4640b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks                                               ProgramPoint::Kind K) {
4650b3ade86a1c60cf0c7b56aa238aff458eb7f5974Anna Zaks  CheckDeadSymbolsContext C(DeadSymbolsCheckers, SymReaper, S, Eng, K);
466183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  expandGraphWithCheckers(C, Dst, Src);
467183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
468183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
469183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief True if at least one checker wants to check region changes.
4708bef8238181a30e52dea380789a7e2d760eac532Ted Kremenekbool CheckerManager::wantsRegionChangeUpdate(ProgramStateRef state) {
471183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i)
472183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    if (RegionChangesCheckers[i].WantUpdateFn(state))
473183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      return true;
474183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
475183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  return false;
476183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
477183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
478183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis/// \brief Run checkers for region changes.
4798bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef
4808bef8238181a30e52dea380789a7e2d760eac532Ted KremenekCheckerManager::runCheckersForRegionChanges(ProgramStateRef state,
48135bdbf40624beba3fc00cb72ab444659939c1a6bTed Kremenek                            const StoreManager::InvalidatedSymbols *invalidated,
482537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose                                    ArrayRef<const MemRegion *> ExplicitRegions,
48366c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks                                          ArrayRef<const MemRegion *> Regions,
484740d490593e0de8732a697c9f77b90ddd463863bJordan Rose                                          const CallEvent *Call) {
485183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  for (unsigned i = 0, e = RegionChangesCheckers.size(); i != e; ++i) {
486183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    // If any checker declares the state infeasible (or if it starts that way),
487183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    // bail out.
488183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis    if (!state)
489183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis      return NULL;
490537716ad8dd10f984b6cfe6985afade1185c5e3cJordy Rose    state = RegionChangesCheckers[i].CheckFn(state, invalidated,
49166c40400e7d6272b0cd675ada18dd62c1f0362c7Anna Zaks                                             ExplicitRegions, Regions, Call);
492183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  }
493183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  return state;
494183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
495183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
496312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis/// \brief Run checkers for handling assumptions on symbolic values.
4978bef8238181a30e52dea380789a7e2d760eac532Ted KremenekProgramStateRef
4988bef8238181a30e52dea380789a7e2d760eac532Ted KremenekCheckerManager::runCheckersForEvalAssume(ProgramStateRef state,
499312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis                                         SVal Cond, bool Assumption) {
500312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  for (unsigned i = 0, e = EvalAssumeCheckers.size(); i != e; ++i) {
501312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    // If any checker declares the state infeasible (or if it starts that way),
502312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    // bail out.
503312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    if (!state)
504312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis      return NULL;
505312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis    state = EvalAssumeCheckers[i](state, Cond, Assumption);
506312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  }
507312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  return state;
508312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
509312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
510e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis/// \brief Run checkers for evaluating a call.
511e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis/// Only one checker will evaluate the call.
512e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid CheckerManager::runCheckersForEvalCall(ExplodedNodeSet &Dst,
513e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis                                            const ExplodedNodeSet &Src,
51469f87c956b3ac2b80124fd9604af012e1061473aJordan Rose                                            const SimpleCall &Call,
51569f87c956b3ac2b80124fd9604af012e1061473aJordan Rose                                            ExprEngine &Eng) {
51669f87c956b3ac2b80124fd9604af012e1061473aJordan Rose  const CallExpr *CE = Call.getOriginExpr();
517e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  for (ExplodedNodeSet::iterator
518e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis         NI = Src.begin(), NE = Src.end(); NI != NE; ++NI) {
519e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
520e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    ExplodedNode *Pred = *NI;
521e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    bool anyEvaluated = false;
522dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks
523dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    // First, check if any of the InlineCall callbacks can evaluate the call.
524dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    assert(InlineCallCheckers.size() <= 1 &&
525dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks           "InlineCall is a special hacky callback to allow intrusive"
526dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks           "evaluation of the call (which simulates inlining). It is "
527dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks           "currently only used by OSAtomicChecker and should go away "
528dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks           "at some point.");
529dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    for (std::vector<InlineCallFunc>::iterator
530dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks           EI = InlineCallCheckers.begin(), EE = InlineCallCheckers.end();
531dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks         EI != EE; ++EI) {
532dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks      ExplodedNodeSet checkDst;
533dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks      bool evaluated = (*EI)(CE, Eng, Pred, checkDst);
534dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks      assert(!(evaluated && anyEvaluated)
535dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks             && "There are more than one checkers evaluating the call");
536dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks      if (evaluated) {
537dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks        anyEvaluated = true;
538dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks        Dst.insert(checkDst);
539dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks#ifdef NDEBUG
540dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks        break; // on release don't check that no other checker also evals.
541dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks#endif
542dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks      }
543dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    }
544dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks
545dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks#ifdef NDEBUG // on release don't check that no other checker also evals.
546dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    if (anyEvaluated) {
547dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks      break;
548dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    }
549dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks#endif
550dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks
5518ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    ExplodedNodeSet checkDst;
5528ff5c41f2bde7ebbe568b4c15e59f14b8befae66Anna Zaks    NodeBuilder B(Pred, checkDst, Eng.getBuilderContext());
553dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    // Next, check if any of the EvalCall callbacks can evaluate the call.
554e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    for (std::vector<EvalCallFunc>::iterator
555e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis           EI = EvalCallCheckers.begin(), EE = EvalCallCheckers.end();
556e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis         EI != EE; ++EI) {
5573f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      ProgramPoint::Kind K = ProgramPoint::PostStmtKind;
5583f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks      const ProgramPoint &L = ProgramPoint::getProgramPoint(CE, K,
5593f5e8d87dbf449d8b39fe96068415428594d370eAnna Zaks                                Pred->getLocationContext(), EI->Checker);
560b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks      bool evaluated = false;
561b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks      { // CheckerContext generates transitions(populates checkDest) on
562b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks        // destruction, so introduce the scope to make sure it gets properly
563b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks        // populated.
564063e0887ad65d666d23ee3178436ad6507abbd1bAnna Zaks        CheckerContext C(B, Eng, Pred, L);
565b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks        evaluated = (*EI)(CE, C);
566b1576f7136163ce3efd6dcf5a3e53e1c8ec6520cAnna Zaks      }
567e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      assert(!(evaluated && anyEvaluated)
568e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis             && "There are more than one checkers evaluating the call");
569e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      if (evaluated) {
570e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis        anyEvaluated = true;
571e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis        Dst.insert(checkDst);
572e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis#ifdef NDEBUG
573e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis        break; // on release don't check that no other checker also evals.
574e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis#endif
575e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis      }
576e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis    }
577e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
578dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks    // If none of the checkers evaluated the call, ask ExprEngine to handle it.
57969f87c956b3ac2b80124fd9604af012e1061473aJordan Rose    if (!anyEvaluated)
58069f87c956b3ac2b80124fd9604af012e1061473aJordan Rose      Eng.defaultEvalCall(Dst, Pred, Call);
581e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  }
582e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis}
583e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
5849be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek/// \brief Run checkers for the entire Translation Unit.
5859be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenekvoid CheckerManager::runCheckersOnEndOfTranslationUnit(
5869be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                                  const TranslationUnitDecl *TU,
5879be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                                  AnalysisManager &mgr,
5889be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                                  BugReporter &BR) {
5899be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  for (unsigned i = 0, e = EndOfTranslationUnitCheckers.size(); i != e; ++i)
5909be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek    EndOfTranslationUnitCheckers[i](TU, mgr, BR);
5919be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek}
5929be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
593dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rosevoid CheckerManager::runCheckersForPrintState(raw_ostream &Out,
5948bef8238181a30e52dea380789a7e2d760eac532Ted Kremenek                                              ProgramStateRef State,
595dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose                                              const char *NL, const char *Sep) {
596dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose  for (llvm::DenseMap<CheckerTag, CheckerRef>::iterator
597dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose        I = CheckerTags.begin(), E = CheckerTags.end(); I != E; ++I)
598dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose    I->second->printState(Out, State, NL, Sep);
599dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose}
600dbd658e139b3e0bf084f75feaea8d844af9e319fJordy Rose
601769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
602769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for AST traversing.
603769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
604769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
605769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
606769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                      HandlesDeclFunc isForDeclFn) {
607769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  DeclCheckerInfo info = { checkfn, isForDeclFn };
608769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  DeclCheckers.push_back(info);
609769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
610769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
611769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
612769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  BodyCheckers.push_back(checkfn);
613769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
614769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
615769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
616769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for path-sensitive checking.
617769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
618769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
619769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
620769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                         HandlesStmtFunc isForStmtFn) {
621769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
622769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckers.push_back(info);
623769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
624769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
625769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                          HandlesStmtFunc isForStmtFn) {
626769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
627769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckers.push_back(info);
628769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
629769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
630769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
631769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  PreObjCMessageCheckers.push_back(checkfn);
632769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
633769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
634769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  PostObjCMessageCheckers.push_back(checkfn);
635769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
636769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
63796479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::_registerForPreCall(CheckCallFunc checkfn) {
63896479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  PreCallCheckers.push_back(checkfn);
63996479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
64096479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rosevoid CheckerManager::_registerForPostCall(CheckCallFunc checkfn) {
64196479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose  PostCallCheckers.push_back(checkfn);
64296479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose}
64396479da6ad9d921d875e7be29fe1bfa127be8069Jordan Rose
644769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
645769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  LocationCheckers.push_back(checkfn);
646769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
647769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
648312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::_registerForBind(CheckBindFunc checkfn) {
649312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  BindCheckers.push_back(checkfn);
650312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
651312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
65230726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidisvoid CheckerManager::_registerForEndAnalysis(CheckEndAnalysisFunc checkfn) {
65330726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis  EndAnalysisCheckers.push_back(checkfn);
65430726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis}
65530726c6baee1417307236e854f1474fdb3cedb98Argyrios Kyrtzidis
656af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidisvoid CheckerManager::_registerForEndPath(CheckEndPathFunc checkfn) {
657af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis  EndPathCheckers.push_back(checkfn);
658af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis}
659af5800a1e287990bb547e052f257adeeae5ab476Argyrios Kyrtzidis
660cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidisvoid CheckerManager::_registerForBranchCondition(
661cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis                                             CheckBranchConditionFunc checkfn) {
662cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis  BranchConditionCheckers.push_back(checkfn);
663cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis}
664cc05d511b26ac6dc80fcbcc78ac305d2755aa0b9Argyrios Kyrtzidis
665183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForLiveSymbols(CheckLiveSymbolsFunc checkfn) {
666183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  LiveSymbolsCheckers.push_back(checkfn);
667183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
668183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
669183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForDeadSymbols(CheckDeadSymbolsFunc checkfn) {
670183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  DeadSymbolsCheckers.push_back(checkfn);
671183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
672183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
673183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidisvoid CheckerManager::_registerForRegionChanges(CheckRegionChangesFunc checkfn,
674183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis                                     WantsRegionChangeUpdateFunc wantUpdateFn) {
675183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  RegionChangesCheckerInfo info = {checkfn, wantUpdateFn};
676183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis  RegionChangesCheckers.push_back(info);
677183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis}
678183ff98f425d470c2a0276880aaf43496c9dad14Argyrios Kyrtzidis
679312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidisvoid CheckerManager::_registerForEvalAssume(EvalAssumeFunc checkfn) {
680312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis  EvalAssumeCheckers.push_back(checkfn);
681312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis}
682312dbec867f6b8d6b86fd562c53352cd4db27468Argyrios Kyrtzidis
683e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidisvoid CheckerManager::_registerForEvalCall(EvalCallFunc checkfn) {
684e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis  EvalCallCheckers.push_back(checkfn);
685e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis}
686e1bfb7ae0dd0762c88e1fd94746e973c37f2e04eArgyrios Kyrtzidis
687dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaksvoid CheckerManager::_registerForInlineCall(InlineCallFunc checkfn) {
688dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks  InlineCallCheckers.push_back(checkfn);
689dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks}
690dff6ef903ff4fcb43b5ea292ecd772e381393b5dAnna Zaks
6919be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenekvoid CheckerManager::_registerForEndOfTranslationUnit(
6929be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek                                            CheckEndOfTranslationUnit checkfn) {
6939be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek  EndOfTranslationUnitCheckers.push_back(checkfn);
6949be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek}
6959be6e7ce5788e50c62d40c59b0bbc2ea423683f7Ted Kremenek
696769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
697769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Implementation details.
698769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
699769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
700769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::CachedStmtCheckers *
701769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
702769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  assert(S);
703769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
704769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
705769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CachedStmtCheckers *checkers = 0;
706769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
707769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  if (CCI != CachedStmtCheckersMap.end()) {
708769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    checkers = &(CCI->second);
709769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  } else {
710769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    // Find the checkers that should run for this Stmt and cache them.
711769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    checkers = &CachedStmtCheckersMap[key];
712769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
713769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      StmtCheckerInfo &info = StmtCheckers[i];
714769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
715769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis        checkers->push_back(info.CheckFn);
716769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
7179fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
718769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
719769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  assert(checkers);
720769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  return checkers;
721769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
722769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
723769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::~CheckerManager() {
724769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
725769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckerDtors[i]();
7269fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
727