1 //== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file defines Checker, used to create and register checkers. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H 14 #define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H 15 16 #include "clang/Analysis/ProgramPoint.h" 17 #include "clang/Basic/LangOptions.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> 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 } 39 public: 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 48 class 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 55 public: 56 template <typename CHECKER> 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> 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> 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> 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 } 91 public: 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 100 template <typename STMT> 101 class 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 } 110 public: 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 119 class 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 126 public: 127 template <typename CHECKER> 128 static void _register(CHECKER *checker, CheckerManager &mgr) { 129 mgr._registerForPreObjCMessage( 130 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 131 } 132 }; 133 134 class 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 141 public: 142 template <typename CHECKER> 143 static void _register(CHECKER *checker, CheckerManager &mgr) { 144 mgr._registerForObjCMessageNil( 145 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 146 } 147 }; 148 149 class 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 156 public: 157 template <typename CHECKER> 158 static void _register(CHECKER *checker, CheckerManager &mgr) { 159 mgr._registerForPostObjCMessage( 160 CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); 161 } 162 }; 163 164 class 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 171 public: 172 template <typename CHECKER> 173 static void _register(CHECKER *checker, CheckerManager &mgr) { 174 mgr._registerForPreCall( 175 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 176 } 177 }; 178 179 class 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 186 public: 187 template <typename CHECKER> 188 static void _register(CHECKER *checker, CheckerManager &mgr) { 189 mgr._registerForPostCall( 190 CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); 191 } 192 }; 193 194 class 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 202 public: 203 template <typename CHECKER> 204 static void _register(CHECKER *checker, CheckerManager &mgr) { 205 mgr._registerForLocation( 206 CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); 207 } 208 }; 209 210 class 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 218 public: 219 template <typename CHECKER> 220 static void _register(CHECKER *checker, CheckerManager &mgr) { 221 mgr._registerForBind( 222 CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); 223 } 224 }; 225 226 class 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 233 public: 234 template <typename CHECKER> 235 static void _register(CHECKER *checker, CheckerManager &mgr) { 236 mgr._registerForEndAnalysis( 237 CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); 238 } 239 }; 240 241 class BeginFunction { 242 template <typename CHECKER> 243 static void _checkBeginFunction(void *checker, CheckerContext &C) { 244 ((const CHECKER *)checker)->checkBeginFunction(C); 245 } 246 247 public: 248 template <typename CHECKER> 249 static void _register(CHECKER *checker, CheckerManager &mgr) { 250 mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc( 251 checker, _checkBeginFunction<CHECKER>)); 252 } 253 }; 254 255 class EndFunction { 256 template <typename CHECKER> 257 static void _checkEndFunction(void *checker, const ReturnStmt *RS, 258 CheckerContext &C) { 259 ((const CHECKER *)checker)->checkEndFunction(RS, C); 260 } 261 262 public: 263 template <typename CHECKER> 264 static void _register(CHECKER *checker, CheckerManager &mgr) { 265 mgr._registerForEndFunction( 266 CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); 267 } 268 }; 269 270 class 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 277 public: 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 286 class NewAllocator { 287 template <typename CHECKER> 288 static void _checkNewAllocator(void *checker, const CXXAllocatorCall &Call, 289 CheckerContext &C) { 290 ((const CHECKER *)checker)->checkNewAllocator(Call, C); 291 } 292 293 public: 294 template <typename CHECKER> 295 static void _register(CHECKER *checker, CheckerManager &mgr) { 296 mgr._registerForNewAllocator( 297 CheckerManager::CheckNewAllocatorFunc(checker, 298 _checkNewAllocator<CHECKER>)); 299 } 300 }; 301 302 class LiveSymbols { 303 template <typename CHECKER> 304 static void _checkLiveSymbols(void *checker, ProgramStateRef state, 305 SymbolReaper &SR) { 306 ((const CHECKER *)checker)->checkLiveSymbols(state, SR); 307 } 308 309 public: 310 template <typename CHECKER> 311 static void _register(CHECKER *checker, CheckerManager &mgr) { 312 mgr._registerForLiveSymbols( 313 CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); 314 } 315 }; 316 317 class DeadSymbols { 318 template <typename CHECKER> 319 static void _checkDeadSymbols(void *checker, 320 SymbolReaper &SR, CheckerContext &C) { 321 ((const CHECKER *)checker)->checkDeadSymbols(SR, C); 322 } 323 324 public: 325 template <typename CHECKER> 326 static void _register(CHECKER *checker, CheckerManager &mgr) { 327 mgr._registerForDeadSymbols( 328 CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); 329 } 330 }; 331 332 class RegionChanges { 333 template <typename CHECKER> 334 static ProgramStateRef 335 _checkRegionChanges(void *checker, 336 ProgramStateRef state, 337 const InvalidatedSymbols *invalidated, 338 ArrayRef<const MemRegion *> Explicits, 339 ArrayRef<const MemRegion *> Regions, 340 const LocationContext *LCtx, 341 const CallEvent *Call) { 342 return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, 343 Explicits, Regions, 344 LCtx, Call); 345 } 346 347 public: 348 template <typename CHECKER> 349 static void _register(CHECKER *checker, CheckerManager &mgr) { 350 mgr._registerForRegionChanges( 351 CheckerManager::CheckRegionChangesFunc(checker, 352 _checkRegionChanges<CHECKER>)); 353 } 354 }; 355 356 class PointerEscape { 357 template <typename CHECKER> 358 static ProgramStateRef 359 _checkPointerEscape(void *Checker, 360 ProgramStateRef State, 361 const InvalidatedSymbols &Escaped, 362 const CallEvent *Call, 363 PointerEscapeKind Kind, 364 RegionAndSymbolInvalidationTraits *ETraits) { 365 366 if (!ETraits) 367 return ((const CHECKER *)Checker)->checkPointerEscape(State, 368 Escaped, 369 Call, 370 Kind); 371 372 InvalidatedSymbols RegularEscape; 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 RegularEscape.insert(*I); 380 381 if (RegularEscape.empty()) 382 return State; 383 384 return ((const CHECKER *)Checker)->checkPointerEscape(State, 385 RegularEscape, 386 Call, 387 Kind); 388 } 389 390 public: 391 template <typename CHECKER> 392 static void _register(CHECKER *checker, CheckerManager &mgr) { 393 mgr._registerForPointerEscape( 394 CheckerManager::CheckPointerEscapeFunc(checker, 395 _checkPointerEscape<CHECKER>)); 396 } 397 }; 398 399 class ConstPointerEscape { 400 template <typename CHECKER> 401 static ProgramStateRef 402 _checkConstPointerEscape(void *Checker, 403 ProgramStateRef State, 404 const InvalidatedSymbols &Escaped, 405 const CallEvent *Call, 406 PointerEscapeKind Kind, 407 RegionAndSymbolInvalidationTraits *ETraits) { 408 409 if (!ETraits) 410 return State; 411 412 InvalidatedSymbols ConstEscape; 413 for (InvalidatedSymbols::const_iterator I = Escaped.begin(), 414 E = Escaped.end(); I != E; ++I) 415 if (ETraits->hasTrait(*I, 416 RegionAndSymbolInvalidationTraits::TK_PreserveContents) && 417 !ETraits->hasTrait(*I, 418 RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) 419 ConstEscape.insert(*I); 420 421 if (ConstEscape.empty()) 422 return State; 423 424 return ((const CHECKER *)Checker)->checkConstPointerEscape(State, 425 ConstEscape, 426 Call, 427 Kind); 428 } 429 430 public: 431 template <typename CHECKER> 432 static void _register(CHECKER *checker, CheckerManager &mgr) { 433 mgr._registerForPointerEscape( 434 CheckerManager::CheckPointerEscapeFunc(checker, 435 _checkConstPointerEscape<CHECKER>)); 436 } 437 }; 438 439 440 template <typename EVENT> 441 class Event { 442 template <typename CHECKER> 443 static void _checkEvent(void *checker, const void *event) { 444 ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); 445 } 446 public: 447 template <typename CHECKER> 448 static void _register(CHECKER *checker, CheckerManager &mgr) { 449 mgr._registerListenerForEvent<EVENT>( 450 CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); 451 } 452 }; 453 454 } // end check namespace 455 456 namespace eval { 457 458 class Assume { 459 template <typename CHECKER> 460 static ProgramStateRef _evalAssume(void *checker, 461 ProgramStateRef state, 462 const SVal &cond, 463 bool assumption) { 464 return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); 465 } 466 467 public: 468 template <typename CHECKER> 469 static void _register(CHECKER *checker, CheckerManager &mgr) { 470 mgr._registerForEvalAssume( 471 CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); 472 } 473 }; 474 475 class Call { 476 template <typename CHECKER> 477 static bool _evalCall(void *checker, const CallEvent &Call, 478 CheckerContext &C) { 479 return ((const CHECKER *)checker)->evalCall(Call, C); 480 } 481 482 public: 483 template <typename CHECKER> 484 static void _register(CHECKER *checker, CheckerManager &mgr) { 485 mgr._registerForEvalCall( 486 CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); 487 } 488 }; 489 490 } // end eval namespace 491 492 class CheckerBase : public ProgramPointTag { 493 CheckerNameRef Name; 494 friend class ::clang::ento::CheckerManager; 495 496 public: 497 StringRef getTagDescription() const override; 498 CheckerNameRef getCheckerName() const; 499 500 /// See CheckerManager::runCheckersForPrintState. 501 virtual void printState(raw_ostream &Out, ProgramStateRef State, 502 const char *NL, const char *Sep) const { } 503 }; 504 505 /// Dump checker name to stream. 506 raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); 507 508 /// Tag that can use a checker name as a message provider 509 /// (see SimpleProgramPointTag). 510 class CheckerProgramPointTag : public SimpleProgramPointTag { 511 public: 512 CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); 513 CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); 514 }; 515 516 template <typename CHECK1, typename... CHECKs> 517 class Checker : public CHECK1, public CHECKs..., public CheckerBase { 518 public: 519 template <typename CHECKER> 520 static void _register(CHECKER *checker, CheckerManager &mgr) { 521 CHECK1::_register(checker, mgr); 522 Checker<CHECKs...>::_register(checker, mgr); 523 } 524 }; 525 526 template <typename CHECK1> 527 class Checker<CHECK1> : public CHECK1, public CheckerBase { 528 public: 529 template <typename CHECKER> 530 static void _register(CHECKER *checker, CheckerManager &mgr) { 531 CHECK1::_register(checker, mgr); 532 } 533 }; 534 535 template <typename EVENT> 536 class EventDispatcher { 537 CheckerManager *Mgr; 538 public: 539 EventDispatcher() : Mgr(nullptr) { } 540 541 template <typename CHECKER> 542 static void _register(CHECKER *checker, CheckerManager &mgr) { 543 mgr._registerDispatcherForEvent<EVENT>(); 544 static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; 545 } 546 547 void dispatchEvent(const EVENT &event) const { 548 Mgr->_dispatchEvent(event); 549 } 550 }; 551 552 /// We dereferenced a location that may be null. 553 struct ImplicitNullDerefEvent { 554 SVal Location; 555 bool IsLoad; 556 ExplodedNode *SinkNode; 557 BugReporter *BR; 558 // When true, the dereference is in the source code directly. When false, the 559 // dereference might happen later (for example pointer passed to a parameter 560 // that is marked with nonnull attribute.) 561 bool IsDirectDereference; 562 563 static int Tag; 564 }; 565 566 } // end ento namespace 567 568 } // end clang namespace 569 570 #endif 571