diff options
| author | Stephen Hines <srhines@google.com> | 2019-07-02 16:25:20 -0700 |
|---|---|---|
| committer | Ali B <abittin@gmail.com> | 2019-07-05 19:33:16 +0300 |
| commit | 9afee4e65dc5f9f5eb371683729ff67b8df81d03 (patch) | |
| tree | 4cf241d6c9044f91ee8c06e6920174d06f8de0b6 /clang-r353983e/include/clang/StaticAnalyzer/Core/Checker.h | |
| parent | 2f19bd722c4c825320d1511c1ed83161b7f95d51 (diff) | |
clang 9.0.5 (based on r353983e) from build 5696680.
Bug: http://b/135931688
Bug: http://b/136008926
Test: N/A
Change-Id: I922d17410047d2e2df4625615352c588ee71b203
Diffstat (limited to 'clang-r353983e/include/clang/StaticAnalyzer/Core/Checker.h')
| -rw-r--r-- | clang-r353983e/include/clang/StaticAnalyzer/Core/Checker.h | 581 |
1 files changed, 581 insertions, 0 deletions
diff --git a/clang-r353983e/include/clang/StaticAnalyzer/Core/Checker.h b/clang-r353983e/include/clang/StaticAnalyzer/Core/Checker.h new file mode 100644 index 00000000..db3ae74f --- /dev/null +++ b/clang-r353983e/include/clang/StaticAnalyzer/Core/Checker.h @@ -0,0 +1,581 @@ +//== Checker.h - Registration mechanism for checkers -------------*- C++ -*--=// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines Checker, used to create and register checkers. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H +#define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H + +#include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/LangOptions.h" +#include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/Support/Casting.h" + +namespace clang { +namespace ento { + class BugReporter; + +namespace check { + +template <typename DECL> +class ASTDecl { + template <typename CHECKER> + static void _checkDecl(void *checker, const Decl *D, AnalysisManager& mgr, + BugReporter &BR) { + ((const CHECKER *)checker)->checkASTDecl(cast<DECL>(D), mgr, BR); + } + + static bool _handlesDecl(const Decl *D) { + return isa<DECL>(D); + } +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForDecl(CheckerManager::CheckDeclFunc(checker, + _checkDecl<CHECKER>), + _handlesDecl); + } +}; + +class ASTCodeBody { + template <typename CHECKER> + static void _checkBody(void *checker, const Decl *D, AnalysisManager& mgr, + BugReporter &BR) { + ((const CHECKER *)checker)->checkASTCodeBody(D, mgr, BR); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForBody(CheckerManager::CheckDeclFunc(checker, + _checkBody<CHECKER>)); + } +}; + +class EndOfTranslationUnit { + template <typename CHECKER> + static void _checkEndOfTranslationUnit(void *checker, + const TranslationUnitDecl *TU, + AnalysisManager& mgr, + BugReporter &BR) { + ((const CHECKER *)checker)->checkEndOfTranslationUnit(TU, mgr, BR); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr){ + mgr._registerForEndOfTranslationUnit( + CheckerManager::CheckEndOfTranslationUnit(checker, + _checkEndOfTranslationUnit<CHECKER>)); + } +}; + +template <typename STMT> +class PreStmt { + template <typename CHECKER> + static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { + ((const CHECKER *)checker)->checkPreStmt(cast<STMT>(S), C); + } + + static bool _handlesStmt(const Stmt *S) { + return isa<STMT>(S); + } +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPreStmt(CheckerManager::CheckStmtFunc(checker, + _checkStmt<CHECKER>), + _handlesStmt); + } +}; + +template <typename STMT> +class PostStmt { + template <typename CHECKER> + static void _checkStmt(void *checker, const Stmt *S, CheckerContext &C) { + ((const CHECKER *)checker)->checkPostStmt(cast<STMT>(S), C); + } + + static bool _handlesStmt(const Stmt *S) { + return isa<STMT>(S); + } +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPostStmt(CheckerManager::CheckStmtFunc(checker, + _checkStmt<CHECKER>), + _handlesStmt); + } +}; + +class PreObjCMessage { + template <typename CHECKER> + static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkPreObjCMessage(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPreObjCMessage( + CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); + } +}; + +class ObjCMessageNil { + template <typename CHECKER> + static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkObjCMessageNil(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForObjCMessageNil( + CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); + } +}; + +class PostObjCMessage { + template <typename CHECKER> + static void _checkObjCMessage(void *checker, const ObjCMethodCall &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkPostObjCMessage(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPostObjCMessage( + CheckerManager::CheckObjCMessageFunc(checker, _checkObjCMessage<CHECKER>)); + } +}; + +class PreCall { + template <typename CHECKER> + static void _checkCall(void *checker, const CallEvent &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkPreCall(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPreCall( + CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); + } +}; + +class PostCall { + template <typename CHECKER> + static void _checkCall(void *checker, const CallEvent &msg, + CheckerContext &C) { + ((const CHECKER *)checker)->checkPostCall(msg, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPostCall( + CheckerManager::CheckCallFunc(checker, _checkCall<CHECKER>)); + } +}; + +class Location { + template <typename CHECKER> + static void _checkLocation(void *checker, + const SVal &location, bool isLoad, const Stmt *S, + CheckerContext &C) { + ((const CHECKER *)checker)->checkLocation(location, isLoad, S, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForLocation( + CheckerManager::CheckLocationFunc(checker, _checkLocation<CHECKER>)); + } +}; + +class Bind { + template <typename CHECKER> + static void _checkBind(void *checker, + const SVal &location, const SVal &val, const Stmt *S, + CheckerContext &C) { + ((const CHECKER *)checker)->checkBind(location, val, S, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForBind( + CheckerManager::CheckBindFunc(checker, _checkBind<CHECKER>)); + } +}; + +class EndAnalysis { + template <typename CHECKER> + static void _checkEndAnalysis(void *checker, ExplodedGraph &G, + BugReporter &BR, ExprEngine &Eng) { + ((const CHECKER *)checker)->checkEndAnalysis(G, BR, Eng); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEndAnalysis( + CheckerManager::CheckEndAnalysisFunc(checker, _checkEndAnalysis<CHECKER>)); + } +}; + +class BeginFunction { + template <typename CHECKER> + static void _checkBeginFunction(void *checker, CheckerContext &C) { + ((const CHECKER *)checker)->checkBeginFunction(C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForBeginFunction(CheckerManager::CheckBeginFunctionFunc( + checker, _checkBeginFunction<CHECKER>)); + } +}; + +class EndFunction { + template <typename CHECKER> + static void _checkEndFunction(void *checker, const ReturnStmt *RS, + CheckerContext &C) { + ((const CHECKER *)checker)->checkEndFunction(RS, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEndFunction( + CheckerManager::CheckEndFunctionFunc(checker, _checkEndFunction<CHECKER>)); + } +}; + +class BranchCondition { + template <typename CHECKER> + static void _checkBranchCondition(void *checker, const Stmt *Condition, + CheckerContext & C) { + ((const CHECKER *)checker)->checkBranchCondition(Condition, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForBranchCondition( + CheckerManager::CheckBranchConditionFunc(checker, + _checkBranchCondition<CHECKER>)); + } +}; + +class NewAllocator { + template <typename CHECKER> + static void _checkNewAllocator(void *checker, const CXXNewExpr *NE, + SVal Target, CheckerContext &C) { + ((const CHECKER *)checker)->checkNewAllocator(NE, Target, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForNewAllocator( + CheckerManager::CheckNewAllocatorFunc(checker, + _checkNewAllocator<CHECKER>)); + } +}; + +class LiveSymbols { + template <typename CHECKER> + static void _checkLiveSymbols(void *checker, ProgramStateRef state, + SymbolReaper &SR) { + ((const CHECKER *)checker)->checkLiveSymbols(state, SR); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForLiveSymbols( + CheckerManager::CheckLiveSymbolsFunc(checker, _checkLiveSymbols<CHECKER>)); + } +}; + +class DeadSymbols { + template <typename CHECKER> + static void _checkDeadSymbols(void *checker, + SymbolReaper &SR, CheckerContext &C) { + ((const CHECKER *)checker)->checkDeadSymbols(SR, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForDeadSymbols( + CheckerManager::CheckDeadSymbolsFunc(checker, _checkDeadSymbols<CHECKER>)); + } +}; + +class RegionChanges { + template <typename CHECKER> + static ProgramStateRef + _checkRegionChanges(void *checker, + ProgramStateRef state, + const InvalidatedSymbols *invalidated, + ArrayRef<const MemRegion *> Explicits, + ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, + const CallEvent *Call) { + return ((const CHECKER *) checker)->checkRegionChanges(state, invalidated, + Explicits, Regions, + LCtx, Call); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForRegionChanges( + CheckerManager::CheckRegionChangesFunc(checker, + _checkRegionChanges<CHECKER>)); + } +}; + +class PointerEscape { + template <typename CHECKER> + static ProgramStateRef + _checkPointerEscape(void *Checker, + ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind, + RegionAndSymbolInvalidationTraits *ETraits) { + + if (!ETraits) + return ((const CHECKER *)Checker)->checkPointerEscape(State, + Escaped, + Call, + Kind); + + InvalidatedSymbols RegularEscape; + for (InvalidatedSymbols::const_iterator I = Escaped.begin(), + E = Escaped.end(); I != E; ++I) + if (!ETraits->hasTrait(*I, + RegionAndSymbolInvalidationTraits::TK_PreserveContents) && + !ETraits->hasTrait(*I, + RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) + RegularEscape.insert(*I); + + if (RegularEscape.empty()) + return State; + + return ((const CHECKER *)Checker)->checkPointerEscape(State, + RegularEscape, + Call, + Kind); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPointerEscape( + CheckerManager::CheckPointerEscapeFunc(checker, + _checkPointerEscape<CHECKER>)); + } +}; + +class ConstPointerEscape { + template <typename CHECKER> + static ProgramStateRef + _checkConstPointerEscape(void *Checker, + ProgramStateRef State, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, + PointerEscapeKind Kind, + RegionAndSymbolInvalidationTraits *ETraits) { + + if (!ETraits) + return State; + + InvalidatedSymbols ConstEscape; + for (InvalidatedSymbols::const_iterator I = Escaped.begin(), + E = Escaped.end(); I != E; ++I) + if (ETraits->hasTrait(*I, + RegionAndSymbolInvalidationTraits::TK_PreserveContents) && + !ETraits->hasTrait(*I, + RegionAndSymbolInvalidationTraits::TK_SuppressEscape)) + ConstEscape.insert(*I); + + if (ConstEscape.empty()) + return State; + + return ((const CHECKER *)Checker)->checkConstPointerEscape(State, + ConstEscape, + Call, + Kind); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForPointerEscape( + CheckerManager::CheckPointerEscapeFunc(checker, + _checkConstPointerEscape<CHECKER>)); + } +}; + + +template <typename EVENT> +class Event { + template <typename CHECKER> + static void _checkEvent(void *checker, const void *event) { + ((const CHECKER *)checker)->checkEvent(*(const EVENT *)event); + } +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerListenerForEvent<EVENT>( + CheckerManager::CheckEventFunc(checker, _checkEvent<CHECKER>)); + } +}; + +} // end check namespace + +namespace eval { + +class Assume { + template <typename CHECKER> + static ProgramStateRef _evalAssume(void *checker, + ProgramStateRef state, + const SVal &cond, + bool assumption) { + return ((const CHECKER *)checker)->evalAssume(state, cond, assumption); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEvalAssume( + CheckerManager::EvalAssumeFunc(checker, _evalAssume<CHECKER>)); + } +}; + +class Call { + template <typename CHECKER> + static bool _evalCall(void *checker, const CallExpr *CE, CheckerContext &C) { + return ((const CHECKER *)checker)->evalCall(CE, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForEvalCall( + CheckerManager::EvalCallFunc(checker, _evalCall<CHECKER>)); + } +}; + +} // end eval namespace + +class CheckerBase : public ProgramPointTag { + CheckName Name; + friend class ::clang::ento::CheckerManager; + +public: + StringRef getTagDescription() const override; + CheckName getCheckName() const; + + /// See CheckerManager::runCheckersForPrintState. + virtual void printState(raw_ostream &Out, ProgramStateRef State, + const char *NL, const char *Sep) const { } +}; + +/// Dump checker name to stream. +raw_ostream& operator<<(raw_ostream &Out, const CheckerBase &Checker); + +/// Tag that can use a checker name as a message provider +/// (see SimpleProgramPointTag). +class CheckerProgramPointTag : public SimpleProgramPointTag { +public: + CheckerProgramPointTag(StringRef CheckerName, StringRef Msg); + CheckerProgramPointTag(const CheckerBase *Checker, StringRef Msg); +}; + +template <typename CHECK1, typename... CHECKs> +class Checker : public CHECK1, public CHECKs..., public CheckerBase { +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + CHECK1::_register(checker, mgr); + Checker<CHECKs...>::_register(checker, mgr); + } +}; + +template <typename CHECK1> +class Checker<CHECK1> : public CHECK1, public CheckerBase { +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + CHECK1::_register(checker, mgr); + } +}; + +template <typename EVENT> +class EventDispatcher { + CheckerManager *Mgr; +public: + EventDispatcher() : Mgr(nullptr) { } + + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerDispatcherForEvent<EVENT>(); + static_cast<EventDispatcher<EVENT> *>(checker)->Mgr = &mgr; + } + + void dispatchEvent(const EVENT &event) const { + Mgr->_dispatchEvent(event); + } +}; + +/// We dereferenced a location that may be null. +struct ImplicitNullDerefEvent { + SVal Location; + bool IsLoad; + ExplodedNode *SinkNode; + BugReporter *BR; + // When true, the dereference is in the source code directly. When false, the + // dereference might happen later (for example pointer passed to a parameter + // that is marked with nonnull attribute.) + bool IsDirectDereference; + + static int Tag; +}; + +/// A helper class which wraps a boolean value set to false by default. +/// +/// This class should behave exactly like 'bool' except that it doesn't need to +/// be explicitly initialized. +struct DefaultBool { + bool val; + DefaultBool() : val(false) {} + /*implicit*/ operator bool&() { return val; } + /*implicit*/ operator const bool&() const { return val; } + DefaultBool &operator=(bool b) { val = b; return *this; } +}; + +} // end ento namespace + +} // end clang namespace + +#endif |
