Checker.h revision f3014761c955345d6e05491608e73228d014afb7
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_STATICANALYZER_CORE_CHECKER_H 15#define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H 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 28template <typename DECL> 29class ASTDecl { 30 template <typename CHECKER> 31 static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, 32 BugReporter &BR) { 33 ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR); 34 } 35 36 static bool _handlesDecl(const Decl *D) { 37 return isa<DECL>(D); 38 } 39public: 40 template <typename CHECKER> 41 static void _register(CHECKER *checker, CheckerManager &mgr) { 42 mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, 43 _checkDecl<CHECKER>), 44 _handlesDecl); 45 } 46}; 47 48class ASTCodeBody { 49 template <typename CHECKER> 50 static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, 51 BugReporter &BR) { 52 ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); 53 } 54 55public: 56 template <typename CHECKER> 57 static void _register(CHECKER *checker, CheckerManager &mgr) { 58 mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, 59 _checkBody<CHECKER>)); 60 } 61}; 62 63class EndOfTranslationUnit { 64 template <typename CHECKER> 65 static void _checkEndOfTranslationUnit(void *checker, 66 const TranslationUnitDecl *TU, 67 AnalysisManager& mgr, 68 BugReporter &BR) { 69 ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); 70 } 71 72public: 73 template <typename CHECKER> 74 static void _register(CHECKER *checker, CheckerManager &mgr){ 75 mgr._registerForEndOfTranslationUnit( 76 CheckerManager::CheckEndOfTranslationUnit(checker, 77 _checkEndOfTranslationUnit<CHECKER>)); 78 } 79}; 80 81template <typename STMT> 82class PreStmt { 83 template <typename CHECKER> 84 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 85 ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C); 86 } 87 88 static bool _handlesStmt(const Stmt *S) { 89 return isa<STMT>(S); 90 } 91public: 92 template <typename CHECKER> 93 static void _register(CHECKER *checker, CheckerManager &mgr) { 94 mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, 95 _checkStmt<CHECKER>), 96 _handlesStmt); 97 } 98}; 99 100template <typename STMT> 101class PostStmt { 102 template <typename CHECKER> 103 static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { 104 ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C); 105 } 106 107 static bool _handlesStmt(const Stmt *S) { 108 return isa<STMT>(S); 109 } 110public: 111 template <typename CHECKER> 112 static void _register(CHECKER *checker, CheckerManager &mgr) { 113 mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, 114 _checkStmt<CHECKER>), 115 _handlesStmt); 116 } 117}; 118 119class PreObjCMessage { 120 template <typename CHECKER> 121 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 122 CheckerContext &C) { 123 ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); 124 } 125 126public: 127 template <typename CHECKER> 128 static void _register(CHECKER *checker, CheckerManager &mgr) { 129 mgr._registerForPreObjCMessage( 130 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 131 } 132}; 133 134class ObjCMessageNil { 135 template <typename CHECKER> 136 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 137 CheckerContext &C) { 138 ((const CHECKER *)checker)->checkObjCMessageNil(msg, C); 139 } 140 141public: 142 template <typename CHECKER> 143 static void _register(CHECKER *checker, CheckerManager &mgr) { 144 mgr._registerForObjCMessageNil( 145 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 146 } 147}; 148 149class PostObjCMessage { 150 template <typename CHECKER> 151 static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, 152 CheckerContext &C) { 153 ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); 154 } 155 156public: 157 template <typename CHECKER> 158 static void _register(CHECKER *checker, CheckerManager &mgr) { 159 mgr._registerForPostObjCMessage( 160 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 161 } 162}; 163 164class PreCall { 165 template <typename CHECKER> 166 static void _checkCall(void *checker, const CallEvent &msg, 167 CheckerContext &C) { 168 ((const CHECKER *)checker)->checkPreCall(msg, C); 169 } 170 171public: 172 template <typename CHECKER> 173 static void _register(CHECKER *checker, CheckerManager &mgr) { 174 mgr._registerForPreCall( 175 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 176 } 177}; 178 179class PostCall { 180 template <typename CHECKER> 181 static void _checkCall(void *checker, const CallEvent &msg, 182 CheckerContext &C) { 183 ((const CHECKER *)checker)->checkPostCall(msg, C); 184 } 185 186public: 187 template <typename CHECKER> 188 static void _register(CHECKER *checker, CheckerManager &mgr) { 189 mgr._registerForPostCall( 190 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 191 } 192}; 193 194class Location { 195 template <typename CHECKER> 196 static void _checkLocation(void *checker, 197 const SVal &location, bool isLoad, const Stmt *S, 198 CheckerContext &C) { 199 ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); 200 } 201 202public: 203 template <typename CHECKER> 204 static void _register(CHECKER *checker, CheckerManager &mgr) { 205 mgr._registerForLocation( 206 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 207 } 208}; 209 210class Bind { 211 template <typename CHECKER> 212 static void _checkBind(void *checker, 213 const SVal &location, const SVal &val, const Stmt *S, 214 CheckerContext &C) { 215 ((const CHECKER *)checker)->checkBind(location, val, S, C); 216 } 217 218public: 219 template <typename CHECKER> 220 static void _register(CHECKER *checker, CheckerManager &mgr) { 221 mgr._registerForBind( 222 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 223 } 224}; 225 226class EndAnalysis { 227 template <typename CHECKER> 228 static void _checkEndAnalysis(void *checker, ExplodedGraph &G, 229 BugReporter &BR, ExprEngine &Eng) { 230 ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); 231 } 232 233public: 234 template <typename CHECKER> 235 static void _register(CHECKER *checker, CheckerManager &mgr) { 236 mgr._registerForEndAnalysis( 237 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 238 } 239}; 240 241class BeginFunction { 242 template <typename CHECKER> 243 static void _checkBeginFunction(void *checker, CheckerContext &C) { 244 ((const CHECKER *)checker)->checkBeginFunction(C); 245 } 246 247public: 248 template <typename CHECKER> 249 static void _register(CHECKER *checker, CheckerManager &mgr) { 250 mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc( 251 checker, _checkBeginFunction<CHECKER>)); 252 } 253}; 254 255class EndFunction { 256 template <typename CHECKER> 257 static void _checkEndFunction(void *checker, 258 CheckerContext &C) { 259 ((const CHECKER *)checker)->checkEndFunction(C); 260 } 261 262public: 263 template <typename CHECKER> 264 static void _register(CHECKER *checker, CheckerManager &mgr) { 265 mgr._registerForEndFunction( 266 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); 267 } 268}; 269 270class BranchCondition { 271 template <typename CHECKER> 272 static void _checkBranchCondition(void *checker, const Stmt *Condition, 273 CheckerContext & C) { 274 ((const CHECKER *)checker)->checkBranchCondition(Condition, C); 275 } 276 277public: 278 template <typename CHECKER> 279 static void _register(CHECKER *checker, CheckerManager &mgr) { 280 mgr._registerForBranchCondition( 281 CheckerManager::CheckBranchConditionFunc(checker, 282 _checkBranchCondition<CHECKER>)); 283 } 284}; 285 286class LiveSymbols { 287 template <typename CHECKER> 288 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 289 SymbolReaper &SR) { 290 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 291 } 292 293public: 294 template <typename CHECKER> 295 static void _register(CHECKER *checker, CheckerManager &mgr) { 296 mgr._registerForLiveSymbols( 297 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 298 } 299}; 300 301class DeadSymbols { 302 template <typename CHECKER> 303 static void _checkDeadSymbols(void *checker, 304 SymbolReaper &SR, CheckerContext &C) { 305 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 306 } 307 308public: 309 template <typename CHECKER> 310 static void _register(CHECKER *checker, CheckerManager &mgr) { 311 mgr._registerForDeadSymbols( 312 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 313 } 314}; 315 316class RegionChanges { 317 template <typename CHECKER> 318 static ProgramStateRef 319 _checkRegionChanges(void *checker, 320 ProgramStateRef state, 321 const InvalidatedSymbols *invalidated, 322 ArrayRef<const MemRegion *> Explicits, 323 ArrayRef<const MemRegion *> Regions, 324 const LocationContext *LCtx, 325 const CallEvent *Call) { 326 return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, 327 Explicits, Regions, 328 LCtx, Call); 329 } 330 331public: 332 template <typename CHECKER> 333 static void _register(CHECKER *checker, CheckerManager &mgr) { 334 mgr._registerForRegionChanges( 335 CheckerManager::CheckRegionChangesFunc(checker, 336 _checkRegionChanges<CHECKER>)); 337 } 338}; 339 340class PointerEscape { 341 template <typename CHECKER> 342 static ProgramStateRef 343 _checkPointerEscape(void *Checker, 344 ProgramStateRef State, 345 const InvalidatedSymbols &Escaped, 346 const CallEvent *Call, 347 PointerEscapeKind Kind, 348 RegionAndSymbolInvalidationTraits *ETraits) { 349 350 if (!ETraits) 351 return ((const CHECKER *)Checker)->checkPointerEscape(State, 352 Escaped, 353 Call, 354 Kind); 355 356 InvalidatedSymbols RegularEscape; 357 for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 358 E = Escaped.end(); I != E; ++I) 359 if (!ETraits->hasTrait(*I, 360 RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 361 !ETraits->hasTrait(*I, 362 RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 363 RegularEscape.insert(*I); 364 365 if (RegularEscape.empty()) 366 return State; 367 368 return ((const CHECKER *)Checker)->checkPointerEscape(State, 369 RegularEscape, 370 Call, 371 Kind); 372 } 373 374public: 375 template <typename CHECKER> 376 static void _register(CHECKER *checker, CheckerManager &mgr) { 377 mgr._registerForPointerEscape( 378 CheckerManager::CheckPointerEscapeFunc(checker, 379 _checkPointerEscape<CHECKER>)); 380 } 381}; 382 383class ConstPointerEscape { 384 template <typename CHECKER> 385 static ProgramStateRef 386 _checkConstPointerEscape(void *Checker, 387 ProgramStateRef State, 388 const InvalidatedSymbols &Escaped, 389 const CallEvent *Call, 390 PointerEscapeKind Kind, 391 RegionAndSymbolInvalidationTraits *ETraits) { 392 393 if (!ETraits) 394 return State; 395 396 InvalidatedSymbols ConstEscape; 397 for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 398 E = Escaped.end(); I != E; ++I) 399 if (ETraits->hasTrait(*I, 400 RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 401 !ETraits->hasTrait(*I, 402 RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 403 ConstEscape.insert(*I); 404 405 if (ConstEscape.empty()) 406 return State; 407 408 return ((const CHECKER *)Checker)->checkConstPointerEscape(State, 409 ConstEscape, 410 Call, 411 Kind); 412 } 413 414public: 415 template <typename CHECKER> 416 static void _register(CHECKER *checker, CheckerManager &mgr) { 417 mgr._registerForPointerEscape( 418 CheckerManager::CheckPointerEscapeFunc(checker, 419 _checkConstPointerEscape<CHECKER>)); 420 } 421}; 422 423 424template <typename EVENT> 425class Event { 426 template <typename CHECKER> 427 static void _checkEvent(void *checker, const void *event) { 428 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 429 } 430public: 431 template <typename CHECKER> 432 static void _register(CHECKER *checker, CheckerManager &mgr) { 433 mgr._registerListenerForEvent<EVENT>( 434 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 435 } 436}; 437 438} // end check namespace 439 440namespace eval { 441 442class Assume { 443 template <typename CHECKER> 444 static ProgramStateRef _evalAssume(void *checker, 445 ProgramStateRef state, 446 const SVal &cond, 447 bool assumption) { 448 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 449 } 450 451public: 452 template <typename CHECKER> 453 static void _register(CHECKER *checker, CheckerManager &mgr) { 454 mgr._registerForEvalAssume( 455 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 456 } 457}; 458 459class Call { 460 template <typename CHECKER> 461 static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { 462 return ((const CHECKER *)checker)->evalCall(CE, C); 463 } 464 465public: 466 template <typename CHECKER> 467 static void _register(CHECKER *checker, CheckerManager &mgr) { 468 mgr._registerForEvalCall( 469 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 470 } 471}; 472 473} // end eval namespace 474 475class CheckerBase : public ProgramPointTag { 476 CheckName Name; 477 friend class ::clang::ento::CheckerManager; 478 479public: 480 StringRef getTagDescription() const override; 481 CheckName getCheckName() const; 482 483 /// See CheckerManager::runCheckersForPrintState. 484 virtual void printState(raw_ostream &Out, ProgramStateRef State, 485 const char *NL, const char *Sep) const { } 486}; 487 488/// Dump checker name to stream. 489raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); 490 491/// Tag that can use a checker name as a message provider 492/// (see SimpleProgramPointTag). 493class CheckerProgramPointTag : public SimpleProgramPointTag { 494public: 495 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); 496 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); 497}; 498 499template <typename CHECK1, typename... CHECKs> 500class Checker : public CHECK1, public CHECKs..., public CheckerBase { 501public: 502 template <typename CHECKER> 503 static void _register(CHECKER *checker, CheckerManager &mgr) { 504 CHECK1::_register(checker, mgr); 505 Checker<CHECKs...>::_register(checker, mgr); 506 } 507}; 508 509template <typename CHECK1> 510class Checker<CHECK1> : public CHECK1, public CheckerBase { 511public: 512 template <typename CHECKER> 513 static void _register(CHECKER *checker, CheckerManager &mgr) { 514 CHECK1::_register(checker, mgr); 515 } 516}; 517 518template <typename EVENT> 519class EventDispatcher { 520 CheckerManager *Mgr; 521public: 522 EventDispatcher() : Mgr(nullptr) { } 523 524 template <typename CHECKER> 525 static void _register(CHECKER *checker, CheckerManager &mgr) { 526 mgr._registerDispatcherForEvent<EVENT>(); 527 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 528 } 529 530 void dispatchEvent(const EVENT &event) const { 531 Mgr->_dispatchEvent(event); 532 } 533}; 534 535/// \brief We dereferenced a location that may be null. 536struct ImplicitNullDerefEvent { 537 SVal Location; 538 bool IsLoad; 539 ExplodedNode *SinkNode; 540 BugReporter *BR; 541 // When true, the dereference is in the source code directly. When false, the 542 // dereference might happen later (for example pointer passed to a parameter 543 // that is marked with nonnull attribute.) 544 bool IsDirectDereference; 545}; 546 547/// \brief A helper class which wraps a boolean value set to false by default. 548/// 549/// This class should behave exactly like 'bool' except that it doesn't need to 550/// be explicitly initialized. 551struct DefaultBool { 552 bool val; 553 DefaultBool() : val(false) {} 554 /*implicit*/ operator bool&() { return val; } 555 /*implicit*/ operator const bool&() const { return val; } 556 DefaultBool &operator=(bool b) { val = b; return *this; } 557}; 558 559} // end ento namespace 560 561} // end clang namespace 562 563#endif 564