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 BeginFunction {
    242   template <typename CHECKER>
    243   static void _checkBeginFunction(void *checker, CheckerContext &C) {
    244     ((const CHECKER *)checker)->checkBeginFunction(C);
    245   }
    246 
    247 public:
    248   template <typename CHECKER>
    249   static void _register(CHECKER *checker, CheckerManager &mgr) {
    250     mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc(
    251         checker, _checkBeginFunction<CHECKER>));
    252   }
    253 };
    254 
    255 class EndFunction {
    256   template <typename CHECKER>
    257   static void _checkEndFunction(void *checker,
    258                                 CheckerContext &C) {
    259     ((const CHECKER *)checker)->checkEndFunction(C);
    260   }
    261 
    262 public:
    263   template <typename CHECKER>
    264   static void _register(CHECKER *checker, CheckerManager &mgr) {
    265     mgr._registerForEndFunction(
    266      CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>));
    267   }
    268 };
    269 
    270 class BranchCondition {
    271   template <typename CHECKER>
    272   static void _checkBranchCondition(void *checker, const Stmt *Condition,
    273                                     CheckerContext & C) {
    274     ((const CHECKER *)checker)->checkBranchCondition(Condition, C);
    275   }
    276 
    277 public:
    278   template <typename CHECKER>
    279   static void _register(CHECKER *checker, CheckerManager &mgr) {
    280     mgr._registerForBranchCondition(
    281       CheckerManager::CheckBranchConditionFunc(checker,
    282                                                _checkBranchCondition<CHECKER>));
    283   }
    284 };
    285 
    286 class LiveSymbols {
    287   template <typename CHECKER>
    288   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
    289                                 SymbolReaper &SR) {
    290     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
    291   }
    292 
    293 public:
    294   template <typename CHECKER>
    295   static void _register(CHECKER *checker, CheckerManager &mgr) {
    296     mgr._registerForLiveSymbols(
    297      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
    298   }
    299 };
    300 
    301 class DeadSymbols {
    302   template <typename CHECKER>
    303   static void _checkDeadSymbols(void *checker,
    304                                 SymbolReaper &SR, CheckerContext &C) {
    305     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
    306   }
    307 
    308 public:
    309   template <typename CHECKER>
    310   static void _register(CHECKER *checker, CheckerManager &mgr) {
    311     mgr._registerForDeadSymbols(
    312      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
    313   }
    314 };
    315 
    316 class RegionChanges {
    317   template <typename CHECKER>
    318   static ProgramStateRef
    319   _checkRegionChanges(void *checker,
    320                       ProgramStateRef state,
    321                       const InvalidatedSymbols *invalidated,
    322                       ArrayRef<const MemRegion *> Explicits,
    323                       ArrayRef<const MemRegion *> Regions,
    324                       const CallEvent *Call) {
    325     return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
    326                                                       Explicits, Regions, Call);
    327   }
    328   template <typename CHECKER>
    329   static bool _wantsRegionChangeUpdate(void *checker,
    330                                        ProgramStateRef state) {
    331     return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
    332   }
    333 
    334 public:
    335   template <typename CHECKER>
    336   static void _register(CHECKER *checker, CheckerManager &mgr) {
    337     mgr._registerForRegionChanges(
    338           CheckerManager::CheckRegionChangesFunc(checker,
    339                                                  _checkRegionChanges<CHECKER>),
    340           CheckerManager::WantsRegionChangeUpdateFunc(checker,
    341                                             _wantsRegionChangeUpdate<CHECKER>));
    342   }
    343 };
    344 
    345 class PointerEscape {
    346   template <typename CHECKER>
    347   static ProgramStateRef
    348   _checkPointerEscape(void *Checker,
    349                      ProgramStateRef State,
    350                      const InvalidatedSymbols &Escaped,
    351                      const CallEvent *Call,
    352                      PointerEscapeKind Kind,
    353                      RegionAndSymbolInvalidationTraits *ETraits) {
    354 
    355     if (!ETraits)
    356       return ((const CHECKER *)Checker)->checkPointerEscape(State,
    357                                                             Escaped,
    358                                                             Call,
    359                                                             Kind);
    360 
    361     InvalidatedSymbols RegularEscape;
    362     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    363                                             E = Escaped.end(); I != E; ++I)
    364       if (!ETraits->hasTrait(*I,
    365               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    366           !ETraits->hasTrait(*I,
    367               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    368         RegularEscape.insert(*I);
    369 
    370     if (RegularEscape.empty())
    371       return State;
    372 
    373     return ((const CHECKER *)Checker)->checkPointerEscape(State,
    374                                                           RegularEscape,
    375                                                           Call,
    376                                                           Kind);
    377   }
    378 
    379 public:
    380   template <typename CHECKER>
    381   static void _register(CHECKER *checker, CheckerManager &mgr) {
    382     mgr._registerForPointerEscape(
    383           CheckerManager::CheckPointerEscapeFunc(checker,
    384                                                 _checkPointerEscape<CHECKER>));
    385   }
    386 };
    387 
    388 class ConstPointerEscape {
    389   template <typename CHECKER>
    390   static ProgramStateRef
    391   _checkConstPointerEscape(void *Checker,
    392                       ProgramStateRef State,
    393                       const InvalidatedSymbols &Escaped,
    394                       const CallEvent *Call,
    395                       PointerEscapeKind Kind,
    396                       RegionAndSymbolInvalidationTraits *ETraits) {
    397 
    398     if (!ETraits)
    399       return State;
    400 
    401     InvalidatedSymbols ConstEscape;
    402     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    403                                             E = Escaped.end(); I != E; ++I)
    404       if (ETraits->hasTrait(*I,
    405               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    406           !ETraits->hasTrait(*I,
    407               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    408         ConstEscape.insert(*I);
    409 
    410     if (ConstEscape.empty())
    411       return State;
    412 
    413     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
    414                                                                ConstEscape,
    415                                                                Call,
    416                                                                Kind);
    417   }
    418 
    419 public:
    420   template <typename CHECKER>
    421   static void _register(CHECKER *checker, CheckerManager &mgr) {
    422     mgr._registerForPointerEscape(
    423       CheckerManager::CheckPointerEscapeFunc(checker,
    424                                             _checkConstPointerEscape<CHECKER>));
    425   }
    426 };
    427 
    428 
    429 template <typename EVENT>
    430 class Event {
    431   template <typename CHECKER>
    432   static void _checkEvent(void *checker, const void *event) {
    433     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
    434   }
    435 public:
    436   template <typename CHECKER>
    437   static void _register(CHECKER *checker, CheckerManager &mgr) {
    438     mgr._registerListenerForEvent<EVENT>(
    439                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
    440   }
    441 };
    442 
    443 } // end check namespace
    444 
    445 namespace eval {
    446 
    447 class Assume {
    448   template <typename CHECKER>
    449   static ProgramStateRef _evalAssume(void *checker,
    450                                          ProgramStateRef state,
    451                                          const SVal &cond,
    452                                          bool assumption) {
    453     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
    454   }
    455 
    456 public:
    457   template <typename CHECKER>
    458   static void _register(CHECKER *checker, CheckerManager &mgr) {
    459     mgr._registerForEvalAssume(
    460                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
    461   }
    462 };
    463 
    464 class Call {
    465   template <typename CHECKER>
    466   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
    467     return ((const CHECKER *)checker)->evalCall(CE, C);
    468   }
    469 
    470 public:
    471   template <typename CHECKER>
    472   static void _register(CHECKER *checker, CheckerManager &mgr) {
    473     mgr._registerForEvalCall(
    474                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
    475   }
    476 };
    477 
    478 } // end eval namespace
    479 
    480 class CheckerBase : public ProgramPointTag {
    481   CheckName Name;
    482   friend class ::clang::ento::CheckerManager;
    483 
    484 public:
    485   StringRef getTagDescription() const override;
    486   CheckName getCheckName() const;
    487 
    488   /// See CheckerManager::runCheckersForPrintState.
    489   virtual void printState(raw_ostream &Out, ProgramStateRef State,
    490                           const char *NL, const char *Sep) const { }
    491 };
    492 
    493 /// Dump checker name to stream.
    494 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
    495 
    496 /// Tag that can use a checker name as a message provider
    497 /// (see SimpleProgramPointTag).
    498 class CheckerProgramPointTag : public SimpleProgramPointTag {
    499 public:
    500   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
    501   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
    502 };
    503 
    504 template <typename CHECK1, typename... CHECKs>
    505 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
    506 public:
    507   template <typename CHECKER>
    508   static void _register(CHECKER *checker, CheckerManager &mgr) {
    509     CHECK1::_register(checker, mgr);
    510     Checker<CHECKs...>::_register(checker, mgr);
    511   }
    512 };
    513 
    514 template <typename CHECK1>
    515 class Checker<CHECK1> : public CHECK1, public CheckerBase {
    516 public:
    517   template <typename CHECKER>
    518   static void _register(CHECKER *checker, CheckerManager &mgr) {
    519     CHECK1::_register(checker, mgr);
    520   }
    521 };
    522 
    523 template <typename EVENT>
    524 class EventDispatcher {
    525   CheckerManager *Mgr;
    526 public:
    527   EventDispatcher() : Mgr(nullptr) { }
    528 
    529   template <typename CHECKER>
    530   static void _register(CHECKER *checker, CheckerManager &mgr) {
    531     mgr._registerDispatcherForEvent<EVENT>();
    532     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
    533   }
    534 
    535   void dispatchEvent(const EVENT &event) const {
    536     Mgr->_dispatchEvent(event);
    537   }
    538 };
    539 
    540 /// \brief We dereferenced a location that may be null.
    541 struct ImplicitNullDerefEvent {
    542   SVal Location;
    543   bool IsLoad;
    544   ExplodedNode *SinkNode;
    545   BugReporter *BR;
    546   // When true, the dereference is in the source code directly. When false, the
    547   // dereference might happen later (for example pointer passed to a parameter
    548   // that is marked with nonnull attribute.)
    549   bool IsDirectDereference;
    550 };
    551 
    552 /// \brief A helper class which wraps a boolean value set to false by default.
    553 ///
    554 /// This class should behave exactly like 'bool' except that it doesn't need to
    555 /// be explicitly initialized.
    556 struct DefaultBool {
    557   bool val;
    558   DefaultBool() : val(false) {}
    559   /*implicit*/ operator bool&() { return val; }
    560   /*implicit*/ operator const bool&() const { return val; }
    561   DefaultBool &operator=(bool b) { val = b; return *this; }
    562 };
    563 
    564 } // end ento namespace
    565 
    566 } // end clang namespace
    567 
    568 #endif
    569