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