diff options
Diffstat (limited to 'include/clang/Analysis/ProgramPoint.h')
-rw-r--r-- | include/clang/Analysis/ProgramPoint.h | 321 |
1 files changed, 163 insertions, 158 deletions
diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index d2b536c..666e45b 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -15,7 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT #define LLVM_CLANG_ANALYSIS_PROGRAM_POINT -#include "clang/AST/CFG.h" +#include "clang/Analysis/CFG.h" #include "llvm/Support/DataTypes.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -24,123 +24,95 @@ #include <utility> namespace clang { - + +class LocationContext; + 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, + enum Kind { BlockEdgeKind, + BlockEntranceKind, + BlockExitKind, + PreStmtKind, + // Keep the following together and in this order. + PostStmtKind, + PostLocationChecksSucceedKind, + PostOutOfBoundsCheckFailedKind, + PostNullCheckFailedKind, + PostUndefLocationCheckFailedKind, + PostLoadKind, + PostStoreKind, + PostPurgeDeadSymbolsKind, + PostStmtCustomKind, + PostLValueKind, MinPostStmtKind = PostStmtKind, MaxPostStmtKind = PostLValueKind }; private: - enum { TwoPointers = 0x1, Custom = 0x2, Mask = 0x3 }; - - std::pair<uintptr_t,uintptr_t> Data; + std::pair<const void *, const void *> Data; + Kind K; + + // The LocationContext could be NULL to allow ProgramPoint to be used in + // context insensitive analysis. + const LocationContext *L; 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); - } + ProgramPoint(const void* P, Kind k, const LocationContext *l, + const void *tag = 0) + : Data(P, NULL), K(k), L(l), Tag(tag) {} - void* getData2() const { - Kind k = getKind(); k = k; - assert(k == BlockEdgeKind || k == PostStmtCustomKind); - return reinterpret_cast<void*>(Data.second); - } - + ProgramPoint(const void* P1, const void* P2, Kind k, const LocationContext *l, + const void *tag = 0) + : Data(P1, P2), K(k), L(l), Tag(tag) {} + +protected: + const void* getData1() const { return Data.first; } + const void* getData2() const { return 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; - } - } + +public: + Kind getKind() const { return K; } + + const LocationContext *getLocationContext() const { return L; } // 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); + Profile(ID); return ID.ComputeHash(); } - + static bool classof(const ProgramPoint*) { return true; } bool operator==(const ProgramPoint & RHS) const { - return Data == RHS.Data && Tag == RHS.Tag; + return K == RHS.K && Data == RHS.Data && L == RHS.L && Tag == RHS.Tag; } bool operator!=(const ProgramPoint& RHS) const { - return Data != RHS.Data || Tag != RHS.Tag; + return K != RHS.K || Data != RHS.Data || L != RHS.L || 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.AddInteger((unsigned) K); + ID.AddPointer(Data.first); + ID.AddPointer(Data.second); + ID.AddPointer(L); ID.AddPointer(Tag); } }; - + class BlockEntrance : public ProgramPoint { public: - BlockEntrance(const CFGBlock* B, const void *tag = 0) - : ProgramPoint(B, BlockEntranceKind, tag) {} - + BlockEntrance(const CFGBlock* B, const LocationContext *L, + const void *tag = 0) + : ProgramPoint(B, BlockEntranceKind, L, tag) {} + CFGBlock* getBlock() const { - return reinterpret_cast<CFGBlock*>(getData1NoMask()); + return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); } - + Stmt* getFirstStmt() const { - CFGBlock* B = getBlock(); + const CFGBlock* B = getBlock(); return B->empty() ? NULL : B->front(); } @@ -151,42 +123,70 @@ public: class BlockExit : public ProgramPoint { public: - BlockExit(const CFGBlock* B) : ProgramPoint(B, BlockExitKind) {} - + BlockExit(const CFGBlock* B, const LocationContext *L) + : ProgramPoint(B, BlockExitKind, L) {} + CFGBlock* getBlock() const { - return reinterpret_cast<CFGBlock*>(getData1NoMask()); + return const_cast<CFGBlock*>(reinterpret_cast<const CFGBlock*>(getData1())); } Stmt* getLastStmt() const { - CFGBlock* B = getBlock(); + 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) {} +class StmtPoint : public ProgramPoint { +public: + StmtPoint(const Stmt *S, const void *p2, Kind k, const LocationContext *L, + const void *tag) + : ProgramPoint(S, p2, k, L, tag) {} + + const Stmt *getStmt() const { return (const Stmt*) getData1(); } - PostStmt(const Stmt* S, const void* data, bool, const void *tag =0) - : ProgramPoint(S, data, true, tag) {} - + template <typename T> + const T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); } + + static bool classof(const ProgramPoint* Location) { + unsigned k = Location->getKind(); + return k >= PreStmtKind && k <= MaxPostStmtKind; + } +}; + + +class PreStmt : public StmtPoint { public: - PostStmt(const Stmt* S, const void *tag = 0) - : ProgramPoint(S, PostStmtKind, tag) {} + PreStmt(const Stmt *S, const LocationContext *L, const void *tag, + const Stmt *SubStmt = 0) + : StmtPoint(S, SubStmt, PreStmtKind, L, tag) {} - Stmt* getStmt() const { return (Stmt*) getData1(); } - - template<typename T> - T* getStmtAs() const { return llvm::dyn_cast<T>(getStmt()); } + const Stmt *getSubStmt() const { return (const Stmt*) getData2(); } + + static bool classof(const ProgramPoint* Location) { + return Location->getKind() == PreStmtKind; + } +}; + +class PostStmt : public StmtPoint { +protected: + PostStmt(const Stmt* S, Kind k, const LocationContext *L, const void *tag = 0) + : StmtPoint(S, NULL, k, L, tag) {} + + PostStmt(const Stmt* S, const void* data, Kind k, const LocationContext *L, + const void *tag =0) + : StmtPoint(S, data, k, L, tag) {} + +public: + explicit PostStmt(const Stmt* S, const LocationContext *L,const void *tag = 0) + : StmtPoint(S, NULL, PostStmtKind, L, tag) {} static bool classof(const ProgramPoint* Location) { unsigned k = Location->getKind(); @@ -196,40 +196,42 @@ public: class PostLocationChecksSucceed : public PostStmt { public: - PostLocationChecksSucceed(const Stmt* S, const void *tag = 0) - : PostStmt(S, PostLocationChecksSucceedKind, tag) {} - + PostLocationChecksSucceed(const Stmt* S, const LocationContext *L, + const void *tag = 0) + : PostStmt(S, PostLocationChecksSucceedKind, L, 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*>* TaggedData,\ + const LocationContext *L) + : PostStmt(S, TaggedData, PostStmtCustomKind, L) {} const std::pair<const void*, const void*>& getTaggedPair() const { - return *reinterpret_cast<std::pair<const void*, const void*>*>(getData2()); + return + *reinterpret_cast<const 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) {} - + PostOutOfBoundsCheckFailed(const Stmt* S, const LocationContext *L, + const void *tag = 0) + : PostStmt(S, PostOutOfBoundsCheckFailedKind, L, tag) {} + static bool classof(const ProgramPoint* Location) { return Location->getKind() == PostOutOfBoundsCheckFailedKind; } @@ -237,39 +239,41 @@ public: class PostUndefLocationCheckFailed : public PostStmt { public: - PostUndefLocationCheckFailed(const Stmt* S, const void *tag = 0) - : PostStmt(S, PostUndefLocationCheckFailedKind, tag) {} - + PostUndefLocationCheckFailed(const Stmt* S, const LocationContext *L, + const void *tag = 0) + : PostStmt(S, PostUndefLocationCheckFailedKind, L, 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) {} - + PostNullCheckFailed(const Stmt* S, const LocationContext *L, + const void *tag = 0) + : PostStmt(S, PostNullCheckFailedKind, L, 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) {} - + PostLoad(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostLoadKind, L, 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) {} - + PostStore(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostStoreKind, L, tag) {} + static bool classof(const ProgramPoint* Location) { return Location->getKind() == PostStoreKind; } @@ -277,60 +281,61 @@ public: class PostLValue : public PostStmt { public: - PostLValue(const Stmt* S, const void *tag = 0) - : PostStmt(S, PostLValueKind, tag) {} - + PostLValue(const Stmt* S, const LocationContext *L, const void *tag = 0) + : PostStmt(S, PostLValueKind, L, 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) {} - + PostPurgeDeadSymbols(const Stmt* S, const LocationContext *L, + const void *tag = 0) + : PostStmt(S, PostPurgeDeadSymbolsKind, L, 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) {} - + BlockEdge(const CFGBlock* B1, const CFGBlock* B2, const LocationContext *L) + : ProgramPoint(B1, B2, BlockEdgeKind, L) {} + CFGBlock* getSrc() const { - return static_cast<CFGBlock*>(getData1()); + return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData1())); } - + CFGBlock* getDst() const { - return static_cast<CFGBlock*>(getData2()); + return const_cast<CFGBlock*>(static_cast<const CFGBlock*>(getData2())); } - + static bool classof(const ProgramPoint* Location) { return Location->getKind() == BlockEdgeKind; } }; - + } // end namespace clang -namespace llvm { // Traits specialization for DenseMap - +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)); + reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getEmptyKey()) & ~0x7; + return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); } static inline clang::ProgramPoint getTombstoneKey() { uintptr_t x = - reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; - return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x)); + reinterpret_cast<uintptr_t>(DenseMapInfo<void*>::getTombstoneKey()) & ~0x7; + return clang::BlockEntrance(reinterpret_cast<clang::CFGBlock*>(x), 0); } static unsigned getHashValue(const clang::ProgramPoint& Loc) { |