From e0e4ebf6bfca5a71b2344d8a1b748b852509279c Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 26 Mar 2009 03:35:11 +0000 Subject: [PATCH] analyzer infrastructure: make a bunch of changes to symbolic expressions that Zhongxing and I discussed by email. Main changes: - Removed SymIntConstraintVal and SymIntConstraint - Added SymExpr as a parent class to SymbolData, SymSymExpr, SymIntExpr - Added nonloc::SymExprVal to wrap SymExpr - SymbolRef is now just a typedef of 'const SymbolData*' - Bunch of minor code cleanups in how some methods were invoked (no functionality change) This changes are part of a long-term plan to have full symbolic expression trees. This will be useful for lazily evaluating complicated expressions. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@67731 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../PathSensitive/BasicValueFactory.h | 8 - .../PathSensitive/ConstraintManager.h | 1 - .../Analysis/PathSensitive/GRExprEngine.h | 14 +- .../clang/Analysis/PathSensitive/GRState.h | 2 +- .../Analysis/PathSensitive/GRTransferFuncs.h | 5 +- .../clang/Analysis/PathSensitive/MemRegion.h | 7 +- include/clang/Analysis/PathSensitive/SVals.h | 101 +++---- .../Analysis/PathSensitive/SymbolManager.h | 273 ++++++++---------- lib/Analysis/BasicStore.cpp | 7 +- lib/Analysis/BasicValueFactory.cpp | 19 -- lib/Analysis/BugReporter.cpp | 6 +- lib/Analysis/CFRefCount.cpp | 20 +- lib/Analysis/GRExprEngine.cpp | 34 ++- lib/Analysis/GRSimpleVals.cpp | 111 +++---- lib/Analysis/GRSimpleVals.h | 2 +- lib/Analysis/GRTransferFuncs.cpp | 5 +- lib/Analysis/MemRegion.cpp | 14 +- lib/Analysis/RegionStore.cpp | 14 +- lib/Analysis/SVals.cpp | 216 +++++++------- lib/Analysis/SimpleConstraintManager.cpp | 94 +++--- lib/Analysis/SimpleConstraintManager.h | 2 +- lib/Analysis/SymbolManager.cpp | 195 ++++++++----- 22 files changed, 571 insertions(+), 579 deletions(-) diff --git a/include/clang/Analysis/PathSensitive/BasicValueFactory.h b/include/clang/Analysis/PathSensitive/BasicValueFactory.h index 3a401d69df..553f8a31bc 100644 --- a/include/clang/Analysis/PathSensitive/BasicValueFactory.h +++ b/include/clang/Analysis/PathSensitive/BasicValueFactory.h @@ -47,15 +47,10 @@ class BasicValueFactory { typedef llvm::FoldingSet > APSIntSetTy; - typedef llvm::FoldingSet - SymIntCSetTy; - - ASTContext& Ctx; llvm::BumpPtrAllocator& BPAlloc; APSIntSetTy APSIntSet; - SymIntCSetTy SymIntCSet; void* PersistentSVals; void* PersistentSValPairs; @@ -135,9 +130,6 @@ public: return getValue(b ? 1 : 0, Ctx.getTypeSize(Ctx.IntTy), false); } - const SymIntConstraint& getConstraint(SymbolRef sym, BinaryOperator::Opcode Op, - const llvm::APSInt& V); - const CompoundValData* getCompoundValData(QualType T, llvm::ImmutableList Vals); diff --git a/include/clang/Analysis/PathSensitive/ConstraintManager.h b/include/clang/Analysis/PathSensitive/ConstraintManager.h index 32e5bb0cb3..c8e5e85c8a 100644 --- a/include/clang/Analysis/PathSensitive/ConstraintManager.h +++ b/include/clang/Analysis/PathSensitive/ConstraintManager.h @@ -26,7 +26,6 @@ namespace clang { class GRState; class GRStateManager; class SVal; -class SymbolRef; class ConstraintManager { public: diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index dc9767312c..4c0abdcb09 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -642,24 +642,24 @@ protected: return X.isValid() ? getTF().EvalComplement(*this, cast(X)) : X; } - SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R) { - return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R) + SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T) { + return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R, T) : R; } - SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R) { + SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R, QualType T) { return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, - cast(R)) : R; + cast(R), T) : R; } void EvalBinOp(ExplodedNodeSet& Dst, Expr* Ex, BinaryOperator::Opcode Op, NonLoc L, NonLoc R, - ExplodedNode* Pred); + ExplodedNode* Pred, QualType T); void EvalBinOp(GRStateSet& OStates, const GRState* St, Expr* Ex, - BinaryOperator::Opcode Op, NonLoc L, NonLoc R); + BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T); - SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R); + SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, QualType T); void EvalCall(NodeSet& Dst, CallExpr* CE, SVal L, NodeTy* Pred) { assert (Builder && "GRStmtNodeBuilder must be defined."); diff --git a/include/clang/Analysis/PathSensitive/GRState.h b/include/clang/Analysis/PathSensitive/GRState.h index 72418583ae..7110c7bc2d 100644 --- a/include/clang/Analysis/PathSensitive/GRState.h +++ b/include/clang/Analysis/PathSensitive/GRState.h @@ -310,7 +310,7 @@ public: ISetFactory(alloc), GDMFactory(alloc), BasicVals(Ctx, alloc), - SymMgr(Ctx, alloc), + SymMgr(Ctx, BasicVals, alloc), Alloc(alloc), cfg(c), codedecl(cd), diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 69a7a12dd2..bee139f968 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -32,7 +32,7 @@ class GRTransferFuncs { protected: virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R) { + NonLoc L, NonLoc R, QualType T) { return UnknownVal(); } @@ -59,7 +59,8 @@ public: // for OStates virtual void EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng, const GRState* St, Expr* Ex, - BinaryOperator::Opcode Op, NonLoc L, NonLoc R); + BinaryOperator::Opcode Op, NonLoc L, NonLoc R, + QualType T); virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op, Loc L, Loc R) = 0; diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 8cf084ad57..b54efadd3a 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -182,11 +182,10 @@ public: class SymbolicRegion : public TypedRegion { protected: const SymbolRef sym; - const SymbolManager& SymMgr; public: - SymbolicRegion(const SymbolRef s, const SymbolManager& mgr, MemRegion* sreg) - : TypedRegion(sreg, SymbolicRegionKind), sym(s), SymMgr(mgr) {} + SymbolicRegion(const SymbolRef s, const MemRegion* sreg) + : TypedRegion(sreg, SymbolicRegionKind), sym(s) {} SymbolRef getSymbol() const { return sym; @@ -539,7 +538,7 @@ public: getCompoundLiteralRegion(const CompoundLiteralExpr* CL); /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. - SymbolicRegion* getSymbolicRegion(const SymbolRef sym, const SymbolManager&); + SymbolicRegion* getSymbolicRegion(SymbolRef sym); StringRegion* getStringRegion(const StringLiteral* Str); diff --git a/include/clang/Analysis/PathSensitive/SVals.h b/include/clang/Analysis/PathSensitive/SVals.h index 030115387a..a025325590 100644 --- a/include/clang/Analysis/PathSensitive/SVals.h +++ b/include/clang/Analysis/PathSensitive/SVals.h @@ -96,54 +96,45 @@ public: bool isZeroConstant() const; /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and - /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolRef - /// where 'isValid()' returns false. + /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolData* SymbolRef getAsLocSymbol() const; /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. /// Otherwise return a SymbolRef where 'isValid()' returns false. SymbolRef getAsSymbol() const; + + /// getAsSymbolicExpression - If this Sval wraps a symbolic expression then + /// return that expression. Otherwise return NULL. + const SymExpr *getAsSymbolicExpression() const; void print(std::ostream& OS) const; void print(llvm::raw_ostream& OS) const; void printStdErr() const; - + + // Iterators. class symbol_iterator { - SymbolRef SingleRef; - const SymbolRef* sptr; + llvm::SmallVector itr; + void expand(); public: + symbol_iterator() {} + symbol_iterator(const SymExpr* SE); - bool operator==(const symbol_iterator& X) { - return SingleRef == X.SingleRef && sptr == X.sptr; - } - - bool operator!=(const symbol_iterator& X) { - return SingleRef != X.SingleRef || sptr != X.sptr; - } - - symbol_iterator& operator++() { - if (sptr) - ++sptr; - else - SingleRef = SymbolRef(); + symbol_iterator& operator++(); + SymbolRef operator*(); - return *this; - } - - SymbolRef operator*() const { - if (sptr) - return *sptr; - - return SingleRef; - } - - symbol_iterator(SymbolRef x) : SingleRef(x), sptr(0) {} - symbol_iterator() : sptr(0) {} - symbol_iterator(const SymbolRef* x) : sptr(x) {} + bool operator==(const symbol_iterator& X) const; + bool operator!=(const symbol_iterator& X) const; }; - symbol_iterator symbol_begin() const; - symbol_iterator symbol_end() const; + symbol_iterator symbol_begin() const { + const SymExpr *SE = getAsSymbolicExpression(); + if (SE) + return symbol_iterator(SE); + else + return symbol_iterator(); + } + + symbol_iterator symbol_end() const { return symbol_iterator(); } // Implement isa support. static inline bool classof(const SVal*) { return true; } @@ -178,14 +169,15 @@ public: void print(llvm::raw_ostream& Out) const; // Utility methods to create NonLocs. - static NonLoc MakeVal(SymbolRef sym); - static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs, - BinaryOperator::Opcode op, const llvm::APSInt& v); + static NonLoc MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, + BinaryOperator::Opcode op, const llvm::APSInt& rhs, + QualType T); - static NonLoc MakeVal(SymbolManager& SymMgr, SymbolRef lhs, - BinaryOperator::Opcode op, SymbolRef rhs); + static NonLoc MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, + BinaryOperator::Opcode op, const SymExpr *rhs, + QualType T); static NonLoc MakeIntVal(BasicValueFactory& BasicVals, uint64_t X, bool isUnsigned); @@ -219,8 +211,8 @@ protected: : SVal(const_cast(D), true, SubKind) {} // Equality operators. - NonLoc EQ(BasicValueFactory& BasicVals, const Loc& R) const; - NonLoc NE(BasicValueFactory& BasicVals, const Loc& R) const; + NonLoc EQ(SymbolManager& SM, const Loc& R) const; + NonLoc NE(SymbolManager& SM, const Loc& R) const; public: void print(llvm::raw_ostream& Out) const; @@ -248,17 +240,15 @@ public: namespace nonloc { -enum Kind { ConcreteIntKind, SymbolValKind, SymIntConstraintValKind, +enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind, LocAsIntegerKind, CompoundValKind }; class SymbolVal : public NonLoc { public: - SymbolVal(SymbolRef SymID) - : NonLoc(SymbolValKind, - reinterpret_cast((uintptr_t) SymID.getNumber())) {} + SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) {} SymbolRef getSymbol() const { - return (SymbolRef) reinterpret_cast(Data); + return (const SymbolData*) Data; } static inline bool classof(const SVal* V) { @@ -271,22 +261,22 @@ public: } }; -class SymIntConstraintVal : public NonLoc { +class SymExprVal : public NonLoc { public: - SymIntConstraintVal(const SymIntConstraint& C) - : NonLoc(SymIntConstraintValKind, reinterpret_cast(&C)) {} + SymExprVal(const SymExpr *SE) + : NonLoc(SymExprValKind, reinterpret_cast(SE)) {} - const SymIntConstraint& getConstraint() const { - return *reinterpret_cast(Data); + const SymExpr *getSymbolicExpression() const { + return reinterpret_cast(Data); } static inline bool classof(const SVal* V) { return V->getBaseKind() == NonLocKind && - V->getSubKind() == SymIntConstraintValKind; + V->getSubKind() == SymExprValKind; } static inline bool classof(const NonLoc* V) { - return V->getSubKind() == SymIntConstraintValKind; + return V->getSubKind() == SymExprValKind; } }; @@ -387,12 +377,9 @@ enum Kind { SymbolValKind, GotoLabelKind, MemRegionKind, FuncValKind, class SymbolVal : public Loc { public: - SymbolVal(SymbolRef SymID) - : Loc(SymbolValKind, reinterpret_cast((uintptr_t) SymID.getNumber())){} + SymbolVal(SymbolRef sym) : Loc(SymbolValKind, sym) {} - SymbolRef getSymbol() const { - return (SymbolRef) reinterpret_cast(Data); - } + SymbolRef getSymbol() const { return (SymbolRef) Data; } static inline bool classof(const SVal* V) { return V->getBaseKind() == LocKind && diff --git a/include/clang/Analysis/PathSensitive/SymbolManager.h b/include/clang/Analysis/PathSensitive/SymbolManager.h index 72a8b7907f..9bdbd88cae 100644 --- a/include/clang/Analysis/PathSensitive/SymbolManager.h +++ b/include/clang/Analysis/PathSensitive/SymbolManager.h @@ -28,92 +28,64 @@ namespace llvm { class raw_ostream; } +namespace clang { + class MemRegion; + class ASTContext; + class BasicValueFactory; +} + namespace clang { -class MemRegion; -class SymbolManager; -class ASTContext; - -class SymbolRef { - unsigned Data; +class SymExpr : public llvm::FoldingSetNode { public: - SymbolRef() : Data(~0U - 2) {} - SymbolRef(unsigned x) : Data(x) {} - - bool isValid() const { return Data != (unsigned) (~0U - 2); } - unsigned getNumber() const { assert (isValid()); return Data; } - - bool operator<(const SymbolRef& X) const { return Data < X.Data; } - bool operator>(const SymbolRef& X) const { return Data > X.Data; } - bool operator==(const SymbolRef& X) const { return Data == X.Data; } - bool operator!=(const SymbolRef& X) const { return Data != X.Data; } - - void Profile(llvm::FoldingSetNodeID& ID) const { - ID.AddInteger(Data); - } -}; -} // end clang namespace - -namespace llvm { - llvm::raw_ostream& operator<<(llvm::raw_ostream& Out, clang::SymbolRef Sym); -} -namespace std { - std::ostream& operator<<(std::ostream& Out, clang::SymbolRef Sym); -} - -namespace llvm { -template <> struct DenseMapInfo { - static inline clang::SymbolRef getEmptyKey() { - return clang::SymbolRef(~0U); - } - static inline clang::SymbolRef getTombstoneKey() { - return clang::SymbolRef(~0U - 1); - } - static unsigned getHashValue(clang::SymbolRef X) { - return X.getNumber(); - } - static bool isEqual(clang::SymbolRef X, clang::SymbolRef Y) { - return X == Y; - } - static bool isPod() { return true; } -}; -} - -// SymbolData: Used to record meta data about symbols. + enum Kind { BEGIN_SYMBOLS, RegionRValue, ConjuredKind, END_SYMBOLS, + SymIntKind, SymSymKind }; +private: + Kind K; -namespace clang { +protected: + SymExpr(Kind k) : K(k) {} -class SymbolData : public llvm::FoldingSetNode { public: - enum Kind { RegionRValue, ConjuredKind, SymIntKind, SymSymKind }; + virtual ~SymExpr() {} + + Kind getKind() const { return K; } + + virtual QualType getType(ASTContext&) const = 0; + virtual void Profile(llvm::FoldingSetNodeID& profile) = 0; + + // Implement isa support. + static inline bool classof(const SymExpr*) { return true; } +}; + +typedef unsigned SymbolID; +class SymbolData : public SymExpr { private: - Kind K; - SymbolRef Sym; + const SymbolID Sym; protected: - SymbolData(Kind k, SymbolRef sym) : K(k), Sym(sym) {} + SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) {} public: virtual ~SymbolData() {} - Kind getKind() const { return K; } - - SymbolRef getSymbol() const { return Sym; } + SymbolID getSymbolID() const { return Sym; } - virtual QualType getType(ASTContext&) const = 0; - - virtual void Profile(llvm::FoldingSetNodeID& profile) = 0; - // Implement isa support. - static inline bool classof(const SymbolData*) { return true; } + static inline bool classof(const SymExpr* SE) { + Kind k = SE->getKind(); + return k > BEGIN_SYMBOLS && k < END_SYMBOLS; + } }; + +typedef const SymbolData* SymbolRef; class SymbolRegionRValue : public SymbolData { const MemRegion *R; public: - SymbolRegionRValue(SymbolRef MySym, const MemRegion *r) - : SymbolData(RegionRValue, MySym), R(r) {} + SymbolRegionRValue(SymbolID sym, const MemRegion *r) + : SymbolData(RegionRValue, sym), R(r) {} const MemRegion* getRegion() const { return R; } @@ -129,8 +101,8 @@ public: QualType getType(ASTContext&) const; // Implement isa support. - static inline bool classof(const SymbolData* D) { - return D->getKind() == RegionRValue; + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == RegionRValue; } }; @@ -141,9 +113,9 @@ class SymbolConjured : public SymbolData { const void* SymbolTag; public: - SymbolConjured(SymbolRef Sym, const Stmt* s, QualType t, unsigned count, + SymbolConjured(SymbolID sym, const Stmt* s, QualType t, unsigned count, const void* symbolTag) - : SymbolData(ConjuredKind, Sym), S(s), T(t), Count(count), + : SymbolData(ConjuredKind, sym), S(s), T(t), Count(count), SymbolTag(symbolTag) {} const Stmt* getStmt() const { return S; } @@ -166,143 +138,135 @@ public: } // Implement isa support. - static inline bool classof(const SymbolData* D) { - return D->getKind() == ConjuredKind; + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == ConjuredKind; } }; // SymIntExpr - Represents symbolic expression like 'x' + 3. -class SymIntExpr : public SymbolData { - SymbolRef LHS; +class SymIntExpr : public SymExpr { + const SymExpr *LHS; BinaryOperator::Opcode Op; - const llvm::APSInt& Val; + const llvm::APSInt& RHS; QualType T; public: - SymIntExpr(SymbolRef sym, SymbolRef lhs, BinaryOperator::Opcode op, - const llvm::APSInt& V, QualType t) - : SymbolData(SymIntKind, sym), LHS(lhs), Op(op), Val(V), T(t) {} + SymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, + const llvm::APSInt& rhs, QualType t) + : SymExpr(SymIntKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} - QualType getType(ASTContext& C) const { - return T; - } + // FIXME: We probably need to make this out-of-line to avoid redundant + // generation of virtual functions. + QualType getType(ASTContext& C) const { return T; } + + BinaryOperator::Opcode getOpcode() const { return Op; } + + const SymExpr *getLHS() const { return LHS; } + const llvm::APSInt &getRHS() const { return RHS; } - static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs, - BinaryOperator::Opcode op, const llvm::APSInt& V, + static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, + BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType t) { - lhs.Profile(ID); + ID.AddInteger((unsigned) SymIntKind); + ID.AddPointer(lhs); ID.AddInteger(op); - ID.AddPointer(&V); + ID.AddPointer(&rhs); ID.Add(t); } void Profile(llvm::FoldingSetNodeID& ID) { - Profile(ID, LHS, Op, Val, T); + Profile(ID, LHS, Op, RHS, T); } + + // Implement isa support. + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == SymIntKind; + } }; // SymSymExpr - Represents symbolic expression like 'x' + 'y'. -class SymSymExpr : public SymbolData { - SymbolRef LHS; +class SymSymExpr : public SymExpr { + const SymExpr *LHS; BinaryOperator::Opcode Op; - SymbolRef RHS; + const SymExpr *RHS; QualType T; public: - SymSymExpr(SymbolRef sym, SymbolRef lhs, BinaryOperator::Opcode op, - SymbolRef rhs, QualType t) - : SymbolData(SymSymKind, sym), LHS(lhs), Op(op), RHS(rhs), T(t) {} + SymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, + QualType t) + : SymExpr(SymSymKind), LHS(lhs), Op(op), RHS(rhs), T(t) {} - QualType getType(ASTContext& C) const { - return T; - } + const SymExpr *getLHS() const { return LHS; } + const SymExpr *getRHS() const { return RHS; } + + // FIXME: We probably need to make this out-of-line to avoid redundant + // generation of virtual functions. + QualType getType(ASTContext& C) const { return T; } - static void Profile(llvm::FoldingSetNodeID& ID, SymbolRef lhs, - BinaryOperator::Opcode op, SymbolRef rhs, QualType t) { - lhs.Profile(ID); + static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, + BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { + ID.AddInteger((unsigned) SymSymKind); + ID.AddPointer(lhs); ID.AddInteger(op); - rhs.Profile(ID); + ID.AddPointer(rhs); ID.Add(t); } void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, LHS, Op, RHS, T); } -}; - -// Constraints on symbols. Usually wrapped by SValues. - -class SymIntConstraint : public llvm::FoldingSetNode { - SymbolRef Symbol; - BinaryOperator::Opcode Op; - const llvm::APSInt& Val; -public: - SymIntConstraint(SymbolRef sym, BinaryOperator::Opcode op, - const llvm::APSInt& V) - : Symbol(sym), - Op(op), Val(V) {} - - BinaryOperator::Opcode getOpcode() const { return Op; } - const SymbolRef& getSymbol() const { return Symbol; } - const llvm::APSInt& getInt() const { return Val; } - - static inline void Profile(llvm::FoldingSetNodeID& ID, - SymbolRef 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); - } + // Implement isa support. + static inline bool classof(const SymExpr* SE) { + return SE->getKind() == SymSymKind; + } }; - class SymbolManager { - typedef llvm::FoldingSet DataSetTy; - typedef llvm::DenseMap DataMapTy; - - DataSetTy DataSet; - DataMapTy DataMap; - + typedef llvm::FoldingSet DataSetTy; + DataSetTy DataSet; unsigned SymbolCounter; llvm::BumpPtrAllocator& BPAlloc; + BasicValueFactory &BV; ASTContext& Ctx; public: - SymbolManager(ASTContext& ctx, llvm::BumpPtrAllocator& bpalloc) - : SymbolCounter(0), BPAlloc(bpalloc), Ctx(ctx) {} + SymbolManager(ASTContext& ctx, BasicValueFactory &bv, + llvm::BumpPtrAllocator& bpalloc) + : SymbolCounter(0), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {} ~SymbolManager(); static bool canSymbolicate(QualType T); /// Make a unique symbol for MemRegion R according to its kind. - SymbolRef getRegionRValueSymbol(const MemRegion* R); - SymbolRef getConjuredSymbol(const Stmt* E, QualType T, unsigned VisitCount, - const void* SymbolTag = 0); + const SymbolRegionRValue* getRegionRValueSymbol(const MemRegion* R); + const SymbolConjured* getConjuredSymbol(const Stmt* E, QualType T, + unsigned VisitCount, + const void* SymbolTag = 0); - SymbolRef getConjuredSymbol(const Expr* E, unsigned VisitCount, - const void* SymbolTag = 0) { + const SymbolConjured* getConjuredSymbol(const Expr* E, unsigned VisitCount, + const void* SymbolTag = 0) { return getConjuredSymbol(E, E->getType(), VisitCount, SymbolTag); } - SymbolRef getSymIntExpr(SymbolRef lhs, BinaryOperator::Opcode op, - const llvm::APSInt& v, QualType t); - - SymbolRef getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op, - SymbolRef rhs, QualType t); + const SymIntExpr *getSymIntExpr(const SymExpr *lhs, BinaryOperator::Opcode op, + const llvm::APSInt& rhs, QualType t); - const SymbolData& getSymbolData(SymbolRef ID) const; + const SymIntExpr *getSymIntExpr(const SymExpr &lhs, BinaryOperator::Opcode op, + const llvm::APSInt& rhs, QualType t) { + return getSymIntExpr(&lhs, op, rhs, t); + } + + const SymSymExpr *getSymSymExpr(const SymExpr *lhs, BinaryOperator::Opcode op, + const SymExpr *rhs, QualType t); - QualType getType(SymbolRef ID) const { - return getSymbolData(ID).getType(Ctx); + QualType getType(const SymExpr *SE) const { + return SE->getType(Ctx); } - ASTContext& getContext() { return Ctx; } + ASTContext &getContext() { return Ctx; } + BasicValueFactory &getBasicVals() { return BV; } }; class SymbolReaper { @@ -353,4 +317,13 @@ public: } // end clang namespace +namespace llvm { + llvm::raw_ostream& operator<<(llvm::raw_ostream& Out, + const clang::SymExpr *SE); +} +namespace std { + std::ostream& operator<<(std::ostream& Out, + const clang::SymExpr *SE); +} + #endif diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp index 01260480d1..8c5b71f234 100644 --- a/lib/Analysis/BasicStore.cpp +++ b/lib/Analysis/BasicStore.cpp @@ -197,8 +197,8 @@ SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base, switch(BaseL.getSubKind()) { case loc::SymbolValKind: - BaseR = MRMgr.getSymbolicRegion(cast(&BaseL)->getSymbol(), - StateMgr.getSymbolManager()); + BaseR = + MRMgr.getSymbolicRegion(cast(&BaseL)->getSymbol()); break; case loc::GotoLabelKind: @@ -243,8 +243,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base, // Create a region to represent this symbol. // FIXME: In the future we may just use symbolic regions instead of // SymbolVals to reason about symbolic memory chunks. - const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym, - StateMgr.getSymbolManager()); + const MemRegion* SymR = MRMgr.getSymbolicRegion(Sym); // Layered a typed region on top of this. QualType T = StateMgr.getSymbolManager().getType(Sym); BaseR = MRMgr.getTypedViewRegion(T, SymR); diff --git a/lib/Analysis/BasicValueFactory.cpp b/lib/Analysis/BasicValueFactory.cpp index 6ceab93b08..72ad0a5ed8 100644 --- a/lib/Analysis/BasicValueFactory.cpp +++ b/lib/Analysis/BasicValueFactory.cpp @@ -97,25 +97,6 @@ const llvm::APSInt& BasicValueFactory::getValue(uint64_t X, QualType T) { return getValue(V); } -const SymIntConstraint& -BasicValueFactory::getConstraint(SymbolRef 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(); - new (C) SymIntConstraint(sym, Op, V); - SymIntCSet.InsertNode(C, InsertPos); - } - - return *C; -} - const CompoundValData* BasicValueFactory::getCompoundValData(QualType T, llvm::ImmutableList Vals) { diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index ffa1593fd5..6807c9f08e 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -443,7 +443,7 @@ public: bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal V) { - SymbolRef ScanSym; + SymbolRef ScanSym = 0; if (loc::SymbolVal* SV = dyn_cast(&V)) ScanSym = SV->getSymbol(); @@ -545,7 +545,7 @@ public: bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal V) { - SymbolRef ScanSym; + SymbolRef ScanSym = 0; if (loc::SymbolVal* SV = dyn_cast(&V)) ScanSym = SV->getSymbol(); @@ -554,7 +554,7 @@ public: else return true; - assert (ScanSym.isValid()); + assert (ScanSym); if (!BR.isNotable(ScanSym)) return true; diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index be1d794252..6e43ec5faf 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -1591,8 +1591,8 @@ public: static void PrintPool(std::ostream &Out, SymbolRef Sym, const GRState *state) { Out << ' '; - if (Sym.isValid()) - Out << Sym; + if (Sym) + Out << Sym->getSymbolID(); else Out << ""; Out << ":{"; @@ -1705,7 +1705,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, SVal V = state.GetSValAsScalarOrLoc(*I); SymbolRef Sym = V.getAsLocSymbol(); - if (Sym.isValid()) + if (Sym) if (RefBindings::data_type* T = state.get(Sym)) { state = Update(state, Sym, *T, GetArgE(Summ, idx), hasErr); if (hasErr) { @@ -1746,7 +1746,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, SymbolRef Sym = state.GetSValAsScalarOrLoc(R).getAsLocSymbol(); // Remove any existing reference-count binding. - if (Sym.isValid()) state = state.remove(Sym); + if (Sym) state = state.remove(Sym); if (R->isBoundable(Ctx)) { // Set the value of the variable to be a conjured symbol. @@ -1833,7 +1833,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, // Evaluate the effect on the message receiver. if (!ErrorExpr && Receiver) { SymbolRef Sym = state.GetSValAsScalarOrLoc(Receiver).getAsLocSymbol(); - if (Sym.isValid()) { + if (Sym) { if (const RefVal* T = state.get(Sym)) { state = Update(state, Sym, *T, GetReceiverE(Summ), hasErr); if (hasErr) { @@ -1977,7 +1977,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst, SVal V = Eng.getStateManager().GetSValAsScalarOrLoc(St, Receiver); SymbolRef Sym = V.getAsLocSymbol(); - if (Sym.isValid()) { + if (Sym) { if (const RefVal* T = St->get(Sym)) { QualType Ty = T->getType(); @@ -2127,7 +2127,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst, GRStateRef state(Builder.GetState(Pred), Eng.getStateManager()); SymbolRef Sym = state.GetSValAsScalarOrLoc(RetE).getAsLocSymbol(); - if (!Sym.isValid()) + if (!Sym) return; // Get the reference count binding (if any). @@ -2824,9 +2824,9 @@ class VISIBILITY_HIDDEN FindUniqueBinding : bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal val) { - SymbolRef SymV = val.getAsSymbol(); - - if (!SymV.isValid() || SymV != Sym) + + SymbolRef SymV = val.getAsSymbol(); + if (!SymV || SymV != Sym) return true; if (Binding) { diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 80467ebb27..2f3f0bf5cc 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -782,7 +782,8 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { do { nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt())); - SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal); + SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal, + getContext().IntTy); // Now "assume" that the case matches. bool isFeasible = false; @@ -1449,7 +1450,7 @@ void GRExprEngine::EvalEagerlyAssume(NodeSet &Dst, NodeSet &Src, Expr *Ex) { const GRState* state = Pred->getState(); SVal V = GetSVal(state, Ex); - if (isa(V)) { + if (isa(V)) { // First assume that the condition is true. bool isFeasible = false; const GRState *stateTrue = Assume(state, V, true, isFeasible); @@ -1940,8 +1941,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ } StoreManager& StoreMgr = getStoreManager(); - const MemRegion* R = - StoreMgr.getRegionManager().getSymbolicRegion(Sym, getSymbolManager()); + const MemRegion* R = StoreMgr.getRegionManager().getSymbolicRegion(Sym); // Delegate to store manager to get the result of casting a region // to a different type. @@ -2394,7 +2394,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, if (isa(V)) { loc::ConcreteInt X(getBasicVals().getZeroWithPtrWidth()); - SVal Result = EvalBinOp(BinaryOperator::EQ, cast(V), X); + SVal Result = EvalBinOp(BinaryOperator::EQ, cast(V), X, + U->getType()); state = BindExpr(state, U, Result); } else { @@ -2403,7 +2404,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, SVal Result = EvalBinOp(BinaryOperator::EQ, cast(V), X); state = SetSVal(state, U, Result); #else - EvalBinOp(Dst, U, BinaryOperator::EQ, cast(V), X, *I); + EvalBinOp(Dst, U, BinaryOperator::EQ, cast(V), X, *I, + U->getType()); continue; #endif } @@ -2449,7 +2451,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add : BinaryOperator::Sub; - SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U)); + SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U), U->getType()); // Conjure a new symbol if necessary to recover precision. if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)) @@ -2643,7 +2645,6 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, return; } - if (B->isAssignmentOp()) VisitLValue(LHS, Pred, Tmp1); else @@ -2716,7 +2717,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Process non-assignements except commas or short-circuited // logical expressions (LAnd and LOr). - SVal Result = EvalBinOp(Op, LeftV, RightV); + SVal Result = EvalBinOp(Op, LeftV, RightV, B->getType()); if (Result.isUnknown()) { if (OldSt != state) { @@ -2828,7 +2829,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, } // Compute the result of the operation. - SVal Result = EvalCast(EvalBinOp(Op, V, RightV), B->getType()); + SVal Result = EvalCast(EvalBinOp(Op, V, RightV, CTy), B->getType()); if (Result.isUndef()) { // The operands were not undefined, but the result is undefined. @@ -2882,10 +2883,10 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, void GRExprEngine::EvalBinOp(ExplodedNodeSet& Dst, Expr* Ex, BinaryOperator::Opcode Op, NonLoc L, NonLoc R, - ExplodedNode* Pred) { + ExplodedNode* Pred, QualType T) { GRStateSet OStates; - EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R); + EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R, T); for (GRStateSet::iterator I=OStates.begin(), E=OStates.end(); I!=E; ++I) MakeNode(Dst, Ex, Pred, *I); @@ -2893,13 +2894,14 @@ void GRExprEngine::EvalBinOp(ExplodedNodeSet& Dst, Expr* Ex, void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* state, Expr* Ex, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R) { + NonLoc L, NonLoc R, QualType T) { GRStateSet::AutoPopulate AP(OStates, state); - if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R); + if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R, T); } -SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R) { +SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, + QualType T) { if (L.isUndef() || R.isUndef()) return UndefinedVal(); @@ -2926,7 +2928,7 @@ SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R) { } else return getTF().DetermEvalBinOpNN(*this, Op, cast(L), - cast(R)); + cast(R), T); } //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index 22ccd7b8aa..3bd51ecd72 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -131,7 +131,8 @@ static unsigned char LNotOpMap[] = { SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R) { + NonLoc L, NonLoc R, + QualType T) { BasicValueFactory& BasicVals = Eng.getBasicVals(); unsigned subkind = L.getSubKind(); @@ -173,34 +174,35 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng, } } - case nonloc::SymIntConstraintValKind: { - + case nonloc::SymExprValKind: { // Logical not? if (!(Op == BinaryOperator::EQ && R.isZeroConstant())) return UnknownVal(); - - const SymIntConstraint& C = - cast(L).getConstraint(); - - BinaryOperator::Opcode Opc = C.getOpcode(); - - if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE) - return UnknownVal(); - // For comparison operators, translate the constraint by - // changing the opcode. + const SymExpr &SE=*cast(L).getSymbolicExpression(); - int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT; + // Only handle ($sym op constant) for now. + if (const SymIntExpr *E = dyn_cast(&SE)) { + BinaryOperator::Opcode Opc = E->getOpcode(); - assert (idx >= 0 && - (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char)); + if (Opc < BinaryOperator::LT || Opc > BinaryOperator::NE) + return UnknownVal(); + + // For comparison operators, translate the constraint by + // changing the opcode. + int idx = (unsigned) Opc - (unsigned) BinaryOperator::LT; - Opc = (BinaryOperator::Opcode) LNotOpMap[idx]; + assert (idx >= 0 && + (unsigned) idx < sizeof(LNotOpMap)/sizeof(unsigned char)); - const SymIntConstraint& CNew = - BasicVals.getConstraint(C.getSymbol(), Opc, C.getInt()); + Opc = (BinaryOperator::Opcode) LNotOpMap[idx]; + assert(E->getType(Eng.getContext()) == T); + E = Eng.getSymbolManager().getSymIntExpr(E->getLHS(), Opc, + E->getRHS(), T); + return nonloc::SymExprVal(E); + } - return nonloc::SymIntConstraintVal(CNew); + return UnknownVal(); } case nonloc::ConcreteIntKind: @@ -231,14 +233,18 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng, case nonloc::SymbolValKind: if (isa(R)) { if (Op >= BinaryOperator::LT && Op <= BinaryOperator::NE) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast(L).getSymbol(), - Op, cast(R).getValue()); - return nonloc::SymIntConstraintVal(C); + const SymIntExpr *SE = + Eng.getSymbolManager().getSymIntExpr( + cast(L).getSymbol(), Op, + cast(R).getValue(),T); + + + return nonloc::SymExprVal(SE); } else { return NonLoc::MakeVal(Eng.getSymbolManager(), cast(L).getSymbol(), - Op, cast(R).getValue()); + Op, cast(R).getValue(), + T); } } else @@ -308,25 +314,28 @@ TryAgain: } else if (isa(R)) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast(R).getSymbol(), - BinaryOperator::EQ, - cast(L).getValue()); + const SymIntExpr *SE = + Eng.getSymbolManager().getSymIntExpr(cast(R).getSymbol(), + BinaryOperator::EQ, + cast(L).getValue(), + Eng.getContext().IntTy); - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } break; case loc::SymbolValKind: { - if (isa(R)) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast(L).getSymbol(), - BinaryOperator::EQ, - cast(R).getValue()); + if (isa(R)) { + const SymIntExpr *SE = + Eng.getSymbolManager().getSymIntExpr( + cast(L).getSymbol(), + BinaryOperator::EQ, + cast(R).getValue(), + Eng.getContext().IntTy); - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } // FIXME: Implement == for lval Symbols. This is mainly useful @@ -378,25 +387,27 @@ TryAgain: return NonLoc::MakeIntTruthVal(BasicVals, b); } - else if (isa(R)) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast(R).getSymbol(), - BinaryOperator::NE, - cast(L).getValue()); - - return nonloc::SymIntConstraintVal(C); + else if (isa(R)) { + const SymIntExpr * SE = + Eng.getSymbolManager().getSymIntExpr( + cast(R).getSymbol(), + BinaryOperator::NE, + cast(L).getValue(), + Eng.getContext().IntTy); + return nonloc::SymExprVal(SE); } break; case loc::SymbolValKind: { - if (isa(R)) { - const SymIntConstraint& C = - BasicVals.getConstraint(cast(L).getSymbol(), - BinaryOperator::NE, - cast(R).getValue()); - - return nonloc::SymIntConstraintVal(C); + if (isa(R)) { + const SymIntExpr *SE = + Eng.getSymbolManager().getSymIntExpr( + cast(L).getSymbol(), + BinaryOperator::NE, + cast(R).getValue(), + Eng.getContext().IntTy); + return nonloc::SymExprVal(SE); } // FIXME: Implement != for lval Symbols. This is mainly useful diff --git a/lib/Analysis/GRSimpleVals.h b/lib/Analysis/GRSimpleVals.h index 6848ced2be..efe7c631ab 100644 --- a/lib/Analysis/GRSimpleVals.h +++ b/lib/Analysis/GRSimpleVals.h @@ -29,7 +29,7 @@ protected: virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R); + NonLoc L, NonLoc R, QualType T); public: GRSimpleVals() {} diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp index c08bd8f0b1..69c09d9a2e 100644 --- a/lib/Analysis/GRTransferFuncs.cpp +++ b/lib/Analysis/GRTransferFuncs.cpp @@ -21,7 +21,8 @@ void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng, const GRState *St, Expr* Ex, BinaryOperator::Opcode Op, - NonLoc L, NonLoc R) { + NonLoc L, NonLoc R, QualType T) { - OStates.Add(Eng.getStateManager().BindExpr(St, Ex, DetermEvalBinOpNN(Eng, Op, L, R))); + OStates.Add(Eng.getStateManager().BindExpr(St, Ex, + DetermEvalBinOpNN(Eng, Op, L, R, T))); } diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp index 5bfc989eb8..738e8c67d6 100644 --- a/lib/Analysis/MemRegion.cpp +++ b/lib/Analysis/MemRegion.cpp @@ -112,10 +112,8 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const { //===----------------------------------------------------------------------===// QualType SymbolicRegion::getRValueType(ASTContext& C) const { - const SymbolData& data = SymMgr.getSymbolData(sym); - // Get the type of the symbol. - QualType T = data.getType(C); + QualType T = sym->getType(C); if (const PointerType* PTy = T->getAsPointerType()) return PTy->getPointeeType(); @@ -132,8 +130,7 @@ QualType SymbolicRegion::getRValueType(ASTContext& C) const { } QualType SymbolicRegion::getLValueType(ASTContext& C) const { - const SymbolData& data = SymMgr.getSymbolData(sym); - return data.getType(C); + return sym->getType(C); } QualType ElementRegion::getRValueType(ASTContext& C) const { @@ -332,12 +329,9 @@ MemRegionManager::getElementRegion(SVal Idx, const TypedRegion* superRegion){ } /// getSymbolicRegion - Retrieve or create a "symbolic" memory region. -SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym, - const SymbolManager& mgr) { - +SymbolicRegion* MemRegionManager::getSymbolicRegion(SymbolRef sym) { llvm::FoldingSetNodeID ID; SymbolicRegion::ProfileRegion(ID, sym); - void* InsertPos; MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos); SymbolicRegion* R = cast_or_null(data); @@ -345,7 +339,7 @@ SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolRef sym, if (!R) { R = (SymbolicRegion*) A.Allocate(); // SymbolicRegion's storage class is usually unknown. - new (R) SymbolicRegion(sym, mgr, getUnknownRegion()); + new (R) SymbolicRegion(sym, getUnknownRegion()); Regions.InsertNode(R, InsertPos); } diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index 78dda87392..f23369c8e1 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -367,8 +367,7 @@ SVal RegionStoreManager::getLValueFieldOrIvar(const GRState* St, SVal Base, break; case loc::SymbolValKind: - BaseR = MRMgr.getSymbolicRegion(cast(&BaseL)->getSymbol(), - StateMgr.getSymbolManager()); + BaseR = MRMgr.getSymbolicRegion(cast(&BaseL)->getSymbol()); break; case loc::GotoLabelKind: @@ -412,11 +411,9 @@ SVal RegionStoreManager::getLValueElement(const GRState* St, const TypedRegion* BaseRegion = 0; - if (isa(Base)) - BaseRegion = MRMgr.getSymbolicRegion(cast(Base).getSymbol(), - StateMgr.getSymbolManager()); - else - BaseRegion = cast(cast(Base).getRegion()); + BaseRegion = isa(Base) + ? MRMgr.getSymbolicRegion(cast(Base).getSymbol()) + : cast(cast(Base).getRegion()); // Pointer of any type can be cast and used as array base. const ElementRegion *ElemR = dyn_cast(BaseRegion); @@ -862,8 +859,7 @@ Store RegionStoreManager::Remove(Store store, Loc L) { if (isa(L)) R = cast(L).getRegion(); else if (isa(L)) - R = MRMgr.getSymbolicRegion(cast(L).getSymbol(), - StateMgr.getSymbolManager()); + R = MRMgr.getSymbolicRegion(cast(L).getSymbol()); if (R) { RegionBindingsTy B = GetRegionBindings(store); diff --git a/lib/Analysis/SVals.cpp b/lib/Analysis/SVals.cpp index 0f345602a2..9225f994d3 100644 --- a/lib/Analysis/SVals.cpp +++ b/lib/Analysis/SVals.cpp @@ -22,37 +22,13 @@ using llvm::cast; using llvm::APSInt; //===----------------------------------------------------------------------===// -// Symbol Iteration. +// Symbol iteration within an SVal. //===----------------------------------------------------------------------===// -SVal::symbol_iterator SVal::symbol_begin() const { - // FIXME: This is a rat's nest. Cleanup. - - if (isa(this)) - return symbol_iterator(SymbolRef((uintptr_t)Data)); - else if (isa(this)) - return symbol_iterator(SymbolRef((uintptr_t)Data)); - else if (isa(this)) { - const SymIntConstraint& C = - cast(this)->getConstraint(); - return symbol_iterator(C.getSymbol()); - } - else if (isa(this)) { - const nonloc::LocAsInteger& V = cast(*this); - return V.getPersistentLoc().symbol_begin(); - } - else if (isa(this)) { - const MemRegion* R = cast(this)->getRegion(); - if (const SymbolicRegion* S = dyn_cast(R)) - return symbol_iterator(S->getSymbol()); - } - - return symbol_iterator(); -} -SVal::symbol_iterator SVal::symbol_end() const { - return symbol_iterator(); -} +//===----------------------------------------------------------------------===// +// Utility methods. +//===----------------------------------------------------------------------===// /// getAsLocSymbol - If this SVal is a location (subclasses Loc) and /// wraps a symbol, return that SymbolRef. Otherwise return a SymbolRef @@ -78,7 +54,7 @@ SymbolRef SVal::getAsLocSymbol() const { } } - return SymbolRef(); + return 0; } /// getAsSymbol - If this Sval wraps a symbol return that SymbolRef. @@ -87,9 +63,66 @@ SymbolRef SVal::getAsSymbol() const { if (const nonloc::SymbolVal *X = dyn_cast(this)) return X->getSymbol(); + if (const nonloc::SymExprVal *X = dyn_cast(this)) + if (SymbolRef Y = dyn_cast(X->getSymbolicExpression())) + return Y; + return getAsLocSymbol(); } +/// getAsSymbolicExpression - If this Sval wraps a symbolic expression then +/// return that expression. Otherwise return NULL. +const SymExpr *SVal::getAsSymbolicExpression() const { + if (const nonloc::SymExprVal *X = dyn_cast(this)) + return X->getSymbolicExpression(); + + return getAsSymbol(); +} + +bool SVal::symbol_iterator::operator==(const symbol_iterator &X) const { + return itr == X.itr; +} + +bool SVal::symbol_iterator::operator!=(const symbol_iterator &X) const { + return itr != X.itr; +} + +SVal::symbol_iterator::symbol_iterator(const SymExpr *SE) { + itr.push_back(SE); + while (!isa(itr.back())) expand(); +} + +SVal::symbol_iterator& SVal::symbol_iterator::operator++() { + assert(!itr.empty() && "attempting to iterate on an 'end' iterator"); + assert(isa(itr.back())); + itr.pop_back(); + if (!itr.empty()) + while (!isa(itr.back())) expand(); + return *this; +} + +SymbolRef SVal::symbol_iterator::operator*() { + assert(!itr.empty() && "attempting to dereference an 'end' iterator"); + return cast(itr.back()); +} + +void SVal::symbol_iterator::expand() { + const SymExpr *SE = itr.back(); + itr.pop_back(); + + if (const SymIntExpr *SIE = dyn_cast(SE)) { + itr.push_back(SIE->getLHS()); + return; + } + else if (const SymSymExpr *SSE = dyn_cast(SE)) { + itr.push_back(SSE->getLHS()); + itr.push_back(SSE->getRHS()); + return; + } + + assert(false && "unhandled expansion case"); +} + //===----------------------------------------------------------------------===// // Other Iterators. //===----------------------------------------------------------------------===// @@ -168,7 +201,7 @@ SVal loc::ConcreteInt::EvalBinOp(BasicValueFactory& BasicVals, return UndefinedVal(); } -NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const { +NonLoc Loc::EQ(SymbolManager& SymMgr, const Loc& R) const { switch (getSubKind()) { default: @@ -180,49 +213,48 @@ NonLoc Loc::EQ(BasicValueFactory& BasicVals, const Loc& R) const { bool b = cast(this)->getValue() == cast(R).getValue(); - return NonLoc::MakeIntTruthVal(BasicVals, b); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b); } else if (isa(R)) { - - const SymIntConstraint& C = - BasicVals.getConstraint(cast(R).getSymbol(), + const SymIntExpr *SE = + SymMgr.getSymIntExpr(cast(R).getSymbol(), BinaryOperator::EQ, - cast(this)->getValue()); + cast(this)->getValue(), + SymMgr.getContext().IntTy); - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } break; case loc::SymbolValKind: { if (isa(R)) { - - const SymIntConstraint& C = - BasicVals.getConstraint(cast(this)->getSymbol(), + const SymIntExpr *SE = + SymMgr.getSymIntExpr(cast(this)->getSymbol(), BinaryOperator::EQ, - cast(R).getValue()); + cast(R).getValue(), + SymMgr.getContext().IntTy); - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } - - assert (!isa(R) && "FIXME: Implement unification."); - + + assert (!isa(R) && "FIXME: Implement unification."); break; } case loc::MemRegionKind: if (isa(R)) { bool b = cast(*this) == cast(R); - return NonLoc::MakeIntTruthVal(BasicVals, b); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b); } break; } - return NonLoc::MakeIntTruthVal(BasicVals, false); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), false); } -NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const { +NonLoc Loc::NE(SymbolManager& SymMgr, const Loc& R) const { switch (getSubKind()) { default: assert(false && "NE not implemented for this Loc."); @@ -233,46 +265,43 @@ NonLoc Loc::NE(BasicValueFactory& BasicVals, const Loc& R) const { bool b = cast(this)->getValue() != cast(R).getValue(); - return NonLoc::MakeIntTruthVal(BasicVals, b); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b); } else if (isa(R)) { - - const SymIntConstraint& C = - BasicVals.getConstraint(cast(R).getSymbol(), - BinaryOperator::NE, - cast(this)->getValue()); - - return nonloc::SymIntConstraintVal(C); + const SymIntExpr *SE = + SymMgr.getSymIntExpr(cast(R).getSymbol(), + BinaryOperator::NE, + cast(this)->getValue(), + SymMgr.getContext().IntTy); + return nonloc::SymExprVal(SE); } - break; case loc::SymbolValKind: { if (isa(R)) { + const SymIntExpr *SE = + SymMgr.getSymIntExpr(cast(this)->getSymbol(), + BinaryOperator::NE, + cast(R).getValue(), + SymMgr.getContext().IntTy); - const SymIntConstraint& C = - BasicVals.getConstraint(cast(this)->getSymbol(), - BinaryOperator::NE, - cast(R).getValue()); - - return nonloc::SymIntConstraintVal(C); + return nonloc::SymExprVal(SE); } assert (!isa(R) && "FIXME: Implement sym !=."); - break; } case loc::MemRegionKind: if (isa(R)) { bool b = cast(*this)==cast(R); - return NonLoc::MakeIntTruthVal(BasicVals, b); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), b); } break; } - return NonLoc::MakeIntTruthVal(BasicVals, true); + return NonLoc::MakeIntTruthVal(SymMgr.getBasicVals(), true); } //===----------------------------------------------------------------------===// @@ -283,21 +312,21 @@ NonLoc NonLoc::MakeVal(SymbolRef sym) { return nonloc::SymbolVal(sym); } -NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs, - BinaryOperator::Opcode op, const APSInt& v) { +NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, + BinaryOperator::Opcode op, const APSInt& v, QualType T) { // The Environment ensures we always get a persistent APSInt in // BasicValueFactory, so we don't need to get the APSInt from // BasicValueFactory again. - - SymbolRef sym = SymMgr.getSymIntExpr(lhs, op, v, SymMgr.getType(lhs)); - return nonloc::SymbolVal(sym); + assert(!Loc::IsLocType(T)); + return nonloc::SymExprVal(SymMgr.getSymIntExpr(lhs, op, v, T)); } -NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, SymbolRef lhs, - BinaryOperator::Opcode op, SymbolRef rhs) { +NonLoc NonLoc::MakeVal(SymbolManager& SymMgr, const SymExpr *lhs, + BinaryOperator::Opcode op, const SymExpr *rhs, +QualType T) { assert(SymMgr.getType(lhs) == SymMgr.getType(rhs)); - SymbolRef sym = SymMgr.getSymSymExpr(lhs, op, rhs, SymMgr.getType(lhs)); - return nonloc::SymbolVal(sym); + assert(!Loc::IsLocType(T)); + return nonloc::SymExprVal(SymMgr.getSymSymExpr(lhs, op, rhs, T)); } NonLoc NonLoc::MakeIntVal(BasicValueFactory& BasicVals, uint64_t X, @@ -419,30 +448,6 @@ void SVal::print(llvm::raw_ostream& Out) const { } } -static void printOpcode(llvm::raw_ostream& Out, BinaryOperator::Opcode Op) { - - switch (Op) { - case BinaryOperator::Mul: Out << '*' ; break; - case BinaryOperator::Div: Out << '/' ; break; - case BinaryOperator::Rem: Out << '%' ; break; - case BinaryOperator::Add: Out << '+' ; break; - case BinaryOperator::Sub: Out << '-' ; break; - case BinaryOperator::Shl: Out << "<<" ; break; - case BinaryOperator::Shr: Out << ">>" ; break; - case BinaryOperator::LT: Out << "<" ; break; - case BinaryOperator::GT: Out << '>' ; break; - case BinaryOperator::LE: Out << "<=" ; break; - case BinaryOperator::GE: Out << ">=" ; break; - case BinaryOperator::EQ: Out << "==" ; break; - case BinaryOperator::NE: Out << "!=" ; break; - case BinaryOperator::And: Out << '&' ; break; - case BinaryOperator::Xor: Out << '^' ; break; - case BinaryOperator::Or: Out << '|' ; break; - - default: assert(false && "Not yet implemented."); - } -} - void NonLoc::print(llvm::raw_ostream& Out) const { switch (getSubKind()) { @@ -459,17 +464,10 @@ void NonLoc::print(llvm::raw_ostream& Out) const { Out << '$' << cast(this)->getSymbol(); break; - case nonloc::SymIntConstraintValKind: { - const nonloc::SymIntConstraintVal& C = - *cast(this); - - Out << '$' << C.getConstraint().getSymbol() << ' '; - printOpcode(Out, C.getConstraint().getOpcode()); - Out << ' ' << C.getConstraint().getInt().getZExtValue(); - - if (C.getConstraint().getInt().isUnsigned()) - Out << 'U'; - + case nonloc::SymExprValKind: { + const nonloc::SymExprVal& C = *cast(this); + const SymExpr *SE = C.getSymbolicExpression(); + Out << SE; break; } diff --git a/lib/Analysis/SimpleConstraintManager.cpp b/lib/Analysis/SimpleConstraintManager.cpp index 50552c1144..904479c4c3 100644 --- a/lib/Analysis/SimpleConstraintManager.cpp +++ b/lib/Analysis/SimpleConstraintManager.cpp @@ -21,11 +21,35 @@ namespace clang { SimpleConstraintManager::~SimpleConstraintManager() {} bool SimpleConstraintManager::canReasonAbout(SVal X) const { - if (nonloc::SymbolVal* SymVal = dyn_cast(&X)) { - const SymbolData& data - = getSymbolManager().getSymbolData(SymVal->getSymbol()); - return !(data.getKind() == SymbolData::SymIntKind || - data.getKind() == SymbolData::SymSymKind ); + if (nonloc::SymExprVal *SymVal = dyn_cast(&X)) { + const SymExpr *SE = SymVal->getSymbolicExpression(); + + if (isa(SE)) + return true; + + if (const SymIntExpr *SIE = dyn_cast(SE)) { + switch (SIE->getOpcode()) { + // We don't reason yet about bitwise-constraints on symbolic values. + case BinaryOperator::And: + case BinaryOperator::Or: + case BinaryOperator::Xor: + return false; + // We don't reason yet about arithmetic constraints on symbolic values. + case BinaryOperator::Mul: + case BinaryOperator::Div: + case BinaryOperator::Rem: + case BinaryOperator::Add: + case BinaryOperator::Sub: + case BinaryOperator::Shl: + case BinaryOperator::Shr: + return false; + // All other cases. + default: + return true; + } + } + + return false; } return true; @@ -150,11 +174,14 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond, return AssumeSymEQ(St, sym, BasicVals.getValue(0, T), isFeasible); } - case nonloc::SymIntConstraintValKind: - return - AssumeSymInt(St, Assumption, - cast(Cond).getConstraint(), - isFeasible); + case nonloc::SymExprValKind: { + nonloc::SymExprVal V = cast(Cond); + if (const SymIntExpr *SE = dyn_cast(V.getSymbolicExpression())) + return AssumeSymInt(St, Assumption, SE, isFeasible); + + isFeasible = true; + return St; + } case nonloc::ConcreteIntKind: { bool b = cast(Cond).getValue() != 0; @@ -170,50 +197,43 @@ SimpleConstraintManager::AssumeAux(const GRState* St,NonLoc Cond, const GRState* SimpleConstraintManager::AssumeSymInt(const GRState* St, bool Assumption, - const SymIntConstraint& C, - bool& isFeasible) { + const SymIntExpr *SE, bool& isFeasible) { + - switch (C.getOpcode()) { + // Here we assume that LHS is a symbol. This is consistent with the + // rest of the constraint manager logic. + SymbolRef Sym = cast(SE->getLHS()); + const llvm::APSInt &Int = SE->getRHS(); + + switch (SE->getOpcode()) { default: // No logic yet for other operators. isFeasible = true; return St; case BinaryOperator::EQ: - if (Assumption) - return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymEQ(St, Sym, Int, isFeasible) + : AssumeSymNE(St, Sym, Int, isFeasible); case BinaryOperator::NE: - if (Assumption) - return AssumeSymNE(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymEQ(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymNE(St, Sym, Int, isFeasible) + : AssumeSymEQ(St, Sym, Int, isFeasible); case BinaryOperator::GT: - if (Assumption) - return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymGT(St, Sym, Int, isFeasible) + : AssumeSymLE(St, Sym, Int, isFeasible); case BinaryOperator::GE: - if (Assumption) - return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymGE(St, Sym, Int, isFeasible) + : AssumeSymLT(St, Sym, Int, isFeasible); case BinaryOperator::LT: - if (Assumption) - return AssumeSymLT(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymGE(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymLT(St, Sym, Int, isFeasible) + : AssumeSymGE(St, Sym, Int, isFeasible); case BinaryOperator::LE: - if (Assumption) - return AssumeSymLE(St, C.getSymbol(), C.getInt(), isFeasible); - else - return AssumeSymGT(St, C.getSymbol(), C.getInt(), isFeasible); + return Assumption ? AssumeSymLE(St, Sym, Int, isFeasible) + : AssumeSymGT(St, Sym, Int, isFeasible); } // end switch } diff --git a/lib/Analysis/SimpleConstraintManager.h b/lib/Analysis/SimpleConstraintManager.h index 8195c8ed36..fb41e2f1da 100644 --- a/lib/Analysis/SimpleConstraintManager.h +++ b/lib/Analysis/SimpleConstraintManager.h @@ -45,7 +45,7 @@ public: bool& isFeasible); const GRState* AssumeSymInt(const GRState* St, bool Assumption, - const SymIntConstraint& C, bool& isFeasible); + const SymIntExpr *SE, bool& isFeasible); virtual const GRState* AssumeSymNE(const GRState* St, SymbolRef sym, const llvm::APSInt& V, diff --git a/lib/Analysis/SymbolManager.cpp b/lib/Analysis/SymbolManager.cpp index 33d6a5722e..f8e2db7268 100644 --- a/lib/Analysis/SymbolManager.cpp +++ b/lib/Analysis/SymbolManager.cpp @@ -18,110 +18,149 @@ using namespace clang; -llvm::raw_ostream& llvm::operator<<(llvm::raw_ostream& os, - clang::SymbolRef sym) { - if (sym.isValid()) - os << sym.getNumber(); - else - os << "(Invalid)"; +static void print(llvm::raw_ostream& os, const SymExpr *SE); + +static void print(llvm::raw_ostream& os, BinaryOperator::Opcode Op) { + switch (Op) { + default: + assert(false && "operator printing not implemented"); + break; + case BinaryOperator::Mul: os << '*' ; break; + case BinaryOperator::Div: os << '/' ; break; + case BinaryOperator::Rem: os << '%' ; break; + case BinaryOperator::Add: os << '+' ; break; + case BinaryOperator::Sub: os << '-' ; break; + case BinaryOperator::Shl: os << "<<" ; break; + case BinaryOperator::Shr: os << ">>" ; break; + case BinaryOperator::LT: os << "<" ; break; + case BinaryOperator::GT: os << '>' ; break; + case BinaryOperator::LE: os << "<=" ; break; + case BinaryOperator::GE: os << ">=" ; break; + case BinaryOperator::EQ: os << "==" ; break; + case BinaryOperator::NE: os << "!=" ; break; + case BinaryOperator::And: os << '&' ; break; + case BinaryOperator::Xor: os << '^' ; break; + case BinaryOperator::Or: os << '|' ; break; + } +} + +static void print(llvm::raw_ostream& os, const SymIntExpr *SE) { + os << '('; + print(os, SE->getLHS()); + os << ") "; + print(os, SE->getOpcode()); + os << ' ' << SE->getRHS().getZExtValue(); + if (SE->getRHS().isUnsigned()) os << 'U'; +} +static void print(llvm::raw_ostream& os, const SymSymExpr *SE) { + os << '('; + print(os, SE->getLHS()); + os << ") "; + os << '('; + print(os, SE->getRHS()); + os << ')'; +} + +static void print(llvm::raw_ostream& os, const SymExpr *SE) { + switch (SE->getKind()) { + case SymExpr::BEGIN_SYMBOLS: + case SymExpr::RegionRValue: + case SymExpr::ConjuredKind: + case SymExpr::END_SYMBOLS: + os << '$' << cast(SE)->getSymbolID(); + return; + case SymExpr::SymIntKind: + print(os, cast(SE)); + return; + case SymExpr::SymSymKind: + print(os, cast(SE)); + return; + } +} + + +llvm::raw_ostream& llvm::operator<<(llvm::raw_ostream& os, const SymExpr *SE) { + print(os, SE); return os; } -std::ostream& std::operator<<(std::ostream& os, clang::SymbolRef sym) { - if (sym.isValid()) - os << sym.getNumber(); - else - os << "(Invalid)"; - +std::ostream& std::operator<<(std::ostream& os, const SymExpr *SE) { + llvm::raw_os_ostream O(os); + print(O, SE); return os; } -SymbolRef SymbolManager::getRegionRValueSymbol(const MemRegion* R) { +const SymbolRegionRValue* +SymbolManager::getRegionRValueSymbol(const MemRegion* R) { llvm::FoldingSetNodeID profile; - SymbolRegionRValue::Profile(profile, R); void* InsertPos; - SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - if (SD) return SD->getSymbol(); + SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); + if (!SD) { + SD = (SymExpr*) BPAlloc.Allocate(); + new (SD) SymbolRegionRValue(SymbolCounter, R); + DataSet.InsertNode(SD, InsertPos); + ++SymbolCounter; + } - SD = (SymbolData*) BPAlloc.Allocate(); - new (SD) SymbolRegionRValue(SymbolCounter, R); - DataSet.InsertNode(SD, InsertPos); - DataMap[SymbolCounter] = SD; - return SymbolCounter++; + return cast(SD); } -SymbolRef SymbolManager::getConjuredSymbol(const Stmt* E, QualType T, - unsigned Count, - const void* SymbolTag) { +const SymbolConjured* +SymbolManager::getConjuredSymbol(const Stmt* E, QualType T, unsigned Count, + const void* SymbolTag) { llvm::FoldingSetNodeID profile; SymbolConjured::Profile(profile, E, T, Count, SymbolTag); - void* InsertPos; - - SymbolData* SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); - - if (SD) - return SD->getSymbol(); - - SD = (SymbolData*) BPAlloc.Allocate(); - new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag); - - DataSet.InsertNode(SD, InsertPos); - DataMap[SymbolCounter] = SD; + void* InsertPos; + SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos); + if (!SD) { + SD = (SymExpr*) BPAlloc.Allocate(); + new (SD) SymbolConjured(SymbolCounter, E, T, Count, SymbolTag); + DataSet.InsertNode(SD, InsertPos); + ++SymbolCounter; + } - return SymbolCounter++; + return cast(SD); } -SymbolRef SymbolManager::getSymIntExpr(SymbolRef lhs,BinaryOperator::Opcode op, - const llvm::APSInt& v, QualType t) { +const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs, + BinaryOperator::Opcode op, + const llvm::APSInt& v, + QualType t) { llvm::FoldingSetNodeID ID; SymIntExpr::Profile(ID, lhs, op, v, t); - void* InsertPos; - - SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - - if (data) - return data->getSymbol(); - - data = (SymIntExpr*) BPAlloc.Allocate(); - new (data) SymIntExpr(SymbolCounter, lhs, op, v, t); - - DataSet.InsertNode(data, InsertPos); - DataMap[SymbolCounter] = data; - - return SymbolCounter++; + void *InsertPos; + SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); + + if (!data) { + data = (SymIntExpr*) BPAlloc.Allocate(); + new (data) SymIntExpr(lhs, op, v, t); + DataSet.InsertNode(data, InsertPos); + } + + return cast(data); } -SymbolRef SymbolManager::getSymSymExpr(SymbolRef lhs, BinaryOperator::Opcode op, - SymbolRef rhs, QualType t) { +const SymSymExpr *SymbolManager::getSymSymExpr(const SymExpr *lhs, + BinaryOperator::Opcode op, + const SymExpr *rhs, + QualType t) { llvm::FoldingSetNodeID ID; SymSymExpr::Profile(ID, lhs, op, rhs, t); - void* InsertPos; - - SymbolData* data = DataSet.FindNodeOrInsertPos(ID, InsertPos); - - if (data) - return data->getSymbol(); - - data = (SymSymExpr*) BPAlloc.Allocate(); - new (data) SymSymExpr(SymbolCounter, lhs, op, rhs, t); - - DataSet.InsertNode(data, InsertPos); - DataMap[SymbolCounter] = data; - - return SymbolCounter++; -} - - -const SymbolData& SymbolManager::getSymbolData(SymbolRef Sym) const { - DataMapTy::const_iterator I = DataMap.find(Sym); - assert (I != DataMap.end()); - return *I->second; + void *InsertPos; + SymExpr *data = DataSet.FindNodeOrInsertPos(ID, InsertPos); + + if (!data) { + data = (SymSymExpr*) BPAlloc.Allocate(); + new (data) SymSymExpr(lhs, op, rhs, t); + DataSet.InsertNode(data, InsertPos); + } + + return cast(data); } - QualType SymbolConjured::getType(ASTContext&) const { return T; } @@ -158,7 +197,7 @@ bool SymbolReaper::isLive(SymbolRef sym) { // Interogate the symbol. It may derive from an input value to // the analyzed function/method. - return isa(SymMgr.getSymbolData(sym)); + return isa(sym); } SymbolVisitor::~SymbolVisitor() {} -- 2.40.0