diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRExprEngine.h | 4 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRTransferFuncs.h | 11 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/ValueState.h | 27 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 41 | ||||
-rw-r--r-- | lib/Analysis/GRTransferFuncs.cpp | 15 |
5 files changed, 93 insertions, 5 deletions
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 1bae83b982..752f5cbe8a 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -609,6 +609,10 @@ protected: return TF->EvalBinOp(*this, Op, cast<NonLVal>(L), cast<NonLVal>(R)); } + void EvalBinOp(ExplodedNodeSet<ValueState>& Dst, Expr* E, + BinaryOperator::Opcode Op, + NonLVal L, NonLVal R, ExplodedNode<ValueState>* Pred); + void EvalCall(NodeSet& Dst, CallExpr* CE, RVal L, NodeTy* Pred) { assert (Builder && "GRStmtNodeBuilder must be defined."); TF->EvalCall(Dst, *this, *Builder, CE, L, Pred); diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 4e267f8859..e5fa069c45 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -49,7 +49,16 @@ public: // Binary Operators. virtual RVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op, - NonLVal L, NonLVal R) = 0; + NonLVal L, NonLVal R) { + return UnknownVal(); + } + + virtual void EvalBinOpNN(ExplodedNodeSet<ValueState>& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder<ValueState>& Builder, + BinaryOperator::Opcode Op, Expr* Ex, + NonLVal L, NonLVal R, + ExplodedNode<ValueState>* Pred); 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 ea86dfbf35..1a571f3c29 100644 --- a/include/clang/Analysis/PathSensitive/ValueState.h +++ b/include/clang/Analysis/PathSensitive/ValueState.h @@ -185,6 +185,7 @@ template<> struct GRTrait<ValueState*> { class ValueStateManager { + friend class GRExprEngine; private: EnvironmentManager EnvMgr; @@ -210,6 +211,13 @@ private: /// This vector is persistent because it is reused over and over. StoreManager::DeclRootsTy DRoots; + /// CurrentStmt - The block-level statement currently being visited. This + /// is set by GRExprEngine. + Stmt* CurrentStmt; + + /// cfg - The CFG for the analyzed function/method. + CFG& cfg; + private: Environment RemoveBlkExpr(const Environment& Env, Expr* E) { @@ -223,7 +231,7 @@ private: public: ValueStateManager(ASTContext& Ctx, StoreManager* stmgr, - llvm::BumpPtrAllocator& alloc) + llvm::BumpPtrAllocator& alloc, CFG& c) : EnvMgr(alloc), StMgr(stmgr), ISetFactory(alloc), @@ -231,7 +239,8 @@ public: CEFactory(alloc), BasicVals(Ctx, alloc), SymMgr(alloc), - Alloc(alloc) {} + Alloc(alloc), + cfg(c) {} const ValueState* getInitialState(); @@ -273,6 +282,20 @@ public: NewSt.Env = NewEnv; return getPersistentState(NewSt); } + + const ValueState* SetRVal(const ValueState* St, Expr* Ex, RVal V) { + + bool isBlkExpr = false; + + if (Ex == CurrentStmt) { + isBlkExpr = cfg.isBlkExpr(Ex); + + if (!isBlkExpr) + return St; + } + + return SetRVal(St, Ex, V, isBlkExpr, true); + } // Methods that query & manipulate the Store. diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index fa8009f3ef..e32fd0b331 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -121,7 +121,7 @@ GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, Liveness(L), Builder(NULL), StateMgr(G.getContext(), CreateBasicStoreManager(G.getAllocator()), - G.getAllocator()), + G.getAllocator(), G.getCFG()), BasicVals(StateMgr.getBasicValueFactory()), TF(NULL), // FIXME SymMgr(StateMgr.getSymbolManager()), @@ -242,7 +242,10 @@ void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { Builder = &builder; EntryNode = builder.getLastNode(); + + // FIXME: Consolidate. CurrentStmt = S; + StateMgr.CurrentStmt = S; // Set up our simple checks. if (BatchAuditor) @@ -296,7 +299,11 @@ void GRExprEngine::ProcessStmt(Stmt* S, StmtNodeBuilder& builder) { // NULL out these variables to cleanup. CleanedState = NULL; EntryNode = NULL; - CurrentStmt = NULL; + + // FIXME: Consolidate. + StateMgr.CurrentStmt = 0; + CurrentStmt = 0; + Builder = NULL; } @@ -1802,8 +1809,13 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, } else { nonlval::ConcreteInt X(BasicVals.getValue(0, Ex->getType())); +#if 0 RVal Result = EvalBinOp(BinaryOperator::EQ, cast<NonLVal>(V), X); St = SetRVal(St, U, Result); +#else + EvalBinOp(Dst, U, BinaryOperator::EQ, cast<NonLVal>(V), X, *I); + continue; +#endif } break; @@ -2226,6 +2238,31 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, } //===----------------------------------------------------------------------===// +// Transfer-function Helpers. +//===----------------------------------------------------------------------===// + +void GRExprEngine::EvalBinOp(ExplodedNodeSet<ValueState>& Dst, Expr* Ex, + BinaryOperator::Opcode Op, + NonLVal L, NonLVal R, + ExplodedNode<ValueState>* Pred) { + + 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); + + TF->EvalBinOpNN(Dst, *this, *Builder, Op, Ex, L, R, Pred); + + if (!Builder->BuildSinks && Dst.size() == size && + !Builder->HasGeneratedNode) + MakeNode(Dst, Ex, Pred, GetState(Pred)); +} + +//===----------------------------------------------------------------------===// // "Assume" logic. //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp index a31f8aaa1b..cf32a073c1 100644 --- a/lib/Analysis/GRTransferFuncs.cpp +++ b/lib/Analysis/GRTransferFuncs.cpp @@ -37,3 +37,18 @@ void GRTransferFuncs::EvalStore(ExplodedNodeSet<ValueState>& Dst, Builder.MakeNode(Dst, E, Pred, Eng.getStateManager().SetRVal(St, cast<LVal>(TargetLV), Val)); } + +void GRTransferFuncs::EvalBinOpNN(ExplodedNodeSet<ValueState>& Dst, + GRExprEngine& Engine, + GRStmtNodeBuilder<ValueState>& Builder, + BinaryOperator::Opcode Op, + Expr* Ex, + NonLVal L, NonLVal R, + ExplodedNode<ValueState>* Pred) { + + ValueStateManager& StateMgr = Engine.getStateManager(); + const ValueState* St = Builder.GetState(Pred); + + RVal Result = EvalBinOp(Engine, Op, L, R); + Builder.MakeNode(Dst, Ex, Pred, StateMgr.SetRVal(St, Ex, Result)); +} |