Checker.h revision dff6ef903ff4fcb43b5ea292ecd772e381393b5d
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, const SVal &location, bool isLoad, 156 CheckerContext &C) { 157 ((const CHECKER *)checker)->checkLocation(location, isLoad, C); 158 } 159 160public: 161 template <typename CHECKER> 162 static void _register(CHECKER *checker, CheckerManager &mgr) { 163 mgr._registerForLocation( 164 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 165 } 166}; 167 168class Bind { 169 template <typename CHECKER> 170 static void _checkBind(void *checker, const SVal &location, const SVal &val, 171 CheckerContext &C) { 172 ((const CHECKER *)checker)->checkBind(location, val, C); 173 } 174 175public: 176 template <typename CHECKER> 177 static void _register(CHECKER *checker, CheckerManager &mgr) { 178 mgr._registerForBind( 179 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 180 } 181}; 182 183class EndAnalysis { 184 template <typename CHECKER> 185 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 186 BugReporter &BR, ExprEngine &Eng) { 187 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 188 } 189 190public: 191 template <typename CHECKER> 192 static void _register(CHECKER *checker, CheckerManager &mgr) { 193 mgr._registerForEndAnalysis( 194 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 195 } 196}; 197 198class EndPath { 199 template <typename CHECKER> 200 static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B, 201 ExprEngine &Eng) { 202 ((const CHECKER *)checker)->checkEndPath(B, Eng); 203 } 204 205public: 206 template <typename CHECKER> 207 static void _register(CHECKER *checker, CheckerManager &mgr) { 208 mgr._registerForEndPath( 209 CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>)); 210 } 211}; 212 213class BranchCondition { 214 template <typename CHECKER> 215 static void _checkBranchCondition(void *checker, const Stmt *condition, 216 BranchNodeBuilder &B, ExprEngine &Eng) { 217 ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng); 218 } 219 220public: 221 template <typename CHECKER> 222 static void _register(CHECKER *checker, CheckerManager &mgr) { 223 mgr._registerForBranchCondition( 224 CheckerManager::CheckBranchConditionFunc(checker, 225 _checkBranchCondition<CHECKER>)); 226 } 227}; 228 229class LiveSymbols { 230 template <typename CHECKER> 231 static void _checkLiveSymbols(void *checker, const ProgramState *state, 232 SymbolReaper &SR) { 233 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 234 } 235 236public: 237 template <typename CHECKER> 238 static void _register(CHECKER *checker, CheckerManager &mgr) { 239 mgr._registerForLiveSymbols( 240 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 241 } 242}; 243 244class DeadSymbols { 245 template <typename CHECKER> 246 static void _checkDeadSymbols(void *checker, 247 SymbolReaper &SR, CheckerContext &C) { 248 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 249 } 250 251public: 252 template <typename CHECKER> 253 static void _register(CHECKER *checker, CheckerManager &mgr) { 254 mgr._registerForDeadSymbols( 255 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 256 } 257}; 258 259class RegionChanges { 260 template <typename CHECKER> 261 static const ProgramState * 262 _checkRegionChanges(void *checker, 263 const ProgramState *state, 264 const StoreManager::InvalidatedSymbols *invalidated, 265 ArrayRef<const MemRegion *> Explicits, 266 ArrayRef<const MemRegion *> Regions) { 267 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 268 Explicits, Regions); 269 } 270 template <typename CHECKER> 271 static bool _wantsRegionChangeUpdate(void *checker, 272 const ProgramState *state) { 273 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 274 } 275 276public: 277 template <typename CHECKER> 278 static void _register(CHECKER *checker, CheckerManager &mgr) { 279 mgr._registerForRegionChanges( 280 CheckerManager::CheckRegionChangesFunc(checker, 281 _checkRegionChanges<CHECKER>), 282 CheckerManager::WantsRegionChangeUpdateFunc(checker, 283 _wantsRegionChangeUpdate<CHECKER>)); 284 } 285}; 286 287template <typename EVENT> 288class Event { 289 template <typename CHECKER> 290 static void _checkEvent(void *checker, const void *event) { 291 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 292 } 293public: 294 template <typename CHECKER> 295 static void _register(CHECKER *checker, CheckerManager &mgr) { 296 mgr._registerListenerForEvent<EVENT>( 297 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 298 } 299}; 300 301} // end check namespace 302 303namespace eval { 304 305class Assume { 306 template <typename CHECKER> 307 static const ProgramState *_evalAssume(void *checker, 308 const ProgramState *state, 309 const SVal &cond, 310 bool assumption) { 311 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 312 } 313 314public: 315 template <typename CHECKER> 316 static void _register(CHECKER *checker, CheckerManager &mgr) { 317 mgr._registerForEvalAssume( 318 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 319 } 320}; 321 322class Call { 323 template <typename CHECKER> 324 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 325 return ((const CHECKER *)checker)->evalCall(CE, C); 326 } 327 328public: 329 template <typename CHECKER> 330 static void _register(CHECKER *checker, CheckerManager &mgr) { 331 mgr._registerForEvalCall( 332 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 333 } 334}; 335 336class InlineCall { 337 template <typename CHECKER> 338 static bool _inlineCall(void *checker, const CallExpr *CE, 339 ExprEngine &Eng, 340 ExplodedNode *Pred, 341 ExplodedNodeSet &Dst) { 342 return ((const CHECKER *)checker)->inlineCall(CE, Eng, Pred, Dst); 343 } 344 345public: 346 template <typename CHECKER> 347 static void _register(CHECKER *checker, CheckerManager &mgr) { 348 mgr._registerForInlineCall( 349 CheckerManager::InlineCallFunc(checker, _inlineCall<CHECKER>)); 350 } 351}; 352 353} // end eval namespace 354 355class CheckerBase : public ProgramPointTag { 356public: 357 StringRef getTagDescription() const; 358 359 /// See CheckerManager::runCheckersForPrintState. 360 virtual void printState(raw_ostream &Out, const ProgramState *State, 361 const char *NL, const char *Sep) const { } 362}; 363 364template <typename CHECK1, typename CHECK2=check::_VoidCheck, 365 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 366 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 367 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 368 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 369 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, 370 typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, 371 typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck> 372class Checker; 373 374template <> 375class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 376 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 377 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 378 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 379 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 380 check::_VoidCheck> 381 : public CheckerBase 382{ 383public: 384 static void _register(void *checker, CheckerManager &mgr) { } 385}; 386 387template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 388 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 389 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, 390 typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16> 391class Checker 392 : public CHECK1, 393 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 394 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 395 CHECK16> { 396public: 397 template <typename CHECKER> 398 static void _register(CHECKER *checker, CheckerManager &mgr) { 399 CHECK1::_register(checker, mgr); 400 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 401 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 402 CHECK16>::_register(checker, mgr); 403 } 404}; 405 406template <typename EVENT> 407class EventDispatcher { 408 CheckerManager *Mgr; 409public: 410 EventDispatcher() : Mgr(0) { } 411 412 template <typename CHECKER> 413 static void _register(CHECKER *checker, CheckerManager &mgr) { 414 mgr._registerDispatcherForEvent<EVENT>(); 415 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 416 } 417 418 void dispatchEvent(const EVENT &event) const { 419 Mgr->_dispatchEvent(event); 420 } 421}; 422 423/// \brief We dereferenced a location that may be null. 424struct ImplicitNullDerefEvent { 425 SVal Location; 426 bool IsLoad; 427 ExplodedNode *SinkNode; 428 BugReporter *BR; 429}; 430 431} // end ento namespace 432 433} // end clang namespace 434 435#endif 436