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