diff options
Diffstat (limited to 'include/clang/Analysis/ProgramEdge.h')
-rw-r--r-- | include/clang/Analysis/ProgramEdge.h | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/include/clang/Analysis/ProgramEdge.h b/include/clang/Analysis/ProgramEdge.h new file mode 100644 index 0000000000..9772a5e1a6 --- /dev/null +++ b/include/clang/Analysis/ProgramEdge.h @@ -0,0 +1,138 @@ +//==- ProgramEdge.h - Program Points for Path-Sensitive Analysis --*- C++ -*-=// +// +// The LLVM Compiler Infrastructure +// +// This file was developed by Ted Kremenek and is distributed under +// the University of Illinois Open Source License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the interface ProgramEdge, which identifies a distinct +// location in a function based on edges within its CFG. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_PATHSENS_PROGRAM_POINT +#define LLVM_CLANG_ANALYSIS_PATHSENS_PROGRAM_POINT + +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/DenseMap.h" +#include <cassert> + +namespace clang { + + class CFGBlock; + class Stmt; + +class ProgramEdge { + uintptr_t Src, Dst; +public: + enum EdgeKind { StmtBlk=0, BlkStmt=1, StmtStmt=2, BlkBlk=3 }; + static bool classof(const ProgramEdge*) { return true; } + + unsigned getKind() const { return (unsigned) Src & 0x3; } + void* RawSrc() const { return reinterpret_cast<void*>(Src & ~0x3); } + void* RawDst() const { return reinterpret_cast<void*>(Dst); } + + bool operator==(const ProgramEdge & RHS) const { + // comparing pointer values canoncalizes "NULL" edges where both pointers + // are NULL without having to worry about edgekind. We can otherwise + // ignore edgekind because no CFGBlock* or Stmt* will have the same value. + return RawSrc() == RHS.RawSrc() && RawDst() == RHS.RawDst(); + } + + bool operator!=(const ProgramEdge& RHS) const { + return RawSrc() != RHS.RawSrc() || RawDst() != RHS.RawDst(); + } + + unsigned getHashValue() const { + uintptr_t v1 = reinterpret_cast<uintptr_t>(RawSrc()); + uintptr_t v2 = reinterpret_cast<uintptr_t>(RawDst()); + return static_cast<unsigned>( (v1 >> 4) ^ (v1 >> 9) ^ + (v2 >> 5) ^ (v2 >> 10) ); + } + +protected: + + ProgramEdge(const void* src, const void* dst, EdgeKind k) { + assert (k >= StmtBlk && k <= BlkBlk); + Src = reinterpret_cast<uintptr_t>(const_cast<void*>(src)) | k; + Dst = reinterpret_cast<uintptr_t>(const_cast<void*>(dst)); + } +}; + +class StmtBlkEdge : public ProgramEdge { +public: + StmtBlkEdge(const Stmt* S,const CFGBlock* B) + : ProgramEdge(S,B,StmtBlk) {} + + const Stmt* Src() const { return reinterpret_cast<Stmt*>(RawSrc()); } + const CFGBlock* Dst() const { return reinterpret_cast<CFGBlock*>(RawDst()); } + + static bool classof(const ProgramEdge* E) { return E->getKind() == StmtBlk; } +}; + +class BlkStmtEdge : public ProgramEdge { +public: + BlkStmtEdge(const CFGBlock* B, const Stmt* S) + : ProgramEdge(B,S,BlkStmt) {} + + const CFGBlock* Src() const { return reinterpret_cast<CFGBlock*>(RawSrc()); } + const Stmt* Dst() const { return reinterpret_cast<Stmt*>(RawDst()); } + + static bool classof(const ProgramEdge* E) { return E->getKind() == StmtBlk; } +}; + +class StmtStmtEdge : public ProgramEdge { +public: + StmtStmtEdge(const Stmt* S1, const Stmt* S2) + : ProgramEdge(S1,S2,StmtStmt) {} + + const Stmt* Src() const { return reinterpret_cast<Stmt*>(RawSrc()); } + const Stmt* Dst() const { return reinterpret_cast<Stmt*>(RawDst()); } + + static bool classof(const ProgramEdge* E) { return E->getKind() == StmtStmt; } +}; + + +class BlkBlkEdge : public ProgramEdge { +public: + BlkBlkEdge(const CFGBlock* B1, const CFGBlock* B2) + : ProgramEdge(B1,B2,BlkBlk) {} + + const CFGBlock* Src() const { return reinterpret_cast<CFGBlock*>(RawSrc()); } + const CFGBlock* Dst() const { return reinterpret_cast<CFGBlock*>(RawDst()); } + + static bool classof(const ProgramEdge* E) { return E->getKind() == BlkBlk; } +}; + +} // end namespace clang + + +namespace llvm { // Traits specialization for DenseMap + +template <> struct DenseMapInfo<clang::ProgramEdge> { + + static inline clang::ProgramEdge getEmptyKey() { + return clang::BlkBlkEdge(NULL,NULL); + } + + static inline clang::ProgramEdge getTombstoneKey() { + return clang::BlkBlkEdge(reinterpret_cast<clang::CFGBlock*>(-1), + reinterpret_cast<clang::CFGBlock*>(-1)); + } + + static unsigned getHashValue(const clang::ProgramEdge& E) { + return E.getHashValue(); + } + + static bool isEqual(const clang::ProgramEdge& LHS, + const clang::ProgramEdge& RHS) { + return LHS == RHS; + } + + static bool isPod() { return true; } +}; +} // end namespace llvm + +#endif |