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_STATICANALYZER_CORE_CHECKER_H
     15 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
     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 template <typename DECL>
     29 class ASTDecl {
     30   template <typename CHECKER>
     31   static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
     32                          BugReporter &BR) {
     33     ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR);
     34   }
     35 
     36   static bool _handlesDecl(const Decl *D) {
     37     return isa<DECL>(D);
     38   }
     39 public:
     40   template <typename CHECKER>
     41   static void _register(CHECKER *checker, CheckerManager &mgr) {
     42     mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
     43                                                        _checkDecl<CHECKER>),
     44                          _handlesDecl);
     45   }
     46 };
     47 
     48 class ASTCodeBody {
     49   template <typename CHECKER>
     50   static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
     51                          BugReporter &BR) {
     52     ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
     53   }
     54 
     55 public:
     56   template <typename CHECKER>
     57   static void _register(CHECKER *checker, CheckerManager &mgr) {
     58     mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
     59                                                        _checkBody<CHECKER>));
     60   }
     61 };
     62 
     63 class EndOfTranslationUnit {
     64   template <typename CHECKER>
     65   static void _checkEndOfTranslationUnit(void *checker,
     66                                          const TranslationUnitDecl *TU,
     67                                          AnalysisManager& mgr,
     68                                          BugReporter &BR) {
     69     ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
     70   }
     71 
     72 public:
     73   template <typename CHECKER>
     74   static void _register(CHECKER *checker, CheckerManager &mgr){
     75     mgr._registerForEndOfTranslationUnit(
     76                               CheckerManager::CheckEndOfTranslationUnit(checker,
     77                                           _checkEndOfTranslationUnit<CHECKER>));
     78   }
     79 };
     80 
     81 template <typename STMT>
     82 class PreStmt {
     83   template <typename CHECKER>
     84   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
     85     ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C);
     86   }
     87 
     88   static bool _handlesStmt(const Stmt *S) {
     89     return isa<STMT>(S);
     90   }
     91 public:
     92   template <typename CHECKER>
     93   static void _register(CHECKER *checker, CheckerManager &mgr) {
     94     mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
     95                                                           _checkStmt<CHECKER>),
     96                             _handlesStmt);
     97   }
     98 };
     99 
    100 template <typename STMT>
    101 class PostStmt {
    102   template <typename CHECKER>
    103   static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
    104     ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C);
    105   }
    106 
    107   static bool _handlesStmt(const Stmt *S) {
    108     return isa<STMT>(S);
    109   }
    110 public:
    111   template <typename CHECKER>
    112   static void _register(CHECKER *checker, CheckerManager &mgr) {
    113     mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
    114                                                            _checkStmt<CHECKER>),
    115                              _handlesStmt);
    116   }
    117 };
    118 
    119 class PreObjCMessage {
    120   template <typename CHECKER>
    121   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
    122                                 CheckerContext &C) {
    123     ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
    124   }
    125 
    126 public:
    127   template <typename CHECKER>
    128   static void _register(CHECKER *checker, CheckerManager &mgr) {
    129     mgr._registerForPreObjCMessage(
    130      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
    131   }
    132 };
    133 
    134 class PostObjCMessage {
    135   template <typename CHECKER>
    136   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
    137                                 CheckerContext &C) {
    138     ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
    139   }
    140 
    141 public:
    142   template <typename CHECKER>
    143   static void _register(CHECKER *checker, CheckerManager &mgr) {
    144     mgr._registerForPostObjCMessage(
    145      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
    146   }
    147 };
    148 
    149 class PreCall {
    150   template <typename CHECKER>
    151   static void _checkCall(void *checker, const CallEvent &msg,
    152                          CheckerContext &C) {
    153     ((const CHECKER *)checker)->checkPreCall(msg, C);
    154   }
    155 
    156 public:
    157   template <typename CHECKER>
    158   static void _register(CHECKER *checker, CheckerManager &mgr) {
    159     mgr._registerForPreCall(
    160      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
    161   }
    162 };
    163 
    164 class PostCall {
    165   template <typename CHECKER>
    166   static void _checkCall(void *checker, const CallEvent &msg,
    167                          CheckerContext &C) {
    168     ((const CHECKER *)checker)->checkPostCall(msg, C);
    169   }
    170 
    171 public:
    172   template <typename CHECKER>
    173   static void _register(CHECKER *checker, CheckerManager &mgr) {
    174     mgr._registerForPostCall(
    175      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
    176   }
    177 };
    178 
    179 class Location {
    180   template <typename CHECKER>
    181   static void _checkLocation(void *checker,
    182                              const SVal &location, bool isLoad, const Stmt *S,
    183                              CheckerContext &C) {
    184     ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
    185   }
    186 
    187 public:
    188   template <typename CHECKER>
    189   static void _register(CHECKER *checker, CheckerManager &mgr) {
    190     mgr._registerForLocation(
    191            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
    192   }
    193 };
    194 
    195 class Bind {
    196   template <typename CHECKER>
    197   static void _checkBind(void *checker,
    198                          const SVal &location, const SVal &val, const Stmt *S,
    199                          CheckerContext &C) {
    200     ((const CHECKER *)checker)->checkBind(location, val, S, C);
    201   }
    202 
    203 public:
    204   template <typename CHECKER>
    205   static void _register(CHECKER *checker, CheckerManager &mgr) {
    206     mgr._registerForBind(
    207            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
    208   }
    209 };
    210 
    211 class EndAnalysis {
    212   template <typename CHECKER>
    213   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
    214                                 BugReporter &BR, ExprEngine &Eng) {
    215     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
    216   }
    217 
    218 public:
    219   template <typename CHECKER>
    220   static void _register(CHECKER *checker, CheckerManager &mgr) {
    221     mgr._registerForEndAnalysis(
    222      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
    223   }
    224 };
    225 
    226 class EndFunction {
    227   template <typename CHECKER>
    228   static void _checkEndFunction(void *checker,
    229                                 CheckerContext &C) {
    230     ((const CHECKER *)checker)->checkEndFunction(C);
    231   }
    232 
    233 public:
    234   template <typename CHECKER>
    235   static void _register(CHECKER *checker, CheckerManager &mgr) {
    236     mgr._registerForEndFunction(
    237      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
    238   }
    239 };
    240 
    241 class BranchCondition {
    242   template <typename CHECKER>
    243   static void _checkBranchCondition(void *checker, const Stmt *Condition,
    244                                     CheckerContext & C) {
    245     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
    246   }
    247 
    248 public:
    249   template <typename CHECKER>
    250   static void _register(CHECKER *checker, CheckerManager &mgr) {
    251     mgr._registerForBranchCondition(
    252       CheckerManager::CheckBranchConditionFunc(checker,
    253                                                _checkBranchCondition<CHECKER>));
    254   }
    255 };
    256 
    257 class LiveSymbols {
    258   template <typename CHECKER>
    259   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
    260                                 SymbolReaper &SR) {
    261     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
    262   }
    263 
    264 public:
    265   template <typename CHECKER>
    266   static void _register(CHECKER *checker, CheckerManager &mgr) {
    267     mgr._registerForLiveSymbols(
    268      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
    269   }
    270 };
    271 
    272 class DeadSymbols {
    273   template <typename CHECKER>
    274   static void _checkDeadSymbols(void *checker,
    275                                 SymbolReaper &SR, CheckerContext &C) {
    276     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
    277   }
    278 
    279 public:
    280   template <typename CHECKER>
    281   static void _register(CHECKER *checker, CheckerManager &mgr) {
    282     mgr._registerForDeadSymbols(
    283      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
    284   }
    285 };
    286 
    287 class RegionChanges {
    288   template <typename CHECKER>
    289   static ProgramStateRef
    290   _checkRegionChanges(void *checker,
    291                       ProgramStateRef state,
    292                       const InvalidatedSymbols *invalidated,
    293                       ArrayRef<const MemRegion *> Explicits,
    294                       ArrayRef<const MemRegion *> Regions,
    295                       const CallEvent *Call) {
    296     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
    297                                                       Explicits, Regions, Call);
    298   }
    299   template <typename CHECKER>
    300   static bool _wantsRegionChangeUpdate(void *checker,
    301                                        ProgramStateRef state) {
    302     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
    303   }
    304 
    305 public:
    306   template <typename CHECKER>
    307   static void _register(CHECKER *checker, CheckerManager &mgr) {
    308     mgr._registerForRegionChanges(
    309           CheckerManager::CheckRegionChangesFunc(checker,
    310                                                  _checkRegionChanges<CHECKER>),
    311           CheckerManager::WantsRegionChangeUpdateFunc(checker,
    312                                             _wantsRegionChangeUpdate<CHECKER>));
    313   }
    314 };
    315 
    316 class PointerEscape {
    317   template <typename CHECKER>
    318   static ProgramStateRef
    319   _checkPointerEscape(void *Checker,
    320                      ProgramStateRef State,
    321                      const InvalidatedSymbols &Escaped,
    322                      const CallEvent *Call,
    323                      PointerEscapeKind Kind,
    324                      RegionAndSymbolInvalidationTraits *ETraits) {
    325 
    326     if (!ETraits)
    327       return ((const CHECKER *)Checker)->checkPointerEscape(State,
    328                                                             Escaped,
    329                                                             Call,
    330                                                             Kind);
    331 
    332     InvalidatedSymbols RegularEscape;
    333     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    334                                             E = Escaped.end(); I != E; ++I)
    335       if (!ETraits->hasTrait(*I,
    336               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    337           !ETraits->hasTrait(*I,
    338               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    339         RegularEscape.insert(*I);
    340 
    341     if (RegularEscape.empty())
    342       return State;
    343 
    344     return ((const CHECKER *)Checker)->checkPointerEscape(State,
    345                                                           RegularEscape,
    346                                                           Call,
    347                                                           Kind);
    348   }
    349 
    350 public:
    351   template <typename CHECKER>
    352   static void _register(CHECKER *checker, CheckerManager &mgr) {
    353     mgr._registerForPointerEscape(
    354           CheckerManager::CheckPointerEscapeFunc(checker,
    355                                                 _checkPointerEscape<CHECKER>));
    356   }
    357 };
    358 
    359 class ConstPointerEscape {
    360   template <typename CHECKER>
    361   static ProgramStateRef
    362   _checkConstPointerEscape(void *Checker,
    363                       ProgramStateRef State,
    364                       const InvalidatedSymbols &Escaped,
    365                       const CallEvent *Call,
    366                       PointerEscapeKind Kind,
    367                       RegionAndSymbolInvalidationTraits *ETraits) {
    368 
    369     if (!ETraits)
    370       return State;
    371 
    372     InvalidatedSymbols ConstEscape;
    373     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    374                                             E = Escaped.end(); I != E; ++I)
    375       if (ETraits->hasTrait(*I,
    376               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    377           !ETraits->hasTrait(*I,
    378               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    379         ConstEscape.insert(*I);
    380 
    381     if (ConstEscape.empty())
    382       return State;
    383 
    384     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
    385                                                                ConstEscape,
    386                                                                Call,
    387                                                                Kind);
    388   }
    389 
    390 public:
    391   template <typename CHECKER>
    392   static void _register(CHECKER *checker, CheckerManager &mgr) {
    393     mgr._registerForPointerEscape(
    394       CheckerManager::CheckPointerEscapeFunc(checker,
    395                                             _checkConstPointerEscape<CHECKER>));
    396   }
    397 };
    398 
    399 
    400 template <typename EVENT>
    401 class Event {
    402   template <typename CHECKER>
    403   static void _checkEvent(void *checker, const void *event) {
    404     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
    405   }
    406 public:
    407   template <typename CHECKER>
    408   static void _register(CHECKER *checker, CheckerManager &mgr) {
    409     mgr._registerListenerForEvent<EVENT>(
    410                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
    411   }
    412 };
    413 
    414 } // end check namespace
    415 
    416 namespace eval {
    417 
    418 class Assume {
    419   template <typename CHECKER>
    420   static ProgramStateRef _evalAssume(void *checker,
    421                                          ProgramStateRef state,
    422                                          const SVal &cond,
    423                                          bool assumption) {
    424     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
    425   }
    426 
    427 public:
    428   template <typename CHECKER>
    429   static void _register(CHECKER *checker, CheckerManager &mgr) {
    430     mgr._registerForEvalAssume(
    431                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
    432   }
    433 };
    434 
    435 class Call {
    436   template <typename CHECKER>
    437   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
    438     return ((const CHECKER *)checker)->evalCall(CE, C);
    439   }
    440 
    441 public:
    442   template <typename CHECKER>
    443   static void _register(CHECKER *checker, CheckerManager &mgr) {
    444     mgr._registerForEvalCall(
    445                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
    446   }
    447 };
    448 
    449 } // end eval namespace
    450 
    451 class CheckerBase : public ProgramPointTag {
    452   CheckName Name;
    453   friend class ::clang::ento::CheckerManager;
    454 
    455 public:
    456   StringRef getTagDescription() const override;
    457   CheckName getCheckName() const;
    458 
    459   /// See CheckerManager::runCheckersForPrintState.
    460   virtual void printState(raw_ostream &Out, ProgramStateRef State,
    461                           const char *NL, const char *Sep) const { }
    462 };
    463 
    464 /// Dump checker name to stream.
    465 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
    466 
    467 /// Tag that can use a checker name as a message provider
    468 /// (see SimpleProgramPointTag).
    469 class CheckerProgramPointTag : public SimpleProgramPointTag {
    470 public:
    471   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
    472   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
    473 };
    474 
    475 template <typename CHECK1, typename... CHECKs>
    476 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
    477 public:
    478   template <typename CHECKER>
    479   static void _register(CHECKER *checker, CheckerManager &mgr) {
    480     CHECK1::_register(checker, mgr);
    481     Checker<CHECKs...>::_register(checker, mgr);
    482   }
    483 };
    484 
    485 template <typename CHECK1>
    486 class Checker<CHECK1> : public CHECK1, public CheckerBase {
    487 public:
    488   template <typename CHECKER>
    489   static void _register(CHECKER *checker, CheckerManager &mgr) {
    490     CHECK1::_register(checker, mgr);
    491   }
    492 };
    493 
    494 template <typename EVENT>
    495 class EventDispatcher {
    496   CheckerManager *Mgr;
    497 public:
    498   EventDispatcher() : Mgr(nullptr) { }
    499 
    500   template <typename CHECKER>
    501   static void _register(CHECKER *checker, CheckerManager &mgr) {
    502     mgr._registerDispatcherForEvent<EVENT>();
    503     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
    504   }
    505 
    506   void dispatchEvent(const EVENT &event) const {
    507     Mgr->_dispatchEvent(event);
    508   }
    509 };
    510 
    511 /// \brief We dereferenced a location that may be null.
    512 struct ImplicitNullDerefEvent {
    513   SVal Location;
    514   bool IsLoad;
    515   ExplodedNode *SinkNode;
    516   BugReporter *BR;
    517 };
    518 
    519 /// \brief A helper class which wraps a boolean value set to false by default.
    520 ///
    521 /// This class should behave exactly like 'bool' except that it doesn't need to
    522 /// be explicitly initialized.
    523 struct DefaultBool {
    524   bool val;
    525   DefaultBool() : val(false) {}
    526   /*implicit*/ operator bool&() { return val; }
    527   /*implicit*/ operator const bool&() const { return val; }
    528   DefaultBool &operator=(bool b) { val = b; return *this; }
    529 };
    530 
    531 } // end ento namespace
    532 
    533 } // end clang namespace
    534 
    535 #endif
    536