CheckerManager.h revision 64be13795a9b5b25de6b151551a2f5ef2bab353c
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                              const GRState *state,
181                              ExprEngine &Eng);
182
183  /// \brief Run checkers for end of analysis.
184  void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
185                                 ExprEngine &Eng);
186
187  /// \brief Run checkers for end of path.
188  void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng);
189
190  /// \brief Run checkers for live symbols.
191  void runCheckersForLiveSymbols(const GRState *state,
192                                 SymbolReaper &SymReaper);
193
194  /// \brief Run checkers for dead symbols.
195  void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
196                                 const ExplodedNodeSet &Src,
197                                 SymbolReaper &SymReaper, const Stmt *S,
198                                 ExprEngine &Eng);
199
200  /// \brief True if at least one checker wants to check region changes.
201  bool wantsRegionChangeUpdate(const GRState *state);
202
203  /// \brief Run checkers for region changes.
204  const GRState *runCheckersForRegionChanges(const GRState *state,
205                                             const MemRegion * const *Begin,
206                                             const MemRegion * const *End);
207
208  /// \brief Run checkers for evaluating a call.
209  void runCheckersForEvalCall(ExplodedNodeSet &Dst,
210                              const ExplodedNodeSet &Src,
211                              const CallExpr *CE, ExprEngine &Eng,
212                              GraphExpander *defaultEval = 0);
213
214//===----------------------------------------------------------------------===//
215// Internal registration functions for AST traversing.
216//===----------------------------------------------------------------------===//
217
218  // Functions used by the registration mechanism, checkers should not touch
219  // these directly.
220
221  typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &>
222      CheckDeclFunc;
223  typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc;
224
225  typedef bool (*HandlesDeclFunc)(const Decl *D);
226  void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
227
228  void _registerForBody(CheckDeclFunc checkfn);
229
230//===----------------------------------------------------------------------===//
231// Internal registration functions for path-sensitive checking.
232//===----------------------------------------------------------------------===//
233
234  typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc;
235  typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &>
236      CheckLocationFunc;
237  typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &>
238      CheckEndAnalysisFunc;
239  typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc;
240  typedef CheckerFn<SymbolReaper &, CheckerContext &> CheckDeadSymbolsFunc;
241  typedef CheckerFn<const GRState *, SymbolReaper &> CheckLiveSymbolsFunc;
242
243  typedef bool (*HandlesStmtFunc)(const Stmt *D);
244  void _registerForPreStmt(CheckStmtFunc checkfn,
245                           HandlesStmtFunc isForStmtFn);
246  void _registerForPostStmt(CheckStmtFunc checkfn,
247                            HandlesStmtFunc isForStmtFn);
248
249  void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
250  void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
251
252  void _registerForLocation(CheckLocationFunc checkfn);
253
254  void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
255
256  void _registerForEndPath(CheckEndPathFunc checkfn);
257
258  void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
259
260  void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
261
262  class CheckRegionChangesFunc {
263    typedef const GRState * (*Func)(void *, const GRState *,
264                                    const MemRegion * const *,
265                                    const MemRegion * const *);
266    Func Fn;
267  public:
268    void *Checker;
269    CheckRegionChangesFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {}
270    const GRState *operator()(const GRState *state,
271                              const MemRegion * const *begin,
272                              const MemRegion * const *end) {
273      return Fn(Checker, state, begin, end);
274    }
275  };
276
277  class WantsRegionChangeUpdateFunc {
278    typedef bool (*Func)(void *, const GRState *);
279    Func Fn;
280  public:
281    void *Checker;
282    WantsRegionChangeUpdateFunc(void *checker, Func fn)
283      : Fn(fn), Checker(checker) { }
284    bool operator()(const GRState *state) {
285      return Fn(Checker, state);
286    }
287  };
288
289  void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
290                                 WantsRegionChangeUpdateFunc wantUpdateFn);
291
292  class EvalCallFunc {
293    typedef bool (*Func)(void *, const CallExpr *, CheckerContext &);
294    Func Fn;
295  public:
296    void *Checker;
297    EvalCallFunc(void *checker, Func fn) : Fn(fn), Checker(checker) { }
298    bool operator()(const CallExpr *CE, CheckerContext &C) {
299      return Fn(Checker, CE, C);
300    }
301  };
302
303  void _registerForEvalCall(EvalCallFunc checkfn);
304
305//===----------------------------------------------------------------------===//
306// Implementation details.
307//===----------------------------------------------------------------------===//
308
309private:
310  template <typename CHECKER>
311  static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
312
313  std::vector<CheckerDtor> CheckerDtors;
314
315  struct DeclCheckerInfo {
316    CheckDeclFunc CheckFn;
317    HandlesDeclFunc IsForDeclFn;
318  };
319  std::vector<DeclCheckerInfo> DeclCheckers;
320
321  std::vector<CheckDeclFunc> BodyCheckers;
322
323  typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
324  typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
325  CachedDeclCheckersMapTy CachedDeclCheckersMap;
326
327  struct StmtCheckerInfo {
328    CheckStmtFunc CheckFn;
329    HandlesStmtFunc IsForStmtFn;
330    bool IsPreVisit;
331  };
332  std::vector<StmtCheckerInfo> StmtCheckers;
333
334  struct CachedStmtCheckersKey {
335    unsigned StmtKind;
336    bool IsPreVisit;
337
338    CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
339    CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
340      : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
341
342    static CachedStmtCheckersKey getSentinel() {
343      return CachedStmtCheckersKey(~0U, 0);
344    }
345    unsigned getHashValue() const {
346      llvm::FoldingSetNodeID ID;
347      ID.AddInteger(StmtKind);
348      ID.AddBoolean(IsPreVisit);
349      return ID.ComputeHash();
350    }
351    bool operator==(const CachedStmtCheckersKey &RHS) const {
352      return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
353    }
354  };
355  friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
356
357  typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
358  typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
359      CachedStmtCheckersMapTy;
360  CachedStmtCheckersMapTy CachedStmtCheckersMap;
361
362  CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
363
364  std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
365  std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
366
367  std::vector<CheckLocationFunc> LocationCheckers;
368
369  std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
370
371  std::vector<CheckEndPathFunc> EndPathCheckers;
372
373  std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
374
375  std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
376
377  struct RegionChangesCheckerInfo {
378    CheckRegionChangesFunc CheckFn;
379    WantsRegionChangeUpdateFunc WantUpdateFn;
380  };
381  std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
382
383  std::vector<EvalCallFunc> EvalCallCheckers;
384};
385
386} // end ento namespace
387
388} // end clang namespace
389
390namespace llvm {
391  /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
392  /// in DenseMap and DenseSets.
393  template <>
394  struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
395    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
396        getEmptyKey() {
397      return clang::ento::CheckerManager::CachedStmtCheckersKey();
398    }
399    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
400        getTombstoneKey() {
401      return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
402    }
403
404    static unsigned
405        getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
406      return S.getHashValue();
407    }
408
409    static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
410                       clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
411      return LHS == RHS;
412    }
413  };
414} // end namespace llvm
415
416#endif
417