CheckerManager.h revision fc26107870e0e450d863541179234bf9063a4da7
1//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Defines the Static Analyzer Checker Manager.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
15#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
16
17#include "llvm/ADT/SmallVector.h"
18#include "llvm/ADT/DenseMap.h"
19#include "llvm/ADT/FoldingSet.h"
20#include <vector>
21
22namespace clang {
23  class Decl;
24  class Stmt;
25
26namespace ento {
27  class ExprEngine;
28  class AnalysisManager;
29  class BugReporter;
30  class CheckerContext;
31  class ObjCMessage;
32  class SVal;
33  class ExplodedNodeSet;
34  class GRState;
35
36struct VoidCheckerFnParm {};
37template <typename P1=VoidCheckerFnParm, typename P2=VoidCheckerFnParm,
38          typename P3=VoidCheckerFnParm, typename P4=VoidCheckerFnParm>
39class CheckerFn {
40  typedef void (*Func)(void *, P1, P2, P3, P4);
41  Func Fn;
42public:
43  void *Checker;
44  CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
45  void operator()(P1 p1, P2 p2, P3 p3, P4 p4) { Fn(Checker, p1, p2, p3, p4); }
46};
47
48template <typename P1, typename P2, typename P3>
49class CheckerFn<P1, P2, P3, VoidCheckerFnParm> {
50  typedef void (*Func)(void *, P1, P2, P3);
51  Func Fn;
52public:
53  void *Checker;
54  CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
55  void operator()(P1 p1, P2 p2, P3 p3) { Fn(Checker, p1, p2, p3); }
56};
57
58template <typename P1, typename P2>
59class CheckerFn<P1, P2, VoidCheckerFnParm, VoidCheckerFnParm> {
60  typedef void (*Func)(void *, P1, P2);
61  Func Fn;
62public:
63  void *Checker;
64  CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
65  void operator()(P1 p1, P2 p2) { Fn(Checker, p1, p2); }
66};
67
68template <>
69class CheckerFn<VoidCheckerFnParm, VoidCheckerFnParm, VoidCheckerFnParm,
70                VoidCheckerFnParm> {
71  typedef void (*Func)(void *);
72  Func Fn;
73public:
74  void *Checker;
75  CheckerFn(void *checker, Func fn) : Fn(fn), Checker(checker) { }
76  void operator()() { Fn(Checker); }
77};
78
79class CheckerManager {
80public:
81  ~CheckerManager();
82
83  typedef void *CheckerRef;
84  typedef CheckerFn<> CheckerDtor;
85
86//===----------------------------------------------------------------------===//
87// registerChecker
88//===----------------------------------------------------------------------===//
89
90  /// \brief Used to register checkers.
91  template <typename CHECKER>
92  void registerChecker() {
93    CHECKER *checker = new CHECKER();
94    CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
95    CHECKER::_register(checker, *this);
96  }
97
98  typedef void (*RegisterToEngFunc)(ExprEngine &Eng);
99  void addCheckerRegisterFunction(RegisterToEngFunc fn) {
100    Funcs.push_back(fn);
101  }
102
103//===----------------------------------------------------------------------===//
104// Functions for running checkers for AST traversing..
105//===----------------------------------------------------------------------===//
106
107  /// \brief Run checkers handling Decls.
108  void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
109                            BugReporter &BR);
110
111  /// \brief Run checkers handling Decls containing a Stmt body.
112  void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
113                            BugReporter &BR);
114
115//===----------------------------------------------------------------------===//
116// Functions for running checkers for path-sensitive checking.
117//===----------------------------------------------------------------------===//
118
119  /// \brief Run checkers for pre-visiting Stmts.
120  void runCheckersForPreStmt(ExplodedNodeSet &Dst,
121                             ExplodedNodeSet &Src,
122                             const Stmt *S,
123                             ExprEngine &Eng) {
124    runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
125  }
126
127  /// \brief Run checkers for post-visiting Stmts.
128  void runCheckersForPostStmt(ExplodedNodeSet &Dst,
129                              ExplodedNodeSet &Src,
130                              const Stmt *S,
131                              ExprEngine &Eng) {
132    runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng);
133  }
134
135  /// \brief Run checkers for visiting Stmts.
136  void runCheckersForStmt(bool isPreVisit,
137                          ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
138                          const Stmt *S, ExprEngine &Eng);
139
140  /// \brief Run checkers for pre-visiting obj-c messages.
141  void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
142                                    ExplodedNodeSet &Src,
143                                    const ObjCMessage &msg,
144                                    ExprEngine &Eng) {
145    runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
146  }
147
148  /// \brief Run checkers for post-visiting obj-c messages.
149  void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
150                                     ExplodedNodeSet &Src,
151                                     const ObjCMessage &msg,
152                                     ExprEngine &Eng) {
153    runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng);
154  }
155
156  /// \brief Run checkers for visiting obj-c messages.
157  void runCheckersForObjCMessage(bool isPreVisit,
158                                 ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
159                                 const ObjCMessage &msg, ExprEngine &Eng);
160
161  /// \brief Run checkers for load/store of a location.
162  void runCheckersForLocation(ExplodedNodeSet &Dst,
163                              ExplodedNodeSet &Src,
164                              SVal location, bool isLoad,
165                              const Stmt *S,
166                              const GRState *state,
167                              ExprEngine &Eng);
168
169  // FIXME: Temporary until checker running is moved completely into
170  // CheckerManager.
171  void registerCheckersToEngine(ExprEngine &eng);
172
173//===----------------------------------------------------------------------===//
174// Internal registration functions for AST traversing.
175//===----------------------------------------------------------------------===//
176
177  // Functions used by the registration mechanism, checkers should not touch
178  // these directly.
179
180  typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &>
181      CheckDeclFunc;
182  typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc;
183
184  typedef bool (*HandlesDeclFunc)(const Decl *D);
185  void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
186
187  void _registerForBody(CheckDeclFunc checkfn);
188
189//===----------------------------------------------------------------------===//
190// Internal registration functions for path-sensitive checking.
191//===----------------------------------------------------------------------===//
192
193  typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc;
194  typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &>
195      CheckLocationFunc;
196
197  typedef bool (*HandlesStmtFunc)(const Stmt *D);
198  void _registerForPreStmt(CheckStmtFunc checkfn,
199                           HandlesStmtFunc isForStmtFn);
200  void _registerForPostStmt(CheckStmtFunc checkfn,
201                            HandlesStmtFunc isForStmtFn);
202
203  void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
204  void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
205
206  void _registerForLocation(CheckLocationFunc checkfn);
207
208//===----------------------------------------------------------------------===//
209// Implementation details.
210//===----------------------------------------------------------------------===//
211
212private:
213  template <typename CHECKER>
214  static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
215
216  std::vector<CheckerDtor> CheckerDtors;
217
218  std::vector<RegisterToEngFunc> Funcs;
219
220  struct DeclCheckerInfo {
221    CheckDeclFunc CheckFn;
222    HandlesDeclFunc IsForDeclFn;
223  };
224  std::vector<DeclCheckerInfo> DeclCheckers;
225
226  std::vector<CheckDeclFunc> BodyCheckers;
227
228  typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
229  typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
230  CachedDeclCheckersMapTy CachedDeclCheckersMap;
231
232  struct StmtCheckerInfo {
233    CheckStmtFunc CheckFn;
234    HandlesStmtFunc IsForStmtFn;
235    bool IsPreVisit;
236  };
237  std::vector<StmtCheckerInfo> StmtCheckers;
238
239  struct CachedStmtCheckersKey {
240    unsigned StmtKind;
241    bool IsPreVisit;
242
243    CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
244    CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
245      : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
246
247    static CachedStmtCheckersKey getSentinel() {
248      return CachedStmtCheckersKey(~0U, 0);
249    }
250    unsigned getHashValue() const {
251      llvm::FoldingSetNodeID ID;
252      ID.AddInteger(StmtKind);
253      ID.AddBoolean(IsPreVisit);
254      return ID.ComputeHash();
255    }
256    bool operator==(const CachedStmtCheckersKey &RHS) const {
257      return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
258    }
259  };
260  friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
261
262  typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
263  typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
264      CachedStmtCheckersMapTy;
265  CachedStmtCheckersMapTy CachedStmtCheckersMap;
266
267  CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
268
269  std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
270  std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
271
272  std::vector<CheckLocationFunc> LocationCheckers;
273};
274
275} // end ento namespace
276
277} // end clang namespace
278
279namespace llvm {
280  /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
281  /// in DenseMap and DenseSets.
282  template <>
283  struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
284    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
285        getEmptyKey() {
286      return clang::ento::CheckerManager::CachedStmtCheckersKey();
287    }
288    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
289        getTombstoneKey() {
290      return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
291    }
292
293    static unsigned
294        getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
295      return S.getHashValue();
296    }
297
298    static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
299                       clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
300      return LHS == RHS;
301    }
302  };
303} // end namespace llvm
304
305#endif
306