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