Checker.h revision f236b6503a4dbc44c1fccb8756bd57c9d0efdf05
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> 374class Checker; 375 376template <> 377class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 378 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> 383 : public CheckerBase 384{ 385public: 386 static void _register(void *checker, CheckerManager &mgr) { } 387}; 388 389template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 390 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 391 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, 392 typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16> 393class Checker 394 : public CHECK1, 395 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 396 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 397 CHECK16> { 398public: 399 template <typename CHECKER> 400 static void _register(CHECKER *checker, CheckerManager &mgr) { 401 CHECK1::_register(checker, mgr); 402 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 403 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 404 CHECK16>::_register(checker, mgr); 405 } 406}; 407 408template <typename EVENT> 409class EventDispatcher { 410 CheckerManager *Mgr; 411public: 412 EventDispatcher() : Mgr(0) { } 413 414 template <typename CHECKER> 415 static void _register(CHECKER *checker, CheckerManager &mgr) { 416 mgr._registerDispatcherForEvent<EVENT>(); 417 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 418 } 419 420 void dispatchEvent(const EVENT &event) const { 421 Mgr->_dispatchEvent(event); 422 } 423}; 424 425/// \brief We dereferenced a location that may be null. 426struct ImplicitNullDerefEvent { 427 SVal Location; 428 bool IsLoad; 429 ExplodedNode *SinkNode; 430 BugReporter *BR; 431}; 432 433} // end ento namespace 434 435} // end clang namespace 436 437#endif 438