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