aboutsummaryrefslogtreecommitdiff
path: root/include/clang/Analysis/ProgramPoint.h
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2008-09-16 18:44:52 +0000
committerTed Kremenek <kremenek@apple.com>2008-09-16 18:44:52 +0000
commitd452758bb6b59340528a26def9ecc24b329d4ecf (patch)
tree25346308283c18880c7584738c0907dec5968242 /include/clang/Analysis/ProgramPoint.h
parent3f61c18dd765c27bf900b22dc3a5f2a68e2364a1 (diff)
ProgramPoint now takes the space of two pointers instead of one. This change was
motivated because it became clear that the number of subclasses of ProgramPoint would expand and we ran out of bits to represent a pointer variant. As a plus of this change, BlockEdge program points can now be represented explicitly without using a cache of CFGBlock* pairs in CFG. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@56245 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/clang/Analysis/ProgramPoint.h')
-rw-r--r--include/clang/Analysis/ProgramPoint.h153
1 files changed, 88 insertions, 65 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h
index ecb4f742c7..0ea5365692 100644
--- a/include/clang/Analysis/ProgramPoint.h
+++ b/include/clang/Analysis/ProgramPoint.h
@@ -25,38 +25,67 @@ namespace clang {
class ProgramPoint {
public:
- enum Kind { BlockEntranceKind=0,
- PostStmtKind=1, PostLoadKind=2, PostPurgeDeadSymbolsKind=3,
- BlockExitKind=4, BlockEdgeSrcKind=5, BlockEdgeDstKind=6,
- BlockEdgeAuxKind=7 };
-protected:
- uintptr_t Data;
+ enum Kind { BlockEdgeKind=0, BlockEntranceKind, BlockExitKind,
+ // Keep the following three together and in this order.
+ PostStmtKind, PostLoadKind, PostPurgeDeadSymbolsKind };
- ProgramPoint(const void* Ptr, Kind k) {
- setRawData(Ptr, k);
+private:
+ std::pair<uintptr_t,uintptr_t> Data;
+
+protected:
+ ProgramPoint(const void* P, Kind k)
+ : Data(reinterpret_cast<uintptr_t>(P), (uintptr_t) k) {}
+
+ ProgramPoint(const void* P1, const void* P2)
+ : Data(reinterpret_cast<uintptr_t>(P1) | 0x1,
+ reinterpret_cast<uintptr_t>(P2)) {}
+
+protected:
+ void* getData1NoMask() const {
+ assert (getKind() != BlockEdgeKind);
+ return reinterpret_cast<void*>(Data.first);
}
- ProgramPoint() : Data(0) {}
+ void* getData1() const {
+ assert (getKind() == BlockEdgeKind);
+ return reinterpret_cast<void*>(Data.first & ~0x1);
+ }
- void setRawData(const void* Ptr, Kind k) {
- assert ((reinterpret_cast<uintptr_t>(const_cast<void*>(Ptr)) & 0x7) == 0
- && "Address must have at least an 8-byte alignment.");
-
- Data = reinterpret_cast<uintptr_t>(const_cast<void*>(Ptr)) | k;
+ void* getData2() const {
+ assert (getKind() == BlockEdgeKind);
+ return reinterpret_cast<void*>(Data.second);
}
public:
- unsigned getKind() const { return Data & 0x7; }
- void* getRawPtr() const { return reinterpret_cast<void*>(Data & ~0x7); }
- void* getRawData() const { return reinterpret_cast<void*>(Data); }
+
+ uintptr_t getKind() const {
+ return Data.first & 0x1 ? (uintptr_t) BlockEdgeKind : Data.second;
+ }
+
+ // For use with DenseMap.
+ unsigned getHashValue() const {
+ std::pair<void*,void*> P(reinterpret_cast<void*>(Data.first),
+ reinterpret_cast<void*>(Data.second));
+ return llvm::DenseMapInfo<std::pair<void*,void*> >::getHashValue(P);
+ }
static bool classof(const ProgramPoint*) { return true; }
- bool operator==(const ProgramPoint & RHS) const { return Data == RHS.Data; }
- bool operator!=(const ProgramPoint& RHS) const { return Data != RHS.Data; }
+
+ bool operator==(const ProgramPoint & RHS) const {
+ return Data == RHS.Data;
+ }
+
+ bool operator!=(const ProgramPoint& RHS) const {
+ return Data != RHS.Data;
+ }
+
+ bool operator<(const ProgramPoint& RHS) const {
+ return Data < RHS.Data;
+ }
void Profile(llvm::FoldingSetNodeID& ID) const {
- ID.AddInteger(getKind());
- ID.AddPointer(getRawPtr());
+ ID.AddPointer(reinterpret_cast<void*>(Data.first));
+ ID.AddPointer(reinterpret_cast<void*>(Data.second));
}
};
@@ -65,7 +94,7 @@ public:
BlockEntrance(const CFGBlock* B) : ProgramPoint(B, BlockEntranceKind) {}
CFGBlock* getBlock() const {
- return reinterpret_cast<CFGBlock*>(getRawPtr());
+ return reinterpret_cast<CFGBlock*>(getData1NoMask());
}
Stmt* getFirstStmt() const {
@@ -83,7 +112,7 @@ public:
BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {}
CFGBlock* getBlock() const {
- return reinterpret_cast<CFGBlock*>(getRawPtr());
+ return reinterpret_cast<CFGBlock*>(getData1NoMask());
}
Stmt* getLastStmt() const {
@@ -107,7 +136,7 @@ protected:
public:
PostStmt(const Stmt* S) : ProgramPoint(S, PostStmtKind) {}
- Stmt* getStmt() const { return (Stmt*) getRawPtr(); }
+ Stmt* getStmt() const { return (Stmt*) getData1NoMask(); }
static bool classof(const ProgramPoint* Location) {
unsigned k = Location->getKind();
@@ -134,26 +163,22 @@ public:
};
class BlockEdge : public ProgramPoint {
- typedef std::pair<CFGBlock*,CFGBlock*> BPair;
public:
- BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2);
-
- /// This ctor forces the BlockEdge to be constructed using an explicitly
- /// allocated pair object that is stored in the CFG. This is usually
- /// used to construct edges representing jumps using computed gotos.
- BlockEdge(CFG& cfg, const CFGBlock* B1, const CFGBlock* B2, bool)
- : ProgramPoint(cfg.getBlockEdgeImpl(B1, B2), BlockEdgeAuxKind) {}
-
-
- CFGBlock* getSrc() const;
- CFGBlock* getDst() const;
+ 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) {
- unsigned k = Location->getKind();
- return k >= BlockEdgeSrcKind && k <= BlockEdgeAuxKind;
+ return Location->getKind() == BlockEdgeKind;
}
};
-
} // end namespace clang
@@ -163,32 +188,30 @@ 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 DenseMapInfo<void*>::getHashValue(Loc.getRawData());
- }
-
- static bool isEqual(const clang::ProgramPoint& L,
- const clang::ProgramPoint& R) {
- return L == R;
- }
-
- static bool isPod() {
- return true;
- }
+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