diff options
Diffstat (limited to 'include/clang/Analysis/ProgramPoint.h')
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 704 |
1 files changed, 0 insertions, 704 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h deleted file mode 100644 index 6d816fd..0000000 --- a/include/clang/Analysis/ProgramPoint.h +++ /dev/null @@ -1,704 +0,0 @@ -//==- ProgramPoint.h - Program Points for Path-Sensitive Analysis --*- C++ -*-// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the interface ProgramPoint, which identifies a -// distinct location in a function. -// -//===----------------------------------------------------------------------===// - -#ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H -#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H - -#include "clang/Analysis/AnalysisContext.h" -#include "clang/Analysis/CFG.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/Optional.h" -#include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/DataTypes.h" -#include <cassert> -#include <string> -#include <utility> - -namespace clang { - -class AnalysisDeclContext; -class FunctionDecl; -class LocationContext; - -/// ProgramPoints can be "tagged" as representing points specific to a given -/// analysis entity. Tags are abstract annotations, with an associated -/// description and potentially other information. -class ProgramPointTag { -public: - ProgramPointTag(void *tagKind = nullptr) : TagKind(tagKind) {} - virtual ~ProgramPointTag(); - virtual StringRef getTagDescription() const = 0; - -protected: - /// Used to implement 'isKind' in subclasses. - const void *getTagKind() { return TagKind; } - -private: - const void *TagKind; -}; - -class SimpleProgramPointTag : public ProgramPointTag { - std::string Desc; -public: - SimpleProgramPointTag(StringRef MsgProvider, StringRef Msg); - StringRef getTagDescription() const override; -}; - -class ProgramPoint { -public: - enum Kind { BlockEdgeKind, - BlockEntranceKind, - BlockExitKind, - PreStmtKind, - PreStmtPurgeDeadSymbolsKind, - PostStmtPurgeDeadSymbolsKind, - PostStmtKind, - PreLoadKind, - PostLoadKind, - PreStoreKind, - PostStoreKind, - PostConditionKind, - PostLValueKind, - MinPostStmtKind = PostStmtKind, - MaxPostStmtKind = PostLValueKind, - PostInitializerKind, - CallEnterKind, - CallExitBeginKind, - CallExitEndKind, - PreImplicitCallKind, - PostImplicitCallKind, - MinImplicitCallKind = PreImplicitCallKind, - MaxImplicitCallKind = PostImplicitCallKind, - EpsilonKind}; - -private: - const void *Data1; - llvm::PointerIntPair<const void *, 2, unsigned> Data2; - - // The LocationContext could be NULL to allow ProgramPoint to be used in - // context insensitive analysis. - llvm::PointerIntPair<const LocationContext *, 2, unsigned> L; - - llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag; - -protected: - ProgramPoint() {} - ProgramPoint(const void *P, - Kind k, - const LocationContext *l, - const ProgramPointTag *tag = nullptr) - : Data1(P), - Data2(nullptr, (((unsigned) k) >> 0) & 0x3), - L(l, (((unsigned) k) >> 2) & 0x3), - Tag(tag, (((unsigned) k) >> 4) & 0x3) { - assert(getKind() == k); - assert(getLocationContext() == l); - assert(getData1() == P); - } - - ProgramPoint(const void *P1, - const void *P2, - Kind k, - const LocationContext *l, - const ProgramPointTag *tag = nullptr) - : Data1(P1), - Data2(P2, (((unsigned) k) >> 0) & 0x3), - L(l, (((unsigned) k) >> 2) & 0x3), - Tag(tag, (((unsigned) k) >> 4) & 0x3) {} - -protected: - const void *getData1() const { return Data1; } - const void *getData2() const { return Data2.getPointer(); } - void setData2(const void *d) { Data2.setPointer(d); } - -public: - /// Create a new ProgramPoint object that is the same as the original - /// except for using the specified tag value. - ProgramPoint withTag(const ProgramPointTag *tag) const { - return ProgramPoint(getData1(), getData2(), getKind(), - getLocationContext(), tag); - } - - /// \brief Convert to the specified ProgramPoint type, asserting that this - /// ProgramPoint is of the desired type. - template<typename T> - T castAs() const { - assert(T::isKind(*this)); - T t; - ProgramPoint& PP = t; - PP = *this; - return t; - } - - /// \brief Convert to the specified ProgramPoint type, returning None if this - /// ProgramPoint is not of the desired type. - template<typename T> - Optional<T> getAs() const { - if (!T::isKind(*this)) - return None; - T t; - ProgramPoint& PP = t; - PP = *this; - return t; - } - - Kind getKind() const { - unsigned x = Tag.getInt(); - x <<= 2; - x |= L.getInt(); - x <<= 2; - x |= Data2.getInt(); - return (Kind) x; - } - - /// \brief Is this a program point corresponding to purge/removal of dead - /// symbols and bindings. - bool isPurgeKind() { - Kind K = getKind(); - return (K == PostStmtPurgeDeadSymbolsKind || - K == PreStmtPurgeDeadSymbolsKind); - } - - const ProgramPointTag *getTag() const { return Tag.getPointer(); } - - const LocationContext *getLocationContext() const { - return L.getPointer(); - } - - // For use with DenseMap. This hash is probably slow. - unsigned getHashValue() const { - llvm::FoldingSetNodeID ID; - Profile(ID); - return ID.ComputeHash(); - } - - bool operator==(const ProgramPoint & RHS) const { - return Data1 == RHS.Data1 && - Data2 == RHS.Data2 && - L == RHS.L && - Tag == RHS.Tag; - } - - bool operator!=(const ProgramPoint &RHS) const { - return Data1 != RHS.Data1 || - Data2 != RHS.Data2 || - L != RHS.L || - Tag != RHS.Tag; - } - - void Profile(llvm::FoldingSetNodeID& ID) const { - ID.AddInteger((unsigned) getKind()); - ID.AddPointer(getData1()); - ID.AddPointer(getData2()); - ID.AddPointer(getLocationContext()); - ID.AddPointer(getTag()); - } - - static ProgramPoint getProgramPoint(const Stmt *S, ProgramPoint::Kind K, - const LocationContext *LC, - const ProgramPointTag *tag); -}; - -class BlockEntrance : public ProgramPoint { -public: - BlockEntrance(const CFGBlock *B, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : ProgramPoint(B, BlockEntranceKind, L, tag) { - assert(B && "BlockEntrance requires non-null block"); - } - - const CFGBlock *getBlock() const { - return reinterpret_cast<const CFGBlock*>(getData1()); - } - - Optional<CFGElement> getFirstElement() const { - const CFGBlock *B = getBlock(); - return B->empty() ? Optional<CFGElement>() : B->front(); - } - -private: - friend class ProgramPoint; - BlockEntrance() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == BlockEntranceKind; - } -}; - -class BlockExit : public ProgramPoint { -public: - BlockExit(const CFGBlock *B, const LocationContext *L) - : ProgramPoint(B, BlockExitKind, L) {} - - const CFGBlock *getBlock() const { - return reinterpret_cast<const CFGBlock*>(getData1()); - } - - const Stmt *getTerminator() const { - return getBlock()->getTerminator(); - } - -private: - friend class ProgramPoint; - BlockExit() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == BlockExitKind; - } -}; - -class StmtPoint : public ProgramPoint { -public: - StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L, - const ProgramPointTag *tag) - : ProgramPoint(S, p2, k, L, tag) { - assert(S); - } - - const Stmt *getStmt() const { return (const Stmt*) getData1(); } - - template <typename T> - const T* getStmtAs() const { return dyn_cast<T>(getStmt()); } - -protected: - StmtPoint() {} -private: - friend class ProgramPoint; - static bool isKind(const ProgramPoint &Location) { - unsigned k = Location.getKind(); - return k >= PreStmtKind && k <= MaxPostStmtKind; - } -}; - - -class PreStmt : public StmtPoint { -public: - PreStmt(const Stmt *S, const LocationContext *L, const ProgramPointTag *tag, - const Stmt *SubStmt = nullptr) - : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {} - - const Stmt *getSubStmt() const { return (const Stmt*) getData2(); } - -private: - friend class ProgramPoint; - PreStmt() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PreStmtKind; - } -}; - -class PostStmt : public StmtPoint { -protected: - PostStmt() {} - PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : StmtPoint(S, data, k, L, tag) {} - -public: - explicit PostStmt(const Stmt *S, Kind k, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : StmtPoint(S, nullptr, k, L, tag) {} - - explicit PostStmt(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : StmtPoint(S, nullptr, PostStmtKind, L, tag) {} - -private: - friend class ProgramPoint; - static bool isKind(const ProgramPoint &Location) { - unsigned k = Location.getKind(); - return k >= MinPostStmtKind && k <= MaxPostStmtKind; - } -}; - -// PostCondition represents the post program point of a branch condition. -class PostCondition : public PostStmt { -public: - PostCondition(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : PostStmt(S, PostConditionKind, L, tag) {} - -private: - friend class ProgramPoint; - PostCondition() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PostConditionKind; - } -}; - -class LocationCheck : public StmtPoint { -protected: - LocationCheck() {} - LocationCheck(const Stmt *S, const LocationContext *L, - ProgramPoint::Kind K, const ProgramPointTag *tag) - : StmtPoint(S, nullptr, K, L, tag) {} - -private: - friend class ProgramPoint; - static bool isKind(const ProgramPoint &location) { - unsigned k = location.getKind(); - return k == PreLoadKind || k == PreStoreKind; - } -}; - -class PreLoad : public LocationCheck { -public: - PreLoad(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : LocationCheck(S, L, PreLoadKind, tag) {} - -private: - friend class ProgramPoint; - PreLoad() {} - static bool isKind(const ProgramPoint &location) { - return location.getKind() == PreLoadKind; - } -}; - -class PreStore : public LocationCheck { -public: - PreStore(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : LocationCheck(S, L, PreStoreKind, tag) {} - -private: - friend class ProgramPoint; - PreStore() {} - static bool isKind(const ProgramPoint &location) { - return location.getKind() == PreStoreKind; - } -}; - -class PostLoad : public PostStmt { -public: - PostLoad(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : PostStmt(S, PostLoadKind, L, tag) {} - -private: - friend class ProgramPoint; - PostLoad() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PostLoadKind; - } -}; - -/// \brief Represents a program point after a store evaluation. -class PostStore : public PostStmt { -public: - /// Construct the post store point. - /// \param Loc can be used to store the information about the location - /// used in the form it was uttered in the code. - PostStore(const Stmt *S, const LocationContext *L, const void *Loc, - const ProgramPointTag *tag = nullptr) - : PostStmt(S, PostStoreKind, L, tag) { - assert(getData2() == nullptr); - setData2(Loc); - } - - /// \brief Returns the information about the location used in the store, - /// how it was uttered in the code. - const void *getLocationValue() const { - return getData2(); - } - -private: - friend class ProgramPoint; - PostStore() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PostStoreKind; - } -}; - -class PostLValue : public PostStmt { -public: - PostLValue(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : PostStmt(S, PostLValueKind, L, tag) {} - -private: - friend class ProgramPoint; - PostLValue() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PostLValueKind; - } -}; - -/// Represents a point after we ran remove dead bindings BEFORE -/// processing the given statement. -class PreStmtPurgeDeadSymbols : public StmtPoint { -public: - PreStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : StmtPoint(S, nullptr, PreStmtPurgeDeadSymbolsKind, L, tag) { } - -private: - friend class ProgramPoint; - PreStmtPurgeDeadSymbols() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PreStmtPurgeDeadSymbolsKind; - } -}; - -/// Represents a point after we ran remove dead bindings AFTER -/// processing the given statement. -class PostStmtPurgeDeadSymbols : public StmtPoint { -public: - PostStmtPurgeDeadSymbols(const Stmt *S, const LocationContext *L, - const ProgramPointTag *tag = nullptr) - : StmtPoint(S, nullptr, PostStmtPurgeDeadSymbolsKind, L, tag) { } - -private: - friend class ProgramPoint; - PostStmtPurgeDeadSymbols() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PostStmtPurgeDeadSymbolsKind; - } -}; - -class BlockEdge : public ProgramPoint { -public: - BlockEdge(const CFGBlock *B1, const CFGBlock *B2, const LocationContext *L) - : ProgramPoint(B1, B2, BlockEdgeKind, L) { - assert(B1 && "BlockEdge: source block must be non-null"); - assert(B2 && "BlockEdge: destination block must be non-null"); - } - - const CFGBlock *getSrc() const { - return static_cast<const CFGBlock*>(getData1()); - } - - const CFGBlock *getDst() const { - return static_cast<const CFGBlock*>(getData2()); - } - -private: - friend class ProgramPoint; - BlockEdge() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == BlockEdgeKind; - } -}; - -class PostInitializer : public ProgramPoint { -public: - /// \brief Construct a PostInitializer point that represents a location after - /// CXXCtorInitializer expression evaluation. - /// - /// \param I The initializer. - /// \param Loc The location of the field being initialized. - PostInitializer(const CXXCtorInitializer *I, - const void *Loc, - const LocationContext *L) - : ProgramPoint(I, Loc, PostInitializerKind, L) {} - - const CXXCtorInitializer *getInitializer() const { - return static_cast<const CXXCtorInitializer *>(getData1()); - } - - /// \brief Returns the location of the field. - const void *getLocationValue() const { - return getData2(); - } - -private: - friend class ProgramPoint; - PostInitializer() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PostInitializerKind; - } -}; - -/// Represents an implicit call event. -/// -/// The nearest statement is provided for diagnostic purposes. -class ImplicitCallPoint : public ProgramPoint { -public: - ImplicitCallPoint(const Decl *D, SourceLocation Loc, Kind K, - const LocationContext *L, const ProgramPointTag *Tag) - : ProgramPoint(Loc.getPtrEncoding(), D, K, L, Tag) {} - - const Decl *getDecl() const { return static_cast<const Decl *>(getData2()); } - SourceLocation getLocation() const { - return SourceLocation::getFromPtrEncoding(getData1()); - } - -protected: - ImplicitCallPoint() {} -private: - friend class ProgramPoint; - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() >= MinImplicitCallKind && - Location.getKind() <= MaxImplicitCallKind; - } -}; - -/// Represents a program point just before an implicit call event. -/// -/// Explicit calls will appear as PreStmt program points. -class PreImplicitCall : public ImplicitCallPoint { -public: - PreImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L, - const ProgramPointTag *Tag = nullptr) - : ImplicitCallPoint(D, Loc, PreImplicitCallKind, L, Tag) {} - -private: - friend class ProgramPoint; - PreImplicitCall() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PreImplicitCallKind; - } -}; - -/// Represents a program point just after an implicit call event. -/// -/// Explicit calls will appear as PostStmt program points. -class PostImplicitCall : public ImplicitCallPoint { -public: - PostImplicitCall(const Decl *D, SourceLocation Loc, const LocationContext *L, - const ProgramPointTag *Tag = nullptr) - : ImplicitCallPoint(D, Loc, PostImplicitCallKind, L, Tag) {} - -private: - friend class ProgramPoint; - PostImplicitCall() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == PostImplicitCallKind; - } -}; - -/// Represents a point when we begin processing an inlined call. -/// CallEnter uses the caller's location context. -class CallEnter : public ProgramPoint { -public: - CallEnter(const Stmt *stmt, const StackFrameContext *calleeCtx, - const LocationContext *callerCtx) - : ProgramPoint(stmt, calleeCtx, CallEnterKind, callerCtx, nullptr) {} - - const Stmt *getCallExpr() const { - return static_cast<const Stmt *>(getData1()); - } - - const StackFrameContext *getCalleeContext() const { - return static_cast<const StackFrameContext *>(getData2()); - } - -private: - friend class ProgramPoint; - CallEnter() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == CallEnterKind; - } -}; - -/// Represents a point when we start the call exit sequence (for inlined call). -/// -/// The call exit is simulated with a sequence of nodes, which occur between -/// CallExitBegin and CallExitEnd. The following operations occur between the -/// two program points: -/// - CallExitBegin -/// - Bind the return value -/// - Run Remove dead bindings (to clean up the dead symbols from the callee). -/// - CallExitEnd -class CallExitBegin : public ProgramPoint { -public: - // CallExitBegin uses the callee's location context. - CallExitBegin(const StackFrameContext *L) - : ProgramPoint(nullptr, CallExitBeginKind, L, nullptr) {} - -private: - friend class ProgramPoint; - CallExitBegin() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == CallExitBeginKind; - } -}; - -/// Represents a point when we finish the call exit sequence (for inlined call). -/// \sa CallExitBegin -class CallExitEnd : public ProgramPoint { -public: - // CallExitEnd uses the caller's location context. - CallExitEnd(const StackFrameContext *CalleeCtx, - const LocationContext *CallerCtx) - : ProgramPoint(CalleeCtx, CallExitEndKind, CallerCtx, nullptr) {} - - const StackFrameContext *getCalleeContext() const { - return static_cast<const StackFrameContext *>(getData1()); - } - -private: - friend class ProgramPoint; - CallExitEnd() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == CallExitEndKind; - } -}; - -/// This is a meta program point, which should be skipped by all the diagnostic -/// reasoning etc. -class EpsilonPoint : public ProgramPoint { -public: - EpsilonPoint(const LocationContext *L, const void *Data1, - const void *Data2 = nullptr, - const ProgramPointTag *tag = nullptr) - : ProgramPoint(Data1, Data2, EpsilonKind, L, tag) {} - - const void *getData() const { return getData1(); } - -private: - friend class ProgramPoint; - EpsilonPoint() {} - static bool isKind(const ProgramPoint &Location) { - return Location.getKind() == EpsilonKind; - } -}; - -} // end namespace clang - - -namespace llvm { // Traits specialization for DenseMap - -template <> struct DenseMapInfo<clang::ProgramPoint> { - -static inline clang::ProgramPoint getEmptyKey() { - uintptr_t x = - reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; - return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr); -} - -static inline clang::ProgramPoint getTombstoneKey() { - uintptr_t x = - reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; - return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), nullptr); -} - -static unsigned getHashValue(const clang::ProgramPoint &Loc) { - return Loc.getHashValue(); -} - -static bool isEqual(const clang::ProgramPoint &L, - const clang::ProgramPoint &R) { - return L == R; -} - -}; - -template <> -struct isPodLike<clang::ProgramPoint> { static const bool value = true; }; - -} // end namespace llvm - -#endif |