aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Analysis/ProgramEdge.h
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2007-10-02 17:12:02 +0000
committerTed Kremenek <kremenek@apple.com>2007-10-02 17:12:02 +0000
commit4d20f2dd79e7829ade5e23945a2ef65a8fe1cf39 (patch)
tree97a4d19bbf9967fa071bc3c788b740b686732233 /include/clang/Analysis/ProgramEdge.h
parent8f3fde00ad4d4f943321e338b914ae4740711c84 (diff)
Moved ProgramEdge out out include/.../Analysis/PathSensitive to include/.../Analysis, as it is now used by the FlowSensitive subsystem as well.
Removed "Edge" nested class by CFG, as it is now subsumed by ProgramEdge. Adjusted DataflowSolver and DataflowValues to use ProgramEdges instead of CFG::Edge. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@42534 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/Analysis/ProgramEdge.h')
-rw-r--r--include/clang/Analysis/ProgramEdge.h138
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