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