diff --git a/include/clang/Analysis/PathSensitive/BasicValueFactory.h b/include/clang/Analysis/PathSensitive/BasicValueFactory.h index 9462ed597d..e36e521d79 100644 --- a/include/clang/Analysis/PathSensitive/BasicValueFactory.h +++ b/include/clang/Analysis/PathSensitive/BasicValueFactory.h @@ -71,8 +71,8 @@ public: const llvm::APSInt& V1, const llvm::APSInt& V2); - const std::pair& - getPersistentSizedRVal(const RVal& V, unsigned Bits); + const std::pair& + getPersistentRValWithData(const RVal& V, uintptr_t Data); }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/RValues.h b/include/clang/Analysis/PathSensitive/RValues.h index 8a53588564..353046d4be 100644 --- a/include/clang/Analysis/PathSensitive/RValues.h +++ b/include/clang/Analysis/PathSensitive/RValues.h @@ -234,17 +234,20 @@ public: }; class LValAsInteger : public NonLVal { - LValAsInteger(const std::pair& data) : - NonLVal(LValAsIntegerKind, &data) {} + LValAsInteger(const std::pair& data) : + NonLVal(LValAsIntegerKind, &data) { + assert (isa(data.first)); + } public: LVal getLVal() const { - return cast(((std::pair*) Data)->first); + return cast(((std::pair*) Data)->first); } const LVal& getPersistentLVal() const { - return cast(((std::pair*) Data)->first); + const RVal& V = ((std::pair*) Data)->first; + return cast(V); } unsigned getNumBits() const { @@ -263,7 +266,7 @@ public: static inline LValAsInteger Make(BasicValueFactory& Vals, LVal V, unsigned Bits) { - return LValAsInteger(Vals.getPersistentSizedRVal(V, Bits)); + return LValAsInteger(Vals.getPersistentRValWithData(V, Bits)); } }; @@ -276,7 +279,7 @@ public: namespace lval { enum Kind { SymbolValKind, GotoLabelKind, DeclValKind, FuncValKind, - ConcreteIntKind, StringLiteralValKind }; + ConcreteIntKind, StringLiteralValKind, FieldOffsetKind }; class SymbolVal : public LVal { public: @@ -409,7 +412,48 @@ public: return V->getSubKind() == StringLiteralValKind; } }; + +class FieldOffset : public LVal { + FieldOffset(const std::pair& data) + : LVal(FieldOffsetKind, &data) { + assert (isa(data.first)); + } + +public: + + LVal getBase() const { + return reinterpret_cast*> (Data)->first; + } + + const LVal& getPersistentBase() const { + return reinterpret_cast*> (Data)->first; + } + + FieldDecl* getFieldDecl() const { + return (FieldDecl*) + reinterpret_cast*> (Data)->second; + } + + // Implement isa support. + static inline bool classof(const RVal* V) { + return V->getBaseKind() == LValKind && + V->getSubKind() == FieldOffsetKind; + } + + static inline bool classof(const LVal* V) { + return V->getSubKind() == FieldOffsetKind; + } + + static inline RVal Make(BasicValueFactory& Vals, RVal Base, FieldDecl* D) { + + if (Base.isUnknownOrUndef()) + return Base; + + return FieldOffset(Vals.getPersistentRValWithData(cast(Base), + (uintptr_t) D)); + } +}; } // end clang::lval namespace } // end clang namespace diff --git a/lib/Analysis/BasicValueFactory.cpp b/lib/Analysis/BasicValueFactory.cpp index 22fb2d1b6e..b0aa79e067 100644 --- a/lib/Analysis/BasicValueFactory.cpp +++ b/lib/Analysis/BasicValueFactory.cpp @@ -18,18 +18,18 @@ using namespace clang; -typedef std::pair SizedRVal; +typedef std::pair RValData; namespace llvm { -template<> struct FoldingSetTrait { - static inline void Profile(const SizedRVal& X, llvm::FoldingSetNodeID& ID) { +template<> struct FoldingSetTrait { + static inline void Profile(const RValData& X, llvm::FoldingSetNodeID& ID) { X.first.Profile(ID); - ID.AddInteger(X.second); + ID.AddPointer( (void*) X.second); } }; } -typedef llvm::FoldingSet > +typedef llvm::FoldingSet > PersistentRValsTy; BasicValueFactory::~BasicValueFactory() { @@ -184,8 +184,8 @@ BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op, } -const std::pair& -BasicValueFactory::getPersistentSizedRVal(const RVal& V, unsigned Bits) { +const std::pair& +BasicValueFactory::getPersistentRValWithData(const RVal& V, uintptr_t Data) { // Lazily create the folding set. if (!PersistentRVals) PersistentRVals = new PersistentRValsTy(); @@ -193,18 +193,18 @@ BasicValueFactory::getPersistentSizedRVal(const RVal& V, unsigned Bits) { llvm::FoldingSetNodeID ID; void* InsertPos; V.Profile(ID); - ID.AddInteger(Bits); + ID.AddPointer((void*) Data); PersistentRValsTy& Map = *((PersistentRValsTy*) PersistentRVals); - typedef llvm::FoldingSetNodeWrapper FoldNodeTy; + typedef llvm::FoldingSetNodeWrapper FoldNodeTy; FoldNodeTy* P = Map.FindNodeOrInsertPos(ID, InsertPos); if (!P) { P = (FoldNodeTy*) BPAlloc.Allocate(); - new (P) FoldNodeTy(std::make_pair(V, Bits)); + new (P) FoldNodeTy(std::make_pair(V, Data)); Map.InsertNode(P, InsertPos); } - return *P; + return P->getValue(); } diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 2353058e76..a4f1a0512d 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -856,16 +856,12 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, // This is a redunant copy; we do this as a placeholder for future logic. for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { ValueState* St = GetState(*I); - RVal V = GetRVal(St, Base); + RVal BaseV = GetRVal(St, Base); - // TODO: Compute the LVal for the field. This will enable field - // sensitivity for the analysis. - - if (!(V.isUndef() || V.isUnknown() || isa(V))) - V = UnknownVal(); - - MakeNode(Dst, M, *I, SetRVal(St, M, V)); + RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base), + M->getMemberDecl()); + MakeNode(Dst, M, *I, SetRVal(St, M, V)); } return; @@ -879,13 +875,8 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { ValueState* St = GetState(*I); - RVal V = GetRVal(St, Base); - - // TODO: Compute the LVal for the field. This will enable field - // sensitivity for the analysis. - - if (!(V.isUndef() || V.isUnknown() || isa(V))) - V = UnknownVal(); + RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base), + M->getMemberDecl()); EvalLoad(Dst, M, *I, St, V, true); } @@ -2034,7 +2025,11 @@ ValueState* GRExprEngine::AssumeAux(ValueState* St, LVal Cond, case lval::StringLiteralValKind: isFeasible = Assumption; return St; - + + case lval::FieldOffsetKind: + return AssumeAux(St, cast(Cond).getBase(), + Assumption, isFeasible); + case lval::ConcreteIntKind: { bool b = cast(Cond).getValue() != 0; isFeasible = b ? Assumption : !Assumption; diff --git a/lib/Analysis/RValues.cpp b/lib/Analysis/RValues.cpp index 5e161f34a5..ab1cf6a420 100644 --- a/lib/Analysis/RValues.cpp +++ b/lib/Analysis/RValues.cpp @@ -25,6 +25,9 @@ using llvm::APSInt; //===----------------------------------------------------------------------===// RVal::symbol_iterator RVal::symbol_begin() const { + + // FIXME: This is a rat's nest. Cleanup. + if (isa(this)) return (symbol_iterator) (&Data); else if (isa(this)) @@ -39,7 +42,10 @@ RVal::symbol_iterator RVal::symbol_begin() const { const nonlval::LValAsInteger& V = cast(*this); return V.getPersistentLVal().symbol_begin(); } - + else if (isa(this)) { + const lval::FieldOffset& V = cast(*this); + return V.getPersistentBase().symbol_begin(); + } return NULL; } @@ -402,6 +408,13 @@ void LVal::print(std::ostream& Out) const { << "\""; break; + case lval::FieldOffsetKind: { + const lval::FieldOffset& C = *cast(this); + C.getBase().print(Out); + Out << "." << C.getFieldDecl()->getName() << " (field LVal)"; + break; + } + default: assert (false && "Pretty-printing not implemented for this LVal."); break; diff --git a/lib/Analysis/ValueState.cpp b/lib/Analysis/ValueState.cpp index cba0253ea1..e51366d666 100644 --- a/lib/Analysis/ValueState.cpp +++ b/lib/Analysis/ValueState.cpp @@ -212,6 +212,9 @@ RVal ValueStateManager::GetRVal(ValueState* St, LVal LV, QualType T) { return UnknownVal(); } + case lval::FieldOffsetKind: + return UnknownVal(); + case lval::FuncValKind: return LV;