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