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/StaticAnalyzer/Core/CheckerManager.h" 18 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" 19 #include "llvm/Support/Casting.h" 20 21 namespace clang { 22 namespace ento { 23 class BugReporter; 24 25 namespace check { 26 27 struct _VoidCheck { 28 static void _register(void *checker, CheckerManager &mgr) { } 29 }; 30 31 template <typename DECL> 32 class ASTDecl { 33 template <typename CHECKER> 34 static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, 35 BugReporter &BR) { 36 ((const CHECKER *)checker)->checkASTDecl(llvm::cast<DECL>(D), mgr, BR); 37 } 38 39 static bool _handlesDecl(const Decl *D) { 40 return llvm::isa<DECL>(D); 41 } 42 public: 43 template <typename CHECKER> 44 static void _register(CHECKER *checker, CheckerManager &mgr) { 45 mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, 46 _checkDecl<CHECKER>), 47 _handlesDecl); 48 } 49 }; 50 51 class ASTCodeBody { 52 template <typename CHECKER> 53 static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, 54 BugReporter &BR) { 55 ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); 56 } 57 58 public: 59 template <typename CHECKER> 60 static void _register(CHECKER *checker, CheckerManager &mgr) { 61 mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, 62 _checkBody<CHECKER>)); 63 } 64 }; 65 66 class EndOfTranslationUnit { 67 template <typename CHECKER> 68 static void _checkEndOfTranslationUnit(void *checker, 69 const TranslationUnitDecl *TU, 70 AnalysisManager& mgr, 71 BugReporter &BR) { 72 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); 73 } 74 75 public: 76 template <typename CHECKER> 77 static void _register(CHECKER *checker, CheckerManager &mgr){ 78 mgr._registerForEndOfTranslationUnit( 79 CheckerManager::CheckEndOfTranslationUnit(checker, 80 _checkEndOfTranslationUnit<CHECKER>)); 81 } 82 }; 83 84 template <typename STMT> 85 class PreStmt { 86 template <typename CHECKER> 87 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 88 ((const CHECKER *)checker)->checkPreStmt(llvm::cast<STMT>(S), C); 89 } 90 91 static bool _handlesStmt(const Stmt *S) { 92 return llvm::isa<STMT>(S); 93 } 94 public: 95 template <typename CHECKER> 96 static void _register(CHECKER *checker, CheckerManager &mgr) { 97 mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, 98 _checkStmt<CHECKER>), 99 _handlesStmt); 100 } 101 }; 102 103 template <typename STMT> 104 class PostStmt { 105 template <typename CHECKER> 106 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 107 ((const CHECKER *)checker)->checkPostStmt(llvm::cast<STMT>(S), C); 108 } 109 110 static bool _handlesStmt(const Stmt *S) { 111 return llvm::isa<STMT>(S); 112 } 113 public: 114 template <typename CHECKER> 115 static void _register(CHECKER *checker, CheckerManager &mgr) { 116 mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, 117 _checkStmt<CHECKER>), 118 _handlesStmt); 119 } 120 }; 121 122 class PreObjCMessage { 123 template <typename CHECKER> 124 static void _checkObjCMessage(void *checker, const ObjCMessage &msg, 125 CheckerContext &C) { 126 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); 127 } 128 129 public: 130 template <typename CHECKER> 131 static void _register(CHECKER *checker, CheckerManager &mgr) { 132 mgr._registerForPreObjCMessage( 133 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 134 } 135 }; 136 137 class PostObjCMessage { 138 template <typename CHECKER> 139 static void _checkObjCMessage(void *checker, const ObjCMessage &msg, 140 CheckerContext &C) { 141 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); 142 } 143 144 public: 145 template <typename CHECKER> 146 static void _register(CHECKER *checker, CheckerManager &mgr) { 147 mgr._registerForPostObjCMessage( 148 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 149 } 150 }; 151 152 class Location { 153 template <typename CHECKER> 154 static void _checkLocation(void *checker, const SVal &location, bool isLoad, 155 CheckerContext &C) { 156 ((const CHECKER *)checker)->checkLocation(location, isLoad, C); 157 } 158 159 public: 160 template <typename CHECKER> 161 static void _register(CHECKER *checker, CheckerManager &mgr) { 162 mgr._registerForLocation( 163 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 164 } 165 }; 166 167 class Bind { 168 template <typename CHECKER> 169 static void _checkBind(void *checker, const SVal &location, const SVal &val, 170 CheckerContext &C) { 171 ((const CHECKER *)checker)->checkBind(location, val, C); 172 } 173 174 public: 175 template <typename CHECKER> 176 static void _register(CHECKER *checker, CheckerManager &mgr) { 177 mgr._registerForBind( 178 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 179 } 180 }; 181 182 class EndAnalysis { 183 template <typename CHECKER> 184 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 185 BugReporter &BR, ExprEngine &Eng) { 186 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 187 } 188 189 public: 190 template <typename CHECKER> 191 static void _register(CHECKER *checker, CheckerManager &mgr) { 192 mgr._registerForEndAnalysis( 193 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 194 } 195 }; 196 197 class EndPath { 198 template <typename CHECKER> 199 static void _checkEndPath(void *checker, EndOfFunctionNodeBuilder &B, 200 ExprEngine &Eng) { 201 ((const CHECKER *)checker)->checkEndPath(B, Eng); 202 } 203 204 public: 205 template <typename CHECKER> 206 static void _register(CHECKER *checker, CheckerManager &mgr) { 207 mgr._registerForEndPath( 208 CheckerManager::CheckEndPathFunc(checker, _checkEndPath<CHECKER>)); 209 } 210 }; 211 212 class BranchCondition { 213 template <typename CHECKER> 214 static void _checkBranchCondition(void *checker, const Stmt *condition, 215 BranchNodeBuilder &B, ExprEngine &Eng) { 216 ((const CHECKER *)checker)->checkBranchCondition(condition, B, Eng); 217 } 218 219 public: 220 template <typename CHECKER> 221 static void _register(CHECKER *checker, CheckerManager &mgr) { 222 mgr._registerForBranchCondition( 223 CheckerManager::CheckBranchConditionFunc(checker, 224 _checkBranchCondition<CHECKER>)); 225 } 226 }; 227 228 class LiveSymbols { 229 template <typename CHECKER> 230 static void _checkLiveSymbols(void *checker, const GRState *state, 231 SymbolReaper &SR) { 232 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 233 } 234 235 public: 236 template <typename CHECKER> 237 static void _register(CHECKER *checker, CheckerManager &mgr) { 238 mgr._registerForLiveSymbols( 239 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 240 } 241 }; 242 243 class DeadSymbols { 244 template <typename CHECKER> 245 static void _checkDeadSymbols(void *checker, 246 SymbolReaper &SR, CheckerContext &C) { 247 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 248 } 249 250 public: 251 template <typename CHECKER> 252 static void _register(CHECKER *checker, CheckerManager &mgr) { 253 mgr._registerForDeadSymbols( 254 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 255 } 256 }; 257 258 class RegionChanges { 259 template <typename CHECKER> 260 static const GRState *_checkRegionChanges(void *checker, const GRState *state, 261 const StoreManager::InvalidatedSymbols *invalidated, 262 const MemRegion * const *Begin, 263 const MemRegion * const *End) { 264 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 265 Begin, End); 266 } 267 template <typename CHECKER> 268 static bool _wantsRegionChangeUpdate(void *checker, const GRState *state) { 269 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 270 } 271 272 public: 273 template <typename CHECKER> 274 static void _register(CHECKER *checker, CheckerManager &mgr) { 275 mgr._registerForRegionChanges( 276 CheckerManager::CheckRegionChangesFunc(checker, 277 _checkRegionChanges<CHECKER>), 278 CheckerManager::WantsRegionChangeUpdateFunc(checker, 279 _wantsRegionChangeUpdate<CHECKER>)); 280 } 281 }; 282 283 template <typename EVENT> 284 class Event { 285 template <typename CHECKER> 286 static void _checkEvent(void *checker, const void *event) { 287 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 288 } 289 public: 290 template <typename CHECKER> 291 static void _register(CHECKER *checker, CheckerManager &mgr) { 292 mgr._registerListenerForEvent<EVENT>( 293 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 294 } 295 }; 296 297 } // end check namespace 298 299 namespace eval { 300 301 class Assume { 302 template <typename CHECKER> 303 static const GRState *_evalAssume(void *checker, const GRState *state, 304 const SVal &cond, bool assumption) { 305 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 306 } 307 308 public: 309 template <typename CHECKER> 310 static void _register(CHECKER *checker, CheckerManager &mgr) { 311 mgr._registerForEvalAssume( 312 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 313 } 314 }; 315 316 class Call { 317 template <typename CHECKER> 318 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 319 return ((const CHECKER *)checker)->evalCall(CE, C); 320 } 321 322 public: 323 template <typename CHECKER> 324 static void _register(CHECKER *checker, CheckerManager &mgr) { 325 mgr._registerForEvalCall( 326 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 327 } 328 }; 329 330 } // end eval namespace 331 332 template <typename CHECK1, typename CHECK2=check::_VoidCheck, 333 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 334 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 335 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 336 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 337 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck> 338 class Checker; 339 340 template <> 341 class Checker<check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 342 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 343 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck, 344 check::_VoidCheck, check::_VoidCheck, check::_VoidCheck> { 345 public: 346 static void _register(void *checker, CheckerManager &mgr) { } 347 }; 348 349 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 350 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 351 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12> 352 class Checker 353 : public CHECK1, 354 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, 355 CHECK9, CHECK10, CHECK11, CHECK12> { 356 public: 357 template <typename CHECKER> 358 static void _register(CHECKER *checker, CheckerManager &mgr) { 359 CHECK1::_register(checker, mgr); 360 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, CHECK8, CHECK9, 361 CHECK10, CHECK11,CHECK12>::_register(checker, mgr); 362 } 363 }; 364 365 template <typename EVENT> 366 class EventDispatcher { 367 CheckerManager *Mgr; 368 public: 369 EventDispatcher() : Mgr(0) { } 370 371 template <typename CHECKER> 372 static void _register(CHECKER *checker, CheckerManager &mgr) { 373 mgr._registerDispatcherForEvent<EVENT>(); 374 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 375 } 376 377 void dispatchEvent(const EVENT &event) const { 378 Mgr->_dispatchEvent(event); 379 } 380 }; 381 382 /// \brief We dereferenced a location that may be null. 383 struct ImplicitNullDerefEvent { 384 SVal Location; 385 bool IsLoad; 386 ExplodedNode *SinkNode; 387 BugReporter *BR; 388 }; 389 390 } // end ento namespace 391 392 } // end clang namespace 393 394 #endif 395