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 22 namespace clang { 23 namespace ento { 24 class BugReporter; 25 26 namespace check { 27 28 struct _VoidCheck { 29 static void _register(void *checker, CheckerManager &mgr) { } 30 }; 31 32 template <typename DECL> 33 class 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 } 43 public: 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 52 class 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 59 public: 60 template <typename CHECKER> 61 static void _register(CHECKER *checker, CheckerManager &mgr) { 62 mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, 63 _checkBody<CHECKER>)); 64 } 65 }; 66 67 class 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 76 public: 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 85 template <typename STMT> 86 class 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 } 95 public: 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 104 template <typename STMT> 105 class 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 } 114 public: 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 123 class 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 130 public: 131 template <typename CHECKER> 132 static void _register(CHECKER *checker, CheckerManager &mgr) { 133 mgr._registerForPreObjCMessage( 134 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 135 } 136 }; 137 138 class 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 145 public: 146 template <typename CHECKER> 147 static void _register(CHECKER *checker, CheckerManager &mgr) { 148 mgr._registerForPostObjCMessage( 149 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 150 } 151 }; 152 153 class 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 161 public: 162 template <typename CHECKER> 163 static void _register(CHECKER *checker, CheckerManager &mgr) { 164 mgr._registerForLocation( 165 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 166 } 167 }; 168 169 class 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 177 public: 178 template <typename CHECKER> 179 static void _register(CHECKER *checker, CheckerManager &mgr) { 180 mgr._registerForBind( 181 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 182 } 183 }; 184 185 class 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 192 public: 193 template <typename CHECKER> 194 static void _register(CHECKER *checker, CheckerManager &mgr) { 195 mgr._registerForEndAnalysis( 196 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 197 } 198 }; 199 200 class EndPath { 201 template <typename CHECKER> 202 static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B, 203 ExprEngine &Eng) { 204 ((const CHECKER *)checker)->checkEndPath(B, Eng); 205 } 206 207 public: 208 template <typename CHECKER> 209 static void _register(CHECKER *checker, CheckerManager &mgr) { 210 mgr._registerForEndPath( 211 CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>)); 212 } 213 }; 214 215 class 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 223 public: 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 232 class 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 239 public: 240 template <typename CHECKER> 241 static void _register(CHECKER *checker, CheckerManager &mgr) { 242 mgr._registerForLiveSymbols( 243 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 244 } 245 }; 246 247 class 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 254 public: 255 template <typename CHECKER> 256 static void _register(CHECKER *checker, CheckerManager &mgr) { 257 mgr._registerForDeadSymbols( 258 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 259 } 260 }; 261 262 class 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 279 public: 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 290 template <typename EVENT> 291 class Event { 292 template <typename CHECKER> 293 static void _checkEvent(void *checker, const void *event) { 294 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 295 } 296 public: 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 306 namespace eval { 307 308 class 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 317 public: 318 template <typename CHECKER> 319 static void _register(CHECKER *checker, CheckerManager &mgr) { 320 mgr._registerForEvalAssume( 321 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 322 } 323 }; 324 325 class 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 331 public: 332 template <typename CHECKER> 333 static void _register(CHECKER *checker, CheckerManager &mgr) { 334 mgr._registerForEvalCall( 335 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 336 } 337 }; 338 339 class 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 348 public: 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 358 class CheckerBase : public ProgramPointTag { 359 public: 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 367 template <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> 375 class Checker; 376 377 template <> 378 class 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 { 386 public: 387 static void _register(void *checker, CheckerManager &mgr) { } 388 }; 389 390 template <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 class Checker 395 : public CHECK1, 396 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 397 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 398 CHECK16> { 399 public: 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 409 template <typename EVENT> 410 class EventDispatcher { 411 CheckerManager *Mgr; 412 public: 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. 427 struct 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