From: Ted Kremenek Date: Tue, 29 Jan 2008 17:27:31 +0000 (+0000) Subject: Added "SymbolManager", which manages the set of symbolic values used X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=68fd257ada1ed5a20728241962a21826ae36ef63;p=clang Added "SymbolManager", which manages the set of symbolic values used for analyzing a function. The initial state for GRConstants now assigns symbolic values to parameters. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@46517 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/Analysis/GRConstants.cpp b/Analysis/GRConstants.cpp index 46f828bac2..da1a0adfa4 100644 --- a/Analysis/GRConstants.cpp +++ b/Analysis/GRConstants.cpp @@ -48,8 +48,16 @@ using llvm::APSInt; //===----------------------------------------------------------------------===// namespace { -typedef unsigned SymbolID; +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. @@ -70,7 +78,7 @@ public: inline SymbolID getSymbolID() const { assert (getKind() == IsSymbol); - return (SymbolID) (Raw >> 2); + return Raw >> 2; } ValueKey(const ValueDecl* VD) @@ -141,6 +149,70 @@ namespace llvm { }; } // 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. //===----------------------------------------------------------------------===// @@ -295,6 +367,8 @@ public: static NonLValue GetValue(ValueManager& ValMgr, const APSInt& V); static NonLValue GetValue(ValueManager& ValMgr, IntegerLiteral* I); + + static NonLValue GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl *D); // Implement isa support. static inline bool classof(const RValue* V) { @@ -479,6 +553,10 @@ NonLValue NonLValue::GetValue(ValueManager& ValMgr, IntegerLiteral* I) { I->getType()->isUnsignedIntegerType()))); } +NonLValue NonLValue::GetSymbolValue(SymbolManager& SymMgr, ParmVarDecl* D) { + return SymbolicNonLValue(SymMgr.getSymbol(D)); +} + //===----------------------------------------------------------------------===// // Pretty-Printing. //===----------------------------------------------------------------------===// @@ -492,7 +570,7 @@ void RValue::print(std::ostream& Out) const { case NonLValueKind: cast(this)->print(Out); break; - + case LValueKind: assert (false && "FIXME: LValue printing not implemented."); break; @@ -512,6 +590,10 @@ void NonLValue::print(std::ostream& Out) const { Out << cast(this)->getValue().toString(); break; + case SymbolicNonLValueKind: + Out << "sym-" << cast(this)->getSymbolID(); + break; + default: assert (false && "Pretty-printed not implemented for this NonLValue."); break; @@ -591,6 +673,9 @@ protected: /// ValueMgr - Object that manages the data for all created RValues. ValueManager ValMgr; + /// SymMgr - Object that manages the symbol information. + SymbolManager SymMgr; + /// StmtEntryNode - The immediate predecessor node. NodeTy* StmtEntryNode; @@ -631,7 +716,7 @@ public: continue; // FIXME: Set these values to a symbol, not Uninitialized. - St = SetValue(St, LValueDecl(*I), UninitializedValue()); + St = SetValue(St, LValueDecl(*I), NonLValue::GetSymbolValue(SymMgr, *I)); } return St;