CheckerManager.h revision 263508
167754Smsmith//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
267754Smsmith//
367754Smsmith//                     The LLVM Compiler Infrastructure
470243Smsmith//
567754Smsmith// This file is distributed under the University of Illinois Open Source
667754Smsmith// License. See LICENSE.TXT for details.
767754Smsmith//
867754Smsmith//===----------------------------------------------------------------------===//
967754Smsmith//
1067754Smsmith// Defines the Static Analyzer Checker Manager.
1167754Smsmith//
1270243Smsmith//===----------------------------------------------------------------------===//
1370243Smsmith
1467754Smsmith#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
1567754Smsmith#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
1667754Smsmith
1767754Smsmith#include "clang/Analysis/ProgramPoint.h"
1867754Smsmith#include "clang/Basic/LangOptions.h"
1967754Smsmith#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
2067754Smsmith#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
2167754Smsmith#include "llvm/ADT/DenseMap.h"
2267754Smsmith#include "llvm/ADT/SmallVector.h"
2367754Smsmith#include <vector>
2467754Smsmith
2567754Smsmithnamespace clang {
2667754Smsmith  class Decl;
2767754Smsmith  class Stmt;
2867754Smsmith  class CallExpr;
2967754Smsmith
3067754Smsmithnamespace ento {
3167754Smsmith  class CheckerBase;
3267754Smsmith  class ExprEngine;
3367754Smsmith  class AnalysisManager;
3467754Smsmith  class BugReporter;
3567754Smsmith  class CheckerContext;
3667754Smsmith  class SimpleCall;
3767754Smsmith  class ObjCMethodCall;
3867754Smsmith  class SVal;
3967754Smsmith  class ExplodedNode;
4067754Smsmith  class ExplodedNodeSet;
4167754Smsmith  class ExplodedGraph;
4267754Smsmith  class ProgramState;
4367754Smsmith  class NodeBuilder;
4467754Smsmith  struct NodeBuilderContext;
4567754Smsmith  class MemRegion;
4667754Smsmith  class SymbolReaper;
4767754Smsmith
4867754Smsmithtemplate <typename T> class CheckerFn;
4967754Smsmith
5067754Smsmithtemplate <typename RET, typename P1, typename P2, typename P3, typename P4,
5167754Smsmith          typename P5>
5267754Smsmithclass CheckerFn<RET(P1, P2, P3, P4, P5)> {
5367754Smsmith  typedef RET (*Func)(void *, P1, P2, P3, P4, P5);
5467754Smsmith  Func Fn;
5567754Smsmithpublic:
5667754Smsmith  CheckerBase *Checker;
5767754Smsmith  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
5867754Smsmith  RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const {
5967754Smsmith    return Fn(Checker, p1, p2, p3, p4, p5);
6067754Smsmith  }
6167754Smsmith};
6267754Smsmith
6367754Smsmithtemplate <typename RET, typename P1, typename P2, typename P3, typename P4>
6467754Smsmithclass CheckerFn<RET(P1, P2, P3, P4)> {
6567754Smsmith  typedef RET (*Func)(void *, P1, P2, P3, P4);
6667754Smsmith  Func Fn;
6767754Smsmithpublic:
6867754Smsmith  CheckerBase *Checker;
6967754Smsmith  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
7067754Smsmith  RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
7167754Smsmith    return Fn(Checker, p1, p2, p3, p4);
7267754Smsmith  }
7367754Smsmith};
7467754Smsmith
7567754Smsmithtemplate <typename RET, typename P1, typename P2, typename P3>
7667754Smsmithclass CheckerFn<RET(P1, P2, P3)> {
7767754Smsmith  typedef RET (*Func)(void *, P1, P2, P3);
7867754Smsmith  Func Fn;
7967754Smsmithpublic:
8067754Smsmith  CheckerBase *Checker;
8167754Smsmith  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
8267754Smsmith  RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); }
8367754Smsmith};
8467754Smsmith
8567754Smsmithtemplate <typename RET, typename P1, typename P2>
8667754Smsmithclass CheckerFn<RET(P1, P2)> {
8767754Smsmith  typedef RET (*Func)(void *, P1, P2);
8867754Smsmith  Func Fn;
8967754Smsmithpublic:
9067754Smsmith  CheckerBase *Checker;
9167754Smsmith  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
9267754Smsmith  RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); }
9367754Smsmith};
9467754Smsmith
9567754Smsmithtemplate <typename RET, typename P1>
9667754Smsmithclass CheckerFn<RET(P1)> {
9767754Smsmith  typedef RET (*Func)(void *, P1);
9867754Smsmith  Func Fn;
9967754Smsmithpublic:
10067754Smsmith  CheckerBase *Checker;
10167754Smsmith  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
10267754Smsmith  RET operator()(P1 p1) const { return Fn(Checker, p1); }
10367754Smsmith};
10467754Smsmith
10567754Smsmithtemplate <typename RET>
10667754Smsmithclass CheckerFn<RET()> {
10767754Smsmith  typedef RET (*Func)(void *);
10867754Smsmith  Func Fn;
10967754Smsmithpublic:
11067754Smsmith  CheckerBase *Checker;
11167754Smsmith  CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
11267754Smsmith  RET operator()() const { return Fn(Checker); }
11367754Smsmith};
11467754Smsmith
11567754Smsmith/// \brief Describes the different reasons a pointer escapes
11667754Smsmith/// during analysis.
11767754Smsmithenum PointerEscapeKind {
11867754Smsmith  /// A pointer escapes due to binding its value to a location
11967754Smsmith  /// that the analyzer cannot track.
12067754Smsmith  PSK_EscapeOnBind,
12167754Smsmith
12267754Smsmith  /// The pointer has been passed to a function call directly.
12367754Smsmith  PSK_DirectEscapeOnCall,
12467754Smsmith
12567754Smsmith  /// The pointer has been passed to a function indirectly.
12667754Smsmith  /// For example, the pointer is accessible through an
12767754Smsmith  /// argument to a function.
12867754Smsmith  PSK_IndirectEscapeOnCall,
12967754Smsmith
13067754Smsmith  /// The reason for pointer escape is unknown. For example,
13167754Smsmith  /// a region containing this pointer is invalidated.
13267754Smsmith  PSK_EscapeOther
13367754Smsmith};
13467754Smsmith
13567754Smsmithclass CheckerManager {
13667754Smsmith  const LangOptions LangOpts;
13767754Smsmith  AnalyzerOptionsRef AOptions;
13867754Smsmithpublic:
13967754Smsmith  CheckerManager(const LangOptions &langOpts,
14067754Smsmith                 AnalyzerOptionsRef AOptions)
14167754Smsmith    : LangOpts(langOpts),
14267754Smsmith      AOptions(AOptions) {}
14367754Smsmith
14467754Smsmith  ~CheckerManager();
14567754Smsmith
14667754Smsmith  bool hasPathSensitiveCheckers() const;
14767754Smsmith
14867754Smsmith  void finishedCheckerRegistration();
14967754Smsmith
15067754Smsmith  const LangOptions &getLangOpts() const { return LangOpts; }
15167754Smsmith  AnalyzerOptions &getAnalyzerOptions() { return *AOptions; }
15267754Smsmith
15367754Smsmith  typedef CheckerBase *CheckerRef;
15467754Smsmith  typedef const void *CheckerTag;
15567754Smsmith  typedef CheckerFn<void ()> CheckerDtor;
15667754Smsmith
15767754Smsmith//===----------------------------------------------------------------------===//
15867754Smsmith// registerChecker
15967754Smsmith//===----------------------------------------------------------------------===//
16067754Smsmith
16167754Smsmith  /// \brief Used to register checkers.
16267754Smsmith  ///
16367754Smsmith  /// \returns a pointer to the checker object.
16469450Smsmith  template <typename CHECKER>
16567754Smsmith  CHECKER *registerChecker() {
16667754Smsmith    CheckerTag tag = getTag<CHECKER>();
16767754Smsmith    CheckerRef &ref = CheckerTags[tag];
16869450Smsmith    if (ref)
16967754Smsmith      return static_cast<CHECKER *>(ref); // already registered.
17067754Smsmith
17167754Smsmith    CHECKER *checker = new CHECKER();
17267754Smsmith    CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
17367754Smsmith    CHECKER::_register(checker, *this);
17467754Smsmith    ref = checker;
17567754Smsmith    return checker;
17667754Smsmith  }
17767754Smsmith
17867754Smsmith  template <typename CHECKER>
17967754Smsmith  CHECKER *registerChecker(AnalyzerOptions &AOpts) {
18067754Smsmith    CheckerTag tag = getTag<CHECKER>();
18167754Smsmith    CheckerRef &ref = CheckerTags[tag];
18267754Smsmith    if (ref)
18367754Smsmith      return static_cast<CHECKER *>(ref); // already registered.
18467754Smsmith
18567754Smsmith    CHECKER *checker = new CHECKER(AOpts);
18667754Smsmith    CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
18767754Smsmith    CHECKER::_register(checker, *this);
18867754Smsmith    ref = checker;
18967754Smsmith    return checker;
19067754Smsmith  }
19167754Smsmith
19267754Smsmith//===----------------------------------------------------------------------===//
19367754Smsmith// Functions for running checkers for AST traversing..
19467754Smsmith//===----------------------------------------------------------------------===//
19567754Smsmith
19667754Smsmith  /// \brief Run checkers handling Decls.
19767754Smsmith  void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
19867754Smsmith                            BugReporter &BR);
19967754Smsmith
20067754Smsmith  /// \brief Run checkers handling Decls containing a Stmt body.
20167754Smsmith  void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
20267754Smsmith                            BugReporter &BR);
20367754Smsmith
20467754Smsmith//===----------------------------------------------------------------------===//
20567754Smsmith// Functions for running checkers for path-sensitive checking.
20667754Smsmith//===----------------------------------------------------------------------===//
20767754Smsmith
20867754Smsmith  /// \brief Run checkers for pre-visiting Stmts.
20967754Smsmith  ///
21067754Smsmith  /// The notification is performed for every explored CFGElement, which does
21167754Smsmith  /// not include the control flow statements such as IfStmt.
21267754Smsmith  ///
21367754Smsmith  /// \sa runCheckersForBranchCondition, runCheckersForPostStmt
21467754Smsmith  void runCheckersForPreStmt(ExplodedNodeSet &Dst,
21567754Smsmith                             const ExplodedNodeSet &Src,
21667754Smsmith                             const Stmt *S,
21767754Smsmith                             ExprEngine &Eng) {
21867754Smsmith    runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
21967754Smsmith  }
22067754Smsmith
22167754Smsmith  /// \brief Run checkers for post-visiting Stmts.
22267754Smsmith  ///
22367754Smsmith  /// The notification is performed for every explored CFGElement, which does
22467754Smsmith  /// not include the control flow statements such as IfStmt.
22567754Smsmith  ///
22667754Smsmith  /// \sa runCheckersForBranchCondition, runCheckersForPreStmt
22767754Smsmith  void runCheckersForPostStmt(ExplodedNodeSet &Dst,
22867754Smsmith                              const ExplodedNodeSet &Src,
22967754Smsmith                              const Stmt *S,
23067754Smsmith                              ExprEngine &Eng,
23167754Smsmith                              bool wasInlined = false) {
23267754Smsmith    runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
23367754Smsmith  }
23467754Smsmith
23567754Smsmith  /// \brief Run checkers for visiting Stmts.
23667754Smsmith  void runCheckersForStmt(bool isPreVisit,
23767754Smsmith                          ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
23867754Smsmith                          const Stmt *S, ExprEngine &Eng,
23967754Smsmith                          bool wasInlined = false);
24067754Smsmith
24167754Smsmith  /// \brief Run checkers for pre-visiting obj-c messages.
24267754Smsmith  void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
24367754Smsmith                                    const ExplodedNodeSet &Src,
24467754Smsmith                                    const ObjCMethodCall &msg,
24567754Smsmith                                    ExprEngine &Eng) {
24667754Smsmith    runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
24767754Smsmith  }
24867754Smsmith
24967754Smsmith  /// \brief Run checkers for post-visiting obj-c messages.
25067754Smsmith  void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
25167754Smsmith                                     const ExplodedNodeSet &Src,
25267754Smsmith                                     const ObjCMethodCall &msg,
25367754Smsmith                                     ExprEngine &Eng,
25467754Smsmith                                     bool wasInlined = false) {
25567754Smsmith    runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng,
25667754Smsmith                              wasInlined);
25767754Smsmith  }
25867754Smsmith
25967754Smsmith  /// \brief Run checkers for visiting obj-c messages.
26067754Smsmith  void runCheckersForObjCMessage(bool isPreVisit,
26167754Smsmith                                 ExplodedNodeSet &Dst,
26267754Smsmith                                 const ExplodedNodeSet &Src,
26367754Smsmith                                 const ObjCMethodCall &msg, ExprEngine &Eng,
26467754Smsmith                                 bool wasInlined = false);
26567754Smsmith
26667754Smsmith  /// \brief Run checkers for pre-visiting obj-c messages.
26767754Smsmith  void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
26867754Smsmith                             const CallEvent &Call, ExprEngine &Eng) {
26967754Smsmith    runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
27067754Smsmith  }
27167754Smsmith
27267754Smsmith  /// \brief Run checkers for post-visiting obj-c messages.
27367754Smsmith  void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
27467754Smsmith                              const CallEvent &Call, ExprEngine &Eng,
27567754Smsmith                              bool wasInlined = false) {
27667754Smsmith    runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
27767754Smsmith                            wasInlined);
27867754Smsmith  }
27967754Smsmith
28067754Smsmith  /// \brief Run checkers for visiting obj-c messages.
28167754Smsmith  void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
28267754Smsmith                               const ExplodedNodeSet &Src,
28367754Smsmith                               const CallEvent &Call, ExprEngine &Eng,
28467754Smsmith                               bool wasInlined = false);
28567754Smsmith
28667754Smsmith  /// \brief Run checkers for load/store of a location.
28767754Smsmith  void runCheckersForLocation(ExplodedNodeSet &Dst,
28867754Smsmith                              const ExplodedNodeSet &Src,
28967754Smsmith                              SVal location,
29067754Smsmith                              bool isLoad,
29167754Smsmith                              const Stmt *NodeEx,
29267754Smsmith                              const Stmt *BoundEx,
29367754Smsmith                              ExprEngine &Eng);
29467754Smsmith
29567754Smsmith  /// \brief Run checkers for binding of a value to a location.
29667754Smsmith  void runCheckersForBind(ExplodedNodeSet &Dst,
29767754Smsmith                          const ExplodedNodeSet &Src,
29867754Smsmith                          SVal location, SVal val,
29967754Smsmith                          const Stmt *S, ExprEngine &Eng,
30067754Smsmith                          const ProgramPoint &PP);
30167754Smsmith
30267754Smsmith  /// \brief Run checkers for end of analysis.
30367754Smsmith  void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
30467754Smsmith                                 ExprEngine &Eng);
30567754Smsmith
30667754Smsmith  /// \brief Run checkers on end of function.
30767754Smsmith  void runCheckersForEndFunction(NodeBuilderContext &BC,
30867754Smsmith                                 ExplodedNodeSet &Dst,
30967754Smsmith                                 ExplodedNode *Pred,
31067754Smsmith                                 ExprEngine &Eng);
31167754Smsmith
31267754Smsmith  /// \brief Run checkers for branch condition.
31367754Smsmith  void runCheckersForBranchCondition(const Stmt *condition,
31467754Smsmith                                     ExplodedNodeSet &Dst, ExplodedNode *Pred,
31567754Smsmith                                     ExprEngine &Eng);
31667754Smsmith
31767754Smsmith  /// \brief Run checkers for live symbols.
31867754Smsmith  ///
31967754Smsmith  /// Allows modifying SymbolReaper object. For example, checkers can explicitly
32067754Smsmith  /// register symbols of interest as live. These symbols will not be marked
32167754Smsmith  /// dead and removed.
32267754Smsmith  void runCheckersForLiveSymbols(ProgramStateRef state,
32367754Smsmith                                 SymbolReaper &SymReaper);
32467754Smsmith
32567754Smsmith  /// \brief Run checkers for dead symbols.
32667754Smsmith  ///
32767754Smsmith  /// Notifies checkers when symbols become dead. For example, this allows
32867754Smsmith  /// checkers to aggressively clean up/reduce the checker state and produce
32967754Smsmith  /// precise diagnostics.
33067754Smsmith  void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
33167754Smsmith                                 const ExplodedNodeSet &Src,
33267754Smsmith                                 SymbolReaper &SymReaper, const Stmt *S,
33367754Smsmith                                 ExprEngine &Eng,
33467754Smsmith                                 ProgramPoint::Kind K);
33567754Smsmith
33667754Smsmith  /// \brief True if at least one checker wants to check region changes.
33767754Smsmith  bool wantsRegionChangeUpdate(ProgramStateRef state);
33867754Smsmith
33967754Smsmith  /// \brief Run checkers for region changes.
34067754Smsmith  ///
34167754Smsmith  /// This corresponds to the check::RegionChanges callback.
34267754Smsmith  /// \param state The current program state.
34367754Smsmith  /// \param invalidated A set of all symbols potentially touched by the change.
34467754Smsmith  /// \param ExplicitRegions The regions explicitly requested for invalidation.
34567754Smsmith  ///   For example, in the case of a function call, these would be arguments.
34667754Smsmith  /// \param Regions The transitive closure of accessible regions,
34767754Smsmith  ///   i.e. all regions that may have been touched by this change.
34867754Smsmith  /// \param Call The call expression wrapper if the regions are invalidated
34967754Smsmith  ///   by a call.
35067754Smsmith  ProgramStateRef
35167754Smsmith  runCheckersForRegionChanges(ProgramStateRef state,
35267754Smsmith                              const InvalidatedSymbols *invalidated,
35367754Smsmith                              ArrayRef<const MemRegion *> ExplicitRegions,
35467754Smsmith                              ArrayRef<const MemRegion *> Regions,
35567754Smsmith                              const CallEvent *Call);
35667754Smsmith
35767754Smsmith  /// \brief Run checkers when pointers escape.
35867754Smsmith  ///
35967754Smsmith  /// This notifies the checkers about pointer escape, which occurs whenever
36067754Smsmith  /// the analyzer cannot track the symbol any more. For example, as a
36167754Smsmith  /// result of assigning a pointer into a global or when it's passed to a
36267754Smsmith  /// function call the analyzer cannot model.
36367754Smsmith  ///
36467754Smsmith  /// \param State The state at the point of escape.
36567754Smsmith  /// \param Escaped The list of escaped symbols.
36667754Smsmith  /// \param Call The corresponding CallEvent, if the symbols escape as
36767754Smsmith  ///        parameters to the given call.
36867754Smsmith  /// \param Kind The reason of pointer escape.
36967754Smsmith  /// \param ITraits Information about invalidation for a particular
37067754Smsmith  ///        region/symbol.
37167754Smsmith  /// \returns Checkers can modify the state by returning a new one.
37269450Smsmith  ProgramStateRef
37367754Smsmith  runCheckersForPointerEscape(ProgramStateRef State,
37467754Smsmith                              const InvalidatedSymbols &Escaped,
37567754Smsmith                              const CallEvent *Call,
37669450Smsmith                              PointerEscapeKind Kind,
37767754Smsmith                             RegionAndSymbolInvalidationTraits *ITraits);
37867754Smsmith
37967754Smsmith  /// \brief Run checkers for handling assumptions on symbolic values.
38067754Smsmith  ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
38167754Smsmith                                           SVal Cond, bool Assumption);
38267754Smsmith
38367754Smsmith  /// \brief Run checkers for evaluating a call.
38467754Smsmith  ///
38567754Smsmith  /// Warning: Currently, the CallEvent MUST come from a CallExpr!
38667754Smsmith  void runCheckersForEvalCall(ExplodedNodeSet &Dst,
38767754Smsmith                              const ExplodedNodeSet &Src,
38867754Smsmith                              const CallEvent &CE, ExprEngine &Eng);
38967754Smsmith
39067754Smsmith  /// \brief Run checkers for the entire Translation Unit.
39167754Smsmith  void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
39267754Smsmith                                         AnalysisManager &mgr,
39367754Smsmith                                         BugReporter &BR);
39467754Smsmith
39567754Smsmith  /// \brief Run checkers for debug-printing a ProgramState.
39667754Smsmith  ///
39767754Smsmith  /// Unlike most other callbacks, any checker can simply implement the virtual
39867754Smsmith  /// method CheckerBase::printState if it has custom data to print.
39967754Smsmith  /// \param Out The output stream
40067754Smsmith  /// \param State The state being printed
40167754Smsmith  /// \param NL The preferred representation of a newline.
40267754Smsmith  /// \param Sep The preferred separator between different kinds of data.
40367754Smsmith  void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
40467754Smsmith                                const char *NL, const char *Sep);
40567754Smsmith
40667754Smsmith//===----------------------------------------------------------------------===//
40767754Smsmith// Internal registration functions for AST traversing.
40867754Smsmith//===----------------------------------------------------------------------===//
40967754Smsmith
410  // Functions used by the registration mechanism, checkers should not touch
411  // these directly.
412
413  typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
414      CheckDeclFunc;
415
416  typedef bool (*HandlesDeclFunc)(const Decl *D);
417  void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
418
419  void _registerForBody(CheckDeclFunc checkfn);
420
421//===----------------------------------------------------------------------===//
422// Internal registration functions for path-sensitive checking.
423//===----------------------------------------------------------------------===//
424
425  typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
426
427  typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
428      CheckObjCMessageFunc;
429
430  typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
431      CheckCallFunc;
432
433  typedef CheckerFn<void (const SVal &location, bool isLoad,
434                          const Stmt *S,
435                          CheckerContext &)>
436      CheckLocationFunc;
437
438  typedef CheckerFn<void (const SVal &location, const SVal &val,
439                          const Stmt *S, CheckerContext &)>
440      CheckBindFunc;
441
442  typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
443      CheckEndAnalysisFunc;
444
445  typedef CheckerFn<void (CheckerContext &)>
446      CheckEndFunctionFunc;
447
448  typedef CheckerFn<void (const Stmt *, CheckerContext &)>
449      CheckBranchConditionFunc;
450
451  typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
452      CheckDeadSymbolsFunc;
453
454  typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
455
456  typedef CheckerFn<ProgramStateRef (ProgramStateRef,
457                                const InvalidatedSymbols *symbols,
458                                ArrayRef<const MemRegion *> ExplicitRegions,
459                                ArrayRef<const MemRegion *> Regions,
460                                const CallEvent *Call)>
461      CheckRegionChangesFunc;
462
463  typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
464
465  typedef CheckerFn<ProgramStateRef (ProgramStateRef,
466                                     const InvalidatedSymbols &Escaped,
467                                     const CallEvent *Call,
468                                     PointerEscapeKind Kind,
469                                     RegionAndSymbolInvalidationTraits *ITraits)>
470      CheckPointerEscapeFunc;
471
472  typedef CheckerFn<ProgramStateRef (ProgramStateRef,
473                                          const SVal &cond, bool assumption)>
474      EvalAssumeFunc;
475
476  typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
477      EvalCallFunc;
478
479  typedef CheckerFn<void (const TranslationUnitDecl *,
480                          AnalysisManager&, BugReporter &)>
481      CheckEndOfTranslationUnit;
482
483  typedef bool (*HandlesStmtFunc)(const Stmt *D);
484  void _registerForPreStmt(CheckStmtFunc checkfn,
485                           HandlesStmtFunc isForStmtFn);
486  void _registerForPostStmt(CheckStmtFunc checkfn,
487                            HandlesStmtFunc isForStmtFn);
488
489  void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
490  void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
491
492  void _registerForPreCall(CheckCallFunc checkfn);
493  void _registerForPostCall(CheckCallFunc checkfn);
494
495  void _registerForLocation(CheckLocationFunc checkfn);
496
497  void _registerForBind(CheckBindFunc checkfn);
498
499  void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
500
501  void _registerForEndFunction(CheckEndFunctionFunc checkfn);
502
503  void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
504
505  void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
506
507  void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
508
509  void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
510                                 WantsRegionChangeUpdateFunc wantUpdateFn);
511
512  void _registerForPointerEscape(CheckPointerEscapeFunc checkfn);
513
514  void _registerForConstPointerEscape(CheckPointerEscapeFunc checkfn);
515
516  void _registerForEvalAssume(EvalAssumeFunc checkfn);
517
518  void _registerForEvalCall(EvalCallFunc checkfn);
519
520  void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
521
522//===----------------------------------------------------------------------===//
523// Internal registration functions for events.
524//===----------------------------------------------------------------------===//
525
526  typedef void *EventTag;
527  typedef CheckerFn<void (const void *event)> CheckEventFunc;
528
529  template <typename EVENT>
530  void _registerListenerForEvent(CheckEventFunc checkfn) {
531    EventInfo &info = Events[getTag<EVENT>()];
532    info.Checkers.push_back(checkfn);
533  }
534
535  template <typename EVENT>
536  void _registerDispatcherForEvent() {
537    EventInfo &info = Events[getTag<EVENT>()];
538    info.HasDispatcher = true;
539  }
540
541  template <typename EVENT>
542  void _dispatchEvent(const EVENT &event) const {
543    EventsTy::const_iterator I = Events.find(getTag<EVENT>());
544    if (I == Events.end())
545      return;
546    const EventInfo &info = I->second;
547    for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
548      info.Checkers[i](&event);
549  }
550
551//===----------------------------------------------------------------------===//
552// Implementation details.
553//===----------------------------------------------------------------------===//
554
555private:
556  template <typename CHECKER>
557  static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
558
559  template <typename T>
560  static void *getTag() { static int tag; return &tag; }
561
562  llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
563
564  std::vector<CheckerDtor> CheckerDtors;
565
566  struct DeclCheckerInfo {
567    CheckDeclFunc CheckFn;
568    HandlesDeclFunc IsForDeclFn;
569  };
570  std::vector<DeclCheckerInfo> DeclCheckers;
571
572  std::vector<CheckDeclFunc> BodyCheckers;
573
574  typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
575  typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
576  CachedDeclCheckersMapTy CachedDeclCheckersMap;
577
578  struct StmtCheckerInfo {
579    CheckStmtFunc CheckFn;
580    HandlesStmtFunc IsForStmtFn;
581    bool IsPreVisit;
582  };
583  std::vector<StmtCheckerInfo> StmtCheckers;
584
585  typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
586  typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy;
587  CachedStmtCheckersMapTy CachedStmtCheckersMap;
588
589  const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S,
590                                                     bool isPreVisit);
591
592  std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
593  std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
594
595  std::vector<CheckCallFunc> PreCallCheckers;
596  std::vector<CheckCallFunc> PostCallCheckers;
597
598  std::vector<CheckLocationFunc> LocationCheckers;
599
600  std::vector<CheckBindFunc> BindCheckers;
601
602  std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
603
604  std::vector<CheckEndFunctionFunc> EndFunctionCheckers;
605
606  std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
607
608  std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
609
610  std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
611
612  struct RegionChangesCheckerInfo {
613    CheckRegionChangesFunc CheckFn;
614    WantsRegionChangeUpdateFunc WantUpdateFn;
615  };
616  std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
617
618  std::vector<CheckPointerEscapeFunc> PointerEscapeCheckers;
619
620  std::vector<EvalAssumeFunc> EvalAssumeCheckers;
621
622  std::vector<EvalCallFunc> EvalCallCheckers;
623
624  std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
625
626  struct EventInfo {
627    SmallVector<CheckEventFunc, 4> Checkers;
628    bool HasDispatcher;
629    EventInfo() : HasDispatcher(false) { }
630  };
631
632  typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
633  EventsTy Events;
634};
635
636} // end ento namespace
637
638} // end clang namespace
639
640#endif
641