mirror of
https://github.com/opnsense/src.git
synced 2026-05-28 04:12:45 -04:00
615 lines
22 KiB
C++
615 lines
22 KiB
C++
//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===//
|
|
//
|
|
// The LLVM Compiler Infrastructure
|
|
//
|
|
// This file is distributed under the University of Illinois Open Source
|
|
// License. See LICENSE.TXT for details.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
//
|
|
// Defines the Static Analyzer Checker Manager.
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
|
|
#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H
|
|
|
|
#include "clang/Basic/LangOptions.h"
|
|
#include "llvm/ADT/SmallVector.h"
|
|
#include "llvm/ADT/DenseMap.h"
|
|
#include "llvm/ADT/FoldingSet.h"
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/Store.h"
|
|
#include "clang/Analysis/ProgramPoint.h"
|
|
#include <vector>
|
|
|
|
namespace clang {
|
|
class Decl;
|
|
class Stmt;
|
|
class CallExpr;
|
|
|
|
namespace ento {
|
|
class CheckerBase;
|
|
class ExprEngine;
|
|
class AnalysisManager;
|
|
class BugReporter;
|
|
class CheckerContext;
|
|
class SimpleCall;
|
|
class ObjCMethodCall;
|
|
class SVal;
|
|
class ExplodedNode;
|
|
class ExplodedNodeSet;
|
|
class ExplodedGraph;
|
|
class ProgramState;
|
|
class NodeBuilder;
|
|
struct NodeBuilderContext;
|
|
class MemRegion;
|
|
class SymbolReaper;
|
|
|
|
template <typename T> class CheckerFn;
|
|
|
|
template <typename RET, typename P1, typename P2, typename P3, typename P4,
|
|
typename P5>
|
|
class CheckerFn<RET(P1, P2, P3, P4, P5)> {
|
|
typedef RET (*Func)(void *, P1, P2, P3, P4, P5);
|
|
Func Fn;
|
|
public:
|
|
CheckerBase *Checker;
|
|
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
|
|
RET operator()(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const {
|
|
return Fn(Checker, p1, p2, p3, p4, p5);
|
|
}
|
|
};
|
|
|
|
template <typename RET, typename P1, typename P2, typename P3, typename P4>
|
|
class CheckerFn<RET(P1, P2, P3, P4)> {
|
|
typedef RET (*Func)(void *, P1, P2, P3, P4);
|
|
Func Fn;
|
|
public:
|
|
CheckerBase *Checker;
|
|
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
|
|
RET operator()(P1 p1, P2 p2, P3 p3, P4 p4) const {
|
|
return Fn(Checker, p1, p2, p3, p4);
|
|
}
|
|
};
|
|
|
|
template <typename RET, typename P1, typename P2, typename P3>
|
|
class CheckerFn<RET(P1, P2, P3)> {
|
|
typedef RET (*Func)(void *, P1, P2, P3);
|
|
Func Fn;
|
|
public:
|
|
CheckerBase *Checker;
|
|
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
|
|
RET operator()(P1 p1, P2 p2, P3 p3) const { return Fn(Checker, p1, p2, p3); }
|
|
};
|
|
|
|
template <typename RET, typename P1, typename P2>
|
|
class CheckerFn<RET(P1, P2)> {
|
|
typedef RET (*Func)(void *, P1, P2);
|
|
Func Fn;
|
|
public:
|
|
CheckerBase *Checker;
|
|
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
|
|
RET operator()(P1 p1, P2 p2) const { return Fn(Checker, p1, p2); }
|
|
};
|
|
|
|
template <typename RET, typename P1>
|
|
class CheckerFn<RET(P1)> {
|
|
typedef RET (*Func)(void *, P1);
|
|
Func Fn;
|
|
public:
|
|
CheckerBase *Checker;
|
|
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
|
|
RET operator()(P1 p1) const { return Fn(Checker, p1); }
|
|
};
|
|
|
|
template <typename RET>
|
|
class CheckerFn<RET()> {
|
|
typedef RET (*Func)(void *);
|
|
Func Fn;
|
|
public:
|
|
CheckerBase *Checker;
|
|
CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { }
|
|
RET operator()() const { return Fn(Checker); }
|
|
};
|
|
|
|
class CheckerManager {
|
|
const LangOptions LangOpts;
|
|
|
|
public:
|
|
CheckerManager(const LangOptions &langOpts) : LangOpts(langOpts) { }
|
|
~CheckerManager();
|
|
|
|
bool hasPathSensitiveCheckers() const;
|
|
|
|
void finishedCheckerRegistration();
|
|
|
|
const LangOptions &getLangOpts() const { return LangOpts; }
|
|
|
|
typedef CheckerBase *CheckerRef;
|
|
typedef const void *CheckerTag;
|
|
typedef CheckerFn<void ()> CheckerDtor;
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// registerChecker
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \brief Used to register checkers.
|
|
///
|
|
/// \returns a pointer to the checker object.
|
|
template <typename CHECKER>
|
|
CHECKER *registerChecker() {
|
|
CheckerTag tag = getTag<CHECKER>();
|
|
CheckerRef &ref = CheckerTags[tag];
|
|
if (ref)
|
|
return static_cast<CHECKER *>(ref); // already registered.
|
|
|
|
CHECKER *checker = new CHECKER();
|
|
CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>));
|
|
CHECKER::_register(checker, *this);
|
|
ref = checker;
|
|
return checker;
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Functions for running checkers for AST traversing..
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \brief Run checkers handling Decls.
|
|
void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr,
|
|
BugReporter &BR);
|
|
|
|
/// \brief Run checkers handling Decls containing a Stmt body.
|
|
void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr,
|
|
BugReporter &BR);
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Functions for running checkers for path-sensitive checking.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
/// \brief Run checkers for pre-visiting Stmts.
|
|
///
|
|
/// The notification is performed for every explored CFGElement, which does
|
|
/// not include the control flow statements such as IfStmt.
|
|
///
|
|
/// \sa runCheckersForBranchCondition, runCheckersForPostStmt
|
|
void runCheckersForPreStmt(ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
const Stmt *S,
|
|
ExprEngine &Eng) {
|
|
runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng);
|
|
}
|
|
|
|
/// \brief Run checkers for post-visiting Stmts.
|
|
///
|
|
/// The notification is performed for every explored CFGElement, which does
|
|
/// not include the control flow statements such as IfStmt.
|
|
///
|
|
/// \sa runCheckersForBranchCondition, runCheckersForPreStmt
|
|
void runCheckersForPostStmt(ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
const Stmt *S,
|
|
ExprEngine &Eng,
|
|
bool wasInlined = false) {
|
|
runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined);
|
|
}
|
|
|
|
/// \brief Run checkers for visiting Stmts.
|
|
void runCheckersForStmt(bool isPreVisit,
|
|
ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
|
|
const Stmt *S, ExprEngine &Eng,
|
|
bool wasInlined = false);
|
|
|
|
/// \brief Run checkers for pre-visiting obj-c messages.
|
|
void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
const ObjCMethodCall &msg,
|
|
ExprEngine &Eng) {
|
|
runCheckersForObjCMessage(/*isPreVisit=*/true, Dst, Src, msg, Eng);
|
|
}
|
|
|
|
/// \brief Run checkers for post-visiting obj-c messages.
|
|
void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
const ObjCMethodCall &msg,
|
|
ExprEngine &Eng,
|
|
bool wasInlined = false) {
|
|
runCheckersForObjCMessage(/*isPreVisit=*/false, Dst, Src, msg, Eng,
|
|
wasInlined);
|
|
}
|
|
|
|
/// \brief Run checkers for visiting obj-c messages.
|
|
void runCheckersForObjCMessage(bool isPreVisit,
|
|
ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
const ObjCMethodCall &msg, ExprEngine &Eng,
|
|
bool wasInlined = false);
|
|
|
|
/// \brief Run checkers for pre-visiting obj-c messages.
|
|
void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
|
|
const CallEvent &Call, ExprEngine &Eng) {
|
|
runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng);
|
|
}
|
|
|
|
/// \brief Run checkers for post-visiting obj-c messages.
|
|
void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src,
|
|
const CallEvent &Call, ExprEngine &Eng,
|
|
bool wasInlined = false) {
|
|
runCheckersForCallEvent(/*isPreVisit=*/false, Dst, Src, Call, Eng,
|
|
wasInlined);
|
|
}
|
|
|
|
/// \brief Run checkers for visiting obj-c messages.
|
|
void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
const CallEvent &Call, ExprEngine &Eng,
|
|
bool wasInlined = false);
|
|
|
|
/// \brief Run checkers for load/store of a location.
|
|
void runCheckersForLocation(ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
SVal location,
|
|
bool isLoad,
|
|
const Stmt *NodeEx,
|
|
const Stmt *BoundEx,
|
|
ExprEngine &Eng);
|
|
|
|
/// \brief Run checkers for binding of a value to a location.
|
|
void runCheckersForBind(ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
SVal location, SVal val,
|
|
const Stmt *S, ExprEngine &Eng,
|
|
const ProgramPoint &PP);
|
|
|
|
/// \brief Run checkers for end of analysis.
|
|
void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR,
|
|
ExprEngine &Eng);
|
|
|
|
/// \brief Run checkers for end of path.
|
|
void runCheckersForEndPath(NodeBuilderContext &BC,
|
|
ExplodedNodeSet &Dst,
|
|
ExplodedNode *Pred,
|
|
ExprEngine &Eng);
|
|
|
|
/// \brief Run checkers for branch condition.
|
|
void runCheckersForBranchCondition(const Stmt *condition,
|
|
ExplodedNodeSet &Dst, ExplodedNode *Pred,
|
|
ExprEngine &Eng);
|
|
|
|
/// \brief Run checkers for live symbols.
|
|
///
|
|
/// Allows modifying SymbolReaper object. For example, checkers can explicitly
|
|
/// register symbols of interest as live. These symbols will not be marked
|
|
/// dead and removed.
|
|
void runCheckersForLiveSymbols(ProgramStateRef state,
|
|
SymbolReaper &SymReaper);
|
|
|
|
/// \brief Run checkers for dead symbols.
|
|
///
|
|
/// Notifies checkers when symbols become dead. For example, this allows
|
|
/// checkers to aggressively clean up/reduce the checker state and produce
|
|
/// precise diagnostics.
|
|
void runCheckersForDeadSymbols(ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
SymbolReaper &SymReaper, const Stmt *S,
|
|
ExprEngine &Eng,
|
|
ProgramPoint::Kind K);
|
|
|
|
/// \brief True if at least one checker wants to check region changes.
|
|
bool wantsRegionChangeUpdate(ProgramStateRef state);
|
|
|
|
/// \brief Run checkers for region changes.
|
|
///
|
|
/// This corresponds to the check::RegionChanges callback.
|
|
/// \param state The current program state.
|
|
/// \param invalidated A set of all symbols potentially touched by the change.
|
|
/// \param ExplicitRegions The regions explicitly requested for invalidation.
|
|
/// For example, in the case of a function call, these would be arguments.
|
|
/// \param Regions The transitive closure of accessible regions,
|
|
/// i.e. all regions that may have been touched by this change.
|
|
/// \param Call The call expression wrapper if the regions are invalidated
|
|
/// by a call.
|
|
ProgramStateRef
|
|
runCheckersForRegionChanges(ProgramStateRef state,
|
|
const StoreManager::InvalidatedSymbols *invalidated,
|
|
ArrayRef<const MemRegion *> ExplicitRegions,
|
|
ArrayRef<const MemRegion *> Regions,
|
|
const CallEvent *Call);
|
|
|
|
/// \brief Run checkers for handling assumptions on symbolic values.
|
|
ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state,
|
|
SVal Cond, bool Assumption);
|
|
|
|
/// \brief Run checkers for evaluating a call.
|
|
///
|
|
/// Warning: Currently, the CallEvent MUST come from a CallExpr!
|
|
void runCheckersForEvalCall(ExplodedNodeSet &Dst,
|
|
const ExplodedNodeSet &Src,
|
|
const CallEvent &CE, ExprEngine &Eng);
|
|
|
|
/// \brief Run checkers for the entire Translation Unit.
|
|
void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU,
|
|
AnalysisManager &mgr,
|
|
BugReporter &BR);
|
|
|
|
/// \brief Run checkers for debug-printing a ProgramState.
|
|
///
|
|
/// Unlike most other callbacks, any checker can simply implement the virtual
|
|
/// method CheckerBase::printState if it has custom data to print.
|
|
/// \param Out The output stream
|
|
/// \param State The state being printed
|
|
/// \param NL The preferred representation of a newline.
|
|
/// \param Sep The preferred separator between different kinds of data.
|
|
void runCheckersForPrintState(raw_ostream &Out, ProgramStateRef State,
|
|
const char *NL, const char *Sep);
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Internal registration functions for AST traversing.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Functions used by the registration mechanism, checkers should not touch
|
|
// these directly.
|
|
|
|
typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>
|
|
CheckDeclFunc;
|
|
|
|
typedef bool (*HandlesDeclFunc)(const Decl *D);
|
|
void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn);
|
|
|
|
void _registerForBody(CheckDeclFunc checkfn);
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Internal registration functions for path-sensitive checking.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc;
|
|
|
|
typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>
|
|
CheckObjCMessageFunc;
|
|
|
|
typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
|
|
CheckCallFunc;
|
|
|
|
typedef CheckerFn<void (const SVal &location, bool isLoad,
|
|
const Stmt *S,
|
|
CheckerContext &)>
|
|
CheckLocationFunc;
|
|
|
|
typedef CheckerFn<void (const SVal &location, const SVal &val,
|
|
const Stmt *S, CheckerContext &)>
|
|
CheckBindFunc;
|
|
|
|
typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>
|
|
CheckEndAnalysisFunc;
|
|
|
|
typedef CheckerFn<void (CheckerContext &)>
|
|
CheckEndPathFunc;
|
|
|
|
typedef CheckerFn<void (const Stmt *, CheckerContext &)>
|
|
CheckBranchConditionFunc;
|
|
|
|
typedef CheckerFn<void (SymbolReaper &, CheckerContext &)>
|
|
CheckDeadSymbolsFunc;
|
|
|
|
typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc;
|
|
|
|
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
|
|
const StoreManager::InvalidatedSymbols *symbols,
|
|
ArrayRef<const MemRegion *> ExplicitRegions,
|
|
ArrayRef<const MemRegion *> Regions,
|
|
const CallEvent *Call)>
|
|
CheckRegionChangesFunc;
|
|
|
|
typedef CheckerFn<bool (ProgramStateRef)> WantsRegionChangeUpdateFunc;
|
|
|
|
typedef CheckerFn<ProgramStateRef (ProgramStateRef,
|
|
const SVal &cond, bool assumption)>
|
|
EvalAssumeFunc;
|
|
|
|
typedef CheckerFn<bool (const CallExpr *, CheckerContext &)>
|
|
EvalCallFunc;
|
|
|
|
typedef CheckerFn<void (const TranslationUnitDecl *,
|
|
AnalysisManager&, BugReporter &)>
|
|
CheckEndOfTranslationUnit;
|
|
|
|
typedef bool (*HandlesStmtFunc)(const Stmt *D);
|
|
void _registerForPreStmt(CheckStmtFunc checkfn,
|
|
HandlesStmtFunc isForStmtFn);
|
|
void _registerForPostStmt(CheckStmtFunc checkfn,
|
|
HandlesStmtFunc isForStmtFn);
|
|
|
|
void _registerForPreObjCMessage(CheckObjCMessageFunc checkfn);
|
|
void _registerForPostObjCMessage(CheckObjCMessageFunc checkfn);
|
|
|
|
void _registerForPreCall(CheckCallFunc checkfn);
|
|
void _registerForPostCall(CheckCallFunc checkfn);
|
|
|
|
void _registerForLocation(CheckLocationFunc checkfn);
|
|
|
|
void _registerForBind(CheckBindFunc checkfn);
|
|
|
|
void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn);
|
|
|
|
void _registerForEndPath(CheckEndPathFunc checkfn);
|
|
|
|
void _registerForBranchCondition(CheckBranchConditionFunc checkfn);
|
|
|
|
void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn);
|
|
|
|
void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn);
|
|
|
|
void _registerForRegionChanges(CheckRegionChangesFunc checkfn,
|
|
WantsRegionChangeUpdateFunc wantUpdateFn);
|
|
|
|
void _registerForEvalAssume(EvalAssumeFunc checkfn);
|
|
|
|
void _registerForEvalCall(EvalCallFunc checkfn);
|
|
|
|
void _registerForEndOfTranslationUnit(CheckEndOfTranslationUnit checkfn);
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Internal registration functions for events.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
typedef void *EventTag;
|
|
typedef CheckerFn<void (const void *event)> CheckEventFunc;
|
|
|
|
template <typename EVENT>
|
|
void _registerListenerForEvent(CheckEventFunc checkfn) {
|
|
EventInfo &info = Events[getTag<EVENT>()];
|
|
info.Checkers.push_back(checkfn);
|
|
}
|
|
|
|
template <typename EVENT>
|
|
void _registerDispatcherForEvent() {
|
|
EventInfo &info = Events[getTag<EVENT>()];
|
|
info.HasDispatcher = true;
|
|
}
|
|
|
|
template <typename EVENT>
|
|
void _dispatchEvent(const EVENT &event) const {
|
|
EventsTy::const_iterator I = Events.find(getTag<EVENT>());
|
|
if (I == Events.end())
|
|
return;
|
|
const EventInfo &info = I->second;
|
|
for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i)
|
|
info.Checkers[i](&event);
|
|
}
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
// Implementation details.
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
private:
|
|
template <typename CHECKER>
|
|
static void destruct(void *obj) { delete static_cast<CHECKER *>(obj); }
|
|
|
|
template <typename T>
|
|
static void *getTag() { static int tag; return &tag; }
|
|
|
|
llvm::DenseMap<CheckerTag, CheckerRef> CheckerTags;
|
|
|
|
std::vector<CheckerDtor> CheckerDtors;
|
|
|
|
struct DeclCheckerInfo {
|
|
CheckDeclFunc CheckFn;
|
|
HandlesDeclFunc IsForDeclFn;
|
|
};
|
|
std::vector<DeclCheckerInfo> DeclCheckers;
|
|
|
|
std::vector<CheckDeclFunc> BodyCheckers;
|
|
|
|
typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers;
|
|
typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy;
|
|
CachedDeclCheckersMapTy CachedDeclCheckersMap;
|
|
|
|
struct StmtCheckerInfo {
|
|
CheckStmtFunc CheckFn;
|
|
HandlesStmtFunc IsForStmtFn;
|
|
bool IsPreVisit;
|
|
};
|
|
std::vector<StmtCheckerInfo> StmtCheckers;
|
|
|
|
struct CachedStmtCheckersKey {
|
|
unsigned StmtKind;
|
|
bool IsPreVisit;
|
|
|
|
CachedStmtCheckersKey() : StmtKind(0), IsPreVisit(0) { }
|
|
CachedStmtCheckersKey(unsigned stmtKind, bool isPreVisit)
|
|
: StmtKind(stmtKind), IsPreVisit(isPreVisit) { }
|
|
|
|
static CachedStmtCheckersKey getSentinel() {
|
|
return CachedStmtCheckersKey(~0U, 0);
|
|
}
|
|
unsigned getHashValue() const {
|
|
llvm::FoldingSetNodeID ID;
|
|
ID.AddInteger(StmtKind);
|
|
ID.AddBoolean(IsPreVisit);
|
|
return ID.ComputeHash();
|
|
}
|
|
bool operator==(const CachedStmtCheckersKey &RHS) const {
|
|
return StmtKind == RHS.StmtKind && IsPreVisit == RHS.IsPreVisit;
|
|
}
|
|
};
|
|
friend struct llvm::DenseMapInfo<CachedStmtCheckersKey>;
|
|
|
|
typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers;
|
|
typedef llvm::DenseMap<CachedStmtCheckersKey, CachedStmtCheckers>
|
|
CachedStmtCheckersMapTy;
|
|
CachedStmtCheckersMapTy CachedStmtCheckersMap;
|
|
|
|
CachedStmtCheckers *getCachedStmtCheckersFor(const Stmt *S, bool isPreVisit);
|
|
|
|
std::vector<CheckObjCMessageFunc> PreObjCMessageCheckers;
|
|
std::vector<CheckObjCMessageFunc> PostObjCMessageCheckers;
|
|
|
|
std::vector<CheckCallFunc> PreCallCheckers;
|
|
std::vector<CheckCallFunc> PostCallCheckers;
|
|
|
|
std::vector<CheckLocationFunc> LocationCheckers;
|
|
|
|
std::vector<CheckBindFunc> BindCheckers;
|
|
|
|
std::vector<CheckEndAnalysisFunc> EndAnalysisCheckers;
|
|
|
|
std::vector<CheckEndPathFunc> EndPathCheckers;
|
|
|
|
std::vector<CheckBranchConditionFunc> BranchConditionCheckers;
|
|
|
|
std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers;
|
|
|
|
std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers;
|
|
|
|
struct RegionChangesCheckerInfo {
|
|
CheckRegionChangesFunc CheckFn;
|
|
WantsRegionChangeUpdateFunc WantUpdateFn;
|
|
};
|
|
std::vector<RegionChangesCheckerInfo> RegionChangesCheckers;
|
|
|
|
std::vector<EvalAssumeFunc> EvalAssumeCheckers;
|
|
|
|
std::vector<EvalCallFunc> EvalCallCheckers;
|
|
|
|
std::vector<CheckEndOfTranslationUnit> EndOfTranslationUnitCheckers;
|
|
|
|
struct EventInfo {
|
|
SmallVector<CheckEventFunc, 4> Checkers;
|
|
bool HasDispatcher;
|
|
EventInfo() : HasDispatcher(false) { }
|
|
};
|
|
|
|
typedef llvm::DenseMap<EventTag, EventInfo> EventsTy;
|
|
EventsTy Events;
|
|
};
|
|
|
|
} // end ento namespace
|
|
|
|
} // end clang namespace
|
|
|
|
namespace llvm {
|
|
/// Define DenseMapInfo so that CachedStmtCheckersKey can be used as key
|
|
/// in DenseMap and DenseSets.
|
|
template <>
|
|
struct DenseMapInfo<clang::ento::CheckerManager::CachedStmtCheckersKey> {
|
|
static inline clang::ento::CheckerManager::CachedStmtCheckersKey
|
|
getEmptyKey() {
|
|
return clang::ento::CheckerManager::CachedStmtCheckersKey();
|
|
}
|
|
static inline clang::ento::CheckerManager::CachedStmtCheckersKey
|
|
getTombstoneKey() {
|
|
return clang::ento::CheckerManager::CachedStmtCheckersKey::getSentinel();
|
|
}
|
|
|
|
static unsigned
|
|
getHashValue(clang::ento::CheckerManager::CachedStmtCheckersKey S) {
|
|
return S.getHashValue();
|
|
}
|
|
|
|
static bool isEqual(clang::ento::CheckerManager::CachedStmtCheckersKey LHS,
|
|
clang::ento::CheckerManager::CachedStmtCheckersKey RHS) {
|
|
return LHS == RHS;
|
|
}
|
|
};
|
|
} // end namespace llvm
|
|
|
|
#endif
|