[cfe-commits] r46618 - in /cfe/trunk/Analysis: GRConstants.cpp RValues.cpp RValues.h ValueState.h
Ted Kremenek
kremenek at apple.com
Thu Jan 31 11:34:24 PST 2008
Author: kremenek
Date: Thu Jan 31 13:34:24 2008
New Revision: 46618
URL: http://llvm.org/viewvc/llvm-project?rev=46618&view=rev
Log:
Moved RValue code in GRConstants.cpp to RValue.[h,cpp].
Moved ValueKey/ValueMap declaration to ValueState.h.
Added:
cfe/trunk/Analysis/RValues.cpp
cfe/trunk/Analysis/RValues.h
cfe/trunk/Analysis/ValueState.h
Modified:
cfe/trunk/Analysis/GRConstants.cpp
Modified: cfe/trunk/Analysis/GRConstants.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/GRConstants.cpp?rev=46618&r1=46617&r2=46618&view=diff
==============================================================================
--- cfe/trunk/Analysis/GRConstants.cpp (original)
+++ cfe/trunk/Analysis/GRConstants.cpp Thu Jan 31 13:34:24 2008
@@ -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"
@@ -44,726 +47,6 @@
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<void*>(Raw & ~Flags);
- }
-
- inline SymbolID getSymbolID() const {
- assert (getKind() == IsSymbol);
- return Raw >> 2;
- }
-
- ValueKey(const ValueDecl* VD)
- : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {
- assert(VD && "ValueDecl cannot be NULL.");
- }
-
- ValueKey(Stmt* S, bool isBlkExpr = false)
- : Raw(reinterpret_cast<uintptr_t>(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<ValueDecl,ValueKey>(const ValueKey& V) {
- return V.getKind() == ValueKey::IsDecl;
- }
- template<> inline bool isa<Stmt,ValueKey>(const ValueKey& V) {
- return ((unsigned) V.getKind()) < ValueKey::IsDecl;
- }
- template<> struct VISIBILITY_HIDDEN cast_retty_impl<ValueDecl,ValueKey> {
- typedef const ValueDecl* ret_type;
- };
- template<> struct VISIBILITY_HIDDEN cast_retty_impl<Stmt,ValueKey> {
- typedef const Stmt* ret_type;
- };
- template<> struct VISIBILITY_HIDDEN simplify_type<ValueKey> {
- 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<uintptr_t>(D) | ParmKind) {}
-
- inline Kind getKind() const { return (Kind) (Data & Mask); }
- inline void* getPtr() const { return reinterpret_cast<void*>(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<ParmVarDecl,SymbolData>(const SymbolData& V) {
- return V.getKind() == SymbolData::ParmKind;
- }
- template<> struct VISIBILITY_HIDDEN cast_retty_impl<ParmVarDecl,SymbolData> {
- typedef const ParmVarDecl* ret_type;
- };
- template<> struct VISIBILITY_HIDDEN simplify_type<SymbolData> {
- typedef void* SimpleType;
- static inline SimpleType getSimplifiedValue(const SymbolData &V) {
- return V.getPtr();
- }
- };
-} // end llvm namespace
-
-namespace {
-class VISIBILITY_HIDDEN SymbolManager {
- std::vector<SymbolData> SymbolToData;
-
- typedef llvm::DenseMap<void*,SymbolID> 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<APSInt > APSIntSetTy;
-
-
-class VISIBILITY_HIDDEN ValueManager {
- ASTContext& Ctx;
-
- typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<APSInt> > 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<APSInt> FoldNodeTy;
-
- X.Profile(ID);
- FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
-
- if (!P) {
- P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
- 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<void*>(d)),
- Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
-
- explicit RValue(BaseKind k)
- : Data(0), Kind(k) {}
-
- void* getRawPtr() const {
- return reinterpret_cast<void*>(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<void*>(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<T> 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<T> 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<T> 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<void*>((uintptr_t) SymID)) {}
-
- SymbolID getSymbolID() const {
- return (SymbolID) reinterpret_cast<uintptr_t>(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<ValueDecl*>(vd)) {}
-
- ValueDecl* getDecl() const {
- return static_cast<ValueDecl*>(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<T> 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<void*>((uintptr_t) SymID)) {}
-
- SymbolID getSymbolID() const {
- return (SymbolID) reinterpret_cast<uintptr_t>(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<APSInt*>(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<T> 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<ConcreteInt>(this)->Cast(ValMgr, CastExpr);
- default:
- return InvalidValue();
- }
-}
-
-NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
- switch (getSubKind()) {
- case ConcreteIntKind:
- return cast<ConcreteInt>(this)->UnaryMinus(ValMgr, U);
- default:
- return cast<NonLValue>(InvalidValue());
- }
-}
-
-#define NONLVALUE_DISPATCH_CASE(k1,k2,Op)\
-case (k1##Kind*NumNonLValueKind+k2##Kind):\
- return cast<k1>(*this).Op(ValMgr,cast<k2>(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<NonLValue>(UninitializedValue());\
- assert (!isValid() || !RHS.isValid() && "Missing case.");\
- break;\
-}\
-return cast<NonLValue>(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<NonLValue>(InvalidValue());
-
- case LValueDeclKind: {
- bool b = cast<LValueDecl>(*this) == cast<LValueDecl>(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<NonLValue>(InvalidValue());
-
- case LValueDeclKind: {
- bool b = cast<LValueDecl>(*this) != cast<LValueDecl>(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<NonLValue>(this)->print(Out);
- break;
-
- case LValueKind:
- cast<LValue>(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<ConcreteInt>(this)->getValue().toString();
- break;
-
- case SymbolicNonLValueKind:
- Out << '$' << cast<SymbolicNonLValue>(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<SymbolicLValue>(this)->getSymbolID();
- break;
-
- case LValueDeclKind:
- Out << '&'
- << cast<LValueDecl>(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<ValueKey,RValue> ValueMapTy;
-
-namespace clang {
- template<>
- struct VISIBILITY_HIDDEN GRTrait<ValueMapTy> {
- static inline void* toPtr(ValueMapTy M) {
- return reinterpret_cast<void*>(M.getRoot());
- }
- static inline ValueMapTy toState(void* P) {
- return ValueMapTy(static_cast<ValueMapTy::TreeTy*>(P));
- }
- };
-}
-
-typedef ValueMapTy StateTy;
-
-//===----------------------------------------------------------------------===//
// The Checker.
//
// FIXME: This checker logic should be eventually broken into two components.
@@ -780,7 +63,7 @@
class VISIBILITY_HIDDEN GRConstants {
public:
- typedef ValueMapTy StateTy;
+ typedef ValueState StateTy;
typedef GRStmtNodeBuilder<GRConstants> StmtNodeBuilder;
typedef GRBranchNodeBuilder<GRConstants> BranchNodeBuilder;
typedef ExplodedGraph<GRConstants> GraphTy;
@@ -822,7 +105,7 @@
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 @@
// "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:
Added: cfe/trunk/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.cpp?rev=46618&view=auto
==============================================================================
--- cfe/trunk/Analysis/RValues.cpp (added)
+++ cfe/trunk/Analysis/RValues.cpp Thu Jan 31 13:34:24 2008
@@ -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<APSInt> FoldNodeTy;
+
+ X.Profile(ID);
+ FoldNodeTy* P = APSIntSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!P) {
+ P = (FoldNodeTy*) BPAlloc.Allocate<FoldNodeTy>();
+ 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<ConcreteInt>(this)->Cast(ValMgr, CastExpr);
+ default:
+ return InvalidValue();
+ }
+}
+
+NonLValue NonLValue::UnaryMinus(ValueManager& ValMgr, UnaryOperator* U) const {
+ switch (getSubKind()) {
+ case ConcreteIntKind:
+ return cast<ConcreteInt>(this)->UnaryMinus(ValMgr, U);
+ default:
+ return cast<NonLValue>(InvalidValue());
+ }
+}
+
+#define NONLVALUE_DISPATCH_CASE(k1,k2,Op)\
+case (k1##Kind*NumNonLValueKind+k2##Kind):\
+return cast<k1>(*this).Op(ValMgr,cast<k2>(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<NonLValue>(UninitializedValue());\
+assert (!isValid() || !RHS.isValid() && "Missing case.");\
+break;\
+}\
+return cast<NonLValue>(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<NonLValue>(InvalidValue());
+
+ case LValueDeclKind: {
+ bool b = cast<LValueDecl>(*this) == cast<LValueDecl>(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<NonLValue>(InvalidValue());
+
+ case LValueDeclKind: {
+ bool b = cast<LValueDecl>(*this) != cast<LValueDecl>(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<NonLValue>(this)->print(Out);
+ break;
+
+ case LValueKind:
+ cast<LValue>(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<ConcreteInt>(this)->getValue().toString();
+ break;
+
+ case SymbolicNonLValueKind:
+ Out << '$' << cast<SymbolicNonLValue>(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<SymbolicLValue>(this)->getSymbolID();
+ break;
+
+ case LValueDeclKind:
+ Out << '&'
+ << cast<LValueDecl>(this)->getDecl()->getIdentifier()->getName();
+ break;
+
+ default:
+ assert (false && "Pretty-printed not implemented for this LValue.");
+ break;
+ }
+}
Added: cfe/trunk/Analysis/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/RValues.h?rev=46618&view=auto
==============================================================================
--- cfe/trunk/Analysis/RValues.h (added)
+++ cfe/trunk/Analysis/RValues.h Thu Jan 31 13:34:24 2008
@@ -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 <functional>
+
+//==------------------------------------------------------------------------==//
+// 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<uintptr_t>(D) | ParmKind) {}
+
+ inline Kind getKind() const { return (Kind) (Data & Mask); }
+ inline void* getPtr() const { return reinterpret_cast<void*>(Data & ~Mask); }
+ inline bool operator==(const SymbolData& R) const { return Data == R.Data; }
+};
+
+class SymbolManager {
+ std::vector<SymbolData> SymbolToData;
+
+ typedef llvm::DenseMap<void*,SymbolID> 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<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
+ 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<void*>(d)),
+ Kind((isLValue ? LValueKind : NonLValueKind) | (ValKind << BaseBits)) {}
+
+ explicit RValue(BaseKind k)
+ : Data(0), Kind(k) {}
+
+ void* getRawPtr() const {
+ return reinterpret_cast<void*>(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<void*>(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<T> 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<T> 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<T> 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<void*>((uintptr_t) SymID)) {}
+
+ SymbolID getSymbolID() const {
+ return (SymbolID) reinterpret_cast<uintptr_t>(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<ValueDecl*>(vd)) {}
+
+ ValueDecl* getDecl() const {
+ return static_cast<ValueDecl*>(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<T> 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<void*>((uintptr_t) SymID)) {}
+
+ SymbolID getSymbolID() const {
+ return (SymbolID) reinterpret_cast<uintptr_t>(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<llvm::APSInt*>(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<T> 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<clang::ParmVarDecl,clang::SymbolData>(const clang::SymbolData& V) {
+ return V.getKind() == clang::SymbolData::ParmKind;
+}
+
+template<> struct cast_retty_impl<clang::ParmVarDecl,clang::SymbolData> {
+ typedef const clang::ParmVarDecl* ret_type;
+};
+
+template<> struct simplify_type<clang::SymbolData> {
+ typedef void* SimpleType;
+ static inline SimpleType getSimplifiedValue(const clang::SymbolData &V) {
+ return V.getPtr();
+ }
+};
+
+} // end llvm namespace
+
+#endif
Added: cfe/trunk/Analysis/ValueState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/Analysis/ValueState.h?rev=46618&view=auto
==============================================================================
--- cfe/trunk/Analysis/ValueState.h (added)
+++ cfe/trunk/Analysis/ValueState.h Thu Jan 31 13:34:24 2008
@@ -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 <functional>
+
+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<void*>(Raw & ~Mask);
+ }
+
+ inline SymbolID getSymbolID() const {
+ assert (getKind() == IsSymbol);
+ return Raw >> 2;
+ }
+
+ ValueKey(const ValueDecl* VD)
+ : Raw(reinterpret_cast<uintptr_t>(VD) | IsDecl) {
+ assert(VD && "ValueDecl cannot be NULL.");
+ }
+
+ ValueKey(Stmt* S, bool isBlkExpr = false)
+ : Raw(reinterpret_cast<uintptr_t>(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<ValueKey,RValue> ValueState;
+
+template<>
+struct GRTrait<ValueState> {
+ static inline void* toPtr(ValueState M) {
+ return reinterpret_cast<void*>(M.getRoot());
+ }
+ static inline ValueState toState(void* P) {
+ return ValueState(static_cast<ValueState::TreeTy*>(P));
+ }
+};
+
+} // end clang namespace
+
+//==------------------------------------------------------------------------==//
+// Casting machinery to get cast<> and dyn_cast<> working with ValueKey.
+//==------------------------------------------------------------------------==//
+
+namespace llvm {
+
+ template<> inline bool
+ isa<clang::ValueDecl,clang::ValueKey>(const clang::ValueKey& V) {
+ return V.getKind() == clang::ValueKey::IsDecl;
+ }
+
+ template<> inline bool
+ isa<clang::Stmt,clang::ValueKey>(const clang::ValueKey& V) {
+ return ((unsigned) V.getKind()) < clang::ValueKey::IsDecl;
+ }
+
+ template<> struct cast_retty_impl<clang::ValueDecl,clang::ValueKey> {
+ typedef const clang::ValueDecl* ret_type;
+ };
+
+ template<> struct cast_retty_impl<clang::Stmt,clang::ValueKey> {
+ typedef const clang::Stmt* ret_type;
+ };
+
+ template<> struct simplify_type<clang::ValueKey> {
+ typedef void* SimpleType;
+ static inline SimpleType getSimplifiedValue(const clang::ValueKey &V) {
+ return V.getPtr();
+ }
+ };
+} // end llvm namespace
+
+#endif
More information about the cfe-commits
mailing list