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