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,
    203                             CheckerContext &C) {
    204     ((const CHECKER *)checker)->checkEndPath(C);
    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                                     CheckerContext & C) {
    219     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
    220   }
    221 
    222 public:
    223   template <typename CHECKER>
    224   static void _register(CHECKER *checker, CheckerManager &mgr) {
    225     mgr._registerForBranchCondition(
    226       CheckerManager::CheckBranchConditionFunc(checker,
    227                                                _checkBranchCondition<CHECKER>));
    228   }
    229 };
    230 
    231 class LiveSymbols {
    232   template <typename CHECKER>
    233   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
    234                                 SymbolReaper &SR) {
    235     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
    236   }
    237 
    238 public:
    239   template <typename CHECKER>
    240   static void _register(CHECKER *checker, CheckerManager &mgr) {
    241     mgr._registerForLiveSymbols(
    242      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
    243   }
    244 };
    245 
    246 class DeadSymbols {
    247   template <typename CHECKER>
    248   static void _checkDeadSymbols(void *checker,
    249                                 SymbolReaper &SR, CheckerContext &C) {
    250     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
    251   }
    252 
    253 public:
    254   template <typename CHECKER>
    255   static void _register(CHECKER *checker, CheckerManager &mgr) {
    256     mgr._registerForDeadSymbols(
    257      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
    258   }
    259 };
    260 
    261 class RegionChanges {
    262   template <typename CHECKER>
    263   static ProgramStateRef
    264   _checkRegionChanges(void *checker,
    265                       ProgramStateRef state,
    266                       const StoreManager::InvalidatedSymbols *invalidated,
    267                       ArrayRef<const MemRegion *> Explicits,
    268                       ArrayRef<const MemRegion *> Regions,
    269                       const CallOrObjCMessage *Call) {
    270     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
    271                                                       Explicits, Regions, Call);
    272   }
    273   template <typename CHECKER>
    274   static bool _wantsRegionChangeUpdate(void *checker,
    275                                        ProgramStateRef 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 ProgramStateRef _evalAssume(void *checker,
    311                                          ProgramStateRef 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, ProgramStateRef 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           typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck>
    376 class Checker;
    377 
    378 template <>
    379 class Checker<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, check::_VoidCheck, check::_VoidCheck,
    384                 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck>
    385   : public CheckerBase
    386 {
    387   virtual void anchor();
    388 public:
    389   static void _register(void *checker, CheckerManager &mgr) { }
    390 };
    391 
    392 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
    393           typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
    394           typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
    395           typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
    396           typename CHECK17,typename CHECK18>
    397 class Checker
    398     : public CHECK1,
    399       public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
    400                      CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
    401                      CHECK16,CHECK17,CHECK18> {
    402 public:
    403   template <typename CHECKER>
    404   static void _register(CHECKER *checker, CheckerManager &mgr) {
    405     CHECK1::_register(checker, mgr);
    406     Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
    407             CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15,
    408             CHECK16,CHECK17,CHECK18>::_register(checker, mgr);
    409   }
    410 };
    411 
    412 template <typename EVENT>
    413 class EventDispatcher {
    414   CheckerManager *Mgr;
    415 public:
    416   EventDispatcher() : Mgr(0) { }
    417 
    418   template <typename CHECKER>
    419   static void _register(CHECKER *checker, CheckerManager &mgr) {
    420     mgr._registerDispatcherForEvent<EVENT>();
    421     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
    422   }
    423 
    424   void dispatchEvent(const EVENT &event) const {
    425     Mgr->_dispatchEvent(event);
    426   }
    427 };
    428 
    429 /// \brief We dereferenced a location that may be null.
    430 struct ImplicitNullDerefEvent {
    431   SVal Location;
    432   bool IsLoad;
    433   ExplodedNode *SinkNode;
    434   BugReporter *BR;
    435 };
    436 
    437 } // end ento namespace
    438 
    439 } // end clang namespace
    440 
    441 #endif
    442