Further cleanup. Moved definitions for SymbolManager and ValueManager into
their own [.cpp;.h] files.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@47201 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/Analysis/RValues.cpp b/Analysis/RValues.cpp
index a9b44eb..c8a4dfa 100644
--- a/Analysis/RValues.cpp
+++ b/Analysis/RValues.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/RValues.h"
+#include "llvm/Support/Streams.h"
using namespace clang;
using llvm::dyn_cast;
@@ -20,110 +21,6 @@
using llvm::APSInt;
//===----------------------------------------------------------------------===//
-// SymbolManager.
-//===----------------------------------------------------------------------===//
-
-SymbolID SymbolManager::getSymbol(ParmVarDecl* D) {
- SymbolID& X = DataToSymbol[getKey(D)];
-
- if (!X.isInitialized()) {
- X = SymbolToData.size();
- SymbolToData.push_back(SymbolDataParmVar(D));
- }
-
- return X;
-}
-
-SymbolID SymbolManager::getContentsOfSymbol(SymbolID sym) {
- SymbolID& X = DataToSymbol[getKey(sym)];
-
- if (!X.isInitialized()) {
- X = SymbolToData.size();
- SymbolToData.push_back(SymbolDataContentsOf(sym));
- }
-
- return X;
-}
-
-QualType SymbolData::getType() const {
- switch (getKind()) {
- default:
- assert (false && "getType() not implemented for this symbol.");
-
- case ParmKind:
- return cast<SymbolDataParmVar>(this)->getDecl()->getType();
-
- }
-}
-
-SymbolManager::SymbolManager() {}
-SymbolManager::~SymbolManager() {}
-
-//===----------------------------------------------------------------------===//
-// Values and 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();
-}
-
-const 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;
-}
-
-const APSInt& ValueManager::getValue(uint64_t X, unsigned BitWidth,
- bool isUnsigned) {
- APSInt V(BitWidth, isUnsigned);
- V = X;
- return getValue(V);
-}
-
-const 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);
-}
-
-const SymIntConstraint&
-ValueManager::getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
- const llvm::APSInt& V) {
-
- llvm::FoldingSetNodeID ID;
- SymIntConstraint::Profile(ID, sym, Op, V);
- void* InsertPos;
-
- SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos);
-
- if (!C) {
- C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>();
- new (C) SymIntConstraint(sym, Op, V);
- SymIntCSet.InsertNode(C, InsertPos);
- }
-
- return *C;
-}
-
-//===----------------------------------------------------------------------===//
// Symbol Iteration.
//===----------------------------------------------------------------------===//
@@ -154,69 +51,12 @@
// Transfer function dispatch for Non-LValues.
//===----------------------------------------------------------------------===//
-static const
-llvm::APSInt& EvaluateAPSInt(ValueManager& ValMgr, BinaryOperator::Opcode Op,
- const llvm::APSInt& V1, const llvm::APSInt& V2) {
-
- switch (Op) {
- default:
- assert (false && "Invalid Opcode.");
-
- case BinaryOperator::Mul:
- return ValMgr.getValue( V1 * V2 );
-
- case BinaryOperator::Div:
- return ValMgr.getValue( V1 / V2 );
-
- case BinaryOperator::Rem:
- return ValMgr.getValue( V1 % V2 );
-
- case BinaryOperator::Add:
- return ValMgr.getValue( V1 + V2 );
-
- case BinaryOperator::Sub:
- return ValMgr.getValue( V1 - V2 );
-
- case BinaryOperator::Shl:
- return ValMgr.getValue( V1.operator<<( (unsigned) V2.getZExtValue() ));
-
- case BinaryOperator::Shr:
- return ValMgr.getValue( V1.operator>>( (unsigned) V2.getZExtValue() ));
-
- case BinaryOperator::LT:
- return ValMgr.getTruthValue( V1 < V2 );
-
- case BinaryOperator::GT:
- return ValMgr.getTruthValue( V1 > V2 );
-
- case BinaryOperator::LE:
- return ValMgr.getTruthValue( V1 <= V2 );
-
- case BinaryOperator::GE:
- return ValMgr.getTruthValue( V1 >= V2 );
-
- case BinaryOperator::EQ:
- return ValMgr.getTruthValue( V1 == V2 );
-
- case BinaryOperator::NE:
- return ValMgr.getTruthValue( V1 != V2 );
-
- // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
-
- case BinaryOperator::And:
- return ValMgr.getValue( V1 & V2 );
-
- case BinaryOperator::Or:
- return ValMgr.getValue( V1 | V2 );
- }
-}
-
nonlval::ConcreteInt
nonlval::ConcreteInt::EvalBinaryOp(ValueManager& ValMgr,
BinaryOperator::Opcode Op,
const nonlval::ConcreteInt& RHS) const {
- return EvaluateAPSInt(ValMgr, Op, getValue(), RHS.getValue());
+ return ValMgr.EvaluateAPSInt(Op, getValue(), RHS.getValue());
}
@@ -249,7 +89,7 @@
assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub ||
(Op >= BinaryOperator::LT && Op <= BinaryOperator::NE));
- return EvaluateAPSInt(ValMgr, Op, getValue(), RHS.getValue());
+ return ValMgr.EvaluateAPSInt(Op, getValue(), RHS.getValue());
}
NonLValue LValue::EQ(ValueManager& ValMgr, const LValue& RHS) const {
diff --git a/Analysis/SymbolManager.cpp b/Analysis/SymbolManager.cpp
new file mode 100644
index 0000000..bdda0e6
--- /dev/null
+++ b/Analysis/SymbolManager.cpp
@@ -0,0 +1,53 @@
+//== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values
+// created for use by GRExprEngine and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
+
+using namespace clang;
+
+SymbolID SymbolManager::getSymbol(ParmVarDecl* D) {
+ SymbolID& X = DataToSymbol[getKey(D)];
+
+ if (!X.isInitialized()) {
+ X = SymbolToData.size();
+ SymbolToData.push_back(SymbolDataParmVar(D));
+ }
+
+ return X;
+}
+
+SymbolID SymbolManager::getContentsOfSymbol(SymbolID sym) {
+ SymbolID& X = DataToSymbol[getKey(sym)];
+
+ if (!X.isInitialized()) {
+ X = SymbolToData.size();
+ SymbolToData.push_back(SymbolDataContentsOf(sym));
+ }
+
+ return X;
+}
+
+QualType SymbolData::getType() const {
+ switch (getKind()) {
+ default:
+ assert (false && "getType() not implemented for this symbol.");
+
+ case ParmKind:
+ return cast<SymbolDataParmVar>(this)->getDecl()->getType();
+
+ }
+}
+
+SymbolManager::SymbolManager() {}
+SymbolManager::~SymbolManager() {}
diff --git a/Analysis/ValueManager.cpp b/Analysis/ValueManager.cpp
new file mode 100644
index 0000000..61a2154
--- /dev/null
+++ b/Analysis/ValueManager.cpp
@@ -0,0 +1,134 @@
+// ValueManager.h - Low-level value management for 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 ValueManager, a class that manages the lifetime of APSInt
+// objects and symbolic constraints used by GRExprEngine and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/ValueManager.h"
+
+using namespace clang;
+
+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();
+}
+
+const llvm::APSInt& ValueManager::getValue(const llvm::APSInt& X) {
+ llvm::FoldingSetNodeID ID;
+ void* InsertPos;
+ typedef llvm::FoldingSetNodeWrapper<llvm::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;
+}
+
+const llvm::APSInt& ValueManager::getValue(uint64_t X, unsigned BitWidth,
+ bool isUnsigned) {
+ llvm::APSInt V(BitWidth, isUnsigned);
+ V = X;
+ return getValue(V);
+}
+
+const llvm::APSInt& ValueManager::getValue(uint64_t X, QualType T,
+ SourceLocation Loc) {
+
+ unsigned bits = Ctx.getTypeSize(T, Loc);
+ llvm::APSInt V(bits, T->isUnsignedIntegerType());
+ V = X;
+ return getValue(V);
+}
+
+const SymIntConstraint&
+ValueManager::getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
+ const llvm::APSInt& V) {
+
+ llvm::FoldingSetNodeID ID;
+ SymIntConstraint::Profile(ID, sym, Op, V);
+ void* InsertPos;
+
+ SymIntConstraint* C = SymIntCSet.FindNodeOrInsertPos(ID, InsertPos);
+
+ if (!C) {
+ C = (SymIntConstraint*) BPAlloc.Allocate<SymIntConstraint>();
+ new (C) SymIntConstraint(sym, Op, V);
+ SymIntCSet.InsertNode(C, InsertPos);
+ }
+
+ return *C;
+}
+
+const llvm::APSInt&
+ValueManager::EvaluateAPSInt(BinaryOperator::Opcode Op,
+ const llvm::APSInt& V1, const llvm::APSInt& V2) {
+
+ switch (Op) {
+ default:
+ assert (false && "Invalid Opcode.");
+
+ case BinaryOperator::Mul:
+ return getValue( V1 * V2 );
+
+ case BinaryOperator::Div:
+ return getValue( V1 / V2 );
+
+ case BinaryOperator::Rem:
+ return getValue( V1 % V2 );
+
+ case BinaryOperator::Add:
+ return getValue( V1 + V2 );
+
+ case BinaryOperator::Sub:
+ return getValue( V1 - V2 );
+
+ case BinaryOperator::Shl:
+ return getValue( V1.operator<<( (unsigned) V2.getZExtValue() ));
+
+ case BinaryOperator::Shr:
+ return getValue( V1.operator>>( (unsigned) V2.getZExtValue() ));
+
+ case BinaryOperator::LT:
+ return getTruthValue( V1 < V2 );
+
+ case BinaryOperator::GT:
+ return getTruthValue( V1 > V2 );
+
+ case BinaryOperator::LE:
+ return getTruthValue( V1 <= V2 );
+
+ case BinaryOperator::GE:
+ return getTruthValue( V1 >= V2 );
+
+ case BinaryOperator::EQ:
+ return getTruthValue( V1 == V2 );
+
+ case BinaryOperator::NE:
+ return getTruthValue( V1 != V2 );
+
+ // Note: LAnd, LOr, Comma are handled specially by higher-level logic.
+
+ case BinaryOperator::And:
+ return getValue( V1 & V2 );
+
+ case BinaryOperator::Or:
+ return getValue( V1 | V2 );
+ }
+}
diff --git a/include/clang/Analysis/PathSensitive/RValues.h b/include/clang/Analysis/PathSensitive/RValues.h
index 3192707..202c230 100644
--- a/include/clang/Analysis/PathSensitive/RValues.h
+++ b/include/clang/Analysis/PathSensitive/RValues.h
@@ -15,224 +15,9 @@
#ifndef LLVM_CLANG_ANALYSIS_RVALUE_H
#define LLVM_CLANG_ANALYSIS_RVALUE_H
-// FIXME: reduce the number of includes.
-
-#include "clang/Analysis/PathSensitive/GRCoreEngine.h"
-#include "clang/AST/Expr.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/Analysis/Analyses/LiveVariables.h"
-
+#include "clang/Analysis/PathSensitive/ValueManager.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>
-
-//==------------------------------------------------------------------------==//
-// Values and ValueManager.
-//==------------------------------------------------------------------------==//
-
-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; }
-
- void Profile(llvm::FoldingSetNodeID& ID) const {
- assert (isInitialized());
- ID.AddInteger(Data);
- }
-
- static inline void Profile(llvm::FoldingSetNodeID& ID, SymbolID X) {
- X.Profile(ID);
- }
-};
-
- // SymbolData: Used to record meta data about symbols.
-
-class SymbolData {
-public:
- enum Kind { UninitKind, ParmKind, ContentsOfKind };
-
-private:
- uintptr_t Data;
- Kind K;
-
-protected:
- SymbolData(uintptr_t D, Kind k) : Data(D), K(k) {}
- SymbolData(void* D, Kind k) : Data(reinterpret_cast<uintptr_t>(D)), K(k) {}
-
- void* getPtr() const {
- assert (K != UninitKind);
- return reinterpret_cast<void*>(Data);
- }
-
- uintptr_t getInt() const {
- assert (K != UninitKind);
- return Data;
- }
-
-public:
- SymbolData() : Data(0), K(UninitKind) {}
-
- Kind getKind() const { return K; }
-
- inline bool operator==(const SymbolData& R) const {
- return K == R.K && Data == R.Data;
- }
-
- QualType getType() const;
-
- // Implement isa<T> support.
- static inline bool classof(const SymbolData*) { return true; }
-};
-
-class SymbolDataParmVar : public SymbolData {
-public:
- SymbolDataParmVar(ParmVarDecl* VD) : SymbolData(VD, ParmKind) {}
-
- ParmVarDecl* getDecl() const { return (ParmVarDecl*) getPtr(); }
-
- // Implement isa<T> support.
- static inline bool classof(const SymbolData* D) {
- return D->getKind() == ParmKind;
- }
-};
-
-class SymbolDataContentsOf : public SymbolData {
-public:
- SymbolDataContentsOf(SymbolID ID) : SymbolData(ID, ContentsOfKind) {}
-
- SymbolID getSymbol() const { return (SymbolID) getInt(); }
-
- // Implement isa<T> support.
- static inline bool classof(const SymbolData* D) {
- return D->getKind() == ContentsOfKind;
- }
-};
-
- // Constraints on symbols. Usually wrapped by RValues.
-
-class SymIntConstraint : public llvm::FoldingSetNode {
- SymbolID Symbol;
- BinaryOperator::Opcode Op;
- const llvm::APSInt& Val;
-public:
- SymIntConstraint(SymbolID sym, BinaryOperator::Opcode op,
- const llvm::APSInt& V)
- : Symbol(sym),
- Op(op), Val(V) {}
-
- BinaryOperator::Opcode getOpcode() const { return Op; }
- const SymbolID& getSymbol() const { return Symbol; }
- const llvm::APSInt& getInt() const { return Val; }
-
- static inline void Profile(llvm::FoldingSetNodeID& ID,
- const SymbolID& Symbol,
- BinaryOperator::Opcode Op,
- const llvm::APSInt& Val) {
- Symbol.Profile(ID);
- ID.AddInteger(Op);
- ID.AddPointer(&Val);
- }
-
- void Profile(llvm::FoldingSetNodeID& ID) {
- Profile(ID, Symbol, Op, Val);
- }
-};
-
-
-class SymbolManager {
- std::vector<SymbolData> SymbolToData;
-
- typedef llvm::DenseMap<void*,SymbolID> MapTy;
- MapTy DataToSymbol;
-
- void* getKey(void* P) const {
- return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(P) | 0x1);
- }
-
- void* getKey(SymbolID sym) const {
- return reinterpret_cast<void*>((uintptr_t) (sym << 1));
- }
-
-public:
- SymbolManager();
- ~SymbolManager();
-
- SymbolID getSymbol(ParmVarDecl* D);
- SymbolID getContentsOfSymbol(SymbolID sym);
-
- inline const SymbolData& getSymbolData(SymbolID ID) const {
- assert (ID < SymbolToData.size());
- return SymbolToData[ID];
- }
-
- inline QualType getType(SymbolID ID) const {
- return getSymbolData(ID).getType();
- }
-};
-
-
-class ValueManager {
- typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
- APSIntSetTy;
-
- typedef llvm::FoldingSet<SymIntConstraint>
- SymIntCSetTy;
-
-
- ASTContext& Ctx;
- llvm::BumpPtrAllocator& BPAlloc;
-
- APSIntSetTy APSIntSet;
- SymIntCSetTy SymIntCSet;
-
-public:
- ValueManager(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
- : Ctx(ctx), BPAlloc(Alloc) {}
-
- ~ValueManager();
-
- ASTContext& getContext() const { return Ctx; }
-
- const llvm::APSInt& getValue(const llvm::APSInt& X);
- const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
- const llvm::APSInt& getValue(uint64_t X, QualType T,
- SourceLocation Loc = SourceLocation());
-
- inline const llvm::APSInt& getZeroWithPtrWidth() {
- return getValue( 0,
- Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()),
- true );
- }
-
- inline const llvm::APSInt& getTruthValue(bool b) {
- return getValue( b ? 1 : 0,
- Ctx.getTypeSize(Ctx.IntTy, SourceLocation()),
- false );
-
- }
-
- const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
- const llvm::APSInt& V);
-};
-
-} // end clang namespace
-
//==------------------------------------------------------------------------==//
// Base RValue types.
//==------------------------------------------------------------------------==//
diff --git a/include/clang/Analysis/PathSensitive/StateVariant.h b/include/clang/Analysis/PathSensitive/StateVariant.h
deleted file mode 100644
index 9c7618b..0000000
--- a/include/clang/Analysis/PathSensitive/StateVariant.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//==- StateVariant.h - Variant to wrap generated analysis states --*- C++ -*-=//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the template class StateVariant, which serves to wrap
-// states that are generated by transfer functions.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLVM_CLANG_ANALYSIS_PS_STATEVARIANT
-#define LLVM_CLANG_ANALYSIS_PS_STATEVARIANT
-
-namespace clang {
-
-template<typename StateTy>
-class StateVariant {
- enum VariantFlag { Infeasible, ImpotentStmt, HasState };
- StateTy* State;
- VariantFlag Flag;
-
- explicit StateVariant(StateTy* state, VariantFlag f) : State(state), Flag(f){}
-
-public:
- StateVariant(StateTy* state) : State(state), Flag(HasState) {}
-
- bool isInfeasible() const { return Flag == Infeasible; }
- bool isStmtImpotent() const { return Flag == ImpotentStmt; }
-
- StateTy* getState() const {
- assert (!isInfeasible());
- return State;
- }
-
- // Factory methods to create states indicating infeasible paths or that
- // a statement can never modify the program state (from the perspective of
- // the analysis).
- static inline StateVariant DenoteInfeasiblePath(StateTy* state = NULL) {
- return StateVariant(state,Infeasible);
- }
-
- static inline StateVariant DenoteImpotentStmt(StateTy* state) {
- return StateVariant(state,ImpotentStmt);
- }
-};
-
-} // end clang namespace
-
-#endif
diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h
new file mode 100644
index 0000000..2114dc6
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/SymbolManager.h
@@ -0,0 +1,173 @@
+//== SymbolManager.h - Management of Symbolic Values ------------*- 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 SymbolManager, a class that manages symbolic values
+// created for use by GRExprEngine and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_SYMMGR_H
+#define LLVM_CLANG_ANALYSIS_SYMMGR_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/Expr.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/DataTypes.h"
+#include <vector>
+
+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; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const {
+ assert (isInitialized());
+ ID.AddInteger(Data);
+ }
+
+ static inline void Profile(llvm::FoldingSetNodeID& ID, SymbolID X) {
+ X.Profile(ID);
+ }
+};
+
+// SymbolData: Used to record meta data about symbols.
+
+class SymbolData {
+public:
+ enum Kind { UninitKind, ParmKind, ContentsOfKind };
+
+private:
+ uintptr_t Data;
+ Kind K;
+
+protected:
+ SymbolData(uintptr_t D, Kind k) : Data(D), K(k) {}
+ SymbolData(void* D, Kind k) : Data(reinterpret_cast<uintptr_t>(D)), K(k) {}
+
+ void* getPtr() const {
+ assert (K != UninitKind);
+ return reinterpret_cast<void*>(Data);
+ }
+
+ uintptr_t getInt() const {
+ assert (K != UninitKind);
+ return Data;
+ }
+
+public:
+ SymbolData() : Data(0), K(UninitKind) {}
+
+ Kind getKind() const { return K; }
+
+ inline bool operator==(const SymbolData& R) const {
+ return K == R.K && Data == R.Data;
+ }
+
+ QualType getType() const;
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymbolData*) { return true; }
+};
+
+class SymbolDataParmVar : public SymbolData {
+public:
+ SymbolDataParmVar(ParmVarDecl* VD) : SymbolData(VD, ParmKind) {}
+
+ ParmVarDecl* getDecl() const { return (ParmVarDecl*) getPtr(); }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymbolData* D) {
+ return D->getKind() == ParmKind;
+ }
+};
+
+class SymbolDataContentsOf : public SymbolData {
+public:
+ SymbolDataContentsOf(SymbolID ID) : SymbolData(ID, ContentsOfKind) {}
+
+ SymbolID getSymbol() const { return (SymbolID) getInt(); }
+
+ // Implement isa<T> support.
+ static inline bool classof(const SymbolData* D) {
+ return D->getKind() == ContentsOfKind;
+ }
+};
+
+// Constraints on symbols. Usually wrapped by RValues.
+
+class SymIntConstraint : public llvm::FoldingSetNode {
+ SymbolID Symbol;
+ BinaryOperator::Opcode Op;
+ const llvm::APSInt& Val;
+public:
+ SymIntConstraint(SymbolID sym, BinaryOperator::Opcode op,
+ const llvm::APSInt& V)
+ : Symbol(sym),
+ Op(op), Val(V) {}
+
+ BinaryOperator::Opcode getOpcode() const { return Op; }
+ const SymbolID& getSymbol() const { return Symbol; }
+ const llvm::APSInt& getInt() const { return Val; }
+
+ static inline void Profile(llvm::FoldingSetNodeID& ID,
+ const SymbolID& Symbol,
+ BinaryOperator::Opcode Op,
+ const llvm::APSInt& Val) {
+ Symbol.Profile(ID);
+ ID.AddInteger(Op);
+ ID.AddPointer(&Val);
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) {
+ Profile(ID, Symbol, Op, Val);
+ }
+};
+
+
+class SymbolManager {
+ std::vector<SymbolData> SymbolToData;
+
+ typedef llvm::DenseMap<void*,SymbolID> MapTy;
+ MapTy DataToSymbol;
+
+ void* getKey(void* P) const {
+ return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(P) | 0x1);
+ }
+
+ void* getKey(SymbolID sym) const {
+ return reinterpret_cast<void*>((uintptr_t) (sym << 1));
+ }
+
+public:
+ SymbolManager();
+ ~SymbolManager();
+
+ SymbolID getSymbol(ParmVarDecl* D);
+ SymbolID getContentsOfSymbol(SymbolID sym);
+
+ inline const SymbolData& getSymbolData(SymbolID ID) const {
+ assert (ID < SymbolToData.size());
+ return SymbolToData[ID];
+ }
+
+ inline QualType getType(SymbolID ID) const {
+ return getSymbolData(ID).getType();
+ }
+};
+
+} // end clang namespace
+
+#endif
diff --git a/include/clang/Analysis/PathSensitive/ValueManager.h b/include/clang/Analysis/PathSensitive/ValueManager.h
new file mode 100644
index 0000000..aa6ee9b
--- /dev/null
+++ b/include/clang/Analysis/PathSensitive/ValueManager.h
@@ -0,0 +1,79 @@
+// ValueManager.h - Low-level value management for 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 ValueManager, a class that manages the lifetime of APSInt
+// objects and symbolic constraints used by GRExprEngine and related classes.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_VALUEMANAGER_H
+#define LLVM_CLANG_ANALYSIS_VALUEMANAGER_H
+
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
+#include "clang/AST/ASTContext.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/APSInt.h"
+
+namespace llvm {
+ class BumpPtrAllocator;
+}
+
+namespace clang {
+ class ASTContext;
+
+
+class ValueManager {
+ typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
+ APSIntSetTy;
+
+ typedef llvm::FoldingSet<SymIntConstraint>
+ SymIntCSetTy;
+
+ ASTContext& Ctx;
+ llvm::BumpPtrAllocator& BPAlloc;
+
+ APSIntSetTy APSIntSet;
+ SymIntCSetTy SymIntCSet;
+
+public:
+ ValueManager(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc)
+ : Ctx(ctx), BPAlloc(Alloc) {}
+
+ ~ValueManager();
+
+ ASTContext& getContext() const { return Ctx; }
+
+ const llvm::APSInt& getValue(const llvm::APSInt& X);
+ const llvm::APSInt& getValue(uint64_t X, unsigned BitWidth, bool isUnsigned);
+ const llvm::APSInt& getValue(uint64_t X, QualType T,
+ SourceLocation Loc = SourceLocation());
+
+ inline const llvm::APSInt& getZeroWithPtrWidth() {
+ return getValue( 0,
+ Ctx.getTypeSize(Ctx.VoidPtrTy, SourceLocation()),
+ true );
+ }
+
+ inline const llvm::APSInt& getTruthValue(bool b) {
+ return getValue( b ? 1 : 0,
+ Ctx.getTypeSize(Ctx.IntTy, SourceLocation()),
+ false );
+ }
+
+ const SymIntConstraint& getConstraint(SymbolID sym, BinaryOperator::Opcode Op,
+ const llvm::APSInt& V);
+
+ const llvm::APSInt& EvaluateAPSInt(BinaryOperator::Opcode Op,
+ const llvm::APSInt& V1,
+ const llvm::APSInt& V2);
+};
+
+} // end clang namespace
+
+#endif