From: Ted Kremenek Date: Fri, 18 Jul 2008 05:53:58 +0000 (+0000) Subject: Created ValueStateSet class to manage the creation of multiple states by a method. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6297a8ec313c722db50f686fd190842b7ea91118;p=clang Created ValueStateSet class to manage the creation of multiple states by a method. Modified the new EvalBinOpNN to generate states instead of nodes. This is a much simpler interface and is what clients will want to do. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53750 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 0102f55cfe..4a04247139 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -67,9 +67,6 @@ protected: /// StateMgr - Object that manages the data for all created states. ValueStateManager StateMgr; - /// ValueMgr - Object that manages the data for all created RVals. - BasicValueFactory& BasicVals; - /// BugTypes - Objects used for reporting bugs. typedef std::vector BugTypeSet; BugTypeSet BugTypes; @@ -375,8 +372,12 @@ public: ValueStateManager& getStateManager() { return StateMgr; } const ValueStateManager& getStateManger() const { return StateMgr; } - BasicValueFactory& getBasicVals() { return BasicVals; } - const BasicValueFactory& getBasicVals() const { return BasicVals; } + BasicValueFactory& getBasicVals() { + return StateMgr.getBasicVals(); + } + const BasicValueFactory& getBasicVals() const { + return StateMgr.getBasicVals(); + } SymbolManager& getSymbolManager() { return SymMgr; } const SymbolManager& getSymbolManager() const { return SymMgr; } @@ -424,7 +425,7 @@ protected: } inline NonLVal MakeConstantVal(uint64_t X, Expr* Ex) { - return NonLVal::MakeVal(BasicVals, X, Ex->getType()); + return NonLVal::MakeVal(getBasicVals(), X, Ex->getType()); } /// Assume - Create new state by assuming that a given expression @@ -545,15 +546,22 @@ protected: RVal EvalComplement(RVal X) { return X.isValid() ? getTF().EvalComplement(*this, cast(X)) : X; } + + RVal EvalBinOp(BinaryOperator::Opcode Op, NonLVal L, NonLVal R) { + return R.isValid() ? getTF().EvalBinOp(getStateManager(), Op, L, R) : R; + } RVal EvalBinOp(BinaryOperator::Opcode Op, NonLVal L, RVal R) { - return R.isValid() ? getTF().EvalBinOp(*this, Op, L, cast(R)) : R; + return R.isValid() ? getTF().EvalBinOp(getStateManager(), Op, L, + cast(R)) : R; } - void EvalBinOp(ExplodedNodeSet& Dst, Expr* E, + void EvalBinOp(ExplodedNodeSet& Dst, Expr* Ex, BinaryOperator::Opcode Op, NonLVal L, NonLVal R, ExplodedNode* Pred); + void EvalBinOp(ValueStateSet& OStates, const ValueState* St, Expr* Ex, + BinaryOperator::Opcode Op, NonLVal L, NonLVal R); RVal EvalBinOp(BinaryOperator::Opcode Op, RVal L, RVal R) { @@ -577,10 +585,12 @@ protected: assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub); // Commute the operands. - return getTF().EvalBinOp(*this, Op, cast(R), cast(L)); + return getTF().EvalBinOp(*this, Op, cast(R), + cast(L)); } else - return getTF().EvalBinOp(*this, Op, cast(L), cast(R)); + return getTF().EvalBinOp(getStateManager(), Op, cast(L), + cast(R)); } diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index b57244ae04..db7de81621 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -48,17 +48,14 @@ public: // Binary Operators. - virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op, + virtual RVal EvalBinOp(ValueStateManager& StateMgr, BinaryOperator::Opcode Op, NonLVal L, NonLVal R) { return UnknownVal(); } - virtual void EvalBinOpNN(ExplodedNodeSet& Dst, - GRExprEngine& Engine, - GRStmtNodeBuilder& Builder, - BinaryOperator::Opcode Op, Expr* Ex, - NonLVal L, NonLVal R, - ExplodedNode* Pred); + virtual void EvalBinOpNN(ValueStateSet& OStates, ValueStateManager& StateMgr, + const ValueState* St, Expr* Ex, + BinaryOperator::Opcode Op, NonLVal L, NonLVal R); virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op, LVal L, LVal R) = 0; diff --git a/include/clang/Analysis/PathSensitive/ValueState.h b/include/clang/Analysis/PathSensitive/ValueState.h index c508d6f4cd..3a56abe81b 100644 --- a/include/clang/Analysis/PathSensitive/ValueState.h +++ b/include/clang/Analysis/PathSensitive/ValueState.h @@ -184,6 +184,38 @@ template<> struct GRTrait { } }; +class ValueStateSet { + typedef llvm::SmallPtrSet ImplTy; + ImplTy Impl; +public: + ValueStateSet() {} + + inline void Add(const ValueState* St) { + Impl.insert(St); + } + + typedef ImplTy::const_iterator iterator; + + inline unsigned size() const { return Impl.size(); } + inline bool empty() const { return Impl.empty(); } + + inline iterator begin() const { return Impl.begin(); } + inline iterator end() const { return Impl.end(); } + + class AutoPopulate { + ValueStateSet& S; + unsigned StartSize; + const ValueState* St; + public: + AutoPopulate(ValueStateSet& s, const ValueState* st) + : S(s), StartSize(S.size()), St(st) {} + + ~AutoPopulate() { + if (StartSize == S.size()) + S.Add(St); + } + }; +}; class ValueStateManager { friend class GRExprEngine; @@ -249,7 +281,8 @@ public: const ValueState* getInitialState(); - BasicValueFactory& getBasicValueFactory() { return BasicVals; } + BasicValueFactory& getBasicVals() { return BasicVals; } + const BasicValueFactory& getBasicVals() const { return BasicVals; } SymbolManager& getSymbolManager() { return SymMgr; } typedef StoreManager::DeadSymbolsTy DeadSymbolsTy; diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index c4278b1e5b..f3caaa5ad3 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -122,7 +122,6 @@ GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, Builder(NULL), StateMgr(G.getContext(), CreateBasicStoreManager(G.getAllocator()), G.getAllocator(), G.getCFG()), - BasicVals(StateMgr.getBasicValueFactory()), SymMgr(StateMgr.getSymbolManager()), CurrentStmt(NULL), NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL), @@ -707,7 +706,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { // This should be easy once we have "ranges" for NonLVals. do { - nonlval::ConcreteInt CaseVal(BasicVals.getValue(V1)); + nonlval::ConcreteInt CaseVal(getBasicVals().getValue(V1)); RVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal); @@ -823,7 +822,7 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst, bool asLVal) { const ValueState* St = GetState(Pred); - RVal X = RVal::MakeVal(BasicVals, D); + RVal X = RVal::MakeVal(getBasicVals(), D); if (asLVal) MakeNode(Dst, D, Pred, SetRVal(St, D, cast(X))); @@ -869,7 +868,7 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A, NodeTy* Pred, if (nonlval::ConcreteInt* IdxInt = dyn_cast(&IdxV)) useBase = IdxInt->getValue() == 0; - RVal V = useBase ? BaseV : lval::ArrayOffset::Make(BasicVals, BaseV,IdxV); + RVal V = useBase ? BaseV : lval::ArrayOffset::Make(getBasicVals(), BaseV,IdxV); if (asLVal) MakeNode(Dst, A, *I2, SetRVal(St, A, V)); @@ -900,7 +899,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, const ValueState* St = GetState(*I); RVal BaseV = GetRVal(St, Base); - RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base), + RVal V = lval::FieldOffset::Make(getBasicVals(), GetRVal(St, Base), M->getMemberDecl()); MakeNode(Dst, M, *I, SetRVal(St, M, V)); @@ -922,7 +921,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, assert (M->isArrow()); - RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base), + RVal V = lval::FieldOffset::Make(getBasicVals(), GetRVal(St, Base), M->getMemberDecl()); EvalLoad(Dst, M, *I, St, V); @@ -1461,7 +1460,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ // equal or exceeds the number of bits to store the pointer value. // If not, flag an error. - V = nonlval::LValAsInteger::Make(BasicVals, cast(V), bits); + V = nonlval::LValAsInteger::Make(getBasicVals(), cast(V), bits); MakeNode(Dst, CastE, N, SetRVal(St, CastE, V)); continue; } @@ -1548,10 +1547,10 @@ void GRExprEngine::VisitDeclStmtAux(DeclStmt* DS, ScopedDecl* D, if (LVal::IsLValType(T)) St = SetRVal(St, lval::DeclVal(VD), - lval::ConcreteInt(BasicVals.getValue(0, T))); + lval::ConcreteInt(getBasicVals().getValue(0, T))); else if (T->isIntegerType()) St = SetRVal(St, lval::DeclVal(VD), - nonlval::ConcreteInt(BasicVals.getValue(0, T))); + nonlval::ConcreteInt(getBasicVals().getValue(0, T))); // FIXME: Handle structs. Now we treat them as unknown. What // we need to do is treat their members as unknown. @@ -1626,7 +1625,7 @@ void GRExprEngine::VisitSizeOfAlignOfTypeExpr(SizeOfAlignOfTypeExpr* Ex, MakeNode(Dst, Ex, Pred, SetRVal(GetState(Pred), Ex, - NonLVal::MakeVal(BasicVals, amt, Ex->getType()))); + NonLVal::MakeVal(getBasicVals(), amt, Ex->getType()))); } @@ -1699,7 +1698,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, // For all other types, UnaryOperator::Float returns 0. assert (Ex->getType()->isIntegerType()); const ValueState* St = GetState(*I); - RVal X = NonLVal::MakeVal(BasicVals, 0, Ex->getType()); + RVal X = NonLVal::MakeVal(getBasicVals(), 0, Ex->getType()); MakeNode(Dst, U, *I, SetRVal(St, U, X)); } @@ -1787,12 +1786,12 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, // transfer functions as "0 == E". if (isa(V)) { - lval::ConcreteInt X(BasicVals.getZeroWithPtrWidth()); + lval::ConcreteInt X(getBasicVals().getZeroWithPtrWidth()); RVal Result = EvalBinOp(BinaryOperator::EQ, cast(V), X); St = SetRVal(St, U, Result); } else { - nonlval::ConcreteInt X(BasicVals.getValue(0, Ex->getType())); + nonlval::ConcreteInt X(getBasicVals().getValue(0, Ex->getType())); #if 0 RVal Result = EvalBinOp(BinaryOperator::EQ, cast(V), X); St = SetRVal(St, U, Result); @@ -1822,7 +1821,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, uint64_t size = getContext().getTypeSize(T) / 8; const ValueState* St = GetState(Pred); - St = SetRVal(St, U, NonLVal::MakeVal(BasicVals, size, U->getType())); + St = SetRVal(St, U, NonLVal::MakeVal(getBasicVals(), size, U->getType())); MakeNode(Dst, U, Pred, St); return; @@ -2229,21 +2228,20 @@ void GRExprEngine::EvalBinOp(ExplodedNodeSet& Dst, Expr* Ex, BinaryOperator::Opcode Op, NonLVal L, NonLVal R, ExplodedNode* Pred) { + + ValueStateSet OStates; + EvalBinOp(OStates, GetState(Pred), Ex, Op, L, R); + + for (ValueStateSet::iterator I=OStates.begin(), E=OStates.end(); I!=E; ++I) + MakeNode(Dst, Ex, Pred, *I); +} + +void GRExprEngine::EvalBinOp(ValueStateSet& OStates, const ValueState* St, + Expr* Ex, BinaryOperator::Opcode Op, + NonLVal L, NonLVal R) { - if (!R.isValid()) { - MakeNode(Dst, Ex, Pred, SetRVal(GetState(Pred), Ex, R)); - return; - } - - assert (Builder && "GRStmtNodeBuilder must be defined."); - unsigned size = Dst.size(); - SaveOr OldHasGen(Builder->HasGeneratedNode); - - getTF().EvalBinOpNN(Dst, *this, *Builder, Op, Ex, L, R, Pred); - - if (!Builder->BuildSinks && Dst.size() == size && - !Builder->HasGeneratedNode) - MakeNode(Dst, Ex, Pred, GetState(Pred)); + ValueStateSet::AutoPopulate AP(OStates, St); + if (R.isValid()) getTF().EvalBinOpNN(OStates, StateMgr, St, Ex, Op, L, R); } //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index e3ba0f3c4a..f95ccb564f 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -450,10 +450,10 @@ RVal GRSimpleVals::EvalComplement(GRExprEngine& Eng, NonLVal X) { // Binary operators. -RVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op, - NonLVal L, NonLVal R) { +RVal GRSimpleVals::EvalBinOp(ValueStateManager& StateMgr, + BinaryOperator::Opcode Op, NonLVal L, NonLVal R) { - BasicValueFactory& BasicVals = Eng.getBasicVals(); + BasicValueFactory& BasicVals = StateMgr.getBasicVals(); while (1) { diff --git a/lib/Analysis/GRSimpleVals.h b/lib/Analysis/GRSimpleVals.h index d86db51511..fc20c3e5bc 100644 --- a/lib/Analysis/GRSimpleVals.h +++ b/lib/Analysis/GRSimpleVals.h @@ -44,7 +44,7 @@ public: // Binary Operators. - virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op, + virtual RVal EvalBinOp(ValueStateManager& StateMgr, BinaryOperator::Opcode Op, NonLVal L, NonLVal R); virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op, diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp index cf32a073c1..9d9c97f0ed 100644 --- a/lib/Analysis/GRTransferFuncs.cpp +++ b/lib/Analysis/GRTransferFuncs.cpp @@ -38,17 +38,11 @@ void GRTransferFuncs::EvalStore(ExplodedNodeSet& Dst, Eng.getStateManager().SetRVal(St, cast(TargetLV), Val)); } -void GRTransferFuncs::EvalBinOpNN(ExplodedNodeSet& Dst, - GRExprEngine& Engine, - GRStmtNodeBuilder& Builder, +void GRTransferFuncs::EvalBinOpNN(ValueStateSet& OStates, + ValueStateManager& StateMgr, + const ValueState *St, Expr* Ex, BinaryOperator::Opcode Op, - Expr* Ex, - NonLVal L, NonLVal R, - ExplodedNode* Pred) { - - ValueStateManager& StateMgr = Engine.getStateManager(); - const ValueState* St = Builder.GetState(Pred); + NonLVal L, NonLVal R) { - RVal Result = EvalBinOp(Engine, Op, L, R); - Builder.MakeNode(Dst, Ex, Pred, StateMgr.SetRVal(St, Ex, Result)); + OStates.Add(StateMgr.SetRVal(St, Ex, EvalBinOp(StateMgr, Op, L, R))); }