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