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 LocationContext *LCtx,
    325                       const CallEvent *Call) {
    326     return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
    327                                                            Explicits, Regions,
    328                                                            LCtx, Call);
    329   }
    330 
    331 public:
    332   template <typename CHECKER>
    333   static void _register(CHECKER *checker, CheckerManager &mgr) {
    334     mgr._registerForRegionChanges(
    335           CheckerManager::CheckRegionChangesFunc(checker,
    336                                                  _checkRegionChanges<CHECKER>));
    337   }
    338 };
    339 
    340 class PointerEscape {
    341   template <typename CHECKER>
    342   static ProgramStateRef
    343   _checkPointerEscape(void *Checker,
    344                      ProgramStateRef State,
    345                      const InvalidatedSymbols &Escaped,
    346                      const CallEvent *Call,
    347                      PointerEscapeKind Kind,
    348                      RegionAndSymbolInvalidationTraits *ETraits) {
    349 
    350     if (!ETraits)
    351       return ((const CHECKER *)Checker)->checkPointerEscape(State,
    352                                                             Escaped,
    353                                                             Call,
    354                                                             Kind);
    355 
    356     InvalidatedSymbols RegularEscape;
    357     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    358                                             E = Escaped.end(); I != E; ++I)
    359       if (!ETraits->hasTrait(*I,
    360               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    361           !ETraits->hasTrait(*I,
    362               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    363         RegularEscape.insert(*I);
    364 
    365     if (RegularEscape.empty())
    366       return State;
    367 
    368     return ((const CHECKER *)Checker)->checkPointerEscape(State,
    369                                                           RegularEscape,
    370                                                           Call,
    371                                                           Kind);
    372   }
    373 
    374 public:
    375   template <typename CHECKER>
    376   static void _register(CHECKER *checker, CheckerManager &mgr) {
    377     mgr._registerForPointerEscape(
    378           CheckerManager::CheckPointerEscapeFunc(checker,
    379                                                 _checkPointerEscape<CHECKER>));
    380   }
    381 };
    382 
    383 class ConstPointerEscape {
    384   template <typename CHECKER>
    385   static ProgramStateRef
    386   _checkConstPointerEscape(void *Checker,
    387                       ProgramStateRef State,
    388                       const InvalidatedSymbols &Escaped,
    389                       const CallEvent *Call,
    390                       PointerEscapeKind Kind,
    391                       RegionAndSymbolInvalidationTraits *ETraits) {
    392 
    393     if (!ETraits)
    394       return State;
    395 
    396     InvalidatedSymbols ConstEscape;
    397     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    398                                             E = Escaped.end(); I != E; ++I)
    399       if (ETraits->hasTrait(*I,
    400               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    401           !ETraits->hasTrait(*I,
    402               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    403         ConstEscape.insert(*I);
    404 
    405     if (ConstEscape.empty())
    406       return State;
    407 
    408     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
    409                                                                ConstEscape,
    410                                                                Call,
    411                                                                Kind);
    412   }
    413 
    414 public:
    415   template <typename CHECKER>
    416   static void _register(CHECKER *checker, CheckerManager &mgr) {
    417     mgr._registerForPointerEscape(
    418       CheckerManager::CheckPointerEscapeFunc(checker,
    419                                             _checkConstPointerEscape<CHECKER>));
    420   }
    421 };
    422 
    423 
    424 template <typename EVENT>
    425 class Event {
    426   template <typename CHECKER>
    427   static void _checkEvent(void *checker, const void *event) {
    428     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
    429   }
    430 public:
    431   template <typename CHECKER>
    432   static void _register(CHECKER *checker, CheckerManager &mgr) {
    433     mgr._registerListenerForEvent<EVENT>(
    434                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
    435   }
    436 };
    437 
    438 } // end check namespace
    439 
    440 namespace eval {
    441 
    442 class Assume {
    443   template <typename CHECKER>
    444   static ProgramStateRef _evalAssume(void *checker,
    445                                          ProgramStateRef state,
    446                                          const SVal &cond,
    447                                          bool assumption) {
    448     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
    449   }
    450 
    451 public:
    452   template <typename CHECKER>
    453   static void _register(CHECKER *checker, CheckerManager &mgr) {
    454     mgr._registerForEvalAssume(
    455                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
    456   }
    457 };
    458 
    459 class Call {
    460   template <typename CHECKER>
    461   static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
    462     return ((const CHECKER *)checker)->evalCall(CE, C);
    463   }
    464 
    465 public:
    466   template <typename CHECKER>
    467   static void _register(CHECKER *checker, CheckerManager &mgr) {
    468     mgr._registerForEvalCall(
    469                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
    470   }
    471 };
    472 
    473 } // end eval namespace
    474 
    475 class CheckerBase : public ProgramPointTag {
    476   CheckName Name;
    477   friend class ::clang::ento::CheckerManager;
    478 
    479 public:
    480   StringRef getTagDescription() const override;
    481   CheckName getCheckName() const;
    482 
    483   /// See CheckerManager::runCheckersForPrintState.
    484   virtual void printState(raw_ostream &Out, ProgramStateRef State,
    485                           const char *NL, const char *Sep) const { }
    486 };
    487 
    488 /// Dump checker name to stream.
    489 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
    490 
    491 /// Tag that can use a checker name as a message provider
    492 /// (see SimpleProgramPointTag).
    493 class CheckerProgramPointTag : public SimpleProgramPointTag {
    494 public:
    495   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
    496   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
    497 };
    498 
    499 template <typename CHECK1, typename... CHECKs>
    500 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
    501 public:
    502   template <typename CHECKER>
    503   static void _register(CHECKER *checker, CheckerManager &mgr) {
    504     CHECK1::_register(checker, mgr);
    505     Checker<CHECKs...>::_register(checker, mgr);
    506   }
    507 };
    508 
    509 template <typename CHECK1>
    510 class Checker<CHECK1> : public CHECK1, public CheckerBase {
    511 public:
    512   template <typename CHECKER>
    513   static void _register(CHECKER *checker, CheckerManager &mgr) {
    514     CHECK1::_register(checker, mgr);
    515   }
    516 };
    517 
    518 template <typename EVENT>
    519 class EventDispatcher {
    520   CheckerManager *Mgr;
    521 public:
    522   EventDispatcher() : Mgr(nullptr) { }
    523 
    524   template <typename CHECKER>
    525   static void _register(CHECKER *checker, CheckerManager &mgr) {
    526     mgr._registerDispatcherForEvent<EVENT>();
    527     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
    528   }
    529 
    530   void dispatchEvent(const EVENT &event) const {
    531     Mgr->_dispatchEvent(event);
    532   }
    533 };
    534 
    535 /// \brief We dereferenced a location that may be null.
    536 struct ImplicitNullDerefEvent {
    537   SVal Location;
    538   bool IsLoad;
    539   ExplodedNode *SinkNode;
    540   BugReporter *BR;
    541   // When true, the dereference is in the source code directly. When false, the
    542   // dereference might happen later (for example pointer passed to a parameter
    543   // that is marked with nonnull attribute.)
    544   bool IsDirectDereference;
    545 };
    546 
    547 /// \brief A helper class which wraps a boolean value set to false by default.
    548 ///
    549 /// This class should behave exactly like 'bool' except that it doesn't need to
    550 /// be explicitly initialized.
    551 struct DefaultBool {
    552   bool val;
    553   DefaultBool() : val(false) {}
    554   /*implicit*/ operator bool&() { return val; }
    555   /*implicit*/ operator const bool&() const { return val; }
    556   DefaultBool &operator=(bool b) { val = b; return *this; }
    557 };
    558 
    559 } // end ento namespace
    560 
    561 } // end clang namespace
    562 
    563 #endif
    564