CheckerManager.h revision 312dbec867f6b8d6b86fd562c53352cd4db27468
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 void *CheckerTag;
103  typedef CheckerFn<> CheckerDtor;
104
105//===----------------------------------------------------------------------===//
106// registerChecker
107//===----------------------------------------------------------------------===//
108
109  /// \brief Used to register checkers.
110  ///
111  /// \returns a pointer to the checker object.
112  template <typename CHECKER>
113  CHECKER *registerChecker() {
114    CheckerTag tag = getCheckerTag<CHECKER>();
115    CheckerRef &ref = CheckerTags[tag];
116    if (ref)
117      return static_cast<CHECKER *>(ref); // already registered.
118
119    CHECKER *checker = new CHECKER();
120    CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
121    CHECKER::_register(checker, *this);
122    ref = checker;
123    return checker;
124  }
125
126//===----------------------------------------------------------------------===//
127// Functions for running checkers for AST traversing..
128//===----------------------------------------------------------------------===//
129
130  /// \brief Run checkers handling Decls.
131  void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
132                            BugReporter &BR);
133
134  /// \brief Run checkers handling Decls containing a Stmt body.
135  void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
136                            BugReporter &BR);
137
138//===----------------------------------------------------------------------===//
139// Functions for running checkers for path-sensitive checking.
140//===----------------------------------------------------------------------===//
141
142  /// \brief Run checkers for pre-visiting Stmts.
143  void runCheckersForPreStmt(ExplodedNodeSet &Dst,
144                             const ExplodedNodeSet &Src,
145                             const Stmt *S,
146                             ExprEngine &Eng) {
147    runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
148  }
149
150  /// \brief Run checkers for post-visiting Stmts.
151  void runCheckersForPostStmt(ExplodedNodeSet &Dst,
152                              const ExplodedNodeSet &Src,
153                              const Stmt *S,
154                              ExprEngine &Eng) {
155    runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng);
156  }
157
158  /// \brief Run checkers for visiting Stmts.
159  void runCheckersForStmt(bool isPreVisit,
160                          ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
161                          const Stmt *S, ExprEngine &Eng);
162
163  /// \brief Run checkers for pre-visiting obj-c messages.
164  void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
165                                    const ExplodedNodeSet &Src,
166                                    const ObjCMessage &msg,
167                                    ExprEngine &Eng) {
168    runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
169  }
170
171  /// \brief Run checkers for post-visiting obj-c messages.
172  void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
173                                     const ExplodedNodeSet &Src,
174                                     const ObjCMessage &msg,
175                                     ExprEngine &Eng) {
176    runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng);
177  }
178
179  /// \brief Run checkers for visiting obj-c messages.
180  void runCheckersForObjCMessage(bool isPreVisit,
181                                 ExplodedNodeSet &Dst,
182                                 const ExplodedNodeSet &Src,
183                                 const ObjCMessage &msg, ExprEngine &Eng);
184
185  /// \brief Run checkers for load/store of a location.
186  void runCheckersForLocation(ExplodedNodeSet &Dst,
187                              const ExplodedNodeSet &Src,
188                              SVal location, bool isLoad,
189                              const Stmt *S,
190                              ExprEngine &Eng);
191
192  /// \brief Run checkers for binding of a value to a location.
193  void runCheckersForBind(ExplodedNodeSet &Dst,
194                          const ExplodedNodeSet &Src,
195                          SVal location, SVal val,
196                          const Stmt *S, ExprEngine &Eng);
197
198  /// \brief Run checkers for end of analysis.
199  void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
200                                 ExprEngine &Eng);
201
202  /// \brief Run checkers for end of path.
203  void runCheckersForEndPath(EndOfFunctionNodeBuilder &B, ExprEngine &Eng);
204
205  /// \brief Run checkers for live symbols.
206  void runCheckersForLiveSymbols(const GRState *state,
207                                 SymbolReaper &SymReaper);
208
209  /// \brief Run checkers for dead symbols.
210  void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
211                                 const ExplodedNodeSet &Src,
212                                 SymbolReaper &SymReaper, const Stmt *S,
213                                 ExprEngine &Eng);
214
215  /// \brief True if at least one checker wants to check region changes.
216  bool wantsRegionChangeUpdate(const GRState *state);
217
218  /// \brief Run checkers for region changes.
219  const GRState *runCheckersForRegionChanges(const GRState *state,
220                                             const MemRegion * const *Begin,
221                                             const MemRegion * const *End);
222
223  /// \brief Run checkers for handling assumptions on symbolic values.
224  const GRState *runCheckersForEvalAssume(const GRState *state,
225                                          SVal Cond, bool Assumption);
226
227  /// \brief Run checkers for evaluating a call.
228  void runCheckersForEvalCall(ExplodedNodeSet &Dst,
229                              const ExplodedNodeSet &Src,
230                              const CallExpr *CE, ExprEngine &Eng,
231                              GraphExpander *defaultEval = 0);
232
233//===----------------------------------------------------------------------===//
234// Internal registration functions for AST traversing.
235//===----------------------------------------------------------------------===//
236
237  // Functions used by the registration mechanism, checkers should not touch
238  // these directly.
239
240  typedef CheckerFn<const Decl *, AnalysisManager&, BugReporter &>
241      CheckDeclFunc;
242  typedef CheckerFn<const Stmt *, CheckerContext &> CheckStmtFunc;
243
244  typedef bool (*HandlesDeclFunc)(const Decl *D);
245  void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
246
247  void _registerForBody(CheckDeclFunc checkfn);
248
249//===----------------------------------------------------------------------===//
250// Internal registration functions for path-sensitive checking.
251//===----------------------------------------------------------------------===//
252
253  typedef CheckerFn<const ObjCMessage &, CheckerContext &> CheckObjCMessageFunc;
254  typedef CheckerFn<const SVal &/*location*/, bool/*isLoad*/, CheckerContext &>
255      CheckLocationFunc;
256  typedef CheckerFn<const SVal &/*location*/, const SVal &/*val*/,
257                    CheckerContext &> CheckBindFunc;
258  typedef CheckerFn<ExplodedGraph &, BugReporter &, ExprEngine &>
259      CheckEndAnalysisFunc;
260  typedef CheckerFn<EndOfFunctionNodeBuilder &, ExprEngine &> CheckEndPathFunc;
261  typedef CheckerFn<SymbolReaper &, CheckerContext &> CheckDeadSymbolsFunc;
262  typedef CheckerFn<const GRState *, SymbolReaper &> CheckLiveSymbolsFunc;
263
264  typedef bool (*HandlesStmtFunc)(const Stmt *D);
265  void _registerForPreStmt(CheckStmtFunc checkfn,
266                           HandlesStmtFunc isForStmtFn);
267  void _registerForPostStmt(CheckStmtFunc checkfn,
268                            HandlesStmtFunc isForStmtFn);
269
270  void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
271  void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
272
273  void _registerForLocation(CheckLocationFunc checkfn);
274
275  void _registerForBind(CheckBindFunc checkfn);
276
277  void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
278
279  void _registerForEndPath(CheckEndPathFunc checkfn);
280
281  void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
282
283  void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
284
285  class CheckRegionChangesFunc {
286    typedef const GRState * (*Func)(void *, const GRState *,
287                                    const MemRegion * const *,
288                                    const MemRegion * const *);
289    Func Fn;
290  public:
291    void *Checker;
292    CheckRegionChangesFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {}
293    const GRState *operator()(const GRState *state,
294                              const MemRegion * const *begin,
295                              const MemRegion * const *end) {
296      return Fn(Checker, state, begin, end);
297    }
298  };
299
300  class WantsRegionChangeUpdateFunc {
301    typedef bool (*Func)(void *, const GRState *);
302    Func Fn;
303  public:
304    void *Checker;
305    WantsRegionChangeUpdateFunc(void *checker, Func fn)
306      : Fn(fn), Checker(checker) { }
307    bool operator()(const GRState *state) {
308      return Fn(Checker, state);
309    }
310  };
311
312  void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
313                                 WantsRegionChangeUpdateFunc wantUpdateFn);
314
315  class EvalAssumeFunc {
316    typedef const GRState * (*Func)(void *, const GRState *,
317                                    const SVal &/*cond*/, bool /*assumption*/);
318    Func Fn;
319  public:
320    void *Checker;
321    EvalAssumeFunc(void *checker, Func fn) : Fn(fn), Checker(checker) {}
322    const GRState *operator()(const GRState *state,
323                              const SVal &cond, bool assumption) {
324      return Fn(Checker, state, cond, assumption);
325    }
326  };
327
328  void _registerForEvalAssume(EvalAssumeFunc checkfn);
329
330  class EvalCallFunc {
331    typedef bool (*Func)(void *, const CallExpr *, CheckerContext &);
332    Func Fn;
333  public:
334    void *Checker;
335    EvalCallFunc(void *checker, Func fn) : Fn(fn), Checker(checker) { }
336    bool operator()(const CallExpr *CE, CheckerContext &C) {
337      return Fn(Checker, CE, C);
338    }
339  };
340
341  void _registerForEvalCall(EvalCallFunc checkfn);
342
343//===----------------------------------------------------------------------===//
344// Implementation details.
345//===----------------------------------------------------------------------===//
346
347private:
348  template <typename CHECKER>
349  static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
350
351  template <typename CHECKER>
352  static CheckerTag getCheckerTag() { static int tag; return &tag; }
353
354  llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
355
356  std::vector<CheckerDtor> CheckerDtors;
357
358  struct DeclCheckerInfo {
359    CheckDeclFunc CheckFn;
360    HandlesDeclFunc IsForDeclFn;
361  };
362  std::vector<DeclCheckerInfo> DeclCheckers;
363
364  std::vector<CheckDeclFunc> BodyCheckers;
365
366  typedef llvm::SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
367  typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
368  CachedDeclCheckersMapTy CachedDeclCheckersMap;
369
370  struct StmtCheckerInfo {
371    CheckStmtFunc CheckFn;
372    HandlesStmtFunc IsForStmtFn;
373    bool IsPreVisit;
374  };
375  std::vector<StmtCheckerInfo> StmtCheckers;
376
377  struct CachedStmtCheckersKey {
378    unsigned StmtKind;
379    bool IsPreVisit;
380
381    CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
382    CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
383      : StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
384
385    static CachedStmtCheckersKey getSentinel() {
386      return CachedStmtCheckersKey(~0U, 0);
387    }
388    unsigned getHashValue() const {
389      llvm::FoldingSetNodeID ID;
390      ID.AddInteger(StmtKind);
391      ID.AddBoolean(IsPreVisit);
392      return ID.ComputeHash();
393    }
394    bool operator==(const CachedStmtCheckersKey &RHS) const {
395      return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
396    }
397  };
398  friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
399
400  typedef llvm::SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
401  typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
402      CachedStmtCheckersMapTy;
403  CachedStmtCheckersMapTy CachedStmtCheckersMap;
404
405  CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
406
407  std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
408  std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
409
410  std::vector<CheckLocationFunc> LocationCheckers;
411
412  std::vector<CheckBindFunc> BindCheckers;
413
414  std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
415
416  std::vector<CheckEndPathFunc> EndPathCheckers;
417
418  std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
419
420  std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
421
422  struct RegionChangesCheckerInfo {
423    CheckRegionChangesFunc CheckFn;
424    WantsRegionChangeUpdateFunc WantUpdateFn;
425  };
426  std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
427
428  std::vector<EvalAssumeFunc> EvalAssumeCheckers;
429
430  std::vector<EvalCallFunc> EvalCallCheckers;
431};
432
433} // end ento namespace
434
435} // end clang namespace
436
437namespace llvm {
438  /// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
439  /// in DenseMap and DenseSets.
440  template <>
441  struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
442    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
443        getEmptyKey() {
444      return clang::ento::CheckerManager::CachedStmtCheckersKey();
445    }
446    static inline clang::ento::CheckerManager::CachedStmtCheckersKey
447        getTombstoneKey() {
448      return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
449    }
450
451    static unsigned
452        getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
453      return S.getHashValue();
454    }
455
456    static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
457                       clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
458      return LHS == RHS;
459    }
460  };
461} // end namespace llvm
462
463#endif
464