diff options
author | ed <ed@FreeBSD.org> | 2009-06-02 17:58:47 +0000 |
---|---|---|
committer | ed <ed@FreeBSD.org> | 2009-06-02 17:58:47 +0000 |
commit | f27e5a09a0d815b8a4814152954ff87dadfdefc0 (patch) | |
tree | ce7d964cbb5e39695b71481698f10cb099c23d4a /include/clang/Analysis/ProgramPoint.h | |
download | FreeBSD-src-f27e5a09a0d815b8a4814152954ff87dadfdefc0.zip FreeBSD-src-f27e5a09a0d815b8a4814152954ff87dadfdefc0.tar.gz |
Import Clang, at r72732.
Diffstat (limited to 'include/clang/Analysis/ProgramPoint.h')
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 351 |
1 files changed, 351 insertions, 0 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h new file mode 100644 index 0000000..d2b536c --- /dev/null +++ b/include/clang/Analysis/ProgramPoint.h @@ -0,0 +1,351 @@ +//==- 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_PROGRAM_POINT +#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT + +#include "clang/AST/CFG.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <utility> + +namespace clang { + +class ProgramPoint { +public: + enum Kind { BlockEdgeKind = 0x0, + BlockEntranceKind = 0x1, + BlockExitKind = 0x2, + // Keep the following four together and in this order. + PostStmtKind = 0x3, + PostLocationChecksSucceedKind = 0x4, + PostOutOfBoundsCheckFailedKind = 0x5, + PostNullCheckFailedKind = 0x6, + PostUndefLocationCheckFailedKind = 0x7, + PostLoadKind = 0x8, + PostStoreKind = 0x9, + PostPurgeDeadSymbolsKind = 0x10, + PostStmtCustomKind = 0x11, + PostLValueKind = 0x12, + MinPostStmtKind = PostStmtKind, + MaxPostStmtKind = PostLValueKind }; + +private: + enum { TwoPointers = 0x1, Custom = 0x2, Mask = 0x3 }; + + std::pair<uintptr_t,uintptr_t> Data; + const void *Tag; + +protected: + ProgramPoint(const void* P, Kind k, const void *tag = 0) + : Data(reinterpret_cast<uintptr_t>(P), + (uintptr_t) k), Tag(tag) {} + + ProgramPoint(const void* P1, const void* P2, const void *tag = 0) + : Data(reinterpret_cast<uintptr_t>(P1) | TwoPointers, + reinterpret_cast<uintptr_t>(P2)), Tag(tag) {} + + ProgramPoint(const void* P1, const void* P2, bool, const void *tag = 0) + : Data(reinterpret_cast<uintptr_t>(P1) | Custom, + reinterpret_cast<uintptr_t>(P2)), Tag(tag) {} + +protected: + void* getData1NoMask() const { + Kind k = getKind(); k = k; + assert(k == BlockEntranceKind || k == BlockExitKind); + return reinterpret_cast<void*>(Data.first); + } + + void* getData1() const { + Kind k = getKind(); k = k; + assert(k == BlockEdgeKind ||(k >= MinPostStmtKind && k <= MaxPostStmtKind)); + return reinterpret_cast<void*>(Data.first & ~Mask); + } + + void* getData2() const { + Kind k = getKind(); k = k; + assert(k == BlockEdgeKind || k == PostStmtCustomKind); + return reinterpret_cast<void*>(Data.second); + } + + const void *getTag() const { return Tag; } + +public: + Kind getKind() const { + switch (Data.first & Mask) { + case TwoPointers: return BlockEdgeKind; + case Custom: return PostStmtCustomKind; + default: return (Kind) Data.second; + } + } + + // For use with DenseMap. This hash is probably slow. + unsigned getHashValue() const { + llvm::FoldingSetNodeID ID; + ID.AddPointer(reinterpret_cast<void*>(Data.first)); + ID.AddPointer(reinterpret_cast<void*>(Data.second)); + ID.AddPointer(Tag); + return ID.ComputeHash(); + } + + static bool classof(const ProgramPoint*) { return true; } + + bool operator==(const ProgramPoint & RHS) const { + return Data == RHS.Data && Tag == RHS.Tag; + } + + bool operator!=(const ProgramPoint& RHS) const { + return Data != RHS.Data || Tag != RHS.Tag; + } + + bool operator<(const ProgramPoint& RHS) const { + return Data < RHS.Data && Tag < RHS.Tag; + } + + void Profile(llvm::FoldingSetNodeID& ID) const { + ID.AddPointer(reinterpret_cast<void*>(Data.first)); + if (getKind() != PostStmtCustomKind) + ID.AddPointer(reinterpret_cast<void*>(Data.second)); + else { + const std::pair<const void*, const void*> *P = + reinterpret_cast<std::pair<const void*, const void*>*>(Data.second); + ID.AddPointer(P->first); + ID.AddPointer(P->second); + } + ID.AddPointer(Tag); + } +}; + +class BlockEntrance : public ProgramPoint { +public: + BlockEntrance(const CFGBlock* B, const void *tag = 0) + : ProgramPoint(B, BlockEntranceKind, tag) {} + + CFGBlock* getBlock() const { + return reinterpret_cast<CFGBlock*>(getData1NoMask()); + } + + Stmt* getFirstStmt() const { + CFGBlock* B = getBlock(); + return B->empty() ? NULL : B->front(); + } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == BlockEntranceKind; + } +}; + +class BlockExit : public ProgramPoint { +public: + BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {} + + CFGBlock* getBlock() const { + return reinterpret_cast<CFGBlock*>(getData1NoMask()); + } + + Stmt* getLastStmt() const { + CFGBlock* B = getBlock(); + return B->empty() ? NULL : B->back(); + } + + Stmt* getTerminator() const { + return getBlock()->getTerminator(); + } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == BlockExitKind; + } +}; + +class PostStmt : public ProgramPoint { +protected: + PostStmt(const Stmt* S, Kind k,const void *tag = 0) + : ProgramPoint(S, k, tag) {} + + PostStmt(const Stmt* S, const void* data, bool, const void *tag =0) + : ProgramPoint(S, data, true, tag) {} + +public: + PostStmt(const Stmt* S, const void *tag = 0) + : ProgramPoint(S, PostStmtKind, tag) {} + + Stmt* getStmt() const { return (Stmt*) getData1(); } + + template<typename T> + T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); } + + static bool classof(const ProgramPoint* Location) { + unsigned k = Location->getKind(); + return k >= MinPostStmtKind && k <= MaxPostStmtKind; + } +}; + +class PostLocationChecksSucceed : public PostStmt { +public: + PostLocationChecksSucceed(const Stmt* S, const void *tag = 0) + : PostStmt(S, PostLocationChecksSucceedKind, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostLocationChecksSucceedKind; + } +}; + +class PostStmtCustom : public PostStmt { +public: + PostStmtCustom(const Stmt* S, + const std::pair<const void*, const void*>* TaggedData) + : PostStmt(S, TaggedData, true) { + assert(getKind() == PostStmtCustomKind); + } + + const std::pair<const void*, const void*>& getTaggedPair() const { + return *reinterpret_cast<std::pair<const void*, const void*>*>(getData2()); + } + + const void* getTag() const { return getTaggedPair().first; } + + const void* getTaggedData() const { return getTaggedPair().second; } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostStmtCustomKind; + } +}; + +class PostOutOfBoundsCheckFailed : public PostStmt { +public: + PostOutOfBoundsCheckFailed(const Stmt* S, const void *tag = 0) + : PostStmt(S, PostOutOfBoundsCheckFailedKind, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostOutOfBoundsCheckFailedKind; + } +}; + +class PostUndefLocationCheckFailed : public PostStmt { +public: + PostUndefLocationCheckFailed(const Stmt* S, const void *tag = 0) + : PostStmt(S, PostUndefLocationCheckFailedKind, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostUndefLocationCheckFailedKind; + } +}; + +class PostNullCheckFailed : public PostStmt { +public: + PostNullCheckFailed(const Stmt* S, const void *tag = 0) + : PostStmt(S, PostNullCheckFailedKind, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostNullCheckFailedKind; + } +}; + +class PostLoad : public PostStmt { +public: + PostLoad(const Stmt* S, const void *tag = 0) + : PostStmt(S, PostLoadKind, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostLoadKind; + } +}; + +class PostStore : public PostStmt { +public: + PostStore(const Stmt* S, const void *tag = 0) + : PostStmt(S, PostStoreKind, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostStoreKind; + } +}; + +class PostLValue : public PostStmt { +public: + PostLValue(const Stmt* S, const void *tag = 0) + : PostStmt(S, PostLValueKind, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostLValueKind; + } +}; + +class PostPurgeDeadSymbols : public PostStmt { +public: + PostPurgeDeadSymbols(const Stmt* S, const void *tag = 0) + : PostStmt(S, PostPurgeDeadSymbolsKind, tag) {} + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PostPurgeDeadSymbolsKind; + } +}; + +class BlockEdge : public ProgramPoint { +public: + BlockEdge(const CFGBlock* B1, const CFGBlock* B2) + : ProgramPoint(B1, B2) {} + + CFGBlock* getSrc() const { + return static_cast<CFGBlock*>(getData1()); + } + + CFGBlock* getDst() const { + return static_cast<CFGBlock*>(getData2()); + } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == BlockEdgeKind; + } +}; + + +} // 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)); +} + +static inline clang::ProgramPoint getTombstoneKey() { + uintptr_t x = + reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; + return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x)); +} + +static unsigned getHashValue(const clang::ProgramPoint& Loc) { + return Loc.getHashValue(); +} + +static bool isEqual(const clang::ProgramPoint& L, + const clang::ProgramPoint& R) { + return L == R; +} + +static bool isPod() { + return true; +} +}; +} // end namespace llvm + +#endif |