From: Ted Kremenek Date: Thu, 31 Jan 2008 19:34:24 +0000 (+0000) Subject: Moved RValue code in GRConstants.cpp to RValue.[h,cpp]. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a90ccfe03ce62f4c33cbb96982947cf474b4fae4;p=clang Moved RValue code in GRConstants.cpp to RValue.[h,cpp]. Moved ValueKey/ValueMap declaration to ValueState.h. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46618 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp index ae6cdf7bf9..2229e473ef 100644 --- a/Analysis/GRConstants.cpp +++ b/Analysis/GRConstants.cpp @@ -15,6 +15,9 @@ // //===----------------------------------------------------------------------===// +#include "RValues.h" +#include "ValueState.h" + #include "clang/Analysis/PathSensitive/GREngine.h" #include "clang/AST/Expr.h" #include "clang/AST/ASTContext.h" @@ -43,726 +46,6 @@ using llvm::dyn_cast; using llvm::cast; using llvm::APSInt; -//===----------------------------------------------------------------------===// -/// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a -/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type -//===----------------------------------------------------------------------===// -namespace { - -class SymbolID { - unsigned Data; -public: - SymbolID() : Data(~0) {} - SymbolID(unsigned x) : Data(x) {} - - bool isInitialized() const { return Data != (unsigned) ~0; } - operator unsigned() const { assert (isInitialized()); return Data; } -}; - -class VISIBILITY_HIDDEN ValueKey { - uintptr_t Raw; - void operator=(const ValueKey& RHS); // Do not implement. - -public: - enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, // L-Value Bindings. - IsSymbol=0x3, // Symbol Bindings. - Flags=0x3 }; - - inline Kind getKind() const { - return (Kind) (Raw & Flags); - } - - inline void* getPtr() const { - assert (getKind() != IsSymbol); - return reinterpret_cast(Raw & ~Flags); - } - - inline SymbolID getSymbolID() const { - assert (getKind() == IsSymbol); - return Raw >> 2; - } - - ValueKey(const ValueDecl* VD) - : Raw(reinterpret_cast(VD) | IsDecl) { - assert(VD && "ValueDecl cannot be NULL."); - } - - ValueKey(Stmt* S, bool isBlkExpr = false) - : Raw(reinterpret_cast(S) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){ - assert(S && "Tracked statement cannot be NULL."); - } - - ValueKey(SymbolID V) - : Raw((V << 2) | IsSymbol) {} - - bool isSymbol() const { return getKind() == IsSymbol; } - bool isSubExpr() const { return getKind() == IsSubExpr; } - bool isBlkExpr() const { return getKind() == IsBlkExpr; } - bool isDecl() const { return getKind() == IsDecl; } - bool isStmt() const { return getKind() <= IsBlkExpr; } - - inline void Profile(llvm::FoldingSetNodeID& ID) const { - ID.AddInteger(isSymbol() ? 1 : 0); - - if (isSymbol()) - ID.AddInteger(getSymbolID()); - else - ID.AddPointer(getPtr()); - } - - inline bool operator==(const ValueKey& X) const { - return isSymbol() ? getSymbolID() == X.getSymbolID() - : getPtr() == X.getPtr(); - } - - inline bool operator!=(const ValueKey& X) const { - return !operator==(X); - } - - inline bool operator<(const ValueKey& X) const { - if (isSymbol()) - return X.isSymbol() ? getSymbolID() < X.getSymbolID() : false; - - return getPtr() < X.getPtr(); - } -}; -} // end anonymous namespace - -// Machinery to get cast<> and dyn_cast<> working with ValueKey. -namespace llvm { - template<> inline bool isa(const ValueKey& V) { - return V.getKind() == ValueKey::IsDecl; - } - template<> inline bool isa(const ValueKey& V) { - return ((unsigned) V.getKind()) < ValueKey::IsDecl; - } - template<> struct VISIBILITY_HIDDEN cast_retty_impl { - typedef const ValueDecl* ret_type; - }; - template<> struct VISIBILITY_HIDDEN cast_retty_impl { - typedef const Stmt* ret_type; - }; - template<> struct VISIBILITY_HIDDEN simplify_type { - typedef void* SimpleType; - static inline SimpleType getSimplifiedValue(const ValueKey &V) { - return V.getPtr(); - } - }; -} // end llvm namespace - - -//===----------------------------------------------------------------------===// -// SymbolManager. -//===----------------------------------------------------------------------===// - -namespace { -class VISIBILITY_HIDDEN SymbolData { - uintptr_t Data; -public: - enum Kind { ParmKind = 0x0, Mask = 0x3 }; - - SymbolData(ParmVarDecl* D) - : Data(reinterpret_cast(D) | ParmKind) {} - - inline Kind getKind() const { return (Kind) (Data & Mask); } - inline void* getPtr() const { return reinterpret_cast(Data & ~Mask); } - inline bool operator==(const SymbolData& R) const { return Data == R.Data; } -}; -} - -// Machinery to get cast<> and dyn_cast<> working with SymbolData. -namespace llvm { - template<> inline bool isa(const SymbolData& V) { - return V.getKind() == SymbolData::ParmKind; - } - template<> struct VISIBILITY_HIDDEN cast_retty_impl { - typedef const ParmVarDecl* ret_type; - }; - template<> struct VISIBILITY_HIDDEN simplify_type { - typedef void* SimpleType; - static inline SimpleType getSimplifiedValue(const SymbolData &V) { - return V.getPtr(); - } - }; -} // end llvm namespace - -namespace { -class VISIBILITY_HIDDEN SymbolManager { - std::vector SymbolToData; - - typedef llvm::DenseMap MapTy; - MapTy DataToSymbol; - -public: - SymbolData getSymbolData(SymbolID id) const { - assert (id < SymbolToData.size()); - return SymbolToData[id]; - } - - SymbolID getSymbol(ParmVarDecl* D); -}; -} // end anonymous namespace - -SymbolID SymbolManager::getSymbol(ParmVarDecl* D) { - SymbolID& X = DataToSymbol[D]; - - if (!X.isInitialized()) { - X = SymbolToData.size(); - SymbolToData.push_back(D); - } - - return X; -} - -//===----------------------------------------------------------------------===// -// ValueManager. -//===----------------------------------------------------------------------===// - -namespace { - -typedef llvm::ImmutableSet APSIntSetTy; - - -class VISIBILITY_HIDDEN ValueManager { - ASTContext& Ctx; - - typedef llvm::FoldingSet > APSIntSetTy; - APSIntSetTy APSIntSet; - - llvm::BumpPtrAllocator BPAlloc; - -public: - ValueManager(ASTContext& ctx) : Ctx(ctx) {} - ~ValueManager(); - - ASTContext& getContext() const { return Ctx; } - APSInt& getValue(const APSInt& X); - APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); - APSInt& getValue(uint64_t X, QualType T, - SourceLocation Loc = SourceLocation()); -}; -} // end anonymous namespace - -ValueManager::~ValueManager() { - // Note that the dstor for the contents of APSIntSet will never be called, - // so we iterate over the set and invoke the dstor for each APSInt. This - // frees an aux. memory allocated to represent very large constants. - for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I) - I->getValue().~APSInt(); -} - -APSInt& ValueManager::getValue(const APSInt& X) { - llvm::FoldingSetNodeID ID; - void* InsertPos; - typedef llvm::FoldingSetNodeWrapper FoldNodeTy; - - X.Profile(ID); - FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos); - - if (!P) { - P = (FoldNodeTy*) BPAlloc.Allocate(); - new (P) FoldNodeTy(X); - APSIntSet.InsertNode(P, InsertPos); - } - - return *P; -} - -APSInt& ValueManager::getValue(uint64_t X, unsigned BitWidth, bool isUnsigned) { - APSInt V(BitWidth, isUnsigned); - V = X; - return getValue(V); -} - -APSInt& ValueManager::getValue(uint64_t X, QualType T, SourceLocation Loc) { - unsigned bits = Ctx.getTypeSize(T, Loc); - APSInt V(bits, T->isUnsignedIntegerType()); - V = X; - return getValue(V); -} - -//===----------------------------------------------------------------------===// -// Expression Values. -//===----------------------------------------------------------------------===// - -namespace { - -class VISIBILITY_HIDDEN RValue { -public: - enum BaseKind { LValueKind=0x0, NonLValueKind=0x1, - UninitializedKind=0x2, InvalidKind=0x3 }; - - enum { BaseBits = 2, BaseMask = 0x3 }; - -private: - void* Data; - unsigned Kind; - -protected: - RValue(const void* d, bool isLValue, unsigned ValKind) - : Data(const_cast(d)), - Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {} - - explicit RValue(BaseKind k) - : Data(0), Kind(k) {} - - void* getRawPtr() const { - return reinterpret_cast(Data); - } - -public: - ~RValue() {}; - - RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const; - - unsigned getRawKind() const { return Kind; } - BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } - unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; } - - void Profile(llvm::FoldingSetNodeID& ID) const { - ID.AddInteger((unsigned) getRawKind()); - ID.AddPointer(reinterpret_cast(Data)); - } - - bool operator==(const RValue& RHS) const { - return getRawKind() == RHS.getRawKind() && Data == RHS.Data; - } - - static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D); - - inline bool isValid() const { return getRawKind() != InvalidKind; } - inline bool isInvalid() const { return getRawKind() == InvalidKind; } - - void print(std::ostream& OS) const; - void print() const { print(*llvm::cerr.stream()); } - - // Implement isa support. - static inline bool classof(const RValue*) { return true; } -}; - -class VISIBILITY_HIDDEN InvalidValue : public RValue { -public: - InvalidValue() : RValue(InvalidKind) {} - - static inline bool classof(const RValue* V) { - return V->getBaseKind() == InvalidKind; - } -}; - -class VISIBILITY_HIDDEN UninitializedValue : public RValue { -public: - UninitializedValue() : RValue(UninitializedKind) {} - - static inline bool classof(const RValue* V) { - return V->getBaseKind() == UninitializedKind; - } -}; - -class VISIBILITY_HIDDEN NonLValue : public RValue { -protected: - NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {} - -public: - void print(std::ostream& Out) const; - - // Arithmetic operators. - NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const; - - // Equality operators. - NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const; - NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const; - - // Utility methods to create NonLValues. - static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T, - SourceLocation Loc = SourceLocation()); - - static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I); - - static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) { - return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy); - } - - // Implement isa support. - static inline bool classof(const RValue* V) { - return V->getBaseKind() >= NonLValueKind; - } -}; - -class VISIBILITY_HIDDEN LValue : public RValue { -protected: - LValue(unsigned SubKind, void* D) : RValue(D, true, SubKind) {} - -public: - void print(std::ostream& Out) const; - - // Equality operators. - NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const; - NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const; - - // Implement isa support. - static inline bool classof(const RValue* V) { - return V->getBaseKind() == LValueKind; - } -}; - -} // end anonymous namespace - -//===----------------------------------------------------------------------===// -// LValues. -//===----------------------------------------------------------------------===// - -namespace { - -enum { SymbolicLValueKind, LValueDeclKind, NumLValueKind }; - -class VISIBILITY_HIDDEN SymbolicLValue : public LValue { -public: - SymbolicLValue(unsigned SymID) - : LValue(SymbolicLValueKind, reinterpret_cast((uintptr_t) SymID)) {} - - SymbolID getSymbolID() const { - return (SymbolID) reinterpret_cast(getRawPtr()); - } - - static inline bool classof(const RValue* V) { - return V->getSubKind() == SymbolicLValueKind; - } -}; - -class VISIBILITY_HIDDEN LValueDecl : public LValue { -public: - LValueDecl(const ValueDecl* vd) - : LValue(LValueDeclKind,const_cast(vd)) {} - - ValueDecl* getDecl() const { - return static_cast(getRawPtr()); - } - - inline bool operator==(const LValueDecl& R) const { - return getDecl() == R.getDecl(); - } - - inline bool operator!=(const LValueDecl& R) const { - return getDecl() != R.getDecl(); - } - - // Implement isa support. - static inline bool classof(const RValue* V) { - return V->getSubKind() == LValueDeclKind; - } -}; - -} // end anonymous namespace - -//===----------------------------------------------------------------------===// -// Non-LValues. -//===----------------------------------------------------------------------===// - -namespace { - -enum { SymbolicNonLValueKind, ConcreteIntKind, ConstrainedIntegerKind, - NumNonLValueKind }; - -class VISIBILITY_HIDDEN SymbolicNonLValue : public NonLValue { -public: - SymbolicNonLValue(unsigned SymID) - : NonLValue(SymbolicNonLValueKind, - reinterpret_cast((uintptr_t) SymID)) {} - - SymbolID getSymbolID() const { - return (SymbolID) reinterpret_cast(getRawPtr()); - } - - static inline bool classof(const RValue* V) { - return V->getSubKind() == SymbolicNonLValueKind; - } -}; - -class VISIBILITY_HIDDEN ConcreteInt : public NonLValue { -public: - ConcreteInt(const APSInt& V) : NonLValue(ConcreteIntKind, &V) {} - - const APSInt& getValue() const { - return *static_cast(getRawPtr()); - } - - // Arithmetic operators. - - ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() + V.getValue()); - } - - ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() - V.getValue()); - } - - ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() * V.getValue()); - } - - ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() / V.getValue()); - } - - ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const { - return ValMgr.getValue(getValue() % V.getValue()); - } - - ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const { - assert (U->getType() == U->getSubExpr()->getType()); - assert (U->getType()->isIntegerType()); - return ValMgr.getValue(-getValue()); - } - - // Casting. - - ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const { - assert (CastExpr->getType()->isIntegerType()); - - APSInt X(getValue()); - X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(), - CastExpr->getLocStart())); - return ValMgr.getValue(X); - } - - // Equality operators. - - ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const { - const APSInt& Val = getValue(); - return ValMgr.getValue(Val == V.getValue() ? 1U : 0U, - Val.getBitWidth(), Val.isUnsigned()); - } - - ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const { - const APSInt& Val = getValue(); - return ValMgr.getValue(Val != V.getValue() ? 1U : 0U, - Val.getBitWidth(), Val.isUnsigned()); - } - - // Implement isa support. - static inline bool classof(const RValue* V) { - return V->getSubKind() == ConcreteIntKind; - } -}; - -} // end anonymous namespace - -//===----------------------------------------------------------------------===// -// Transfer function dispatch for Non-LValues. -//===----------------------------------------------------------------------===// - -RValue RValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const { - switch (getSubKind()) { - case ConcreteIntKind: - return cast(this)->Cast(ValMgr, CastExpr); - default: - return InvalidValue(); - } -} - -NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const { - switch (getSubKind()) { - case ConcreteIntKind: - return cast(this)->UnaryMinus(ValMgr, U); - default: - return cast(InvalidValue()); - } -} - -#define NONLVALUE_DISPATCH_CASE(k1,k2,Op)\ -case (k1##Kind*NumNonLValueKind+k2##Kind):\ - return cast(*this).Op(ValMgr,cast(RHS)); - -#define NONLVALUE_DISPATCH(Op)\ -switch (getSubKind()*NumNonLValueKind+RHS.getSubKind()){\ - NONLVALUE_DISPATCH_CASE(ConcreteInt,ConcreteInt,Op)\ - default:\ - if (getBaseKind() == UninitializedKind ||\ - RHS.getBaseKind() == UninitializedKind)\ - return cast(UninitializedValue());\ - assert (!isValid() || !RHS.isValid() && "Missing case.");\ - break;\ -}\ -return cast(InvalidValue()); - -NonLValue NonLValue::Add(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Add) -} - -NonLValue NonLValue::Sub(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Sub) -} - -NonLValue NonLValue::Mul(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Mul) -} - -NonLValue NonLValue::Div(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Div) -} - -NonLValue NonLValue::Rem(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(Rem) -} - -NonLValue NonLValue::EQ(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(EQ) -} - -NonLValue NonLValue::NE(ValueManager& ValMgr, const NonLValue& RHS) const { - NONLVALUE_DISPATCH(NE) -} - -#undef NONLVALUE_DISPATCH_CASE -#undef NONLVALUE_DISPATCH - -//===----------------------------------------------------------------------===// -// Transfer function dispatch for LValues. -//===----------------------------------------------------------------------===// - - -NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const { - if (getSubKind() != RHS.getSubKind()) - return NonLValue::GetIntTruthValue(ValMgr, false); - - switch (getSubKind()) { - default: - assert(false && "EQ not implemented for this LValue."); - return cast(InvalidValue()); - - case LValueDeclKind: { - bool b = cast(*this) == cast(RHS); - return NonLValue::GetIntTruthValue(ValMgr, b); - } - } -} - -NonLValue LValue::NE(ValueManager& ValMgr, const LValue& RHS) const { - if (getSubKind() != RHS.getSubKind()) - return NonLValue::GetIntTruthValue(ValMgr, true); - - switch (getSubKind()) { - default: - assert(false && "EQ not implemented for this LValue."); - return cast(InvalidValue()); - - case LValueDeclKind: { - bool b = cast(*this) != cast(RHS); - return NonLValue::GetIntTruthValue(ValMgr, b); - } - } -} - - -//===----------------------------------------------------------------------===// -// Utility methods for constructing Non-LValues. -//===----------------------------------------------------------------------===// - -NonLValue NonLValue::GetValue(ValueManager& ValMgr, uint64_t X, QualType T, - SourceLocation Loc) { - - return ConcreteInt(ValMgr.getValue(X, T, Loc)); -} - -NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) { - return ConcreteInt(ValMgr.getValue(APSInt(I->getValue(), - I->getType()->isUnsignedIntegerType()))); -} - -RValue RValue::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) { - QualType T = D->getType(); - - if (T->isPointerType() || T->isReferenceType()) - return SymbolicLValue(SymMgr.getSymbol(D)); - else - return SymbolicNonLValue(SymMgr.getSymbol(D)); -} - -//===----------------------------------------------------------------------===// -// Pretty-Printing. -//===----------------------------------------------------------------------===// - -void RValue::print(std::ostream& Out) const { - switch (getBaseKind()) { - case InvalidKind: - Out << "Invalid"; - break; - - case NonLValueKind: - cast(this)->print(Out); - break; - - case LValueKind: - cast(this)->print(Out); - break; - - case UninitializedKind: - Out << "Uninitialized"; - break; - - default: - assert (false && "Invalid RValue."); - } -} - -void NonLValue::print(std::ostream& Out) const { - switch (getSubKind()) { - case ConcreteIntKind: - Out << cast(this)->getValue().toString(); - break; - - case SymbolicNonLValueKind: - Out << '$' << cast(this)->getSymbolID(); - break; - - default: - assert (false && "Pretty-printed not implemented for this NonLValue."); - break; - } -} - -void LValue::print(std::ostream& Out) const { - switch (getSubKind()) { - case SymbolicLValueKind: - Out << '$' << cast(this)->getSymbolID(); - break; - - case LValueDeclKind: - Out << '&' - << cast(this)->getDecl()->getIdentifier()->getName(); - break; - - default: - assert (false && "Pretty-printed not implemented for this LValue."); - break; - } -} - -//===----------------------------------------------------------------------===// -// ValueMapTy - A ImmutableMap type Stmt*/Decl*/Symbols to RValues. -//===----------------------------------------------------------------------===// - -typedef llvm::ImmutableMap ValueMapTy; - -namespace clang { - template<> - struct VISIBILITY_HIDDEN GRTrait { - static inline void* toPtr(ValueMapTy M) { - return reinterpret_cast(M.getRoot()); - } - static inline ValueMapTy toState(void* P) { - return ValueMapTy(static_cast(P)); - } - }; -} - -typedef ValueMapTy StateTy; - //===----------------------------------------------------------------------===// // The Checker. // @@ -780,7 +63,7 @@ namespace { class VISIBILITY_HIDDEN GRConstants { public: - typedef ValueMapTy StateTy; + typedef ValueState StateTy; typedef GRStmtNodeBuilder StmtNodeBuilder; typedef GRBranchNodeBuilder BranchNodeBuilder; typedef ExplodedGraph GraphTy; @@ -822,7 +105,7 @@ protected: StmtNodeBuilder* Builder; /// StateMgr - Object that manages the data for all created states. - ValueMapTy::Factory StateMgr; + StateTy::Factory StateMgr; /// ValueMgr - Object that manages the data for all created RValues. ValueManager ValMgr; @@ -1493,13 +776,13 @@ void GRConstants::Visit(Stmt* S, GRConstants::NodeTy* Pred, // "Assume" logic. //===----------------------------------------------------------------------===// -StateTy GRConstants::Assume(StateTy St, LValue Cond, bool Assumption, - bool& isFeasible) { +GRConstants::StateTy GRConstants::Assume(StateTy St, LValue Cond, bool Assumption, + bool& isFeasible) { return St; } -StateTy GRConstants::Assume(StateTy St, NonLValue Cond, bool Assumption, - bool& isFeasible) { +GRConstants::StateTy GRConstants::Assume(StateTy St, NonLValue Cond, bool Assumption, + bool& isFeasible) { switch (Cond.getSubKind()) { default: diff --git a/Analysis/RValues.cpp b/Analysis/RValues.cpp new file mode 100644 index 0000000000..4008e765e0 --- /dev/null +++ b/Analysis/RValues.cpp @@ -0,0 +1,272 @@ +//= RValues.cpp - Abstract RValues for Path-Sens. Value Tracking -*- C++ -*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines RValue, LValue, and NonLValue, classes that represent +// abstract r-values for use with path-sensitive value tracking. +// +//===----------------------------------------------------------------------===// + +#include "RValues.h" + +using namespace clang; +using llvm::dyn_cast; +using llvm::cast; +using llvm::APSInt; + +//===----------------------------------------------------------------------===// +// SymbolManager. +//===----------------------------------------------------------------------===// + +SymbolID SymbolManager::getSymbol(ParmVarDecl* D) { + SymbolID& X = DataToSymbol[D]; + + if (!X.isInitialized()) { + X = SymbolToData.size(); + SymbolToData.push_back(D); + } + + return X; +} + +SymbolManager::SymbolManager() {} +SymbolManager::~SymbolManager() {} + +//===----------------------------------------------------------------------===// +// ValueManager. +//===----------------------------------------------------------------------===// + +ValueManager::~ValueManager() { + // Note that the dstor for the contents of APSIntSet will never be called, + // so we iterate over the set and invoke the dstor for each APSInt. This + // frees an aux. memory allocated to represent very large constants. + for (APSIntSetTy::iterator I=APSIntSet.begin(), E=APSIntSet.end(); I!=E; ++I) + I->getValue().~APSInt(); +} + +APSInt& ValueManager::getValue(const APSInt& X) { + llvm::FoldingSetNodeID ID; + void* InsertPos; + typedef llvm::FoldingSetNodeWrapper FoldNodeTy; + + X.Profile(ID); + FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos); + + if (!P) { + P = (FoldNodeTy*) BPAlloc.Allocate(); + new (P) FoldNodeTy(X); + APSIntSet.InsertNode(P, InsertPos); + } + + return *P; +} + +APSInt& ValueManager::getValue(uint64_t X, unsigned BitWidth, bool isUnsigned) { + APSInt V(BitWidth, isUnsigned); + V = X; + return getValue(V); +} + +APSInt& ValueManager::getValue(uint64_t X, QualType T, SourceLocation Loc) { + unsigned bits = Ctx.getTypeSize(T, Loc); + APSInt V(bits, T->isUnsignedIntegerType()); + V = X; + return getValue(V); +} + + +//===----------------------------------------------------------------------===// +// Transfer function dispatch for Non-LValues. +//===----------------------------------------------------------------------===// + +RValue RValue::Cast(ValueManager& ValMgr, Expr* CastExpr) const { + switch (getSubKind()) { + case ConcreteIntKind: + return cast(this)->Cast(ValMgr, CastExpr); + default: + return InvalidValue(); + } +} + +NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const { + switch (getSubKind()) { + case ConcreteIntKind: + return cast(this)->UnaryMinus(ValMgr, U); + default: + return cast(InvalidValue()); + } +} + +#define NONLVALUE_DISPATCH_CASE(k1,k2,Op)\ +case (k1##Kind*NumNonLValueKind+k2##Kind):\ +return cast(*this).Op(ValMgr,cast(RHS)); + +#define NONLVALUE_DISPATCH(Op)\ +switch (getSubKind()*NumNonLValueKind+RHS.getSubKind()){\ +NONLVALUE_DISPATCH_CASE(ConcreteInt,ConcreteInt,Op)\ +default:\ +if (getBaseKind() == UninitializedKind ||\ +RHS.getBaseKind() == UninitializedKind)\ +return cast(UninitializedValue());\ +assert (!isValid() || !RHS.isValid() && "Missing case.");\ +break;\ +}\ +return cast(InvalidValue()); + +NonLValue NonLValue::Add(ValueManager& ValMgr, const NonLValue& RHS) const { + NONLVALUE_DISPATCH(Add) +} + +NonLValue NonLValue::Sub(ValueManager& ValMgr, const NonLValue& RHS) const { + NONLVALUE_DISPATCH(Sub) +} + +NonLValue NonLValue::Mul(ValueManager& ValMgr, const NonLValue& RHS) const { + NONLVALUE_DISPATCH(Mul) +} + +NonLValue NonLValue::Div(ValueManager& ValMgr, const NonLValue& RHS) const { + NONLVALUE_DISPATCH(Div) +} + +NonLValue NonLValue::Rem(ValueManager& ValMgr, const NonLValue& RHS) const { + NONLVALUE_DISPATCH(Rem) +} + +NonLValue NonLValue::EQ(ValueManager& ValMgr, const NonLValue& RHS) const { + NONLVALUE_DISPATCH(EQ) +} + +NonLValue NonLValue::NE(ValueManager& ValMgr, const NonLValue& RHS) const { + NONLVALUE_DISPATCH(NE) +} + +#undef NONLVALUE_DISPATCH_CASE +#undef NONLVALUE_DISPATCH + +//===----------------------------------------------------------------------===// +// Transfer function dispatch for LValues. +//===----------------------------------------------------------------------===// + + +NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const { + if (getSubKind() != RHS.getSubKind()) + return NonLValue::GetIntTruthValue(ValMgr, false); + + switch (getSubKind()) { + default: + assert(false && "EQ not implemented for this LValue."); + return cast(InvalidValue()); + + case LValueDeclKind: { + bool b = cast(*this) == cast(RHS); + return NonLValue::GetIntTruthValue(ValMgr, b); + } + } +} + +NonLValue LValue::NE(ValueManager& ValMgr, const LValue& RHS) const { + if (getSubKind() != RHS.getSubKind()) + return NonLValue::GetIntTruthValue(ValMgr, true); + + switch (getSubKind()) { + default: + assert(false && "EQ not implemented for this LValue."); + return cast(InvalidValue()); + + case LValueDeclKind: { + bool b = cast(*this) != cast(RHS); + return NonLValue::GetIntTruthValue(ValMgr, b); + } + } +} + + +//===----------------------------------------------------------------------===// +// Utility methods for constructing Non-LValues. +//===----------------------------------------------------------------------===// + +NonLValue NonLValue::GetValue(ValueManager& ValMgr, uint64_t X, QualType T, + SourceLocation Loc) { + + return ConcreteInt(ValMgr.getValue(X, T, Loc)); +} + +NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) { + return ConcreteInt(ValMgr.getValue(APSInt(I->getValue(), + I->getType()->isUnsignedIntegerType()))); +} + +RValue RValue::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) { + QualType T = D->getType(); + + if (T->isPointerType() || T->isReferenceType()) + return SymbolicLValue(SymMgr.getSymbol(D)); + else + return SymbolicNonLValue(SymMgr.getSymbol(D)); +} + +//===----------------------------------------------------------------------===// +// Pretty-Printing. +//===----------------------------------------------------------------------===// + +void RValue::print(std::ostream& Out) const { + switch (getBaseKind()) { + case InvalidKind: + Out << "Invalid"; + break; + + case NonLValueKind: + cast(this)->print(Out); + break; + + case LValueKind: + cast(this)->print(Out); + break; + + case UninitializedKind: + Out << "Uninitialized"; + break; + + default: + assert (false && "Invalid RValue."); + } +} + +void NonLValue::print(std::ostream& Out) const { + switch (getSubKind()) { + case ConcreteIntKind: + Out << cast(this)->getValue().toString(); + break; + + case SymbolicNonLValueKind: + Out << '$' << cast(this)->getSymbolID(); + break; + + default: + assert (false && "Pretty-printed not implemented for this NonLValue."); + break; + } +} + +void LValue::print(std::ostream& Out) const { + switch (getSubKind()) { + case SymbolicLValueKind: + Out << '$' << cast(this)->getSymbolID(); + break; + + case LValueDeclKind: + Out << '&' + << cast(this)->getDecl()->getIdentifier()->getName(); + break; + + default: + assert (false && "Pretty-printed not implemented for this LValue."); + break; + } +} diff --git a/Analysis/RValues.h b/Analysis/RValues.h new file mode 100644 index 0000000000..90446a2cc5 --- /dev/null +++ b/Analysis/RValues.h @@ -0,0 +1,393 @@ +//== RValues.h - Abstract RValues for Path-Sens. Value Tracking -*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines RValue, LValue, and NonLValue, classes that represent +// abstract r-values for use with path-sensitive value tracking. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H +#define LLVM_CLANG_ANALYSIS_RVALUE_H + +// FIXME: reduce the number of includes. + +#include "clang/Analysis/PathSensitive/GREngine.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/ASTContext.h" +#include "clang/Analysis/Analyses/LiveVariables.h" + +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Streams.h" + +#include + +//==------------------------------------------------------------------------==// +// RValue "management" data structures. +//==------------------------------------------------------------------------==// + +namespace clang { + +class SymbolID { + unsigned Data; +public: + SymbolID() : Data(~0) {} + SymbolID(unsigned x) : Data(x) {} + + bool isInitialized() const { return Data != (unsigned) ~0; } + operator unsigned() const { assert (isInitialized()); return Data; } +}; + +class SymbolData { + uintptr_t Data; +public: + enum Kind { ParmKind = 0x0, Mask = 0x3 }; + + SymbolData(ParmVarDecl* D) + : Data(reinterpret_cast(D) | ParmKind) {} + + inline Kind getKind() const { return (Kind) (Data & Mask); } + inline void* getPtr() const { return reinterpret_cast(Data & ~Mask); } + inline bool operator==(const SymbolData& R) const { return Data == R.Data; } +}; + +class SymbolManager { + std::vector SymbolToData; + + typedef llvm::DenseMap MapTy; + MapTy DataToSymbol; + +public: + SymbolManager(); + ~SymbolManager(); + + SymbolData getSymbolData(SymbolID id) const { + assert (id < SymbolToData.size()); + return SymbolToData[id]; + } + + SymbolID getSymbol(ParmVarDecl* D); +}; + +class ValueManager { + typedef llvm::FoldingSet > + APSIntSetTy; + + ASTContext& Ctx; + APSIntSetTy APSIntSet; + llvm::BumpPtrAllocator BPAlloc; + +public: + ValueManager(ASTContext& ctx) : Ctx(ctx) {} + ~ValueManager(); + + ASTContext& getContext() const { return Ctx; } + llvm::APSInt& getValue(const llvm::APSInt& X); + llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned); + llvm::APSInt& getValue(uint64_t X, QualType T, + SourceLocation Loc = SourceLocation()); +}; + +//==------------------------------------------------------------------------==// +// Base RValue types. +//==------------------------------------------------------------------------==// + +class RValue { +public: + enum BaseKind { LValueKind=0x0, + NonLValueKind=0x1, + UninitializedKind=0x2, + InvalidKind=0x3 }; + + enum { BaseBits = 2, + BaseMask = 0x3 }; + +private: + void* Data; + unsigned Kind; + +protected: + RValue(const void* d, bool isLValue, unsigned ValKind) + : Data(const_cast(d)), + Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {} + + explicit RValue(BaseKind k) + : Data(0), Kind(k) {} + + void* getRawPtr() const { + return reinterpret_cast(Data); + } + +public: + ~RValue() {}; + + RValue Cast(ValueManager& ValMgr, Expr* CastExpr) const; + + unsigned getRawKind() const { return Kind; } + BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } + unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; } + + void Profile(llvm::FoldingSetNodeID& ID) const { + ID.AddInteger((unsigned) getRawKind()); + ID.AddPointer(reinterpret_cast(Data)); + } + + bool operator==(const RValue& RHS) const { + return getRawKind() == RHS.getRawKind() && Data == RHS.Data; + } + + static RValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D); + + inline bool isValid() const { return getRawKind() != InvalidKind; } + inline bool isInvalid() const { return getRawKind() == InvalidKind; } + + void print(std::ostream& OS) const; + void print() const { print(*llvm::cerr.stream()); } + + // Implement isa support. + static inline bool classof(const RValue*) { return true; } +}; + +class InvalidValue : public RValue { +public: + InvalidValue() : RValue(InvalidKind) {} + + static inline bool classof(const RValue* V) { + return V->getBaseKind() == InvalidKind; + } +}; + +class UninitializedValue : public RValue { +public: + UninitializedValue() : RValue(UninitializedKind) {} + + static inline bool classof(const RValue* V) { + return V->getBaseKind() == UninitializedKind; + } +}; + +class NonLValue : public RValue { +protected: + NonLValue(unsigned SubKind, const void* d) : RValue(d, false, SubKind) {} + +public: + void print(std::ostream& Out) const; + + // Arithmetic operators. + NonLValue Add(ValueManager& ValMgr, const NonLValue& RHS) const; + NonLValue Sub(ValueManager& ValMgr, const NonLValue& RHS) const; + NonLValue Mul(ValueManager& ValMgr, const NonLValue& RHS) const; + NonLValue Div(ValueManager& ValMgr, const NonLValue& RHS) const; + NonLValue Rem(ValueManager& ValMgr, const NonLValue& RHS) const; + NonLValue UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const; + + // Equality operators. + NonLValue EQ(ValueManager& ValMgr, const NonLValue& RHS) const; + NonLValue NE(ValueManager& ValMgr, const NonLValue& RHS) const; + + // Utility methods to create NonLValues. + static NonLValue GetValue(ValueManager& ValMgr, uint64_t X, QualType T, + SourceLocation Loc = SourceLocation()); + + static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I); + + static inline NonLValue GetIntTruthValue(ValueManager& ValMgr, bool X) { + return GetValue(ValMgr, X ? 1U : 0U, ValMgr.getContext().IntTy); + } + + // Implement isa support. + static inline bool classof(const RValue* V) { + return V->getBaseKind() >= NonLValueKind; + } +}; + +class LValue : public RValue { +protected: + LValue(unsigned SubKind, void* D) : RValue(D, true, SubKind) {} + +public: + void print(std::ostream& Out) const; + + // Equality operators. + NonLValue EQ(ValueManager& ValMgr, const LValue& RHS) const; + NonLValue NE(ValueManager& ValMgr, const LValue& RHS) const; + + // Implement isa support. + static inline bool classof(const RValue* V) { + return V->getBaseKind() == LValueKind; + } +}; + +//==------------------------------------------------------------------------==// +// Subclasses of LValue. +//==------------------------------------------------------------------------==// + +enum LValueKind { SymbolicLValueKind, LValueDeclKind, NumLValueKind }; + +class SymbolicLValue : public LValue { +public: + SymbolicLValue(unsigned SymID) + : LValue(SymbolicLValueKind, reinterpret_cast((uintptr_t) SymID)) {} + + SymbolID getSymbolID() const { + return (SymbolID) reinterpret_cast(getRawPtr()); + } + + static inline bool classof(const RValue* V) { + return V->getSubKind() == SymbolicLValueKind; + } +}; + +class LValueDecl : public LValue { +public: + LValueDecl(const ValueDecl* vd) + : LValue(LValueDeclKind,const_cast(vd)) {} + + ValueDecl* getDecl() const { + return static_cast(getRawPtr()); + } + + inline bool operator==(const LValueDecl& R) const { + return getDecl() == R.getDecl(); + } + + inline bool operator!=(const LValueDecl& R) const { + return getDecl() != R.getDecl(); + } + + // Implement isa support. + static inline bool classof(const RValue* V) { + return V->getSubKind() == LValueDeclKind; + } +}; + +//==------------------------------------------------------------------------==// +// Subclasses of NonLValue. +//==------------------------------------------------------------------------==// + +enum NonLValueKind { SymbolicNonLValueKind, ConcreteIntKind, +NumNonLValueKind }; + +class SymbolicNonLValue : public NonLValue { +public: + SymbolicNonLValue(unsigned SymID) + : NonLValue(SymbolicNonLValueKind, + reinterpret_cast((uintptr_t) SymID)) {} + + SymbolID getSymbolID() const { + return (SymbolID) reinterpret_cast(getRawPtr()); + } + + static inline bool classof(const RValue* V) { + return V->getSubKind() == SymbolicNonLValueKind; + } +}; + +class ConcreteInt : public NonLValue { +public: + ConcreteInt(const llvm::APSInt& V) : NonLValue(ConcreteIntKind, &V) {} + + const llvm::APSInt& getValue() const { + return *static_cast(getRawPtr()); + } + + // Arithmetic operators. + + ConcreteInt Add(ValueManager& ValMgr, const ConcreteInt& V) const { + return ValMgr.getValue(getValue() + V.getValue()); + } + + ConcreteInt Sub(ValueManager& ValMgr, const ConcreteInt& V) const { + return ValMgr.getValue(getValue() - V.getValue()); + } + + ConcreteInt Mul(ValueManager& ValMgr, const ConcreteInt& V) const { + return ValMgr.getValue(getValue() * V.getValue()); + } + + ConcreteInt Div(ValueManager& ValMgr, const ConcreteInt& V) const { + return ValMgr.getValue(getValue() / V.getValue()); + } + + ConcreteInt Rem(ValueManager& ValMgr, const ConcreteInt& V) const { + return ValMgr.getValue(getValue() % V.getValue()); + } + + ConcreteInt UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const { + assert (U->getType() == U->getSubExpr()->getType()); + assert (U->getType()->isIntegerType()); + return ValMgr.getValue(-getValue()); + } + + // Casting. + + ConcreteInt Cast(ValueManager& ValMgr, Expr* CastExpr) const { + assert (CastExpr->getType()->isIntegerType()); + + llvm::APSInt X(getValue()); + X.extOrTrunc(ValMgr.getContext().getTypeSize(CastExpr->getType(), + CastExpr->getLocStart())); + return ValMgr.getValue(X); + } + + // Equality operators. + + ConcreteInt EQ(ValueManager& ValMgr, const ConcreteInt& V) const { + const llvm::APSInt& Val = getValue(); + return ValMgr.getValue(Val == V.getValue() ? 1U : 0U, + Val.getBitWidth(), Val.isUnsigned()); + } + + ConcreteInt NE(ValueManager& ValMgr, const ConcreteInt& V) const { + const llvm::APSInt& Val = getValue(); + return ValMgr.getValue(Val != V.getValue() ? 1U : 0U, + Val.getBitWidth(), Val.isUnsigned()); + } + + // Implement isa support. + static inline bool classof(const RValue* V) { + return V->getSubKind() == ConcreteIntKind; + } +}; + +} // end clang namespace + +//==------------------------------------------------------------------------==// +// Casting machinery to get cast<> and dyn_cast<> working with SymbolData. +//==------------------------------------------------------------------------==// + +namespace llvm { + +template<> inline bool +isa(const clang::SymbolData& V) { + return V.getKind() == clang::SymbolData::ParmKind; +} + +template<> struct cast_retty_impl { + typedef const clang::ParmVarDecl* ret_type; +}; + +template<> struct simplify_type { + typedef void* SimpleType; + static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) { + return V.getPtr(); + } +}; + +} // end llvm namespace + +#endif diff --git a/Analysis/ValueState.h b/Analysis/ValueState.h new file mode 100644 index 0000000000..ef9f89ae8c --- /dev/null +++ b/Analysis/ValueState.h @@ -0,0 +1,162 @@ +//== ValueState.h - Path-Sens. "State" for tracking valuues -----*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines SymbolID, ValueKey, and ValueState. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_VALUESTATE_H +#define LLVM_CLANG_ANALYSIS_VALUESTATE_H + +// FIXME: Reduce the number of includes. + +#include "RValues.h" + +#include "clang/Analysis/PathSensitive/GREngine.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/ASTContext.h" +#include "clang/Analysis/Analyses/LiveVariables.h" + +#include "llvm/Support/Casting.h" +#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SmallPtrSet.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Compiler.h" +#include "llvm/Support/Streams.h" + +#include + +namespace clang { + +/// ValueKey - A variant smart pointer that wraps either a ValueDecl* or a +/// Stmt*. Use cast<> or dyn_cast<> to get actual pointer type +class ValueKey { + uintptr_t Raw; + void operator=(const ValueKey& RHS); // Do not implement. + +public: + enum Kind { IsSubExpr=0x0, IsBlkExpr=0x1, IsDecl=0x2, // L-Value Bindings. + IsSymbol=0x3, // Symbol Bindings. + Mask=0x3 }; + + inline Kind getKind() const { + return (Kind) (Raw & Mask); + } + + inline void* getPtr() const { + assert (getKind() != IsSymbol); + return reinterpret_cast(Raw & ~Mask); + } + + inline SymbolID getSymbolID() const { + assert (getKind() == IsSymbol); + return Raw >> 2; + } + + ValueKey(const ValueDecl* VD) + : Raw(reinterpret_cast(VD) | IsDecl) { + assert(VD && "ValueDecl cannot be NULL."); + } + + ValueKey(Stmt* S, bool isBlkExpr = false) + : Raw(reinterpret_cast(S) | (isBlkExpr ? IsBlkExpr : IsSubExpr)){ + assert(S && "Tracked statement cannot be NULL."); + } + + ValueKey(SymbolID V) + : Raw((V << 2) | IsSymbol) {} + + bool isSymbol() const { return getKind() == IsSymbol; } + bool isSubExpr() const { return getKind() == IsSubExpr; } + bool isBlkExpr() const { return getKind() == IsBlkExpr; } + bool isDecl() const { return getKind() == IsDecl; } + bool isStmt() const { return getKind() <= IsBlkExpr; } + + inline void Profile(llvm::FoldingSetNodeID& ID) const { + ID.AddInteger(isSymbol() ? 1 : 0); + + if (isSymbol()) + ID.AddInteger(getSymbolID()); + else + ID.AddPointer(getPtr()); + } + + inline bool operator==(const ValueKey& X) const { + return isSymbol() ? getSymbolID() == X.getSymbolID() + : getPtr() == X.getPtr(); + } + + inline bool operator!=(const ValueKey& X) const { + return !operator==(X); + } + + inline bool operator<(const ValueKey& X) const { + if (isSymbol()) + return X.isSymbol() ? getSymbolID() < X.getSymbolID() : false; + + return getPtr() < X.getPtr(); + } +}; + +//===----------------------------------------------------------------------===// +// ValueState - An ImmutableMap type Stmt*/Decl*/Symbols to RValues. +//===----------------------------------------------------------------------===// + +typedef llvm::ImmutableMap ValueState; + +template<> +struct GRTrait { + static inline void* toPtr(ValueState M) { + return reinterpret_cast(M.getRoot()); + } + static inline ValueState toState(void* P) { + return ValueState(static_cast(P)); + } +}; + +} // end clang namespace + +//==------------------------------------------------------------------------==// +// Casting machinery to get cast<> and dyn_cast<> working with ValueKey. +//==------------------------------------------------------------------------==// + +namespace llvm { + + template<> inline bool + isa(const clang::ValueKey& V) { + return V.getKind() == clang::ValueKey::IsDecl; + } + + template<> inline bool + isa(const clang::ValueKey& V) { + return ((unsigned) V.getKind()) < clang::ValueKey::IsDecl; + } + + template<> struct cast_retty_impl { + typedef const clang::ValueDecl* ret_type; + }; + + template<> struct cast_retty_impl { + typedef const clang::Stmt* ret_type; + }; + + template<> struct simplify_type { + typedef void* SimpleType; + static inline SimpleType getSimplifiedValue(const clang::ValueKey &V) { + return V.getPtr(); + } + }; +} // end llvm namespace + +#endif