Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Blame | Last modification | View Log | Download | RSS feed

  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. } // end ento namespace
  567.  
  568. } // end clang namespace
  569.  
  570. #endif
  571.