/contrib/llvm/tools/clang/include/clang/StaticAnalyzer/Core/Checker.h

https://github.com/okuoku/freebsd-head · C Header · 394 lines · 328 code · 53 blank · 13 comment · 0 complexity · 288fa5141a1e9a556cee30c023c4ecb4 MD5 · raw file

  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. #ifndef LLVM_CLANG_SA_CORE_CHECKER
  14. #define LLVM_CLANG_SA_CORE_CHECKER
  15. #include "clang/StaticAnalyzer/Core/CheckerManager.h"
  16. #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
  17. #include "llvm/Support/Casting.h"
  18. namespace clang {
  19. namespace ento {
  20. class BugReporter;
  21. namespace check {
  22. struct _VoidCheck {
  23. static void _register(void *checker, CheckerManager &mgr) { }
  24. };
  25. template <typename DECL>
  26. class ASTDecl {
  27. template <typename CHECKER>
  28. static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr,
  29. BugReporter &BR) {
  30. ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR);
  31. }
  32. static bool _handlesDecl(const Decl *D) {
  33. return llvm::isa<DECL>(D);
  34. }
  35. public:
  36. template <typename CHECKER>
  37. static void _register(CHECKER *checker, CheckerManager &mgr) {
  38. mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker,
  39. _checkDecl<CHECKER>),
  40. _handlesDecl);
  41. }
  42. };
  43. class ASTCodeBody {
  44. template <typename CHECKER>
  45. static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr,
  46. BugReporter &BR) {
  47. ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR);
  48. }
  49. public:
  50. template <typename CHECKER>
  51. static void _register(CHECKER *checker, CheckerManager &mgr) {
  52. mgr._registerForBody(CheckerManager::CheckDeclFunc(checker,
  53. _checkBody<CHECKER>));
  54. }
  55. };
  56. class EndOfTranslationUnit {
  57. template <typename CHECKER>
  58. static void _checkEndOfTranslationUnit(void *checker,
  59. const TranslationUnitDecl *TU,
  60. AnalysisManager& mgr,
  61. BugReporter &BR) {
  62. ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR);
  63. }
  64. public:
  65. template <typename CHECKER>
  66. static void _register(CHECKER *checker, CheckerManager &mgr){
  67. mgr._registerForEndOfTranslationUnit(
  68. CheckerManager::CheckEndOfTranslationUnit(checker,
  69. _checkEndOfTranslationUnit<CHECKER>));
  70. }
  71. };
  72. template <typename STMT>
  73. class PreStmt {
  74. template <typename CHECKER>
  75. static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
  76. ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C);
  77. }
  78. static bool _handlesStmt(const Stmt *S) {
  79. return llvm::isa<STMT>(S);
  80. }
  81. public:
  82. template <typename CHECKER>
  83. static void _register(CHECKER *checker, CheckerManager &mgr) {
  84. mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker,
  85. _checkStmt<CHECKER>),
  86. _handlesStmt);
  87. }
  88. };
  89. template <typename STMT>
  90. class PostStmt {
  91. template <typename CHECKER>
  92. static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) {
  93. ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C);
  94. }
  95. static bool _handlesStmt(const Stmt *S) {
  96. return llvm::isa<STMT>(S);
  97. }
  98. public:
  99. template <typename CHECKER>
  100. static void _register(CHECKER *checker, CheckerManager &mgr) {
  101. mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker,
  102. _checkStmt<CHECKER>),
  103. _handlesStmt);
  104. }
  105. };
  106. class PreObjCMessage {
  107. template <typename CHECKER>
  108. static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
  109. CheckerContext &C) {
  110. ((const CHECKER *)checker)->checkPreObjCMessage(msg, C);
  111. }
  112. public:
  113. template <typename CHECKER>
  114. static void _register(CHECKER *checker, CheckerManager &mgr) {
  115. mgr._registerForPreObjCMessage(
  116. CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
  117. }
  118. };
  119. class PostObjCMessage {
  120. template <typename CHECKER>
  121. static void _checkObjCMessage(void *checker, const ObjCMessage &msg,
  122. CheckerContext &C) {
  123. ((const CHECKER *)checker)->checkPostObjCMessage(msg, C);
  124. }
  125. public:
  126. template <typename CHECKER>
  127. static void _register(CHECKER *checker, CheckerManager &mgr) {
  128. mgr._registerForPostObjCMessage(
  129. CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>));
  130. }
  131. };
  132. class Location {
  133. template <typename CHECKER>
  134. static void _checkLocation(void *checker, const SVal &location, bool isLoad,
  135. CheckerContext &C) {
  136. ((const CHECKER *)checker)->checkLocation(location, isLoad, C);
  137. }
  138. public:
  139. template <typename CHECKER>
  140. static void _register(CHECKER *checker, CheckerManager &mgr) {
  141. mgr._registerForLocation(
  142. CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>));
  143. }
  144. };
  145. class Bind {
  146. template <typename CHECKER>
  147. static void _checkBind(void *checker, const SVal &location, const SVal &val,
  148. CheckerContext &C) {
  149. ((const CHECKER *)checker)->checkBind(location, val, C);
  150. }
  151. public:
  152. template <typename CHECKER>
  153. static void _register(CHECKER *checker, CheckerManager &mgr) {
  154. mgr._registerForBind(
  155. CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>));
  156. }
  157. };
  158. class EndAnalysis {
  159. template <typename CHECKER>
  160. static void _checkEndAnalysis(void *checker, ExplodedGraph &G,
  161. BugReporter &BR, ExprEngine &Eng) {
  162. ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng);
  163. }
  164. public:
  165. template <typename CHECKER>
  166. static void _register(CHECKER *checker, CheckerManager &mgr) {
  167. mgr._registerForEndAnalysis(
  168. CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>));
  169. }
  170. };
  171. class EndPath {
  172. template <typename CHECKER>
  173. static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B,
  174. ExprEngine &Eng) {
  175. ((const CHECKER *)checker)->checkEndPath(B, Eng);
  176. }
  177. public:
  178. template <typename CHECKER>
  179. static void _register(CHECKER *checker, CheckerManager &mgr) {
  180. mgr._registerForEndPath(
  181. CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>));
  182. }
  183. };
  184. class BranchCondition {
  185. template <typename CHECKER>
  186. static void _checkBranchCondition(void *checker, const Stmt *condition,
  187. BranchNodeBuilder &B, ExprEngine &Eng) {
  188. ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng);
  189. }
  190. public:
  191. template <typename CHECKER>
  192. static void _register(CHECKER *checker, CheckerManager &mgr) {
  193. mgr._registerForBranchCondition(
  194. CheckerManager::CheckBranchConditionFunc(checker,
  195. _checkBranchCondition<CHECKER>));
  196. }
  197. };
  198. class LiveSymbols {
  199. template <typename CHECKER>
  200. static void _checkLiveSymbols(void *checker, const GRState *state,
  201. SymbolReaper &SR) {
  202. ((const CHECKER *)checker)->checkLiveSymbols(state, SR);
  203. }
  204. public:
  205. template <typename CHECKER>
  206. static void _register(CHECKER *checker, CheckerManager &mgr) {
  207. mgr._registerForLiveSymbols(
  208. CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>));
  209. }
  210. };
  211. class DeadSymbols {
  212. template <typename CHECKER>
  213. static void _checkDeadSymbols(void *checker,
  214. SymbolReaper &SR, CheckerContext &C) {
  215. ((const CHECKER *)checker)->checkDeadSymbols(SR, C);
  216. }
  217. public:
  218. template <typename CHECKER>
  219. static void _register(CHECKER *checker, CheckerManager &mgr) {
  220. mgr._registerForDeadSymbols(
  221. CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>));
  222. }
  223. };
  224. class RegionChanges {
  225. template <typename CHECKER>
  226. static const GRState *_checkRegionChanges(void *checker, const GRState *state,
  227. const StoreManager::InvalidatedSymbols *invalidated,
  228. const MemRegion * const *Begin,
  229. const MemRegion * const *End) {
  230. return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated,
  231. Begin, End);
  232. }
  233. template <typename CHECKER>
  234. static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) {
  235. return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state);
  236. }
  237. public:
  238. template <typename CHECKER>
  239. static void _register(CHECKER *checker, CheckerManager &mgr) {
  240. mgr._registerForRegionChanges(
  241. CheckerManager::CheckRegionChangesFunc(checker,
  242. _checkRegionChanges<CHECKER>),
  243. CheckerManager::WantsRegionChangeUpdateFunc(checker,
  244. _wantsRegionChangeUpdate<CHECKER>));
  245. }
  246. };
  247. template <typename EVENT>
  248. class Event {
  249. template <typename CHECKER>
  250. static void _checkEvent(void *checker, const void *event) {
  251. ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event);
  252. }
  253. public:
  254. template <typename CHECKER>
  255. static void _register(CHECKER *checker, CheckerManager &mgr) {
  256. mgr._registerListenerForEvent<EVENT>(
  257. CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>));
  258. }
  259. };
  260. } // end check namespace
  261. namespace eval {
  262. class Assume {
  263. template <typename CHECKER>
  264. static const GRState *_evalAssume(void *checker, const GRState *state,
  265. const SVal &cond, bool assumption) {
  266. return ((const CHECKER *)checker)->evalAssume(state, cond, assumption);
  267. }
  268. public:
  269. template <typename CHECKER>
  270. static void _register(CHECKER *checker, CheckerManager &mgr) {
  271. mgr._registerForEvalAssume(
  272. CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>));
  273. }
  274. };
  275. class Call {
  276. template <typename CHECKER>
  277. static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) {
  278. return ((const CHECKER *)checker)->evalCall(CE, C);
  279. }
  280. public:
  281. template <typename CHECKER>
  282. static void _register(CHECKER *checker, CheckerManager &mgr) {
  283. mgr._registerForEvalCall(
  284. CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>));
  285. }
  286. };
  287. } // end eval namespace
  288. template <typename CHECK1, typename CHECK2=check::_VoidCheck,
  289. typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck,
  290. typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck,
  291. typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck,
  292. typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck,
  293. typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck>
  294. class Checker;
  295. template <>
  296. class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
  297. check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
  298. check::_VoidCheck, check::_VoidCheck, check::_VoidCheck,
  299. check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> {
  300. public:
  301. static void _register(void *checker, CheckerManager &mgr) { }
  302. };
  303. template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4,
  304. typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8,
  305. typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12>
  306. class Checker
  307. : public CHECK1,
  308. public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8,
  309. CHECK9, CHECK10, CHECK11, CHECK12> {
  310. public:
  311. template <typename CHECKER>
  312. static void _register(CHECKER *checker, CheckerManager &mgr) {
  313. CHECK1::_register(checker, mgr);
  314. Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9,
  315. CHECK10, CHECK11,CHECK12>::_register(checker, mgr);
  316. }
  317. };
  318. template <typename EVENT>
  319. class EventDispatcher {
  320. CheckerManager *Mgr;
  321. public:
  322. EventDispatcher() : Mgr(0) { }
  323. template <typename CHECKER>
  324. static void _register(CHECKER *checker, CheckerManager &mgr) {
  325. mgr._registerDispatcherForEvent<EVENT>();
  326. static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr;
  327. }
  328. void dispatchEvent(const EVENT &event) const {
  329. Mgr->_dispatchEvent(event);
  330. }
  331. };
  332. /// \brief We dereferenced a location that may be null.
  333. struct ImplicitNullDerefEvent {
  334. SVal Location;
  335. bool IsLoad;
  336. ExplodedNode *SinkNode;
  337. BugReporter *BR;
  338. };
  339. } // end ento namespace
  340. } // end clang namespace
  341. #endif