Home | History | Annotate | Download | only in Core
      1 //== Checker.h - Registration mechanism for checkers -------------*- 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 //  This file defines Checker, used to create and register checkers.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_CLANG_SA_CORE_CHECKER
     15 #define LLVM_CLANG_SA_CORE_CHECKER
     16 
     17 #include "clang/StaticAnalyzer/Core/CheckerManager.h"
     18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
     19 #include "llvm/Support/Casting.h"
     20 
     21 namespace clang {
     22 namespace ento {
     23   class BugReporter;
     24 
     25 namespace check {
     26 
     27 struct _VoidCheck {
     28   static void _register(void *checker, CheckerManager &mgr) { }
     29 };
     30 
     31 template <typename DECL>
     32 class ASTDecl {
     33   template <typename CHECKER>
     34   static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
     35                          BugReporter &BR) {
     36     ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR);
     37   }
     38 
     39   static bool _handlesDecl(const Decl *D) {
     40     return llvm::isa<DECL>(D);
     41   }
     42 public:
     43   template <typename CHECKER>
     44   static void _register(CHECKER *checker, CheckerManager &mgr) {
     45     mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
     46                                                        _checkDecl<CHECKER>),
     47                          _handlesDecl);
     48   }
     49 };
     50 
     51 class ASTCodeBody {
     52   template <typename CHECKER>
     53   static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
     54                          BugReporter &BR) {
     55     ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
     56   }
     57 
     58 public:
     59   template <typename CHECKER>
     60   static void _register(CHECKER *checker, CheckerManager &mgr) {
     61     mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
     62                                                        _checkBody<CHECKER>));
     63   }
     64 };
     65 
     66 class EndOfTranslationUnit {
     67   template <typename CHECKER>
     68   static void _checkEndOfTranslationUnit(void *checker,
     69                                          const TranslationUnitDecl *TU,
     70                                          AnalysisManager& mgr,
     71                                          BugReporter &BR) {
     72     ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
     73   }
     74 
     75 public:
     76   template <typename CHECKER>
     77   static void _register(CHECKER *checker, CheckerManager &mgr){
     78     mgr._registerForEndOfTranslationUnit(
     79                               CheckerManager::CheckEndOfTranslationUnit(checker,
     80                                           _checkEndOfTranslationUnit<CHECKER>));
     81   }
     82 };
     83 
     84 template <typename STMT>
     85 class PreStmt {
     86   template <typename CHECKER>
     87   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
     88     ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C);
     89   }
     90 
     91   static bool _handlesStmt(const Stmt *S) {
     92     return llvm::isa<STMT>(S);
     93   }
     94 public:
     95   template <typename CHECKER>
     96   static void _register(CHECKER *checker, CheckerManager &mgr) {
     97     mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
     98                                                           _checkStmt<CHECKER>),
     99                             _handlesStmt);
    100   }
    101 };
    102 
    103 template <typename STMT>
    104 class PostStmt {
    105   template <typename CHECKER>
    106   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
    107     ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C);
    108   }
    109 
    110   static bool _handlesStmt(const Stmt *S) {
    111     return llvm::isa<STMT>(S);
    112   }
    113 public:
    114   template <typename CHECKER>
    115   static void _register(CHECKER *checker, CheckerManager &mgr) {
    116     mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
    117                                                            _checkStmt<CHECKER>),
    118                              _handlesStmt);
    119   }
    120 };
    121 
    122 class PreObjCMessage {
    123   template <typename CHECKER>
    124   static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
    125                                 CheckerContext &C) {
    126     ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
    127   }
    128 
    129 public:
    130   template <typename CHECKER>
    131   static void _register(CHECKER *checker, CheckerManager &mgr) {
    132     mgr._registerForPreObjCMessage(
    133      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
    134   }
    135 };
    136 
    137 class PostObjCMessage {
    138   template <typename CHECKER>
    139   static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
    140                                 CheckerContext &C) {
    141     ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
    142   }
    143 
    144 public:
    145   template <typename CHECKER>
    146   static void _register(CHECKER *checker, CheckerManager &mgr) {
    147     mgr._registerForPostObjCMessage(
    148      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
    149   }
    150 };
    151 
    152 class Location {
    153   template <typename CHECKER>
    154   static void _checkLocation(void *checker, const SVal &location, bool isLoad,
    155                              CheckerContext &C) {
    156     ((const CHECKER *)checker)->checkLocation(location, isLoad, C);
    157   }
    158 
    159 public:
    160   template <typename CHECKER>
    161   static void _register(CHECKER *checker, CheckerManager &mgr) {
    162     mgr._registerForLocation(
    163            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
    164   }
    165 };
    166 
    167 class Bind {
    168   template <typename CHECKER>
    169   static void _checkBind(void *checker, const SVal &location, const SVal &val,
    170                          CheckerContext &C) {
    171     ((const CHECKER *)checker)->checkBind(location, val, C);
    172   }
    173 
    174 public:
    175   template <typename CHECKER>
    176   static void _register(CHECKER *checker, CheckerManager &mgr) {
    177     mgr._registerForBind(
    178            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
    179   }
    180 };
    181 
    182 class EndAnalysis {
    183   template <typename CHECKER>
    184   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
    185                                 BugReporter &BR, ExprEngine &Eng) {
    186     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
    187   }
    188 
    189 public:
    190   template <typename CHECKER>
    191   static void _register(CHECKER *checker, CheckerManager &mgr) {
    192     mgr._registerForEndAnalysis(
    193      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
    194   }
    195 };
    196 
    197 class EndPath {
    198   template <typename CHECKER>
    199   static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
    200                             ExprEngine &Eng) {
    201     ((const CHECKER *)checker)->checkEndPath(B, Eng);
    202   }
    203 
    204 public:
    205   template <typename CHECKER>
    206   static void _register(CHECKER *checker, CheckerManager &mgr) {
    207     mgr._registerForEndPath(
    208      CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
    209   }
    210 };
    211 
    212 class BranchCondition {
    213   template <typename CHECKER>
    214   static void _checkBranchCondition(void *checker, const Stmt *condition,
    215                                     BranchNodeBuilder &B, ExprEngine &Eng) {
    216     ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
    217   }
    218 
    219 public:
    220   template <typename CHECKER>
    221   static void _register(CHECKER *checker, CheckerManager &mgr) {
    222     mgr._registerForBranchCondition(
    223       CheckerManager::CheckBranchConditionFunc(checker,
    224                                                _checkBranchCondition<CHECKER>));
    225   }
    226 };
    227 
    228 class LiveSymbols {
    229   template <typename CHECKER>
    230   static void _checkLiveSymbols(void *checker, const GRState *state,
    231                                 SymbolReaper &SR) {
    232     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
    233   }
    234 
    235 public:
    236   template <typename CHECKER>
    237   static void _register(CHECKER *checker, CheckerManager &mgr) {
    238     mgr._registerForLiveSymbols(
    239      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
    240   }
    241 };
    242 
    243 class DeadSymbols {
    244   template <typename CHECKER>
    245   static void _checkDeadSymbols(void *checker,
    246                                 SymbolReaper &SR, CheckerContext &C) {
    247     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
    248   }
    249 
    250 public:
    251   template <typename CHECKER>
    252   static void _register(CHECKER *checker, CheckerManager &mgr) {
    253     mgr._registerForDeadSymbols(
    254      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
    255   }
    256 };
    257 
    258 class RegionChanges {
    259   template <typename CHECKER>
    260   static const GRState *_checkRegionChanges(void *checker, const GRState *state,
    261                             const StoreManager::InvalidatedSymbols *invalidated,
    262                                             const MemRegion * const *Begin,
    263                                             const MemRegion * const *End) {
    264     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
    265                                                           Begin, End);
    266   }
    267   template <typename CHECKER>
    268   static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
    269     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
    270   }
    271 
    272 public:
    273   template <typename CHECKER>
    274   static void _register(CHECKER *checker, CheckerManager &mgr) {
    275     mgr._registerForRegionChanges(
    276           CheckerManager::CheckRegionChangesFunc(checker,
    277                                                  _checkRegionChanges<CHECKER>),
    278           CheckerManager::WantsRegionChangeUpdateFunc(checker,
    279                                             _wantsRegionChangeUpdate<CHECKER>));
    280   }
    281 };
    282 
    283 template <typename EVENT>
    284 class Event {
    285   template <typename CHECKER>
    286   static void _checkEvent(void *checker, const void *event) {
    287     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
    288   }
    289 public:
    290   template <typename CHECKER>
    291   static void _register(CHECKER *checker, CheckerManager &mgr) {
    292     mgr._registerListenerForEvent<EVENT>(
    293                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
    294   }
    295 };
    296 
    297 } // end check namespace
    298 
    299 namespace eval {
    300 
    301 class Assume {
    302   template <typename CHECKER>
    303   static const GRState *_evalAssume(void *checker, const GRState *state,
    304                                     const SVal &cond, bool assumption) {
    305     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
    306   }
    307 
    308 public:
    309   template <typename CHECKER>
    310   static void _register(CHECKER *checker, CheckerManager &mgr) {
    311     mgr._registerForEvalAssume(
    312                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
    313   }
    314 };
    315 
    316 class Call {
    317   template <typename CHECKER>
    318   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
    319     return ((const CHECKER *)checker)->evalCall(CE, C);
    320   }
    321 
    322 public:
    323   template <typename CHECKER>
    324   static void _register(CHECKER *checker, CheckerManager &mgr) {
    325     mgr._registerForEvalCall(
    326                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
    327   }
    328 };
    329 
    330 } // end eval namespace
    331 
    332 template <typename CHECK1, typename CHECK2=check::_VoidCheck,
    333           typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
    334           typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
    335           typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
    336           typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
    337           typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck>
    338 class Checker;
    339 
    340 template <>
    341 class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
    342                 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
    343                 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
    344                 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> {
    345 public:
    346   static void _register(void *checker, CheckerManager &mgr) { }
    347 };
    348 
    349 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
    350           typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
    351           typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12>
    352 class Checker
    353     : public CHECK1,
    354       public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
    355                        CHECK9, CHECK10, CHECK11, CHECK12> {
    356 public:
    357   template <typename CHECKER>
    358   static void _register(CHECKER *checker, CheckerManager &mgr) {
    359     CHECK1::_register(checker, mgr);
    360     Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9,
    361               CHECK10, CHECK11,CHECK12>::_register(checker, mgr);
    362   }
    363 };
    364 
    365 template <typename EVENT>
    366 class EventDispatcher {
    367   CheckerManager *Mgr;
    368 public:
    369   EventDispatcher() : Mgr(0) { }
    370 
    371   template <typename CHECKER>
    372   static void _register(CHECKER *checker, CheckerManager &mgr) {
    373     mgr._registerDispatcherForEvent<EVENT>();
    374     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
    375   }
    376 
    377   void dispatchEvent(const EVENT &event) const {
    378     Mgr->_dispatchEvent(event);
    379   }
    380 };
    381 
    382 /// \brief We dereferenced a location that may be null.
    383 struct ImplicitNullDerefEvent {
    384   SVal Location;
    385   bool IsLoad;
    386   ExplodedNode *SinkNode;
    387   BugReporter *BR;
    388 };
    389 
    390 } // end ento namespace
    391 
    392 } // end clang namespace
    393 
    394 #endif
    395