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