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