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