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