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(cast<DECL>(D), mgr, BR);
     38   }
     39 
     40   static bool _handlesDecl(const Decl *D) {
     41     return 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(cast<STMT>(S), C);
     90   }
     91 
     92   static bool _handlesStmt(const Stmt *S) {
     93     return 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(cast<STMT>(S), C);
    109   }
    110 
    111   static bool _handlesStmt(const Stmt *S) {
    112     return 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 ObjCMethodCall &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 ObjCMethodCall &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 PreCall {
    154   template <typename CHECKER>
    155   static void _checkCall(void *checker, const CallEvent &msg,
    156                          CheckerContext &C) {
    157     ((const CHECKER *)checker)->checkPreCall(msg, C);
    158   }
    159 
    160 public:
    161   template <typename CHECKER>
    162   static void _register(CHECKER *checker, CheckerManager &mgr) {
    163     mgr._registerForPreCall(
    164      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
    165   }
    166 };
    167 
    168 class PostCall {
    169   template <typename CHECKER>
    170   static void _checkCall(void *checker, const CallEvent &msg,
    171                          CheckerContext &C) {
    172     ((const CHECKER *)checker)->checkPostCall(msg, C);
    173   }
    174 
    175 public:
    176   template <typename CHECKER>
    177   static void _register(CHECKER *checker, CheckerManager &mgr) {
    178     mgr._registerForPostCall(
    179      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
    180   }
    181 };
    182 
    183 class Location {
    184   template <typename CHECKER>
    185   static void _checkLocation(void *checker,
    186                              const SVal &location, bool isLoad, const Stmt *S,
    187                              CheckerContext &C) {
    188     ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
    189   }
    190 
    191 public:
    192   template <typename CHECKER>
    193   static void _register(CHECKER *checker, CheckerManager &mgr) {
    194     mgr._registerForLocation(
    195            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
    196   }
    197 };
    198 
    199 class Bind {
    200   template <typename CHECKER>
    201   static void _checkBind(void *checker,
    202                          const SVal &location, const SVal &val, const Stmt *S,
    203                          CheckerContext &C) {
    204     ((const CHECKER *)checker)->checkBind(location, val, S, C);
    205   }
    206 
    207 public:
    208   template <typename CHECKER>
    209   static void _register(CHECKER *checker, CheckerManager &mgr) {
    210     mgr._registerForBind(
    211            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
    212   }
    213 };
    214 
    215 class EndAnalysis {
    216   template <typename CHECKER>
    217   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
    218                                 BugReporter &BR, ExprEngine &Eng) {
    219     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
    220   }
    221 
    222 public:
    223   template <typename CHECKER>
    224   static void _register(CHECKER *checker, CheckerManager &mgr) {
    225     mgr._registerForEndAnalysis(
    226      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
    227   }
    228 };
    229 
    230 class EndFunction {
    231   template <typename CHECKER>
    232   static void _checkEndFunction(void *checker,
    233                                 CheckerContext &C) {
    234     ((const CHECKER *)checker)->checkEndFunction(C);
    235   }
    236 
    237 public:
    238   template <typename CHECKER>
    239   static void _register(CHECKER *checker, CheckerManager &mgr) {
    240     mgr._registerForEndFunction(
    241      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
    242   }
    243 };
    244 
    245 class BranchCondition {
    246   template <typename CHECKER>
    247   static void _checkBranchCondition(void *checker, const Stmt *Condition,
    248                                     CheckerContext & C) {
    249     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
    250   }
    251 
    252 public:
    253   template <typename CHECKER>
    254   static void _register(CHECKER *checker, CheckerManager &mgr) {
    255     mgr._registerForBranchCondition(
    256       CheckerManager::CheckBranchConditionFunc(checker,
    257                                                _checkBranchCondition<CHECKER>));
    258   }
    259 };
    260 
    261 class LiveSymbols {
    262   template <typename CHECKER>
    263   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
    264                                 SymbolReaper &SR) {
    265     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
    266   }
    267 
    268 public:
    269   template <typename CHECKER>
    270   static void _register(CHECKER *checker, CheckerManager &mgr) {
    271     mgr._registerForLiveSymbols(
    272      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
    273   }
    274 };
    275 
    276 class DeadSymbols {
    277   template <typename CHECKER>
    278   static void _checkDeadSymbols(void *checker,
    279                                 SymbolReaper &SR, CheckerContext &C) {
    280     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
    281   }
    282 
    283 public:
    284   template <typename CHECKER>
    285   static void _register(CHECKER *checker, CheckerManager &mgr) {
    286     mgr._registerForDeadSymbols(
    287      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
    288   }
    289 };
    290 
    291 class RegionChanges {
    292   template <typename CHECKER>
    293   static ProgramStateRef
    294   _checkRegionChanges(void *checker,
    295                       ProgramStateRef state,
    296                       const InvalidatedSymbols *invalidated,
    297                       ArrayRef<const MemRegion *> Explicits,
    298                       ArrayRef<const MemRegion *> Regions,
    299                       const CallEvent *Call) {
    300     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
    301                                                       Explicits, Regions, Call);
    302   }
    303   template <typename CHECKER>
    304   static bool _wantsRegionChangeUpdate(void *checker,
    305                                        ProgramStateRef state) {
    306     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
    307   }
    308 
    309 public:
    310   template <typename CHECKER>
    311   static void _register(CHECKER *checker, CheckerManager &mgr) {
    312     mgr._registerForRegionChanges(
    313           CheckerManager::CheckRegionChangesFunc(checker,
    314                                                  _checkRegionChanges<CHECKER>),
    315           CheckerManager::WantsRegionChangeUpdateFunc(checker,
    316                                             _wantsRegionChangeUpdate<CHECKER>));
    317   }
    318 };
    319 
    320 class PointerEscape {
    321   template <typename CHECKER>
    322   static ProgramStateRef
    323   _checkPointerEscape(void *checker,
    324                      ProgramStateRef State,
    325                      const InvalidatedSymbols &Escaped,
    326                      const CallEvent *Call,
    327                      PointerEscapeKind Kind) {
    328     return ((const CHECKER *)checker)->checkPointerEscape(State,
    329                                                           Escaped,
    330                                                           Call,
    331                                                           Kind);
    332   }
    333 
    334 public:
    335   template <typename CHECKER>
    336   static void _register(CHECKER *checker, CheckerManager &mgr) {
    337     mgr._registerForPointerEscape(
    338           CheckerManager::CheckPointerEscapeFunc(checker,
    339                                                 _checkPointerEscape<CHECKER>));
    340   }
    341 };
    342 
    343 template <typename EVENT>
    344 class Event {
    345   template <typename CHECKER>
    346   static void _checkEvent(void *checker, const void *event) {
    347     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
    348   }
    349 public:
    350   template <typename CHECKER>
    351   static void _register(CHECKER *checker, CheckerManager &mgr) {
    352     mgr._registerListenerForEvent<EVENT>(
    353                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
    354   }
    355 };
    356 
    357 } // end check namespace
    358 
    359 namespace eval {
    360 
    361 class Assume {
    362   template <typename CHECKER>
    363   static ProgramStateRef _evalAssume(void *checker,
    364                                          ProgramStateRef state,
    365                                          const SVal &cond,
    366                                          bool assumption) {
    367     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
    368   }
    369 
    370 public:
    371   template <typename CHECKER>
    372   static void _register(CHECKER *checker, CheckerManager &mgr) {
    373     mgr._registerForEvalAssume(
    374                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
    375   }
    376 };
    377 
    378 class Call {
    379   template <typename CHECKER>
    380   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
    381     return ((const CHECKER *)checker)->evalCall(CE, C);
    382   }
    383 
    384 public:
    385   template <typename CHECKER>
    386   static void _register(CHECKER *checker, CheckerManager &mgr) {
    387     mgr._registerForEvalCall(
    388                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
    389   }
    390 };
    391 
    392 } // end eval namespace
    393 
    394 class CheckerBase : public ProgramPointTag {
    395 public:
    396   StringRef getTagDescription() const;
    397 
    398   /// See CheckerManager::runCheckersForPrintState.
    399   virtual void printState(raw_ostream &Out, ProgramStateRef State,
    400                           const char *NL, const char *Sep) const { }
    401 };
    402 
    403 template <typename CHECK1, typename CHECK2=check::_VoidCheck,
    404           typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
    405           typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
    406           typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
    407           typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
    408           typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck,
    409           typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck,
    410           typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck,
    411           typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck,
    412           typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck,
    413           typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck,
    414           typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck>
    415 class Checker;
    416 
    417 template <>
    418 class Checker<check::_VoidCheck>
    419   : public CheckerBase
    420 {
    421   virtual void anchor();
    422 public:
    423   static void _register(void *checker, CheckerManager &mgr) { }
    424 };
    425 
    426 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
    427           typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
    428           typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12,
    429           typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16,
    430           typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20,
    431           typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24>
    432 class Checker
    433     : public CHECK1,
    434       public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
    435                      CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
    436                      CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
    437                      CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> {
    438 public:
    439   template <typename CHECKER>
    440   static void _register(CHECKER *checker, CheckerManager &mgr) {
    441     CHECK1::_register(checker, mgr);
    442     Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7,
    443             CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,
    444             CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19,
    445             CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr);
    446   }
    447 };
    448 
    449 template <typename EVENT>
    450 class EventDispatcher {
    451   CheckerManager *Mgr;
    452 public:
    453   EventDispatcher() : Mgr(0) { }
    454 
    455   template <typename CHECKER>
    456   static void _register(CHECKER *checker, CheckerManager &mgr) {
    457     mgr._registerDispatcherForEvent<EVENT>();
    458     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
    459   }
    460 
    461   void dispatchEvent(const EVENT &event) const {
    462     Mgr->_dispatchEvent(event);
    463   }
    464 };
    465 
    466 /// \brief We dereferenced a location that may be null.
    467 struct ImplicitNullDerefEvent {
    468   SVal Location;
    469   bool IsLoad;
    470   ExplodedNode *SinkNode;
    471   BugReporter *BR;
    472 };
    473 
    474 /// \brief A helper class which wraps a boolean value set to false by default.
    475 struct DefaultBool {
    476   bool val;
    477   DefaultBool() : val(false) {}
    478   operator bool() const { return val; }
    479   DefaultBool &operator=(bool b) { val = b; return *this; }
    480 };
    481 
    482 } // end ento namespace
    483 
    484 } // end clang namespace
    485 
    486 #endif
    487