Checker.h revision af498a28797c075c48d7e943df5f5a8e78ed8eb0
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 NodeBuilder &B, ExplodedNode *Pred, 219 ExprEngine &Eng) { 220 ((const CHECKER *)checker)->checkBranchCondition(condition, B, Pred, Eng); 221 } 222 223public: 224 template <typename CHECKER> 225 static void _register(CHECKER *checker, CheckerManager &mgr) { 226 mgr._registerForBranchCondition( 227 CheckerManager::CheckBranchConditionFunc(checker, 228 _checkBranchCondition<CHECKER>)); 229 } 230}; 231 232class LiveSymbols { 233 template <typename CHECKER> 234 static void _checkLiveSymbols(void *checker, const ProgramState *state, 235 SymbolReaper &SR) { 236 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 237 } 238 239public: 240 template <typename CHECKER> 241 static void _register(CHECKER *checker, CheckerManager &mgr) { 242 mgr._registerForLiveSymbols( 243 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 244 } 245}; 246 247class DeadSymbols { 248 template <typename CHECKER> 249 static void _checkDeadSymbols(void *checker, 250 SymbolReaper &SR, CheckerContext &C) { 251 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 252 } 253 254public: 255 template <typename CHECKER> 256 static void _register(CHECKER *checker, CheckerManager &mgr) { 257 mgr._registerForDeadSymbols( 258 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 259 } 260}; 261 262class RegionChanges { 263 template <typename CHECKER> 264 static const ProgramState * 265 _checkRegionChanges(void *checker, 266 const ProgramState *state, 267 const StoreManager::InvalidatedSymbols *invalidated, 268 ArrayRef<const MemRegion *> Explicits, 269 ArrayRef<const MemRegion *> Regions) { 270 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 271 Explicits, Regions); 272 } 273 template <typename CHECKER> 274 static bool _wantsRegionChangeUpdate(void *checker, 275 const ProgramState *state) { 276 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 277 } 278 279public: 280 template <typename CHECKER> 281 static void _register(CHECKER *checker, CheckerManager &mgr) { 282 mgr._registerForRegionChanges( 283 CheckerManager::CheckRegionChangesFunc(checker, 284 _checkRegionChanges<CHECKER>), 285 CheckerManager::WantsRegionChangeUpdateFunc(checker, 286 _wantsRegionChangeUpdate<CHECKER>)); 287 } 288}; 289 290template <typename EVENT> 291class Event { 292 template <typename CHECKER> 293 static void _checkEvent(void *checker, const void *event) { 294 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 295 } 296public: 297 template <typename CHECKER> 298 static void _register(CHECKER *checker, CheckerManager &mgr) { 299 mgr._registerListenerForEvent<EVENT>( 300 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 301 } 302}; 303 304} // end check namespace 305 306namespace eval { 307 308class Assume { 309 template <typename CHECKER> 310 static const ProgramState *_evalAssume(void *checker, 311 const ProgramState *state, 312 const SVal &cond, 313 bool assumption) { 314 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 315 } 316 317public: 318 template <typename CHECKER> 319 static void _register(CHECKER *checker, CheckerManager &mgr) { 320 mgr._registerForEvalAssume( 321 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 322 } 323}; 324 325class Call { 326 template <typename CHECKER> 327 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 328 return ((const CHECKER *)checker)->evalCall(CE, C); 329 } 330 331public: 332 template <typename CHECKER> 333 static void _register(CHECKER *checker, CheckerManager &mgr) { 334 mgr._registerForEvalCall( 335 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 336 } 337}; 338 339class InlineCall { 340 template <typename CHECKER> 341 static bool _inlineCall(void *checker, const CallExpr *CE, 342 ExprEngine &Eng, 343 ExplodedNode *Pred, 344 ExplodedNodeSet &Dst) { 345 return ((const CHECKER *)checker)->inlineCall(CE, Eng, Pred, Dst); 346 } 347 348public: 349 template <typename CHECKER> 350 static void _register(CHECKER *checker, CheckerManager &mgr) { 351 mgr._registerForInlineCall( 352 CheckerManager::InlineCallFunc(checker, _inlineCall<CHECKER>)); 353 } 354}; 355 356} // end eval namespace 357 358class CheckerBase : public ProgramPointTag { 359public: 360 StringRef getTagDescription() const; 361 362 /// See CheckerManager::runCheckersForPrintState. 363 virtual void printState(raw_ostream &Out, const ProgramState *State, 364 const char *NL, const char *Sep) const { } 365}; 366 367template <typename CHECK1, typename CHECK2=check::_VoidCheck, 368 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 369 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 370 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 371 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 372 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, 373 typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, 374 typename CHECK15=check::_VoidCheck,typename CHECK16=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> 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> 394class Checker 395 : public CHECK1, 396 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 397 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 398 CHECK16> { 399public: 400 template <typename CHECKER> 401 static void _register(CHECKER *checker, CheckerManager &mgr) { 402 CHECK1::_register(checker, mgr); 403 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 404 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 405 CHECK16>::_register(checker, mgr); 406 } 407}; 408 409template <typename EVENT> 410class EventDispatcher { 411 CheckerManager *Mgr; 412public: 413 EventDispatcher() : Mgr(0) { } 414 415 template <typename CHECKER> 416 static void _register(CHECKER *checker, CheckerManager &mgr) { 417 mgr._registerDispatcherForEvent<EVENT>(); 418 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 419 } 420 421 void dispatchEvent(const EVENT &event) const { 422 Mgr->_dispatchEvent(event); 423 } 424}; 425 426/// \brief We dereferenced a location that may be null. 427struct ImplicitNullDerefEvent { 428 SVal Location; 429 bool IsLoad; 430 ExplodedNode *SinkNode; 431 BugReporter *BR; 432}; 433 434} // end ento namespace 435 436} // end clang namespace 437 438#endif 439