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