CheckerManager.cpp revision 3f8212787d9bd620930817177fbba5f32659377f
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"
1543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/CheckerProvider.h"
16769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
17769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis#include "clang/Analysis/ProgramPoint.h"
189fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis#include "clang/AST/DeclBase.h"
1943dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
2043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace clang;
2143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisusing namespace ento;
2243dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
23769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
24769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for AST traversing..
25769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
26769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
279fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
289fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                                          BugReporter &BR) {
299fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(D);
309fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
319fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  unsigned DeclKind = D->getKind();
329fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  CachedDeclCheckers *checkers = 0;
339fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  CachedDeclCheckersMapTy::iterator CCI = CachedDeclCheckersMap.find(DeclKind);
349fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  if (CCI != CachedDeclCheckersMap.end()) {
359fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    checkers = &(CCI->second);
369fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  } else {
379fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    // Find the checkers that should run for this Decl and cache them.
389fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    checkers = &CachedDeclCheckersMap[DeclKind];
399fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    for (unsigned i = 0, e = DeclCheckers.size(); i != e; ++i) {
409fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      DeclCheckerInfo &info = DeclCheckers[i];
419fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis      if (info.IsForDeclFn(D))
42769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis        checkers->push_back(info.CheckFn);
439fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis    }
449fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
459fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
469fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(checkers);
479fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  for (CachedDeclCheckers::iterator
48769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis         I = checkers->begin(), E = checkers->end(); I != E; ++I)
49769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    (*I)(D, mgr, BR);
509fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
519fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
529fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidisvoid CheckerManager::runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
539fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis                                          BugReporter &BR) {
549fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  assert(D && D->hasBody());
559fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
56769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  for (unsigned i = 0, e = BodyCheckers.size(); i != e; ++i)
57769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    BodyCheckers[i](D, mgr, BR);
58769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
59769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
60769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
61769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Functions for running checkers for path-sensitive checking.
62769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
63769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
64769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidistemplate <typename CHECK_CTX>
65769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisstatic void runPathSensitiveCheckers(CHECK_CTX checkCtx,
66769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                     ExplodedNodeSet &Dst,
67769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                     ExplodedNodeSet &Src) {
68769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
69769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  if (checkCtx.Checkers.empty()) {
70769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    Dst.insert(Src);
71769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    return;
72769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  }
73769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
74769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  ExplodedNodeSet Tmp;
75769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  ExplodedNodeSet *PrevSet = &Src;
76769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
77769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  for (typename CHECK_CTX::CheckersTy::const_iterator
78769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis         I= checkCtx.Checkers.begin(), E= checkCtx.Checkers.end(); I!=E; ++I) {
79769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExplodedNodeSet *CurrSet = 0;
80769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    if (I+1 == E)
81769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CurrSet = &Dst;
82769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    else {
83769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
84769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CurrSet->clear();
85769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
86769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
87769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
88769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis         NI != NE; ++NI)
89769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      checkCtx.runChecker(*I, *CurrSet, *NI);
90769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
91769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    // Update which NodeSet is the current one.
92769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    PrevSet = CurrSet;
939fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
949fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
959fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
96769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
97769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckStmtContext {
98769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    typedef llvm::SmallVectorImpl<CheckerManager::CheckStmtFunc> CheckersTy;
99769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    bool IsPreVisit;
100769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
101769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const Stmt *S;
102769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
103769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
104769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckStmtContext(bool isPreVisit, const CheckersTy &checkers,
105769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                     const Stmt *s, ExprEngine &eng)
106769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      : IsPreVisit(isPreVisit), Checkers(checkers), S(s), Eng(eng) { }
107769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
108769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckStmtFunc checkFn,
109769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
110769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      // FIXME: Remove respondsToCallback from CheckerContext;
111769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
112769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                       IsPreVisit ? ProgramPoint::PreStmtKind :
113769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                    ProgramPoint::PostStmtKind, 0, S);
114769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      checkFn(S, C);
115769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
116769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
117769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
118769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
119769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting Stmts.
120769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForStmt(bool isPreVisit,
121769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                        ExplodedNodeSet &Dst,
122769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                        ExplodedNodeSet &Src,
123769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                        const Stmt *S,
124769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                        ExprEngine &Eng) {
125769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CheckStmtContext C(isPreVisit, *getCachedStmtCheckersFor(S, isPreVisit),
126769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                     S, Eng);
127769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  runPathSensitiveCheckers(C, Dst, Src);
128769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
129769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
130769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
131769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckObjCMessageContext {
132769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckObjCMessageFunc> CheckersTy;
133769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    bool IsPreVisit;
134769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
135769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const ObjCMessage &Msg;
136769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
137769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
138769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckObjCMessageContext(bool isPreVisit, const CheckersTy &checkers,
139769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                            const ObjCMessage &msg, ExprEngine &eng)
140769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      : IsPreVisit(isPreVisit), Checkers(checkers), Msg(msg), Eng(eng) { }
141769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
142769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckObjCMessageFunc checkFn,
143769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
144769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
145769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                       IsPreVisit ? ProgramPoint::PreStmtKind :
146769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                    ProgramPoint::PostStmtKind, 0,
147769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                       Msg.getOriginExpr());
148769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      checkFn(Msg, C);
149769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
150769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
151769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
152769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
153769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for visiting obj-c messages.
154769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForObjCMessage(bool isPreVisit,
155769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                               ExplodedNodeSet &Dst,
156769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                               ExplodedNodeSet &Src,
157769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                               const ObjCMessage &msg,
158769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                               ExprEngine &Eng) {
1593f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis  CheckObjCMessageContext C(isPreVisit,
1603f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis                            isPreVisit ? PreObjCMessageCheckers
1613f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis                                       : PostObjCMessageCheckers,
1623f8212787d9bd620930817177fbba5f32659377fArgyrios Kyrtzidis                            msg, Eng);
163769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  runPathSensitiveCheckers(C, Dst, Src);
164769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
165769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
166769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisnamespace {
167769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  struct CheckLocationContext {
168769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
169769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const CheckersTy &Checkers;
170769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    SVal Loc;
171769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    bool IsLoad;
172769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const Stmt *S;
173769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    const GRState *State;
174769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    ExprEngine &Eng;
175769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
176769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckLocationContext(const CheckersTy &checkers,
177769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                         SVal loc, bool isLoad, const Stmt *s,
178769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                         const GRState *state, ExprEngine &eng)
179769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      : Checkers(checkers), Loc(loc), IsLoad(isLoad), S(s),
180769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis        State(state), Eng(eng) { }
181769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
182769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    void runChecker(CheckerManager::CheckLocationFunc checkFn,
183769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                    ExplodedNodeSet &Dst, ExplodedNode *Pred) {
184769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      CheckerContext C(Dst, Eng.getBuilder(), Eng, Pred, checkFn.Checker,
185769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                       IsLoad ? ProgramPoint::PreLoadKind :
186769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                       ProgramPoint::PreStoreKind, 0, S, State);
187769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      checkFn(Loc, IsLoad, C);
188769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
189769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  };
1909fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
1919fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
192769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis/// \brief Run checkers for load/store of a location.
193769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::runCheckersForLocation(ExplodedNodeSet &Dst,
194769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                            ExplodedNodeSet &Src,
195769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                            SVal location, bool isLoad,
196769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                            const Stmt *S,
197769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                            const GRState *state,
198769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                            ExprEngine &Eng) {
199769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CheckLocationContext C(LocationCheckers, location, isLoad, S, state, Eng);
200769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  runPathSensitiveCheckers(C, Dst, Src);
2019fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
2029fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
20343dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidisvoid CheckerManager::registerCheckersToEngine(ExprEngine &eng) {
20443dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis  for (unsigned i = 0, e = Funcs.size(); i != e; ++i)
20543dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis    Funcs[i](eng);
20643dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis}
20743dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis
208769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
209769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for AST traversing.
210769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
211769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
212769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForDecl(CheckDeclFunc checkfn,
213769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                      HandlesDeclFunc isForDeclFn) {
214769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  DeclCheckerInfo info = { checkfn, isForDeclFn };
215769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  DeclCheckers.push_back(info);
216769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
217769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
218769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForBody(CheckDeclFunc checkfn) {
219769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  BodyCheckers.push_back(checkfn);
220769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
221769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
222769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
223769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Internal registration functions for path-sensitive checking.
224769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
225769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
226769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreStmt(CheckStmtFunc checkfn,
227769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                         HandlesStmtFunc isForStmtFn) {
228769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/true };
229769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckers.push_back(info);
230769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
231769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostStmt(CheckStmtFunc checkfn,
232769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis                                          HandlesStmtFunc isForStmtFn) {
233769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckerInfo info = { checkfn, isForStmtFn, /*IsPreVisit*/false };
234769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  StmtCheckers.push_back(info);
235769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
236769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
237769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPreObjCMessage(CheckObjCMessageFunc checkfn) {
238769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  PreObjCMessageCheckers.push_back(checkfn);
239769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
240769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForPostObjCMessage(CheckObjCMessageFunc checkfn) {
241769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  PostObjCMessageCheckers.push_back(checkfn);
242769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
243769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
244769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidisvoid CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
245769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  LocationCheckers.push_back(checkfn);
246769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
247769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
248769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
249769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis// Implementation details.
250769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis//===----------------------------------------------------------------------===//
251769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
252769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::CachedStmtCheckers *
253769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit) {
254769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  assert(S);
255769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
256769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CachedStmtCheckersKey key(S->getStmtClass(), isPreVisit);
257769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CachedStmtCheckers *checkers = 0;
258769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  CachedStmtCheckersMapTy::iterator CCI = CachedStmtCheckersMap.find(key);
259769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  if (CCI != CachedStmtCheckersMap.end()) {
260769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    checkers = &(CCI->second);
261769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  } else {
262769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    // Find the checkers that should run for this Stmt and cache them.
263769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    checkers = &CachedStmtCheckersMap[key];
264769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    for (unsigned i = 0, e = StmtCheckers.size(); i != e; ++i) {
265769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      StmtCheckerInfo &info = StmtCheckers[i];
266769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis      if (info.IsPreVisit == isPreVisit && info.IsForStmtFn(S))
267769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis        checkers->push_back(info.CheckFn);
268769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    }
2699fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis  }
270769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
271769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  assert(checkers);
272769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  return checkers;
273769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis}
274769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis
275769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios KyrtzidisCheckerManager::~CheckerManager() {
276769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis  for (unsigned i = 0, e = CheckerDtors.size(); i != e; ++i)
277769ce3e93ad35bd9ac28e4d8b8f035ae4fd9a5b5Argyrios Kyrtzidis    CheckerDtors[i]();
2789fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis}
2799fb9474c5b267400d4abfbff63c8b39f378235d4Argyrios Kyrtzidis
28043dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios Kyrtzidis// Anchor for the vtable.
28143dee220252ef0b42c5f8a3bb1eca97f84f2565fArgyrios KyrtzidisCheckerProvider::~CheckerProvider() { }
282