CheckerManager.h revision 18c66fdc3c4008d335885695fe36fb5353c5f672
1558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
2558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//
3558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//                     The LLVM Compiler Infrastructure
4558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//
5558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// This file is distributed under the University of Illinois Open Source
6558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// License. See LICENSE.TXT for details.
7558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//
8558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//===----------------------------------------------------------------------===//
9558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//
10558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Defines the Static Analyzer Checker Manager.
11558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//
12558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch//===----------------------------------------------------------------------===//
13558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
14558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
15558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
1603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
17558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "clang/Basic/LangOptions.h"
18558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "llvm/ADT/SmallVector.h"
19558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "llvm/ADT/DenseMap.h"
2003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "llvm/ADT/FoldingSet.h"
2103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
2203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include <vector>
2303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace clang {
2503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class Decl;
2603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class Stmt;
2703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class CallExpr;
2803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
2903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)namespace ento {
3003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class CheckerBase;
3103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class ExprEngine;
3203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class AnalysisManager;
3303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class BugReporter;
3403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class CheckerContext;
3503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class ObjCMessage;
3603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class SVal;
3703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class ExplodedNode;
3803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class ExplodedNodeSet;
3903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class ExplodedGraph;
4003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class ProgramState;
4103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class EndOfFunctionNodeBuilder;
4203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class BranchNodeBuilder;
4303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  class MemRegion;
44558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  class SymbolReaper;
45558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
46558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochclass GraphExpander {
4703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)public:
4803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual ~GraphExpander();
4903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  virtual void expandGraph(ExplodedNodeSet &Dst, ExplodedNode *Pred) = 0;
5003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
511320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
5203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)template <typename T> class CheckerFn;
5303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)template <typename RET, typename P1, typename P2, typename P3, typename P4>
5503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CheckerFn<RET(P1, P2, P3, P4)> {
56558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  typedef RET (*Func)(void *, P1, P2, P3, P4);
57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  Func Fn;
5803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)public:
5903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckerBase *Checker;
6003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
6103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
6203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)    return Fn(Checker, p1, p2, p3, p4);
6303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  }
6403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
65558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
66558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochtemplate <typename RET, typename P1, typename P2, typename P3>
67558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochclass CheckerFn<RET(P1, P2, P3)> {
6803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  typedef RET (*Func)(void *, P1, P2, P3);
69558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  Func Fn;
7003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)public:
7103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckerBase *Checker;
7203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
7303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); }
7403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
7503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
7603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)template <typename RET, typename P1, typename P2>
7703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CheckerFn<RET(P1, P2)> {
7803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  typedef RET (*Func)(void *, P1, P2);
79558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  Func Fn;
8003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)public:
8103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckerBase *Checker;
8203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
8303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); }
8403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)};
85558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
86558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochtemplate <typename RET, typename P1>
8703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CheckerFn<RET(P1)> {
88558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  typedef RET (*Func)(void *, P1);
89558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  Func Fn;
90558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochpublic:
91558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  CheckerBase *Checker;
92558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
93558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  RET operator()(P1 p1) const { return Fn(Checker, p1); }
94558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch};
95558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
96558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochtemplate <typename RET>
9703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CheckerFn<RET()> {
9803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  typedef RET (*Func)(void *);
9903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  Func Fn;
10003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)public:
10103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckerBase *Checker;
10203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
10303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  RET operator()() const { return Fn(Checker); }
104558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch};
10503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)
10603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)class CheckerManager {
10703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)  const LangOptions LangOpts;
108558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
10903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)public:
110558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { }
111558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  ~CheckerManager();
112558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
113  bool hasPathSensitiveCheckers() const;
114
115  void finishedCheckerRegistration();
116
117  const LangOptions &getLangOptions() const { return LangOpts; }
118
119  typedef CheckerBase *CheckerRef;
120  typedef const void *CheckerTag;
121  typedef CheckerFn<void ()> CheckerDtor;
122
123//===----------------------------------------------------------------------===//
124// registerChecker
125//===----------------------------------------------------------------------===//
126
127  /// \brief Used to register checkers.
128  ///
129  /// \returns a pointer to the checker object.
130  template <typename CHECKER>
131  CHECKER *registerChecker() {
132    CheckerTag tag = getTag<CHECKER>();
133    CheckerRef &ref = CheckerTags[tag];
134    if (ref)
135      return static_cast<CHECKER *>(ref); // already registered.
136
137    CHECKER *checker = new CHECKER();
138    CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
139    CHECKER::_register(checker, *this);
140    ref = checker;
141    return checker;
142  }
143
144//===----------------------------------------------------------------------===//
145// Functions for running checkers for AST traversing..
146//===----------------------------------------------------------------------===//
147
148  /// \brief Run checkers handling Decls.
149  void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
150                            BugReporter &BR);
151
152  /// \brief Run checkers handling Decls containing a Stmt body.
153  void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
154                            BugReporter &BR);
155
156//===----------------------------------------------------------------------===//
157// Functions for running checkers for path-sensitive checking.
158//===----------------------------------------------------------------------===//
159
160  /// \brief Run checkers for pre-visiting Stmts.
161  void runCheckersForPreStmt(ExplodedNodeSet &Dst,
162                             const ExplodedNodeSet &Src,
163                             const Stmt *S,
164                             ExprEngine &Eng) {
165    runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
166  }
167
168  /// \brief Run checkers for post-visiting Stmts.
169  void runCheckersForPostStmt(ExplodedNodeSet &Dst,
170                              const ExplodedNodeSet &Src,
171                              const Stmt *S,
172                              ExprEngine &Eng) {
173    runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng);
174  }
175
176  /// \brief Run checkers for visiting Stmts.
177  void runCheckersForStmt(bool isPreVisit,
178                          ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
179                          const Stmt *S, ExprEngine &Eng);
180
181  /// \brief Run checkers for pre-visiting obj-c messages.
182  void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
183                                    const ExplodedNodeSet &Src,
184                                    const ObjCMessage &msg,
185                                    ExprEngine &Eng) {
186    runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
187  }
188
189  /// \brief Run checkers for post-visiting obj-c messages.
190  void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
191                                     const ExplodedNodeSet &Src,
192                                     const ObjCMessage &msg,
193                                     ExprEngine &Eng) {
194    runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng);
195  }
196
197  /// \brief Run checkers for visiting obj-c messages.
198  void runCheckersForObjCMessage(bool isPreVisit,
199                                 ExplodedNodeSet &Dst,
200                                 const ExplodedNodeSet &Src,
201                                 const ObjCMessage &msg, ExprEngine &Eng);
202
203  /// \brief Run checkers for load/store of a location.
204  void runCheckersForLocation(ExplodedNodeSet &Dst,
205                              const ExplodedNodeSet &Src,
206                              SVal location, bool isLoad,
207                              const Stmt *S,
208                              ExprEngine &Eng);
209
210  /// \brief Run checkers for binding of a value to a location.
211  void runCheckersForBind(ExplodedNodeSet &Dst,
212                          const ExplodedNodeSet &Src,
213                          SVal location, SVal val,
214                          const Stmt *S, ExprEngine &Eng);
215
216  /// \brief Run checkers for end of analysis.
217  void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
218                                 ExprEngine &Eng);
219
220  /// \brief Run checkers for end of path.
221  void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng);
222
223  /// \brief Run checkers for branch condition.
224  void runCheckersForBranchCondition(const Stmt *condition,
225                                     BranchNodeBuilder &B, ExprEngine &Eng);
226
227  /// \brief Run checkers for live symbols.
228  void runCheckersForLiveSymbols(const ProgramState *state,
229                                 SymbolReaper &SymReaper);
230
231  /// \brief Run checkers for dead symbols.
232  void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
233                                 const ExplodedNodeSet &Src,
234                                 SymbolReaper &SymReaper, const Stmt *S,
235                                 ExprEngine &Eng);
236
237  /// \brief True if at least one checker wants to check region changes.
238  bool wantsRegionChangeUpdate(const ProgramState *state);
239
240  /// \brief Run checkers for region changes.
241  const ProgramState *
242  runCheckersForRegionChanges(const ProgramState *state,
243                            const StoreManager::InvalidatedSymbols *invalidated,
244                              const MemRegion * const *Begin,
245                              const MemRegion * const *End);
246
247  /// \brief Run checkers for handling assumptions on symbolic values.
248  const ProgramState *runCheckersForEvalAssume(const ProgramState *state,
249                                          SVal Cond, bool Assumption);
250
251  /// \brief Run checkers for evaluating a call.
252  void runCheckersForEvalCall(ExplodedNodeSet &Dst,
253                              const ExplodedNodeSet &Src,
254                              const CallExpr *CE, ExprEngine &Eng,
255                              GraphExpander *defaultEval = 0);
256
257  /// \brief Run checkers for the entire Translation Unit.
258  void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
259                                         AnalysisManager &mgr,
260                                         BugReporter &BR);
261
262//===----------------------------------------------------------------------===//
263// Internal registration functions for AST traversing.
264//===----------------------------------------------------------------------===//
265
266  // Functions used by the registration mechanism, checkers should not touch
267  // these directly.
268
269  typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
270      CheckDeclFunc;
271
272  typedef bool (*HandlesDeclFunc)(const Decl *D);
273  void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
274
275  void _registerForBody(CheckDeclFunc checkfn);
276
277//===----------------------------------------------------------------------===//
278// Internal registration functions for path-sensitive checking.
279//===----------------------------------------------------------------------===//
280
281  typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
282
283  typedef CheckerFn<void (const ObjCMessage &, CheckerContext &)>
284      CheckObjCMessageFunc;
285
286  typedef CheckerFn<void (const SVal &location, bool isLoad, CheckerContext &)>
287      CheckLocationFunc;
288
289  typedef CheckerFn<void (const SVal &location, const SVal &val,
290                          CheckerContext &)> CheckBindFunc;
291
292  typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
293      CheckEndAnalysisFunc;
294
295  typedef CheckerFn<void (EndOfFunctionNodeBuilder &, ExprEngine &)>
296      CheckEndPathFunc;
297
298  typedef CheckerFn<void (const Stmt *, BranchNodeBuilder &, ExprEngine &)>
299      CheckBranchConditionFunc;
300
301  typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
302      CheckDeadSymbolsFunc;
303
304  typedef CheckerFn<void (const ProgramState *,SymbolReaper &)> CheckLiveSymbolsFunc;
305
306  typedef CheckerFn<const ProgramState * (const ProgramState *,
307                                const StoreManager::InvalidatedSymbols *symbols,
308                                     const MemRegion * const *begin,
309                                     const MemRegion * const *end)>
310      CheckRegionChangesFunc;
311
312  typedef CheckerFn<bool (const ProgramState *)> WantsRegionChangeUpdateFunc;
313
314  typedef CheckerFn<const ProgramState * (const ProgramState *,
315                                          const SVal &cond, bool assumption)>
316      EvalAssumeFunc;
317
318  typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
319      EvalCallFunc;
320
321  typedef CheckerFn<void (const TranslationUnitDecl *,
322                          AnalysisManager&, BugReporter &)>
323      CheckEndOfTranslationUnit;
324
325  typedef bool (*HandlesStmtFunc)(const Stmt *D);
326  void _registerForPreStmt(CheckStmtFunc checkfn,
327                           HandlesStmtFunc isForStmtFn);
328  void _registerForPostStmt(CheckStmtFunc checkfn,
329                            HandlesStmtFunc isForStmtFn);
330
331  void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
332  void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
333
334  void _registerForLocation(CheckLocationFunc checkfn);
335
336  void _registerForBind(CheckBindFunc checkfn);
337
338  void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
339
340  void _registerForEndPath(CheckEndPathFunc checkfn);
341
342  void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
343
344  void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
345
346  void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
347
348  void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
349                                 WantsRegionChangeUpdateFunc wantUpdateFn);
350
351  void _registerForEvalAssume(EvalAssumeFunc checkfn);
352
353  void _registerForEvalCall(EvalCallFunc checkfn);
354
355  void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
356
357//===----------------------------------------------------------------------===//
358// Internal registration functions for events.
359//===----------------------------------------------------------------------===//
360
361  typedef void *EventTag;
362  typedef CheckerFn<void (const void *event)> CheckEventFunc;
363
364  template <typename EVENT>
365  void _registerListenerForEvent(CheckEventFunc checkfn) {
366    EventInfo &info = Events[getTag<EVENT>()];
367    info.Checkers.push_back(checkfn);
368  }
369
370  template <typename EVENT>
371  void _registerDispatcherForEvent() {
372    EventInfo &info = Events[getTag<EVENT>()];
373    info.HasDispatcher = true;
374  }
375
376  template <typename EVENT>
377  void _dispatchEvent(const EVENT &event) const {
378    EventsTy::const_iterator I = Events.find(getTag<EVENT>());
379    if (I == Events.end())
380      return;
381    const EventInfo &info = I->second;
382    for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
383      info.Checkers[i](&event);
384  }
385
386//===----------------------------------------------------------------------===//
387// Implementation details.
388//===----------------------------------------------------------------------===//
389
390private:
391  template <typename CHECKER>
392  static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
393
394  template <typename T>
395  static void *getTag() { static int tag; return &tag; }
396
397  llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
398
399  std::vector<CheckerDtor> CheckerDtors;
400
401  struct DeclCheckerInfo {
402    CheckDeclFunc CheckFn;
403    HandlesDeclFunc IsForDeclFn;
404  };
405  std::vector<DeclCheckerInfo> DeclCheckers;
406
407  std::vector<CheckDeclFunc> BodyCheckers;
408
409  typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
410  typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
411  CachedDeclCheckersMapTy CachedDeclCheckersMap;
412
413  struct StmtCheckerInfo {
414    CheckStmtFunc CheckFn;
415    HandlesStmtFunc IsForStmtFn;
416    bool IsPreVisit;
417  };
418  std::vector<StmtCheckerInfo> StmtCheckers;
419
420  struct CachedStmtCheckersKey {
421    unsigned StmtKind;
422    bool IsPreVisit;
423
424    CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
425    CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
426      : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
427
428    static CachedStmtCheckersKey getSentinel() {
429      return CachedStmtCheckersKey(~0U, 0);
430    }
431    unsigned getHashValue() const {
432      llvm::FoldingSetNodeID ID;
433      ID.AddInteger(StmtKind);
434      ID.AddBoolean(IsPreVisit);
435      return ID.ComputeHash();
436    }
437    bool operator==(const CachedStmtCheckersKey &RHS) const {
438      return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
439    }
440  };
441  friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
442
443  typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
444  typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
445      CachedStmtCheckersMapTy;
446  CachedStmtCheckersMapTy CachedStmtCheckersMap;
447
448  CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
449
450  std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
451  std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
452
453  std::vector<CheckLocationFunc> LocationCheckers;
454
455  std::vector<CheckBindFunc> BindCheckers;
456
457  std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
458
459  std::vector<CheckEndPathFunc> EndPathCheckers;
460
461  std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
462
463  std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
464
465  std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
466
467  struct RegionChangesCheckerInfo {
468    CheckRegionChangesFunc CheckFn;
469    WantsRegionChangeUpdateFunc WantUpdateFn;
470  };
471  std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
472
473  std::vector<EvalAssumeFunc> EvalAssumeCheckers;
474
475  std::vector<EvalCallFunc> EvalCallCheckers;
476
477  std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
478
479  struct EventInfo {
480    SmallVector<CheckEventFunc, 4> Checkers;
481    bool HasDispatcher;
482    EventInfo() : HasDispatcher(false) { }
483  };
484
485  typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
486  EventsTy Events;
487};
488
489} // end ento namespace
490
491} // end clang namespace
492
493namespace llvm {
494  /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
495  /// in DenseMap and DenseSets.
496  template <>
497  struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
498    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
499        getEmptyKey() {
500      return clang::ento::CheckerManager::CachedStmtCheckersKey();
501    }
502    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
503        getTombstoneKey() {
504      return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
505    }
506
507    static unsigned
508        getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
509      return S.getHashValue();
510    }
511
512    static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
513                       clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
514      return LHS == RHS;
515    }
516  };
517} // end namespace llvm
518
519#endif
520