Checker.h revision 6bcf27bb9a4b5c3f79cb44c0e4654a6d7619ad89
183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// 283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// 383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// The LLVM Compiler Infrastructure 483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// 583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// This file is distributed under the University of Illinois Open Source 683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// License. See LICENSE.TXT for details. 7e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org// 81f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com//===----------------------------------------------------------------------===// 983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// 1083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// This file defines Checker, used to create and register checkers. 1183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com// 121f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com//===----------------------------------------------------------------------===// 131f2f338e23789f3eef168dcbd8171a28820ba6c1robertphillips@google.com 148f6884aab8aecd7657cf3f9cdbc682f0deca29c5tfarina@chromium.org#ifndef LLVM_CLANG_SA_CORE_CHECKER 1583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#define LLVM_CLANG_SA_CORE_CHECKER 1683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 1783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "clang/Analysis/ProgramPoint.h" 1883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "clang/StaticAnalyzer/Core/CheckerManager.h" 1983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 2083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com#include "llvm/Support/Casting.h" 2183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 2283226976b532141b26ff3a40f381a5d08ce3259dreed@google.comnamespace clang { 2383226976b532141b26ff3a40f381a5d08ce3259dreed@google.comnamespace ento { 2483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com class BugReporter; 2583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 2683226976b532141b26ff3a40f381a5d08ce3259dreed@google.comnamespace check { 2783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 2883226976b532141b26ff3a40f381a5d08ce3259dreed@google.comstruct _VoidCheck { 2983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _register(void *checker, CheckerManager &mgr) { } 3083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 3183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 3283226976b532141b26ff3a40f381a5d08ce3259dreed@google.comtemplate <typename DECL> 3383226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass ASTDecl { 3483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 3583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, 3683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com BugReporter &BR) { 3783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR); 3883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 3983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 4083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static bool _handlesDecl(const Decl *D) { 4183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com return isa<DECL>(D); 4283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 4383226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 4483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 45e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com static void _register(CHECKER *checker, CheckerManager &mgr) { 4683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, 4783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com _checkDecl<CHECKER>), 4883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com _handlesDecl); 4983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 5083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 5183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 5283226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass ASTCodeBody { 5383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 5483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, 5537ebe3fbf6c4a5728bc2c322cc0f626444f987bfrobertphillips@google.com BugReporter &BR) { 5683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); 5783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 5883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 5983226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 6083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 6183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _register(CHECKER *checker, CheckerManager &mgr) { 6283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, 6383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com _checkBody<CHECKER>)); 6483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 6583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 6683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 67d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.comclass EndOfTranslationUnit { 6883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 6983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _checkEndOfTranslationUnit(void *checker, 7083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com const TranslationUnitDecl *TU, 7183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com AnalysisManager& mgr, 7283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com BugReporter &BR) { 7383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); 7483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 7583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 7683226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 7783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 7883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _register(CHECKER *checker, CheckerManager &mgr){ 7983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com mgr._registerForEndOfTranslationUnit( 80d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com CheckerManager::CheckEndOfTranslationUnit(checker, 8183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com _checkEndOfTranslationUnit<CHECKER>)); 8283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 8383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 8483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 8583226976b532141b26ff3a40f381a5d08ce3259dreed@google.comtemplate <typename STMT> 8683226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass PreStmt { 8783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 8883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 8983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C); 9083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 9183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 9283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static bool _handlesStmt(const Stmt *S) { 9383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com return isa<STMT>(S); 9483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 9583226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 96d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com template <typename CHECKER> 9783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _register(CHECKER *checker, CheckerManager &mgr) { 9883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, 9983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com _checkStmt<CHECKER>), 10083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com _handlesStmt); 10183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 10283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 10383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 10483226976b532141b26ff3a40f381a5d08ce3259dreed@google.comtemplate <typename STMT> 10583226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass PostStmt { 10683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 10783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 10883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C); 109d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com } 11083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 11183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static bool _handlesStmt(const Stmt *S) { 11283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com return isa<STMT>(S); 11383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 11483226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 11583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 11683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _register(CHECKER *checker, CheckerManager &mgr) { 11783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, 11883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com _checkStmt<CHECKER>), 11983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com _handlesStmt); 12083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 12183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 12283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 12383226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass PreObjCMessage { 124d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com template <typename CHECKER> 12583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 12683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com CheckerContext &C) { 12783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); 12883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 12983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 13083226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 131e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org template <typename CHECKER> 132e0e385c1d4171e065348ba17c546b3463a0bd651sugoi@google.com static void _register(CHECKER *checker, CheckerManager &mgr) { 133e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org mgr._registerForPreObjCMessage( 134e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 135e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org } 136e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org}; 137e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org 138e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.orgclass PostObjCMessage { 139e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org template <typename CHECKER> 140e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 141e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org CheckerContext &C) { 142e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); 143e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org } 144e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org 145deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.orgpublic: 146e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org template <typename CHECKER> 147e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org static void _register(CHECKER *checker, CheckerManager &mgr) { 148deee496cd30070e52556dcb538c2e5eb39b66b81mike@reedtribe.org mgr._registerForPostObjCMessage( 149e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 150e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org } 151e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org}; 152e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org 153e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.orgclass PreCall { 154e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org template <typename CHECKER> 155e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org static void _checkCall(void *checker, const CallEvent &msg, 156e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org CheckerContext &C) { 157e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org ((const CHECKER *)checker)->checkPreCall(msg, C); 158e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org } 15983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 16083226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 161e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org template <typename CHECKER> 16283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _register(CHECKER *checker, CheckerManager &mgr) { 16383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com mgr._registerForPreCall( 16483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 16583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 16683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 16783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 16883226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass PostCall { 16983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 17083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _checkCall(void *checker, const CallEvent &msg, 17183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com CheckerContext &C) { 17283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com ((const CHECKER *)checker)->checkPostCall(msg, C); 17383226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 17483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 17583226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 17683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 17783226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _register(CHECKER *checker, CheckerManager &mgr) { 17883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com mgr._registerForPostCall( 17983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 18083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 18183226976b532141b26ff3a40f381a5d08ce3259dreed@google.com}; 18283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 18383226976b532141b26ff3a40f381a5d08ce3259dreed@google.comclass Location { 18483226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 18583226976b532141b26ff3a40f381a5d08ce3259dreed@google.com static void _checkLocation(void *checker, 18683226976b532141b26ff3a40f381a5d08ce3259dreed@google.com const SVal &location, bool isLoad, const Stmt *S, 187d6176b0dcacb124539e0cfd051e6d93a9782f020rmistry@google.com CheckerContext &C) { 18883226976b532141b26ff3a40f381a5d08ce3259dreed@google.com ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); 18983226976b532141b26ff3a40f381a5d08ce3259dreed@google.com } 19083226976b532141b26ff3a40f381a5d08ce3259dreed@google.com 19183226976b532141b26ff3a40f381a5d08ce3259dreed@google.compublic: 19283226976b532141b26ff3a40f381a5d08ce3259dreed@google.com template <typename CHECKER> 193e4fafb146e85cdfcf9d5418597b6818aa0754adatfarina@chromium.org static void _register(CHECKER *checker, CheckerManager &mgr) { 194e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org mgr._registerForLocation( 195e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 196e94b5e40c5fb0e36eebcae1abfe04b9bc33583f4junov@chromium.org } 197}; 198 199class Bind { 200 template <typename CHECKER> 201 static void _checkBind(void *checker, 202 const SVal &location, const SVal &val, const Stmt *S, 203 CheckerContext &C) { 204 ((const CHECKER *)checker)->checkBind(location, val, S, C); 205 } 206 207public: 208 template <typename CHECKER> 209 static void _register(CHECKER *checker, CheckerManager &mgr) { 210 mgr._registerForBind( 211 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 212 } 213}; 214 215class EndAnalysis { 216 template <typename CHECKER> 217 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 218 BugReporter &BR, ExprEngine &Eng) { 219 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 220 } 221 222public: 223 template <typename CHECKER> 224 static void _register(CHECKER *checker, CheckerManager &mgr) { 225 mgr._registerForEndAnalysis( 226 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 227 } 228}; 229 230class EndFunction { 231 template <typename CHECKER> 232 static void _checkEndFunction(void *checker, 233 CheckerContext &C) { 234 ((const CHECKER *)checker)->checkEndFunction(C); 235 } 236 237public: 238 template <typename CHECKER> 239 static void _register(CHECKER *checker, CheckerManager &mgr) { 240 mgr._registerForEndFunction( 241 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); 242 } 243}; 244 245class BranchCondition { 246 template <typename CHECKER> 247 static void _checkBranchCondition(void *checker, const Stmt *Condition, 248 CheckerContext & C) { 249 ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 250 } 251 252public: 253 template <typename CHECKER> 254 static void _register(CHECKER *checker, CheckerManager &mgr) { 255 mgr._registerForBranchCondition( 256 CheckerManager::CheckBranchConditionFunc(checker, 257 _checkBranchCondition<CHECKER>)); 258 } 259}; 260 261class LiveSymbols { 262 template <typename CHECKER> 263 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 264 SymbolReaper &SR) { 265 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 266 } 267 268public: 269 template <typename CHECKER> 270 static void _register(CHECKER *checker, CheckerManager &mgr) { 271 mgr._registerForLiveSymbols( 272 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 273 } 274}; 275 276class DeadSymbols { 277 template <typename CHECKER> 278 static void _checkDeadSymbols(void *checker, 279 SymbolReaper &SR, CheckerContext &C) { 280 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 281 } 282 283public: 284 template <typename CHECKER> 285 static void _register(CHECKER *checker, CheckerManager &mgr) { 286 mgr._registerForDeadSymbols( 287 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 288 } 289}; 290 291class RegionChanges { 292 template <typename CHECKER> 293 static ProgramStateRef 294 _checkRegionChanges(void *checker, 295 ProgramStateRef state, 296 const InvalidatedSymbols *invalidated, 297 ArrayRef<const MemRegion *> Explicits, 298 ArrayRef<const MemRegion *> Regions, 299 const CallEvent *Call) { 300 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 301 Explicits, Regions, Call); 302 } 303 template <typename CHECKER> 304 static bool _wantsRegionChangeUpdate(void *checker, 305 ProgramStateRef state) { 306 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 307 } 308 309public: 310 template <typename CHECKER> 311 static void _register(CHECKER *checker, CheckerManager &mgr) { 312 mgr._registerForRegionChanges( 313 CheckerManager::CheckRegionChangesFunc(checker, 314 _checkRegionChanges<CHECKER>), 315 CheckerManager::WantsRegionChangeUpdateFunc(checker, 316 _wantsRegionChangeUpdate<CHECKER>)); 317 } 318}; 319 320class PointerEscape { 321 template <typename CHECKER> 322 static ProgramStateRef 323 _checkPointerEscape(void *Checker, 324 ProgramStateRef State, 325 const InvalidatedSymbols &Escaped, 326 const CallEvent *Call, 327 PointerEscapeKind Kind, 328 RegionAndSymbolInvalidationTraits *ETraits) { 329 330 if (!ETraits) 331 return ((const CHECKER *)Checker)->checkPointerEscape(State, 332 Escaped, 333 Call, 334 Kind); 335 336 InvalidatedSymbols RegularEscape; 337 for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 338 E = Escaped.end(); I != E; ++I) 339 if (!ETraits->hasTrait(*I, 340 RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 341 !ETraits->hasTrait(*I, 342 RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 343 RegularEscape.insert(*I); 344 345 if (RegularEscape.empty()) 346 return State; 347 348 return ((const CHECKER *)Checker)->checkPointerEscape(State, 349 RegularEscape, 350 Call, 351 Kind); 352 } 353 354public: 355 template <typename CHECKER> 356 static void _register(CHECKER *checker, CheckerManager &mgr) { 357 mgr._registerForPointerEscape( 358 CheckerManager::CheckPointerEscapeFunc(checker, 359 _checkPointerEscape<CHECKER>)); 360 } 361}; 362 363class ConstPointerEscape { 364 template <typename CHECKER> 365 static ProgramStateRef 366 _checkConstPointerEscape(void *Checker, 367 ProgramStateRef State, 368 const InvalidatedSymbols &Escaped, 369 const CallEvent *Call, 370 PointerEscapeKind Kind, 371 RegionAndSymbolInvalidationTraits *ETraits) { 372 373 if (!ETraits) 374 return State; 375 376 InvalidatedSymbols ConstEscape; 377 for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 378 E = Escaped.end(); I != E; ++I) 379 if (ETraits->hasTrait(*I, 380 RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 381 !ETraits->hasTrait(*I, 382 RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 383 ConstEscape.insert(*I); 384 385 if (ConstEscape.empty()) 386 return State; 387 388 return ((const CHECKER *)Checker)->checkConstPointerEscape(State, 389 ConstEscape, 390 Call, 391 Kind); 392 } 393 394public: 395 template <typename CHECKER> 396 static void _register(CHECKER *checker, CheckerManager &mgr) { 397 mgr._registerForPointerEscape( 398 CheckerManager::CheckPointerEscapeFunc(checker, 399 _checkConstPointerEscape<CHECKER>)); 400 } 401}; 402 403 404template <typename EVENT> 405class Event { 406 template <typename CHECKER> 407 static void _checkEvent(void *checker, const void *event) { 408 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 409 } 410public: 411 template <typename CHECKER> 412 static void _register(CHECKER *checker, CheckerManager &mgr) { 413 mgr._registerListenerForEvent<EVENT>( 414 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 415 } 416}; 417 418} // end check namespace 419 420namespace eval { 421 422class Assume { 423 template <typename CHECKER> 424 static ProgramStateRef _evalAssume(void *checker, 425 ProgramStateRef state, 426 const SVal &cond, 427 bool assumption) { 428 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 429 } 430 431public: 432 template <typename CHECKER> 433 static void _register(CHECKER *checker, CheckerManager &mgr) { 434 mgr._registerForEvalAssume( 435 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 436 } 437}; 438 439class Call { 440 template <typename CHECKER> 441 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 442 return ((const CHECKER *)checker)->evalCall(CE, C); 443 } 444 445public: 446 template <typename CHECKER> 447 static void _register(CHECKER *checker, CheckerManager &mgr) { 448 mgr._registerForEvalCall( 449 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 450 } 451}; 452 453} // end eval namespace 454 455class CheckerBase : public ProgramPointTag { 456 CheckName Name; 457 friend class ::clang::ento::CheckerManager; 458 459public: 460 StringRef getTagDescription() const override; 461 CheckName getCheckName() const; 462 463 /// See CheckerManager::runCheckersForPrintState. 464 virtual void printState(raw_ostream &Out, ProgramStateRef State, 465 const char *NL, const char *Sep) const { } 466}; 467 468/// Dump checker name to stream. 469raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); 470 471/// Tag that can use a checker name as a message provider 472/// (see SimpleProgramPointTag). 473class CheckerProgramPointTag : public SimpleProgramPointTag { 474public: 475 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); 476 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); 477}; 478 479template <typename CHECK1, typename CHECK2=check::_VoidCheck, 480 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 481 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 482 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 483 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 484 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, 485 typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, 486 typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck, 487 typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck, 488 typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck, 489 typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck, 490 typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck> 491class Checker; 492 493template <> 494class Checker<check::_VoidCheck> 495 : public CheckerBase 496{ 497 virtual void anchor(); 498public: 499 static void _register(void *checker, CheckerManager &mgr) { } 500}; 501 502template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 503 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 504 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, 505 typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16, 506 typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20, 507 typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24> 508class Checker 509 : public CHECK1, 510 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, 511 CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, 512 CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, 513 CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> { 514public: 515 template <typename CHECKER> 516 static void _register(CHECKER *checker, CheckerManager &mgr) { 517 CHECK1::_register(checker, mgr); 518 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, 519 CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, 520 CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, 521 CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr); 522 } 523}; 524 525template <typename EVENT> 526class EventDispatcher { 527 CheckerManager *Mgr; 528public: 529 EventDispatcher() : Mgr(nullptr) { } 530 531 template <typename CHECKER> 532 static void _register(CHECKER *checker, CheckerManager &mgr) { 533 mgr._registerDispatcherForEvent<EVENT>(); 534 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 535 } 536 537 void dispatchEvent(const EVENT &event) const { 538 Mgr->_dispatchEvent(event); 539 } 540}; 541 542/// \brief We dereferenced a location that may be null. 543struct ImplicitNullDerefEvent { 544 SVal Location; 545 bool IsLoad; 546 ExplodedNode *SinkNode; 547 BugReporter *BR; 548}; 549 550/// \brief A helper class which wraps a boolean value set to false by default. 551/// 552/// This class should behave exactly like 'bool' except that it doesn't need to 553/// be explicitly initialized. 554struct DefaultBool { 555 bool val; 556 DefaultBool() : val(false) {} 557 /*implicit*/ operator bool&() { return val; } 558 /*implicit*/ operator const bool&() const { return val; } 559 DefaultBool &operator=(bool b) { val = b; return *this; } 560}; 561 562} // end ento namespace 563 564} // end clang namespace 565 566#endif 567