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, 203 CheckerContext &C) { 204 ((const CHECKER *)checker)->checkEndPath(C); 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 CheckerContext & C) { 219 ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 220 } 221 222 public: 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 231 class LiveSymbols { 232 template <typename CHECKER> 233 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 234 SymbolReaper &SR) { 235 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 236 } 237 238 public: 239 template <typename CHECKER> 240 static void _register(CHECKER *checker, CheckerManager &mgr) { 241 mgr._registerForLiveSymbols( 242 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 243 } 244 }; 245 246 class 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 253 public: 254 template <typename CHECKER> 255 static void _register(CHECKER *checker, CheckerManager &mgr) { 256 mgr._registerForDeadSymbols( 257 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 258 } 259 }; 260 261 class RegionChanges { 262 template <typename CHECKER> 263 static ProgramStateRef 264 _checkRegionChanges(void *checker, 265 ProgramStateRef state, 266 const StoreManager::InvalidatedSymbols *invalidated, 267 ArrayRef<const MemRegion *> Explicits, 268 ArrayRef<const MemRegion *> Regions, 269 const CallOrObjCMessage *Call) { 270 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 271 Explicits, Regions, Call); 272 } 273 template <typename CHECKER> 274 static bool _wantsRegionChangeUpdate(void *checker, 275 ProgramStateRef 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 ProgramStateRef _evalAssume(void *checker, 311 ProgramStateRef 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, ProgramStateRef 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 typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck> 376 class Checker; 377 378 template <> 379 class Checker<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 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> 385 : public CheckerBase 386 { 387 virtual void anchor(); 388 public: 389 static void _register(void *checker, CheckerManager &mgr) { } 390 }; 391 392 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 393 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 394 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, 395 typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16, 396 typename CHECK17,typename CHECK18> 397 class Checker 398 : public CHECK1, 399 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 400 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 401 CHECK16,CHECK17,CHECK18> { 402 public: 403 template <typename CHECKER> 404 static void _register(CHECKER *checker, CheckerManager &mgr) { 405 CHECK1::_register(checker, mgr); 406 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 407 CHECK9, CHECK10,CHECK11,CHECK12,CHECK13,CHECK14,CHECK15, 408 CHECK16,CHECK17,CHECK18>::_register(checker, mgr); 409 } 410 }; 411 412 template <typename EVENT> 413 class EventDispatcher { 414 CheckerManager *Mgr; 415 public: 416 EventDispatcher() : Mgr(0) { } 417 418 template <typename CHECKER> 419 static void _register(CHECKER *checker, CheckerManager &mgr) { 420 mgr._registerDispatcherForEvent<EVENT>(); 421 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 422 } 423 424 void dispatchEvent(const EVENT &event) const { 425 Mgr->_dispatchEvent(event); 426 } 427 }; 428 429 /// \brief We dereferenced a location that may be null. 430 struct ImplicitNullDerefEvent { 431 SVal Location; 432 bool IsLoad; 433 ExplodedNode *SinkNode; 434 BugReporter *BR; 435 }; 436 437 } // end ento namespace 438 439 } // end clang namespace 440 441 #endif 442