Home | History | Annotate | Line # | Download | only in Core
      1 //== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 //  This file defines Checker, used to create and register checkers.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
     14 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H
     15 
     16 #include "clang/Analysis/ProgramPoint.h"
     17 #include "clang/Basic/LangOptions.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, const ReturnStmt *RS,
    258                                 CheckerContext &C) {
    259     ((const CHECKER *)checker)->checkEndFunction(RS, 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 NewAllocator {
    287   template <typename CHECKER>
    288   static void _checkNewAllocator(void *checker, const CXXAllocatorCall &Call,
    289                                  CheckerContext &C) {
    290     ((const CHECKER *)checker)->checkNewAllocator(Call, C);
    291   }
    292 
    293 public:
    294   template <typename CHECKER>
    295   static void _register(CHECKER *checker, CheckerManager &mgr) {
    296     mgr._registerForNewAllocator(
    297         CheckerManager::CheckNewAllocatorFunc(checker,
    298                                               _checkNewAllocator<CHECKER>));
    299   }
    300 };
    301 
    302 class LiveSymbols {
    303   template <typename CHECKER>
    304   static void _checkLiveSymbols(void *checker, ProgramStateRef state,
    305                                 SymbolReaper &SR) {
    306     ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
    307   }
    308 
    309 public:
    310   template <typename CHECKER>
    311   static void _register(CHECKER *checker, CheckerManager &mgr) {
    312     mgr._registerForLiveSymbols(
    313      CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
    314   }
    315 };
    316 
    317 class DeadSymbols {
    318   template <typename CHECKER>
    319   static void _checkDeadSymbols(void *checker,
    320                                 SymbolReaper &SR, CheckerContext &C) {
    321     ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
    322   }
    323 
    324 public:
    325   template <typename CHECKER>
    326   static void _register(CHECKER *checker, CheckerManager &mgr) {
    327     mgr._registerForDeadSymbols(
    328      CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
    329   }
    330 };
    331 
    332 class RegionChanges {
    333   template <typename CHECKER>
    334   static ProgramStateRef
    335   _checkRegionChanges(void *checker,
    336                       ProgramStateRef state,
    337                       const InvalidatedSymbols *invalidated,
    338                       ArrayRef<const MemRegion *> Explicits,
    339                       ArrayRef<const MemRegion *> Regions,
    340                       const LocationContext *LCtx,
    341                       const CallEvent *Call) {
    342     return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated,
    343                                                            Explicits, Regions,
    344                                                            LCtx, Call);
    345   }
    346 
    347 public:
    348   template <typename CHECKER>
    349   static void _register(CHECKER *checker, CheckerManager &mgr) {
    350     mgr._registerForRegionChanges(
    351           CheckerManager::CheckRegionChangesFunc(checker,
    352                                                  _checkRegionChanges<CHECKER>));
    353   }
    354 };
    355 
    356 class PointerEscape {
    357   template <typename CHECKER>
    358   static ProgramStateRef
    359   _checkPointerEscape(void *Checker,
    360                      ProgramStateRef State,
    361                      const InvalidatedSymbols &Escaped,
    362                      const CallEvent *Call,
    363                      PointerEscapeKind Kind,
    364                      RegionAndSymbolInvalidationTraits *ETraits) {
    365 
    366     if (!ETraits)
    367       return ((const CHECKER *)Checker)->checkPointerEscape(State,
    368                                                             Escaped,
    369                                                             Call,
    370                                                             Kind);
    371 
    372     InvalidatedSymbols RegularEscape;
    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         RegularEscape.insert(*I);
    380 
    381     if (RegularEscape.empty())
    382       return State;
    383 
    384     return ((const CHECKER *)Checker)->checkPointerEscape(State,
    385                                                           RegularEscape,
    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                                                 _checkPointerEscape<CHECKER>));
    396   }
    397 };
    398 
    399 class ConstPointerEscape {
    400   template <typename CHECKER>
    401   static ProgramStateRef
    402   _checkConstPointerEscape(void *Checker,
    403                       ProgramStateRef State,
    404                       const InvalidatedSymbols &Escaped,
    405                       const CallEvent *Call,
    406                       PointerEscapeKind Kind,
    407                       RegionAndSymbolInvalidationTraits *ETraits) {
    408 
    409     if (!ETraits)
    410       return State;
    411 
    412     InvalidatedSymbols ConstEscape;
    413     for (InvalidatedSymbols::const_iterator I = Escaped.begin(),
    414                                             E = Escaped.end(); I != E; ++I)
    415       if (ETraits->hasTrait(*I,
    416               RegionAndSymbolInvalidationTraits::TK_PreserveContents) &&
    417           !ETraits->hasTrait(*I,
    418               RegionAndSymbolInvalidationTraits::TK_SuppressEscape))
    419         ConstEscape.insert(*I);
    420 
    421     if (ConstEscape.empty())
    422       return State;
    423 
    424     return ((const CHECKER *)Checker)->checkConstPointerEscape(State,
    425                                                                ConstEscape,
    426                                                                Call,
    427                                                                Kind);
    428   }
    429 
    430 public:
    431   template <typename CHECKER>
    432   static void _register(CHECKER *checker, CheckerManager &mgr) {
    433     mgr._registerForPointerEscape(
    434       CheckerManager::CheckPointerEscapeFunc(checker,
    435                                             _checkConstPointerEscape<CHECKER>));
    436   }
    437 };
    438 
    439 
    440 template <typename EVENT>
    441 class Event {
    442   template <typename CHECKER>
    443   static void _checkEvent(void *checker, const void *event) {
    444     ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
    445   }
    446 public:
    447   template <typename CHECKER>
    448   static void _register(CHECKER *checker, CheckerManager &mgr) {
    449     mgr._registerListenerForEvent<EVENT>(
    450                  CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
    451   }
    452 };
    453 
    454 } // end check namespace
    455 
    456 namespace eval {
    457 
    458 class Assume {
    459   template <typename CHECKER>
    460   static ProgramStateRef _evalAssume(void *checker,
    461                                          ProgramStateRef state,
    462                                          const SVal &cond,
    463                                          bool assumption) {
    464     return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
    465   }
    466 
    467 public:
    468   template <typename CHECKER>
    469   static void _register(CHECKER *checker, CheckerManager &mgr) {
    470     mgr._registerForEvalAssume(
    471                  CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
    472   }
    473 };
    474 
    475 class Call {
    476   template <typename CHECKER>
    477   static bool _evalCall(void *checker, const CallEvent &Call,
    478                         CheckerContext &C) {
    479     return ((const CHECKER *)checker)->evalCall(Call, C);
    480   }
    481 
    482 public:
    483   template <typename CHECKER>
    484   static void _register(CHECKER *checker, CheckerManager &mgr) {
    485     mgr._registerForEvalCall(
    486                      CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
    487   }
    488 };
    489 
    490 } // end eval namespace
    491 
    492 class CheckerBase : public ProgramPointTag {
    493   CheckerNameRef Name;
    494   friend class ::clang::ento::CheckerManager;
    495 
    496 public:
    497   StringRef getTagDescription() const override;
    498   CheckerNameRef getCheckerName() const;
    499 
    500   /// See CheckerManager::runCheckersForPrintState.
    501   virtual void printState(raw_ostream &Out, ProgramStateRef State,
    502                           const char *NL, const char *Sep) const { }
    503 };
    504 
    505 /// Dump checker name to stream.
    506 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker);
    507 
    508 /// Tag that can use a checker name as a message provider
    509 /// (see SimpleProgramPointTag).
    510 class CheckerProgramPointTag : public SimpleProgramPointTag {
    511 public:
    512   CheckerProgramPointTag(StringRef CheckerName, StringRef Msg);
    513   CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg);
    514 };
    515 
    516 template <typename CHECK1, typename... CHECKs>
    517 class Checker : public CHECK1, public CHECKs..., public CheckerBase {
    518 public:
    519   template <typename CHECKER>
    520   static void _register(CHECKER *checker, CheckerManager &mgr) {
    521     CHECK1::_register(checker, mgr);
    522     Checker<CHECKs...>::_register(checker, mgr);
    523   }
    524 };
    525 
    526 template <typename CHECK1>
    527 class Checker<CHECK1> : public CHECK1, public CheckerBase {
    528 public:
    529   template <typename CHECKER>
    530   static void _register(CHECKER *checker, CheckerManager &mgr) {
    531     CHECK1::_register(checker, mgr);
    532   }
    533 };
    534 
    535 template <typename EVENT>
    536 class EventDispatcher {
    537   CheckerManager *Mgr;
    538 public:
    539   EventDispatcher() : Mgr(nullptr) { }
    540 
    541   template <typename CHECKER>
    542   static void _register(CHECKER *checker, CheckerManager &mgr) {
    543     mgr._registerDispatcherForEvent<EVENT>();
    544     static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
    545   }
    546 
    547   void dispatchEvent(const EVENT &event) const {
    548     Mgr->_dispatchEvent(event);
    549   }
    550 };
    551 
    552 /// We dereferenced a location that may be null.
    553 struct ImplicitNullDerefEvent {
    554   SVal Location;
    555   bool IsLoad;
    556   ExplodedNode *SinkNode;
    557   BugReporter *BR;
    558   // When true, the dereference is in the source code directly. When false, the
    559   // dereference might happen later (for example pointer passed to a parameter
    560   // that is marked with nonnull attribute.)
    561   bool IsDirectDereference;
    562 
    563   static int Tag;
    564 };
    565 
    566 /// A helper class which wraps a boolean value set to false by default.
    567 ///
    568 /// This class should behave exactly like 'bool' except that it doesn't need to
    569 /// be explicitly initialized.
    570 struct DefaultBool {
    571   bool val;
    572   DefaultBool() : val(false) {}
    573   /*implicit*/ operator bool&() { return val; }
    574   /*implicit*/ operator const bool&() const { return val; }
    575   DefaultBool &operator=(bool b) { val = b; return *this; }
    576 };
    577 
    578 } // end ento namespace
    579 
    580 } // end clang namespace
    581 
    582 #endif
    583