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 ObjCMessageNil {
    135   template <typename CHECKER>
    136   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
    137                                 CheckerContext &C) {
    138     ((const CHECKER *)checker)->checkObjCMessageNil(msg, C);
    139   }
    140 
    141 public:
    142   template <typename CHECKER>
    143   static void _register(CHECKER *checker, CheckerManager &mgr) {
    144     mgr._registerForObjCMessageNil(
    145      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
    146   }
    147 };
    148 
    149 class PostObjCMessage {
    150   template <typename CHECKER>
    151   static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg,
    152                                 CheckerContext &C) {
    153     ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
    154   }
    155 
    156 public:
    157   template <typename CHECKER>
    158   static void _register(CHECKER *checker, CheckerManager &mgr) {
    159     mgr._registerForPostObjCMessage(
    160      CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
    161   }
    162 };
    163 
    164 class PreCall {
    165   template <typename CHECKER>
    166   static void _checkCall(void *checker, const CallEvent &msg,
    167                          CheckerContext &C) {
    168     ((const CHECKER *)checker)->checkPreCall(msg, C);
    169   }
    170 
    171 public:
    172   template <typename CHECKER>
    173   static void _register(CHECKER *checker, CheckerManager &mgr) {
    174     mgr._registerForPreCall(
    175      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
    176   }
    177 };
    178 
    179 class PostCall {
    180   template <typename CHECKER>
    181   static void _checkCall(void *checker, const CallEvent &msg,
    182                          CheckerContext &C) {
    183     ((const CHECKER *)checker)->checkPostCall(msg, C);
    184   }
    185 
    186 public:
    187   template <typename CHECKER>
    188   static void _register(CHECKER *checker, CheckerManager &mgr) {
    189     mgr._registerForPostCall(
    190      CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>));
    191   }
    192 };
    193 
    194 class Location {
    195   template <typename CHECKER>
    196   static void _checkLocation(void *checker,
    197                              const SVal &location, bool isLoad, const Stmt *S,
    198                              CheckerContext &C) {
    199     ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C);
    200   }
    201 
    202 public:
    203   template <typename CHECKER>
    204   static void _register(CHECKER *checker, CheckerManager &mgr) {
    205     mgr._registerForLocation(
    206            CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
    207   }
    208 };
    209 
    210 class Bind {
    211   template <typename CHECKER>
    212   static void _checkBind(void *checker,
    213                          const SVal &location, const SVal &val, const Stmt *S,
    214                          CheckerContext &C) {
    215     ((const CHECKER *)checker)->checkBind(location, val, S, C);
    216   }
    217 
    218 public:
    219   template <typename CHECKER>
    220   static void _register(CHECKER *checker, CheckerManager &mgr) {
    221     mgr._registerForBind(
    222            CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
    223   }
    224 };
    225 
    226 class EndAnalysis {
    227   template <typename CHECKER>
    228   static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
    229                                 BugReporter &BR, ExprEngine &Eng) {
    230     ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
    231   }
    232 
    233 public:
    234   template <typename CHECKER>
    235   static void _register(CHECKER *checker, CheckerManager &mgr) {
    236     mgr._registerForEndAnalysis(
    237      CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
    238   }
    239 };
    240 
    241 class EndFunction {
    242   template <typename CHECKER>
    243   static void _checkEndFunction(void *checker,
    244                                 CheckerContext &C) {
    245     ((const CHECKER *)checker)->checkEndFunction(C);
    246   }
    247 
    248 public:
    249   template <typename CHECKER>
    250   static void _register(CHECKER *checker, CheckerManager &mgr) {
    251     mgr._registerForEndFunction(
    252      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
    253   }
    254 };
    255 
    256 class BranchCondition {
    257   template <typename CHECKER>
    258   static void _checkBranchCondition(void *checker, const Stmt *Condition,
    259                                     CheckerContext & C) {
    260     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
    261   }
    262 
    263 public:
    264   template <typename CHECKER>
    265   static void _register(CHECKER *checker, CheckerManager &mgr) {
    266     mgr._registerForBranchCondition(
    267       CheckerManager::CheckBranchConditionFunc(checker,
    268                                                _checkBranchCondition<CHECKER>));
    269   }
    270 };
    271 
    272 class LiveSymbols {
    273   template <typename CHECKER>
    274   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
    275                                 SymbolReaper &SR) {
    276     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
    277   }
    278 
    279 public:
    280   template <typename CHECKER>
    281   static void _register(CHECKER *checker, CheckerManager &mgr) {
    282     mgr._registerForLiveSymbols(
    283      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
    284   }
    285 };
    286 
    287 class DeadSymbols {
    288   template <typename CHECKER>
    289   static void _checkDeadSymbols(void *checker,
    290                                 SymbolReaper &SR, CheckerContext &C) {
    291     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
    292   }
    293 
    294 public:
    295   template <typename CHECKER>
    296   static void _register(CHECKER *checker, CheckerManager &mgr) {
    297     mgr._registerForDeadSymbols(
    298      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
    299   }
    300 };
    301 
    302 class RegionChanges {
    303   template <typename CHECKER>
    304   static ProgramStateRef
    305   _checkRegionChanges(void *checker,
    306                       ProgramStateRef state,
    307                       const InvalidatedSymbols *invalidated,
    308                       ArrayRef<const MemRegion *> Explicits,
    309                       ArrayRef<const MemRegion *> Regions,
    310                       const CallEvent *Call) {
    311     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
    312                                                       Explicits, Regions, Call);
    313   }
    314   template <typename CHECKER>
    315   static bool _wantsRegionChangeUpdate(void *checker,
    316                                        ProgramStateRef state) {
    317     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
    318   }
    319 
    320 public:
    321   template <typename CHECKER>
    322   static void _register(CHECKER *checker, CheckerManager &mgr) {
    323     mgr._registerForRegionChanges(
    324           CheckerManager::CheckRegionChangesFunc(checker,
    325                                                  _checkRegionChanges<CHECKER>),
    326           CheckerManager::WantsRegionChangeUpdateFunc(checker,
    327                                             _wantsRegionChangeUpdate<CHECKER>));
    328   }
    329 };
    330 
    331 class PointerEscape {
    332   template <typename CHECKER>
    333   static ProgramStateRef
    334   _checkPointerEscape(void *Checker,
    335                      ProgramStateRef State,
    336                      const InvalidatedSymbols &Escaped,
    337                      const CallEvent *Call,
    338                      PointerEscapeKind Kind,
    339                      RegionAndSymbolInvalidationTraits *ETraits) {
    340 
    341     if (!ETraits)
    342       return ((const CHECKER *)Checker)->checkPointerEscape(State,
    343                                                             Escaped,
    344                                                             Call,
    345                                                             Kind);
    346 
    347     InvalidatedSymbols RegularEscape;
    348     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    349                                             E = Escaped.end(); I != E; ++I)
    350       if (!ETraits->hasTrait(*I,
    351               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    352           !ETraits->hasTrait(*I,
    353               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    354         RegularEscape.insert(*I);
    355 
    356     if (RegularEscape.empty())
    357       return State;
    358 
    359     return ((const CHECKER *)Checker)->checkPointerEscape(State,
    360                                                           RegularEscape,
    361                                                           Call,
    362                                                           Kind);
    363   }
    364 
    365 public:
    366   template <typename CHECKER>
    367   static void _register(CHECKER *checker, CheckerManager &mgr) {
    368     mgr._registerForPointerEscape(
    369           CheckerManager::CheckPointerEscapeFunc(checker,
    370                                                 _checkPointerEscape<CHECKER>));
    371   }
    372 };
    373 
    374 class ConstPointerEscape {
    375   template <typename CHECKER>
    376   static ProgramStateRef
    377   _checkConstPointerEscape(void *Checker,
    378                       ProgramStateRef State,
    379                       const InvalidatedSymbols &Escaped,
    380                       const CallEvent *Call,
    381                       PointerEscapeKind Kind,
    382                       RegionAndSymbolInvalidationTraits *ETraits) {
    383 
    384     if (!ETraits)
    385       return State;
    386 
    387     InvalidatedSymbols ConstEscape;
    388     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    389                                             E = Escaped.end(); I != E; ++I)
    390       if (ETraits->hasTrait(*I,
    391               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    392           !ETraits->hasTrait(*I,
    393               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    394         ConstEscape.insert(*I);
    395 
    396     if (ConstEscape.empty())
    397       return State;
    398 
    399     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
    400                                                                ConstEscape,
    401                                                                Call,
    402                                                                Kind);
    403   }
    404 
    405 public:
    406   template <typename CHECKER>
    407   static void _register(CHECKER *checker, CheckerManager &mgr) {
    408     mgr._registerForPointerEscape(
    409       CheckerManager::CheckPointerEscapeFunc(checker,
    410                                             _checkConstPointerEscape<CHECKER>));
    411   }
    412 };
    413 
    414 
    415 template <typename EVENT>
    416 class Event {
    417   template <typename CHECKER>
    418   static void _checkEvent(void *checker, const void *event) {
    419     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
    420   }
    421 public:
    422   template <typename CHECKER>
    423   static void _register(CHECKER *checker, CheckerManager &mgr) {
    424     mgr._registerListenerForEvent<EVENT>(
    425                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
    426   }
    427 };
    428 
    429 } // end check namespace
    430 
    431 namespace eval {
    432 
    433 class Assume {
    434   template <typename CHECKER>
    435   static ProgramStateRef _evalAssume(void *checker,
    436                                          ProgramStateRef state,
    437                                          const SVal &cond,
    438                                          bool assumption) {
    439     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
    440   }
    441 
    442 public:
    443   template <typename CHECKER>
    444   static void _register(CHECKER *checker, CheckerManager &mgr) {
    445     mgr._registerForEvalAssume(
    446                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
    447   }
    448 };
    449 
    450 class Call {
    451   template <typename CHECKER>
    452   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
    453     return ((const CHECKER *)checker)->evalCall(CE, C);
    454   }
    455 
    456 public:
    457   template <typename CHECKER>
    458   static void _register(CHECKER *checker, CheckerManager &mgr) {
    459     mgr._registerForEvalCall(
    460                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
    461   }
    462 };
    463 
    464 } // end eval namespace
    465 
    466 class CheckerBase : public ProgramPointTag {
    467   CheckName Name;
    468   friend class ::clang::ento::CheckerManager;
    469 
    470 public:
    471   StringRef getTagDescription() const override;
    472   CheckName getCheckName() const;
    473 
    474   /// See CheckerManager::runCheckersForPrintState.
    475   virtual void printState(raw_ostream &Out, ProgramStateRef State,
    476                           const char *NL, const char *Sep) const { }
    477 };
    478 
    479 /// Dump checker name to stream.
    480 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
    481 
    482 /// Tag that can use a checker name as a message provider
    483 /// (see SimpleProgramPointTag).
    484 class CheckerProgramPointTag : public SimpleProgramPointTag {
    485 public:
    486   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
    487   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
    488 };
    489 
    490 template <typename CHECK1, typename... CHECKs>
    491 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
    492 public:
    493   template <typename CHECKER>
    494   static void _register(CHECKER *checker, CheckerManager &mgr) {
    495     CHECK1::_register(checker, mgr);
    496     Checker<CHECKs...>::_register(checker, mgr);
    497   }
    498 };
    499 
    500 template <typename CHECK1>
    501 class Checker<CHECK1> : public CHECK1, public CheckerBase {
    502 public:
    503   template <typename CHECKER>
    504   static void _register(CHECKER *checker, CheckerManager &mgr) {
    505     CHECK1::_register(checker, mgr);
    506   }
    507 };
    508 
    509 template <typename EVENT>
    510 class EventDispatcher {
    511   CheckerManager *Mgr;
    512 public:
    513   EventDispatcher() : Mgr(nullptr) { }
    514 
    515   template <typename CHECKER>
    516   static void _register(CHECKER *checker, CheckerManager &mgr) {
    517     mgr._registerDispatcherForEvent<EVENT>();
    518     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
    519   }
    520 
    521   void dispatchEvent(const EVENT &event) const {
    522     Mgr->_dispatchEvent(event);
    523   }
    524 };
    525 
    526 /// \brief We dereferenced a location that may be null.
    527 struct ImplicitNullDerefEvent {
    528   SVal Location;
    529   bool IsLoad;
    530   ExplodedNode *SinkNode;
    531   BugReporter *BR;
    532   // When true, the dereference is in the source code directly. When false, the
    533   // dereference might happen later (for example pointer passed to a parameter
    534   // that is marked with nonnull attribute.)
    535   bool IsDirectDereference;
    536 };
    537 
    538 /// \brief A helper class which wraps a boolean value set to false by default.
    539 ///
    540 /// This class should behave exactly like 'bool' except that it doesn't need to
    541 /// be explicitly initialized.
    542 struct DefaultBool {
    543   bool val;
    544   DefaultBool() : val(false) {}
    545   /*implicit*/ operator bool&() { return val; }
    546   /*implicit*/ operator const bool&() const { return val; }
    547   DefaultBool &operator=(bool b) { val = b; return *this; }
    548 };
    549 
    550 } // end ento namespace
    551 
    552 } // end clang namespace
    553 
    554 #endif
    555