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