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(cast<DECL>(D), mgr, BR); 38 } 39 40 static bool _handlesDecl(const Decl *D) { 41 return 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(cast<STMT>(S), C); 90 } 91 92 static bool _handlesStmt(const Stmt *S) { 93 return 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(cast<STMT>(S), C); 109 } 110 111 static bool _handlesStmt(const Stmt *S) { 112 return 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 ObjCMethodCall &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 ObjCMethodCall &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 PreCall { 154 template <typename CHECKER> 155 static void _checkCall(void *checker, const CallEvent &msg, 156 CheckerContext &C) { 157 ((const CHECKER *)checker)->checkPreCall(msg, C); 158 } 159 160 public: 161 template <typename CHECKER> 162 static void _register(CHECKER *checker, CheckerManager &mgr) { 163 mgr._registerForPreCall( 164 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 165 } 166 }; 167 168 class PostCall { 169 template <typename CHECKER> 170 static void _checkCall(void *checker, const CallEvent &msg, 171 CheckerContext &C) { 172 ((const CHECKER *)checker)->checkPostCall(msg, C); 173 } 174 175 public: 176 template <typename CHECKER> 177 static void _register(CHECKER *checker, CheckerManager &mgr) { 178 mgr._registerForPostCall( 179 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 180 } 181 }; 182 183 class Location { 184 template <typename CHECKER> 185 static void _checkLocation(void *checker, 186 const SVal &location, bool isLoad, const Stmt *S, 187 CheckerContext &C) { 188 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); 189 } 190 191 public: 192 template <typename CHECKER> 193 static void _register(CHECKER *checker, CheckerManager &mgr) { 194 mgr._registerForLocation( 195 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 196 } 197 }; 198 199 class Bind { 200 template <typename CHECKER> 201 static void _checkBind(void *checker, 202 const SVal &location, const SVal &val, const Stmt *S, 203 CheckerContext &C) { 204 ((const CHECKER *)checker)->checkBind(location, val, S, C); 205 } 206 207 public: 208 template <typename CHECKER> 209 static void _register(CHECKER *checker, CheckerManager &mgr) { 210 mgr._registerForBind( 211 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 212 } 213 }; 214 215 class EndAnalysis { 216 template <typename CHECKER> 217 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 218 BugReporter &BR, ExprEngine &Eng) { 219 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 220 } 221 222 public: 223 template <typename CHECKER> 224 static void _register(CHECKER *checker, CheckerManager &mgr) { 225 mgr._registerForEndAnalysis( 226 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 227 } 228 }; 229 230 class EndFunction { 231 template <typename CHECKER> 232 static void _checkEndFunction(void *checker, 233 CheckerContext &C) { 234 ((const CHECKER *)checker)->checkEndFunction(C); 235 } 236 237 public: 238 template <typename CHECKER> 239 static void _register(CHECKER *checker, CheckerManager &mgr) { 240 mgr._registerForEndFunction( 241 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); 242 } 243 }; 244 245 class BranchCondition { 246 template <typename CHECKER> 247 static void _checkBranchCondition(void *checker, const Stmt *Condition, 248 CheckerContext & C) { 249 ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 250 } 251 252 public: 253 template <typename CHECKER> 254 static void _register(CHECKER *checker, CheckerManager &mgr) { 255 mgr._registerForBranchCondition( 256 CheckerManager::CheckBranchConditionFunc(checker, 257 _checkBranchCondition<CHECKER>)); 258 } 259 }; 260 261 class LiveSymbols { 262 template <typename CHECKER> 263 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 264 SymbolReaper &SR) { 265 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 266 } 267 268 public: 269 template <typename CHECKER> 270 static void _register(CHECKER *checker, CheckerManager &mgr) { 271 mgr._registerForLiveSymbols( 272 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 273 } 274 }; 275 276 class DeadSymbols { 277 template <typename CHECKER> 278 static void _checkDeadSymbols(void *checker, 279 SymbolReaper &SR, CheckerContext &C) { 280 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 281 } 282 283 public: 284 template <typename CHECKER> 285 static void _register(CHECKER *checker, CheckerManager &mgr) { 286 mgr._registerForDeadSymbols( 287 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 288 } 289 }; 290 291 class RegionChanges { 292 template <typename CHECKER> 293 static ProgramStateRef 294 _checkRegionChanges(void *checker, 295 ProgramStateRef state, 296 const InvalidatedSymbols *invalidated, 297 ArrayRef<const MemRegion *> Explicits, 298 ArrayRef<const MemRegion *> Regions, 299 const CallEvent *Call) { 300 return ((const CHECKER *)checker)->checkRegionChanges(state, invalidated, 301 Explicits, Regions, Call); 302 } 303 template <typename CHECKER> 304 static bool _wantsRegionChangeUpdate(void *checker, 305 ProgramStateRef state) { 306 return ((const CHECKER *)checker)->wantsRegionChangeUpdate(state); 307 } 308 309 public: 310 template <typename CHECKER> 311 static void _register(CHECKER *checker, CheckerManager &mgr) { 312 mgr._registerForRegionChanges( 313 CheckerManager::CheckRegionChangesFunc(checker, 314 _checkRegionChanges<CHECKER>), 315 CheckerManager::WantsRegionChangeUpdateFunc(checker, 316 _wantsRegionChangeUpdate<CHECKER>)); 317 } 318 }; 319 320 class PointerEscape { 321 template <typename CHECKER> 322 static ProgramStateRef 323 _checkPointerEscape(void *checker, 324 ProgramStateRef State, 325 const InvalidatedSymbols &Escaped, 326 const CallEvent *Call, 327 PointerEscapeKind Kind, 328 bool IsConst) { 329 if (!IsConst) 330 return ((const CHECKER *)checker)->checkPointerEscape(State, 331 Escaped, 332 Call, 333 Kind); 334 return State; 335 } 336 337 public: 338 template <typename CHECKER> 339 static void _register(CHECKER *checker, CheckerManager &mgr) { 340 mgr._registerForPointerEscape( 341 CheckerManager::CheckPointerEscapeFunc(checker, 342 _checkPointerEscape<CHECKER>)); 343 } 344 }; 345 346 class ConstPointerEscape { 347 template <typename CHECKER> 348 static ProgramStateRef 349 _checkConstPointerEscape(void *checker, 350 ProgramStateRef State, 351 const InvalidatedSymbols &Escaped, 352 const CallEvent *Call, 353 PointerEscapeKind Kind, 354 bool IsConst) { 355 if (IsConst) 356 return ((const CHECKER *)checker)->checkConstPointerEscape(State, 357 Escaped, 358 Call, 359 Kind); 360 return State; 361 } 362 363 public: 364 template <typename CHECKER> 365 static void _register(CHECKER *checker, CheckerManager &mgr) { 366 mgr._registerForPointerEscape( 367 CheckerManager::CheckPointerEscapeFunc(checker, 368 _checkConstPointerEscape<CHECKER>)); 369 } 370 }; 371 372 373 template <typename EVENT> 374 class Event { 375 template <typename CHECKER> 376 static void _checkEvent(void *checker, const void *event) { 377 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 378 } 379 public: 380 template <typename CHECKER> 381 static void _register(CHECKER *checker, CheckerManager &mgr) { 382 mgr._registerListenerForEvent<EVENT>( 383 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 384 } 385 }; 386 387 } // end check namespace 388 389 namespace eval { 390 391 class Assume { 392 template <typename CHECKER> 393 static ProgramStateRef _evalAssume(void *checker, 394 ProgramStateRef state, 395 const SVal &cond, 396 bool assumption) { 397 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 398 } 399 400 public: 401 template <typename CHECKER> 402 static void _register(CHECKER *checker, CheckerManager &mgr) { 403 mgr._registerForEvalAssume( 404 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 405 } 406 }; 407 408 class Call { 409 template <typename CHECKER> 410 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 411 return ((const CHECKER *)checker)->evalCall(CE, C); 412 } 413 414 public: 415 template <typename CHECKER> 416 static void _register(CHECKER *checker, CheckerManager &mgr) { 417 mgr._registerForEvalCall( 418 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 419 } 420 }; 421 422 } // end eval namespace 423 424 class CheckerBase : public ProgramPointTag { 425 public: 426 StringRef getTagDescription() const; 427 428 /// See CheckerManager::runCheckersForPrintState. 429 virtual void printState(raw_ostream &Out, ProgramStateRef State, 430 const char *NL, const char *Sep) const { } 431 }; 432 433 template <typename CHECK1, typename CHECK2=check::_VoidCheck, 434 typename CHECK3=check::_VoidCheck, typename CHECK4=check::_VoidCheck, 435 typename CHECK5=check::_VoidCheck, typename CHECK6=check::_VoidCheck, 436 typename CHECK7=check::_VoidCheck, typename CHECK8=check::_VoidCheck, 437 typename CHECK9=check::_VoidCheck, typename CHECK10=check::_VoidCheck, 438 typename CHECK11=check::_VoidCheck,typename CHECK12=check::_VoidCheck, 439 typename CHECK13=check::_VoidCheck,typename CHECK14=check::_VoidCheck, 440 typename CHECK15=check::_VoidCheck,typename CHECK16=check::_VoidCheck, 441 typename CHECK17=check::_VoidCheck,typename CHECK18=check::_VoidCheck, 442 typename CHECK19=check::_VoidCheck,typename CHECK20=check::_VoidCheck, 443 typename CHECK21=check::_VoidCheck,typename CHECK22=check::_VoidCheck, 444 typename CHECK23=check::_VoidCheck,typename CHECK24=check::_VoidCheck> 445 class Checker; 446 447 template <> 448 class Checker<check::_VoidCheck> 449 : public CheckerBase 450 { 451 virtual void anchor(); 452 public: 453 static void _register(void *checker, CheckerManager &mgr) { } 454 }; 455 456 template <typename CHECK1, typename CHECK2, typename CHECK3, typename CHECK4, 457 typename CHECK5, typename CHECK6, typename CHECK7, typename CHECK8, 458 typename CHECK9, typename CHECK10,typename CHECK11,typename CHECK12, 459 typename CHECK13,typename CHECK14,typename CHECK15,typename CHECK16, 460 typename CHECK17,typename CHECK18,typename CHECK19,typename CHECK20, 461 typename CHECK21,typename CHECK22,typename CHECK23,typename CHECK24> 462 class Checker 463 : public CHECK1, 464 public Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, 465 CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, 466 CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, 467 CHECK20,CHECK21,CHECK22,CHECK23,CHECK24> { 468 public: 469 template <typename CHECKER> 470 static void _register(CHECKER *checker, CheckerManager &mgr) { 471 CHECK1::_register(checker, mgr); 472 Checker<CHECK2, CHECK3, CHECK4, CHECK5, CHECK6, CHECK7, 473 CHECK8, CHECK9, CHECK10,CHECK11,CHECK12,CHECK13, 474 CHECK14,CHECK15,CHECK16,CHECK17,CHECK18,CHECK19, 475 CHECK20,CHECK21,CHECK22,CHECK23,CHECK24>::_register(checker, mgr); 476 } 477 }; 478 479 template <typename EVENT> 480 class EventDispatcher { 481 CheckerManager *Mgr; 482 public: 483 EventDispatcher() : Mgr(0) { } 484 485 template <typename CHECKER> 486 static void _register(CHECKER *checker, CheckerManager &mgr) { 487 mgr._registerDispatcherForEvent<EVENT>(); 488 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 489 } 490 491 void dispatchEvent(const EVENT &event) const { 492 Mgr->_dispatchEvent(event); 493 } 494 }; 495 496 /// \brief We dereferenced a location that may be null. 497 struct ImplicitNullDerefEvent { 498 SVal Location; 499 bool IsLoad; 500 ExplodedNode *SinkNode; 501 BugReporter *BR; 502 }; 503 504 /// \brief A helper class which wraps a boolean value set to false by default. 505 /// 506 /// This class should behave exactly like 'bool' except that it doesn't need to 507 /// be explicitly initialized. 508 struct DefaultBool { 509 bool val; 510 DefaultBool() : val(false) {} 511 /*implicit*/ operator bool&() { return val; } 512 /*implicit*/ operator const bool&() const { return val; } 513 DefaultBool &operator=(bool b) { val = b; return *this; } 514 }; 515 516 } // end ento namespace 517 518 } // end clang namespace 519 520 #endif 521