From: Ted Kremenek Date: Thu, 10 Jul 2008 22:03:41 +0000 (+0000) Subject: Refactored most of the "Store" piece of ValueState into a Store type. The X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4323a57627e796dcfdfdb7d47672dc09ed308eda;p=clang Refactored most of the "Store" piece of ValueState into a Store type. The current store implementation is now encapsulated by BasicStore. These changes prompted some long due constification of ValueState. Much of the diffs in this patch include adding "const" qualifiers. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@53423 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/BasicStore.h b/include/clang/Analysis/PathSensitive/BasicStore.h new file mode 100644 index 0000000000..88ac9ce381 --- /dev/null +++ b/include/clang/Analysis/PathSensitive/BasicStore.h @@ -0,0 +1,27 @@ +//== BasicStore.h - Basic map from Locations to Values ----------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the BasicStore and BasicStoreManager classes. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_BASICSTORE_H +#define LLVM_CLANG_ANALYSIS_BASICSTORE_H + +#include "clang/Analysis/PathSensitive/Store.h" + +namespace llvm { + class llvm::BumpPtrAllocator; +} + +namespace clang { + StoreManager* CreateBasicStoreManager(llvm::BumpPtrAllocator& Alloc); +} + +#endif diff --git a/include/clang/Analysis/PathSensitive/ExplodedGraph.h b/include/clang/Analysis/PathSensitive/ExplodedGraph.h index 39a064d4c6..71043f0ef6 100644 --- a/include/clang/Analysis/PathSensitive/ExplodedGraph.h +++ b/include/clang/Analysis/PathSensitive/ExplodedGraph.h @@ -95,10 +95,8 @@ protected: /// with this node. const ProgramPoint Location; - /// State - The state associated with this node. Normally this value - /// is immutable, but we anticipate there will be times when algorithms - /// that directly manipulate the analysis graph will need to change it. - void* State; + /// State - The state associated with this node. + const void* State; /// Preds - The predecessors of this node. NodeGroup Preds; @@ -107,7 +105,7 @@ protected: NodeGroup Succs; /// Construct a ExplodedNodeImpl with the provided location and state. - explicit ExplodedNodeImpl(const ProgramPoint& loc, void* state) + explicit ExplodedNodeImpl(const ProgramPoint& loc, const void* state) : Location(loc), State(state) {} /// addPredeccessor - Adds a predecessor to the current node, and @@ -146,19 +144,19 @@ class ExplodedNode : public ExplodedNodeImpl { public: /// Construct a ExplodedNodeImpl with the given node ID, program edge, /// and state. - explicit ExplodedNode(const ProgramPoint& loc, StateTy* St) + explicit ExplodedNode(const ProgramPoint& loc, const StateTy* St) : ExplodedNodeImpl(loc, St) {} /// getState - Returns the state associated with the node. - inline StateTy* getState() const { - return static_cast(State); + inline const StateTy* getState() const { + return static_cast(State); } // Profiling (for FoldingSet). static inline void Profile(llvm::FoldingSetNodeID& ID, const ProgramPoint& Loc, - StateTy* state) { + const StateTy* state) { ID.Add(Loc); GRTrait::Profile(ID, state); } @@ -241,7 +239,8 @@ protected: /// getNodeImpl - Retrieve the node associated with a (Location,State) /// pair, where 'State' is represented as an opaque void*. This method /// is intended to be used only by GRCoreEngineImpl. - virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L, void* State, + virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L, + const void* State, bool* IsNew) = 0; virtual ExplodedGraphImpl* MakeEmptyGraph() const = 0; @@ -300,9 +299,10 @@ protected: protected: virtual ExplodedNodeImpl* getNodeImpl(const ProgramPoint& L, - void* State, bool* IsNew) { + const void* State, + bool* IsNew) { - return getNode(L, static_cast(State), IsNew); + return getNode(L, static_cast(State), IsNew); } virtual ExplodedGraphImpl* MakeEmptyGraph() const { @@ -317,7 +317,8 @@ public: /// where the 'Location' is a ProgramPoint in the CFG. If no node for /// this pair exists, it is created. IsNew is set to true if /// the node was freshly created. - NodeTy* getNode(const ProgramPoint& L, StateTy* State, bool* IsNew = NULL) { + NodeTy* getNode(const ProgramPoint& L, const StateTy* State, + bool* IsNew = NULL) { // Profile 'State' to determine if we already have an existing node. llvm::FoldingSetNodeID profile; diff --git a/include/clang/Analysis/PathSensitive/GRCoreEngine.h b/include/clang/Analysis/PathSensitive/GRCoreEngine.h index 19028ee875..32fe9d3342 100644 --- a/include/clang/Analysis/PathSensitive/GRCoreEngine.h +++ b/include/clang/Analysis/PathSensitive/GRCoreEngine.h @@ -61,14 +61,14 @@ protected: /// number of times different CFGBlocks have been visited along a path. GRBlockCounter::Factory BCounterFactory; - void GenerateNode(const ProgramPoint& Loc, void* State, + void GenerateNode(const ProgramPoint& Loc, const void* State, ExplodedNodeImpl* Pred = NULL); /// getInitialState - Gets the void* representing the initial 'state' /// of the analysis. This is simply a wrapper (implemented /// in GRCoreEngine) that performs type erasure on the initial /// state returned by the checker object. - virtual void* getInitialState() = 0; + virtual const void* getInitialState() = 0; void HandleBlockEdge(const BlockEdge& E, ExplodedNodeImpl* Pred); void HandleBlockEntrance(const BlockEntrance& E, ExplodedNodeImpl* Pred); @@ -81,7 +81,7 @@ protected: virtual void ProcessEndPath(GREndPathNodeBuilderImpl& Builder) = 0; - virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State, + virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State, GRBlockCounter BC) = 0; virtual void ProcessStmt(Stmt* S, GRStmtNodeBuilderImpl& Builder) = 0; @@ -142,11 +142,11 @@ public: } ExplodedNodeImpl* - generateNodeImpl(Stmt* S, void* State, ExplodedNodeImpl* Pred, + generateNodeImpl(Stmt* S, const void* State, ExplodedNodeImpl* Pred, ProgramPoint::Kind K = ProgramPoint::PostStmtKind); ExplodedNodeImpl* - generateNodeImpl(Stmt* S, void* State, + generateNodeImpl(Stmt* S, const void* State, ProgramPoint::Kind K = ProgramPoint::PostStmtKind) { ExplodedNodeImpl* N = getLastNode(); assert (N && "Predecessor of new node is infeasible."); @@ -169,7 +169,7 @@ class GRStmtNodeBuilder { typedef ExplodedNode NodeTy; GRStmtNodeBuilderImpl& NB; - StateTy* CleanedState; + const StateTy* CleanedState; GRAuditor **CallExprAuditBeg, **CallExprAuditEnd; GRAuditor **ObjCMsgExprAuditBeg, **ObjCMsgExprAuditEnd; @@ -201,7 +201,7 @@ public: } NodeTy* - generateNode(Stmt* S, StateTy* St, NodeTy* Pred, + generateNode(Stmt* S, const StateTy* St, NodeTy* Pred, ProgramPoint::Kind K = ProgramPoint::PostStmtKind) { HasGeneratedNode = true; @@ -210,7 +210,7 @@ public: } NodeTy* - generateNode(Stmt* S, StateTy* St, + generateNode(Stmt* S, const StateTy* St, ProgramPoint::Kind K = ProgramPoint::PostStmtKind) { HasGeneratedNode = true; @@ -226,21 +226,21 @@ public: return NB.getCurrentBlockCount(); } - StateTy* GetState(NodeTy* Pred) const { + const StateTy* GetState(NodeTy* Pred) const { if ((ExplodedNodeImpl*) Pred == NB.getBasePredecessor()) return CleanedState; else return Pred->getState(); } - void SetCleanedState(StateTy* St) { + void SetCleanedState(const StateTy* St) { CleanedState = St; } NodeTy* MakeNode(ExplodedNodeSet& Dst, Stmt* S, - NodeTy* Pred, StateTy* St) { + NodeTy* Pred, const StateTy* St) { - StateTy* PredState = GetState(Pred); + const StateTy* PredState = GetState(Pred); GRAuditor **AB = NULL, **AE = NULL; @@ -309,7 +309,7 @@ public: const ExplodedGraphImpl& getGraph() const { return *Eng.G; } GRBlockCounter getBlockCounter() const { return Eng.WList->getBlockCounter();} - ExplodedNodeImpl* generateNodeImpl(void* State, bool branch); + ExplodedNodeImpl* generateNodeImpl(const void* State, bool branch); CFGBlock* getTargetBlock(bool branch) const { return branch ? DstT : DstF; @@ -340,11 +340,11 @@ public: return static_cast(NB.getPredecessor()); } - StateTy* getState() const { + const StateTy* getState() const { return getPredecessor()->getState(); } - NodeTy* generateNode(StateTy* St, bool branch) { + NodeTy* generateNode(const StateTy* St, bool branch) { return static_cast(NB.generateNodeImpl(St, branch)); } @@ -396,11 +396,11 @@ public: Iterator begin() { return Iterator(DispatchBlock.succ_begin()); } Iterator end() { return Iterator(DispatchBlock.succ_end()); } - ExplodedNodeImpl* generateNodeImpl(const Iterator& I, void* State, + ExplodedNodeImpl* generateNodeImpl(const Iterator& I, const void* State, bool isSink); Expr* getTarget() const { return E; } - void* getState() const { return Pred->State; } + const void* getState() const { return Pred->State; } }; template @@ -421,12 +421,12 @@ public: Expr* getTarget() const { return NB.getTarget(); } - NodeTy* generateNode(const iterator& I, StateTy* St, bool isSink=false){ + NodeTy* generateNode(const iterator& I, const StateTy* St, bool isSink=false){ return static_cast(NB.generateNodeImpl(I, St, isSink)); } - StateTy* getState() const { - return static_cast(NB.getState()); + const StateTy* getState() const { + return static_cast(NB.getState()); } }; @@ -462,11 +462,14 @@ public: Iterator begin() { return Iterator(Src->succ_rbegin()+1); } Iterator end() { return Iterator(Src->succ_rend()); } - ExplodedNodeImpl* generateCaseStmtNodeImpl(const Iterator& I, void* State); - ExplodedNodeImpl* generateDefaultCaseNodeImpl(void* State, bool isSink); + ExplodedNodeImpl* generateCaseStmtNodeImpl(const Iterator& I, + const void* State); + + ExplodedNodeImpl* generateDefaultCaseNodeImpl(const void* State, + bool isSink); Expr* getCondition() const { return Condition; } - void* getState() const { return Pred->State; } + const void* getState() const { return Pred->State; } }; template @@ -487,16 +490,16 @@ public: Expr* getCondition() const { return NB.getCondition(); } - NodeTy* generateCaseStmtNode(const iterator& I, StateTy* St) { + NodeTy* generateCaseStmtNode(const iterator& I, const StateTy* St) { return static_cast(NB.generateCaseStmtNodeImpl(I, St)); } - NodeTy* generateDefaultCaseNode(StateTy* St, bool isSink = false) { + NodeTy* generateDefaultCaseNode(const StateTy* St, bool isSink = false) { return static_cast(NB.generateDefaultCaseNodeImpl(St, isSink)); } - StateTy* getState() const { - return static_cast(NB.getState()); + const StateTy* getState() const { + return static_cast(NB.getState()); } }; @@ -522,7 +525,7 @@ public: return getBlockCounter().getNumVisited(B.getBlockID()); } - ExplodedNodeImpl* generateNodeImpl(void* State); + ExplodedNodeImpl* generateNodeImpl(const void* State); CFGBlock* getBlock() const { return &B; } }; @@ -550,11 +553,11 @@ public: return NB.getCurrentBlockCount(); } - StateTy* getState() const { + const StateTy* getState() const { return getPredecessor()->getState(); } - NodeTy* MakeNode(StateTy* St) { + NodeTy* MakeNode(const StateTy* St) { return static_cast(NB.generateNodeImpl(St)); } }; @@ -571,7 +574,7 @@ public: protected: SubEngineTy& SubEngine; - virtual void* getInitialState() { + virtual const void* getInitialState() { return SubEngine.getInitialState(); } @@ -585,9 +588,11 @@ protected: SubEngine.ProcessStmt(S, Builder); } - virtual bool ProcessBlockEntrance(CFGBlock* Blk, void* State, + virtual bool ProcessBlockEntrance(CFGBlock* Blk, const void* State, GRBlockCounter BC) { - return SubEngine.ProcessBlockEntrance(Blk, static_cast(State),BC); + return SubEngine.ProcessBlockEntrance(Blk, + static_cast(State), + BC); } virtual void ProcessBranch(Expr* Condition, Stmt* Terminator, diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index 6dfd428bf4..97699ca902 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -86,7 +86,7 @@ protected: /// CleanedState - The state for EntryNode "cleaned" of all dead /// variables and symbols (as determined by a liveness analysis). - ValueState* CleanedState; + const ValueState* CleanedState; /// CurrentStmt - The current block-level statement. Stmt* CurrentStmt; @@ -210,7 +210,7 @@ public: /// getInitialState - Return the initial state used for the root vertex /// in the ExplodedGraph. - ValueState* getInitialState(); + const ValueState* getInitialState(); GraphTy& getGraph() { return G; } const GraphTy& getGraph() const { return G; } @@ -370,7 +370,8 @@ public: /// ProcessBlockEntrance - Called by GRCoreEngine when start processing /// a CFGBlock. This method returns true if the analysis should continue /// exploring the given path, and false otherwise. - bool ProcessBlockEntrance(CFGBlock* B, ValueState* St, GRBlockCounter BC); + bool ProcessBlockEntrance(CFGBlock* B, const ValueState* St, + GRBlockCounter BC); /// ProcessBranch - Called by GRCoreEngine. Used to generate successor /// nodes by processing the 'effects' of a branch condition. @@ -401,7 +402,7 @@ public: protected: - ValueState* GetState(NodeTy* N) { + const ValueState* GetState(NodeTy* N) { return N == EntryNode ? CleanedState : N->getState(); } @@ -409,35 +410,35 @@ public: // FIXME: Maybe make these accesible only within the StmtBuilder? - ValueState* SetRVal(ValueState* St, Expr* Ex, RVal V); + const ValueState* SetRVal(const ValueState* St, Expr* Ex, RVal V); - ValueState* SetRVal(ValueState* St, const Expr* Ex, RVal V) { + const ValueState* SetRVal(const ValueState* St, const Expr* Ex, RVal V) { return SetRVal(St, const_cast(Ex), V); } protected: - ValueState* SetBlkExprRVal(ValueState* St, Expr* Ex, RVal V) { + const ValueState* SetBlkExprRVal(const ValueState* St, Expr* Ex, RVal V) { return StateMgr.SetRVal(St, Ex, V, true, false); } - ValueState* SetRVal(ValueState* St, LVal LV, RVal V) { + const ValueState* SetRVal(const ValueState* St, LVal LV, RVal V) { return StateMgr.SetRVal(St, LV, V); } - RVal GetRVal(ValueState* St, Expr* Ex) { + RVal GetRVal(const ValueState* St, Expr* Ex) { return StateMgr.GetRVal(St, Ex); } - RVal GetRVal(ValueState* St, const Expr* Ex) { + RVal GetRVal(const ValueState* St, const Expr* Ex) { return GetRVal(St, const_cast(Ex)); } - RVal GetBlkExprRVal(ValueState* St, Expr* Ex) { + RVal GetBlkExprRVal(const ValueState* St, Expr* Ex) { return StateMgr.GetBlkExprRVal(St, Ex); } - RVal GetRVal(ValueState* St, LVal LV, QualType T = QualType()) { + RVal GetRVal(const ValueState* St, LVal LV, QualType T = QualType()) { return StateMgr.GetRVal(St, LV, T); } @@ -447,8 +448,8 @@ protected: /// Assume - Create new state by assuming that a given expression /// is true or false. - ValueState* Assume(ValueState* St, RVal Cond, bool Assumption, - bool& isFeasible) { + const ValueState* Assume(const ValueState* St, RVal Cond, bool Assumption, + bool& isFeasible) { if (Cond.isUnknown()) { isFeasible = true; @@ -461,28 +462,28 @@ protected: return Assume(St, cast(Cond), Assumption, isFeasible); } - ValueState* Assume(ValueState* St, LVal Cond, bool Assumption, - bool& isFeasible); + const ValueState* Assume(const ValueState* St, LVal Cond, bool Assumption, + bool& isFeasible); - ValueState* AssumeAux(ValueState* St, LVal Cond, bool Assumption, - bool& isFeasible); + const ValueState* AssumeAux(const ValueState* St, LVal Cond, bool Assumption, + bool& isFeasible); - ValueState* Assume(ValueState* St, NonLVal Cond, bool Assumption, - bool& isFeasible); + const ValueState* Assume(const ValueState* St, NonLVal Cond, bool Assumption, + bool& isFeasible); - ValueState* AssumeAux(ValueState* St, NonLVal Cond, bool Assumption, - bool& isFeasible); + const ValueState* AssumeAux(const ValueState* St, NonLVal Cond, + bool Assumption, bool& isFeasible); - ValueState* AssumeSymNE(ValueState* St, SymbolID sym, const llvm::APSInt& V, - bool& isFeasible); + const ValueState* AssumeSymNE(const ValueState* St, SymbolID sym, + const llvm::APSInt& V, bool& isFeasible); - ValueState* AssumeSymEQ(ValueState* St, SymbolID sym, const llvm::APSInt& V, - bool& isFeasible); + const ValueState* AssumeSymEQ(const ValueState* St, SymbolID sym, + const llvm::APSInt& V, bool& isFeasible); - ValueState* AssumeSymInt(ValueState* St, bool Assumption, - const SymIntConstraint& C, bool& isFeasible); + const ValueState* AssumeSymInt(const ValueState* St, bool Assumption, + const SymIntConstraint& C, bool& isFeasible); - NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, ValueState* St) { + NodeTy* MakeNode(NodeSet& Dst, Stmt* S, NodeTy* Pred, const ValueState* St) { assert (Builder && "GRStmtNodeBuilder not present."); return Builder->MakeNode(Dst, S, Pred, St); } @@ -568,7 +569,8 @@ protected: void VisitUnaryOperator(UnaryOperator* B, NodeTy* Pred, NodeSet& Dst, bool asLVal); - bool CheckDivideZero(Expr* Ex, ValueState* St, NodeTy* Pred, RVal Denom); + bool CheckDivideZero(Expr* Ex, const ValueState* St, NodeTy* Pred, + RVal Denom); RVal EvalCast(RVal X, QualType CastT) { if (X.isUnknownOrUndef()) @@ -634,21 +636,22 @@ protected: TF->EvalObjCMessageExpr(Dst, *this, *Builder, ME, Pred); } - void EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred, ValueState* St, + void EvalStore(NodeSet& Dst, Expr* E, NodeTy* Pred, const ValueState* St, RVal TargetLV, RVal Val); // FIXME: The "CheckOnly" option exists only because Array and Field // loads aren't fully implemented. Eventually this option will go away. void EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred, - ValueState* St, RVal location, bool CheckOnly = false); + const ValueState* St, RVal location, bool CheckOnly = false); - ValueState* EvalLocation(Expr* Ex, NodeTy* Pred, - ValueState* St, RVal location, bool isLoad = false); + const ValueState* EvalLocation(Expr* Ex, NodeTy* Pred, + const ValueState* St, RVal location, + bool isLoad = false); void EvalReturn(NodeSet& Dst, ReturnStmt* s, NodeTy* Pred); - ValueState* MarkBranch(ValueState* St, Stmt* Terminator, bool branchTaken); + const ValueState* MarkBranch(const ValueState* St, Stmt* Terminator, bool branchTaken); }; } // end clang namespace diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index 323358e0c3..4e267f8859 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -82,7 +82,7 @@ public: GRExprEngine& Engine, GRStmtNodeBuilder& Builder, Expr* E, ExplodedNode* Pred, - ValueState* St, RVal TargetLV, RVal Val); + const ValueState* St, RVal TargetLV, RVal Val); // End-of-path and dead symbol notification. @@ -96,7 +96,7 @@ public: GRStmtNodeBuilder& Builder, ExplodedNode* Pred, Stmt* S, - ValueState* St, + const ValueState* St, const ValueStateManager::DeadSymbolsTy& Dead) {} // Return statements. @@ -109,8 +109,10 @@ public: // Assumptions. - virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St, - RVal Cond, bool Assumption, bool& isFeasible) { + virtual const ValueState* EvalAssume(GRExprEngine& Engine, + const ValueState* St, + RVal Cond, bool Assumption, + bool& isFeasible) { return St; } }; diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h new file mode 100644 index 0000000000..adf9cf8eae --- /dev/null +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -0,0 +1,34 @@ +//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the types Store and StoreManager. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_STORE_H +#define LLVM_CLANG_ANALYSIS_STORE_H + +#include "clang/Analysis/PathSensitive/RValues.h" + +namespace clang { + +typedef const void* Store; + +class StoreManager { +public: + virtual ~StoreManager() {} + virtual RVal GetRVal(Store St, LVal LV, QualType T) = 0; + virtual Store SetRVal(Store St, LVal LV, RVal V) = 0; + virtual Store Remove(Store St, LVal LV) = 0; + virtual Store getInitialStore() = 0; +}; + +} // end clang namespace + +#endif diff --git a/include/clang/Analysis/PathSensitive/ValueState.h b/include/clang/Analysis/PathSensitive/ValueState.h index ab9b4a8b32..36bfdff5b9 100644 --- a/include/clang/Analysis/PathSensitive/ValueState.h +++ b/include/clang/Analysis/PathSensitive/ValueState.h @@ -17,6 +17,7 @@ // FIXME: Reduce the number of includes. #include "clang/Analysis/PathSensitive/Environment.h" +#include "clang/Analysis/PathSensitive/Store.h" #include "clang/Analysis/PathSensitive/RValues.h" #include "clang/Analysis/PathSensitive/GRCoreEngine.h" #include "clang/AST/Expr.h" @@ -54,7 +55,6 @@ class ValueState : public llvm::FoldingSetNode { public: // Typedefs. typedef llvm::ImmutableSet IntSetTy; - typedef llvm::ImmutableMap VarBindingsTy; typedef llvm::ImmutableMap ConstNotEqTy; typedef llvm::ImmutableMap ConstEqTy; @@ -64,10 +64,10 @@ private: friend class ValueStateManager; Environment Env; + Store St; // FIXME: Make these private. public: - VarBindingsTy VarBindings; ConstNotEqTy ConstNotEq; ConstEqTy ConstEq; void* CheckerState; @@ -75,10 +75,10 @@ public: public: /// This ctor is used when creating the first ValueState object. - ValueState(const Environment& env, VarBindingsTy VB, + ValueState(const Environment& env, Store st, ConstNotEqTy CNE, ConstEqTy CE) : Env(env), - VarBindings(VB), + St(st), ConstNotEq(CNE), ConstEq(CE), CheckerState(NULL) {} @@ -88,7 +88,7 @@ public: ValueState(const ValueState& RHS) : llvm::FoldingSetNode(), Env(RHS.Env), - VarBindings(RHS.VarBindings), + St(RHS.St), ConstNotEq(RHS.ConstNotEq), ConstEq(RHS.ConstEq), CheckerState(RHS.CheckerState) {} @@ -97,11 +97,15 @@ public: /// The environment is the mapping from expressions to values. const Environment& getEnvironment() const { return Env; } + /// getStore - Return the store associated with this state. The store + /// is a mapping from locations to values. + Store getStore() const { return St; } + /// Profile - Profile the contents of a ValueState object for use /// in a FoldingSet. static void Profile(llvm::FoldingSetNodeID& ID, const ValueState* V) { V->Env.Profile(ID); - V->VarBindings.Profile(ID); + ID.AddPointer(V->St); V->ConstNotEq.Profile(ID); V->ConstEq.Profile(ID); ID.AddPointer(V->CheckerState); @@ -124,9 +128,18 @@ public: // Iterators. + // FIXME: We'll be removing the VarBindings iterator very soon. Right now + // it assumes that Store is a VarBindingsTy. + typedef llvm::ImmutableMap VarBindingsTy; typedef VarBindingsTy::iterator vb_iterator; - vb_iterator vb_begin() const { return VarBindings.begin(); } - vb_iterator vb_end() const { return VarBindings.end(); } + vb_iterator vb_begin() const { + VarBindingsTy B(static_cast(St)); + return B.begin(); + } + vb_iterator vb_end() const { + VarBindingsTy B(static_cast(St)); + return B.end(); + } typedef Environment::seb_iterator seb_iterator; seb_iterator seb_begin() const { return Env.seb_begin(); } @@ -173,8 +186,8 @@ template<> struct GRTrait { class ValueStateManager { private: EnvironmentManager EnvMgr; + llvm::OwningPtr StMgr; ValueState::IntSetTy::Factory ISetFactory; - ValueState::VarBindingsTy::Factory VBFactory; ValueState::ConstNotEqTy::Factory CNEFactory; ValueState::ConstEqTy::Factory CEFactory; @@ -196,58 +209,53 @@ private: Environment RemoveBlkExpr(const Environment& Env, Expr* E) { return EnvMgr.RemoveBlkExpr(Env, E); } - - ValueState::VarBindingsTy Remove(ValueState::VarBindingsTy B, VarDecl* V) { - return VBFactory.Remove(B, V); - } - - ValueState::VarBindingsTy Remove(const ValueState& V, VarDecl* D) { - return Remove(V.VarBindings, D); + + // FIXME: Remove when we do lazy initializaton of variable bindings. + const ValueState* BindVar(const ValueState* St, VarDecl* D, RVal V) { + return SetRVal(St, lval::DeclVal(D), V); } - - ValueState* BindVar(ValueState* St, VarDecl* D, RVal V); - ValueState* UnbindVar(ValueState* St, VarDecl* D); - + public: - ValueStateManager(ASTContext& Ctx, llvm::BumpPtrAllocator& alloc) - : EnvMgr(alloc), - ISetFactory(alloc), - VBFactory(alloc), - CNEFactory(alloc), - CEFactory(alloc), - BasicVals(Ctx, alloc), - SymMgr(alloc), - Alloc(alloc) {} - - ValueState* getInitialState(); + ValueStateManager(ASTContext& Ctx, StoreManager* stmgr, + llvm::BumpPtrAllocator& alloc) + : EnvMgr(alloc), + StMgr(stmgr), + ISetFactory(alloc), + CNEFactory(alloc), + CEFactory(alloc), + BasicVals(Ctx, alloc), + SymMgr(alloc), + Alloc(alloc) {} + + const ValueState* getInitialState(); BasicValueFactory& getBasicValueFactory() { return BasicVals; } SymbolManager& getSymbolManager() { return SymMgr; } typedef llvm::DenseSet DeadSymbolsTy; - ValueState* RemoveDeadBindings(ValueState* St, Stmt* Loc, - const LiveVariables& Liveness, - DeadSymbolsTy& DeadSymbols); + const ValueState* RemoveDeadBindings(const ValueState* St, Stmt* Loc, + const LiveVariables& Liveness, + DeadSymbolsTy& DeadSymbols); - ValueState* RemoveSubExprBindings(ValueState* St) { + const ValueState* RemoveSubExprBindings(const ValueState* St) { ValueState NewSt = *St; NewSt.Env = EnvMgr.RemoveSubExprBindings(NewSt.Env); - return getPersistentState(NewSt); + return getPersistentState(NewSt); } // Methods that query & manipulate the Environment. - RVal GetRVal(ValueState* St, Expr* Ex) { + RVal GetRVal(const ValueState* St, Expr* Ex) { return St->getEnvironment().GetRVal(Ex, BasicVals); } - RVal GetBlkExprRVal(ValueState* St, Expr* Ex) { + RVal GetBlkExprRVal(const ValueState* St, Expr* Ex) { return St->getEnvironment().GetBlkExprRVal(Ex, BasicVals); } - ValueState* SetRVal(ValueState* St, Expr* Ex, RVal V, bool isBlkExpr, - bool Invalidate) { + const ValueState* SetRVal(const ValueState* St, Expr* Ex, RVal V, + bool isBlkExpr, bool Invalidate) { const Environment& OldEnv = St->getEnvironment(); Environment NewEnv = EnvMgr.SetRVal(OldEnv, Ex, V, isBlkExpr, Invalidate); @@ -262,18 +270,29 @@ public: // Methods that query & manipulate the Store. - RVal GetRVal(ValueState* St, LVal LV, QualType T = QualType()); + RVal GetRVal(const ValueState* St, LVal LV, QualType T = QualType()) { + return StMgr->GetRVal(St->getStore(), LV, T); + } - ValueState* SetRVal(ValueState* St, LVal LV, RVal V); + void SetRVal(ValueState& St, LVal LV, RVal V) { + St.St = StMgr->SetRVal(St.St, LV, V); + } + + const ValueState* SetRVal(const ValueState* St, LVal LV, RVal V); - void BindVar(ValueState& StImpl, VarDecl* D, RVal V); + void Unbind(ValueState& St, LVal LV) { + St.St = StMgr->Remove(St.St, LV); + } - void Unbind(ValueState& StImpl, LVal LV); + const ValueState* Unbind(const ValueState* St, LVal LV); - ValueState* getPersistentState(ValueState& Impl); + const ValueState* getPersistentState(ValueState& Impl); - ValueState* AddEQ(ValueState* St, SymbolID sym, const llvm::APSInt& V); - ValueState* AddNE(ValueState* St, SymbolID sym, const llvm::APSInt& V); + const ValueState* AddEQ(const ValueState* St, SymbolID sym, + const llvm::APSInt& V); + + const ValueState* AddNE(const ValueState* St, SymbolID sym, + const llvm::APSInt& V); }; } // end clang namespace diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp index 1667a21494..4475ed2bc5 100644 --- a/lib/Analysis/BasicObjCFoundationChecks.cpp +++ b/lib/Analysis/BasicObjCFoundationChecks.cpp @@ -107,7 +107,7 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck { typedef std::vector ErrorsTy; ErrorsTy Errors; - RVal GetRVal(ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); } + RVal GetRVal(const ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); } bool isNSString(ObjCInterfaceType* T, const char* suffix); bool AuditNSString(NodeTy* N, ObjCMessageExpr* ME); @@ -338,8 +338,8 @@ class VISIBILITY_HIDDEN AuditCFNumberCreate : public GRSimpleAPICheck { IdentifierInfo* II; ValueStateManager* VMgr; - RVal GetRVal(ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); } - RVal GetRVal(ValueState* St, LVal LV) { return VMgr->GetRVal(St, LV); } + RVal GetRVal(const ValueState* St, Expr* E) { return VMgr->GetRVal(St, E); } + RVal GetRVal(const ValueState* St, LVal LV) { return VMgr->GetRVal(St, LV); } public: diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp new file mode 100644 index 0000000000..38c1db70f1 --- /dev/null +++ b/lib/Analysis/BasicStore.cpp @@ -0,0 +1,141 @@ +//== BasicStore.cpp - Basic map from Locations to Values --------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defined the BasicStore and BasicStoreManager classes. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/PathSensitive/BasicStore.h" +#include "llvm/ADT/ImmutableMap.h" +#include "llvm/Support/Compiler.h" + +using namespace clang; + +namespace { + +class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager { + typedef llvm::ImmutableMap VarBindingsTy; + VarBindingsTy::Factory VBFactory; + +public: + BasicStoreManager(llvm::BumpPtrAllocator& A) : VBFactory(A) {} + virtual ~BasicStoreManager() {} + + virtual RVal GetRVal(Store St, LVal LV, QualType T); + virtual Store SetRVal(Store St, LVal LV, RVal V); + virtual Store Remove(Store St, LVal LV); + + virtual Store getInitialStore() { + return VBFactory.GetEmptyMap().getRoot(); + } +}; + +} // end anonymous namespace + + +StoreManager* clang::CreateBasicStoreManager(llvm::BumpPtrAllocator& A) { + return new BasicStoreManager(A); +} + +RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) { + + if (isa(LV)) + return UnknownVal(); + + assert (!isa(LV)); + + switch (LV.getSubKind()) { + + case lval::DeclValKind: { + VarBindingsTy B(static_cast(St)); + VarBindingsTy::data_type* T = B.lookup(cast(LV).getDecl()); + return T ? *T : UnknownVal(); + } + + case lval::SymbolValKind: { + + // FIXME: This is a broken representation of memory, and is prone + // to crashing the analyzer when addresses to symbolic values are + // passed through casts. We need a better representation of symbolic + // memory (or just memory in general); probably we should do this + // as a plugin class (similar to GRTransferFuncs). + +#if 0 + const lval::SymbolVal& SV = cast(LV); + assert (T.getTypePtr()); + + // Punt on "symbolic" function pointers. + if (T->isFunctionType()) + return UnknownVal(); + + if (T->isPointerType()) + return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol())); + else + return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol())); +#endif + + return UnknownVal(); + } + + case lval::ConcreteIntKind: + // Some clients may call GetRVal with such an option simply because + // they are doing a quick scan through their LVals (potentially to + // invalidate their bindings). Just return Undefined. + return UndefinedVal(); + + case lval::ArrayOffsetKind: + case lval::FieldOffsetKind: + return UnknownVal(); + + case lval::FuncValKind: + return LV; + + case lval::StringLiteralValKind: + // FIXME: Implement better support for fetching characters from strings. + return UnknownVal(); + + default: + assert (false && "Invalid LVal."); + break; + } + + return UnknownVal(); +} + +Store BasicStoreManager::SetRVal(Store St, LVal LV, RVal V) { + + VarBindingsTy B(static_cast(St)); + + switch (LV.getSubKind()) { + + case lval::DeclValKind: + return V.isUnknown() + ? VBFactory.Remove(B,cast(LV).getDecl()).getRoot() + : VBFactory.Add(B, cast(LV).getDecl(), V).getRoot(); + + default: + assert ("SetRVal for given LVal type not yet implemented."); + return St; + } +} + +Store BasicStoreManager::Remove(Store St, LVal LV) { + + VarBindingsTy B(static_cast(St)); + + switch (LV.getSubKind()) { + + case lval::DeclValKind: + return VBFactory.Remove(B,cast(LV).getDecl()).getRoot(); + + default: + assert ("Remove for given LVal type not yet implemented."); + return St; + } +} diff --git a/lib/Analysis/BugReporter.cpp b/lib/Analysis/BugReporter.cpp index fba31f81af..081e7925ee 100644 --- a/lib/Analysis/BugReporter.cpp +++ b/lib/Analysis/BugReporter.cpp @@ -327,7 +327,7 @@ static void HandleNotableSymbol(ExplodedNode* N, Stmt* S, PathDiagnostic& PD) { ExplodedNode* Pred = N->pred_empty() ? 0 : *N->pred_begin(); - ValueState* PrevSt = Pred ? Pred->getState() : 0; + const ValueState* PrevSt = Pred ? Pred->getState() : 0; if (!PrevSt) return; @@ -335,7 +335,7 @@ static void HandleNotableSymbol(ExplodedNode* N, Stmt* S, // Look at the variable bindings of the current state that map to the // specified symbol. Are any of them not in the previous state. - ValueState* St = N->getState(); + const ValueState* St = N->getState(); ValueStateManager& VMgr = cast(BR).getStateManager(); // FIXME: Later generalize for a broader memory model. @@ -633,7 +633,7 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD, if (const PostStmt* PS = dyn_cast(&P)) { - ValueState* St = N->getState(); + const ValueState* St = N->getState(); // Scan the lval bindings, and see if a "notable" symbol has a new // lval binding. diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp index 1a57306f86..4de91daa1b 100644 --- a/lib/Analysis/CFRefCount.cpp +++ b/lib/Analysis/CFRefCount.cpp @@ -1135,8 +1135,8 @@ private: public: - static RefBindings GetRefBindings(ValueState& StImpl) { - return RefBindings((RefBindings::TreeTy*) StImpl.CheckerState); + static RefBindings GetRefBindings(const ValueState& StImpl) { + return RefBindings((const RefBindings::TreeTy*) StImpl.CheckerState); } private: @@ -1156,14 +1156,15 @@ private: GRStmtNodeBuilder& Builder, Expr* NodeExpr, Expr* ErrorExpr, ExplodedNode* Pred, - ValueState* St, + const ValueState* St, RefVal::Kind hasErr, SymbolID Sym); - ValueState* HandleSymbolDeath(ValueStateManager& VMgr, ValueState* St, - SymbolID sid, RefVal V, bool& hasLeak); + const ValueState* HandleSymbolDeath(ValueStateManager& VMgr, + const ValueState* St, + SymbolID sid, RefVal V, bool& hasLeak); - ValueState* NukeBinding(ValueStateManager& VMgr, ValueState* St, - SymbolID sid); + const ValueState* NukeBinding(ValueStateManager& VMgr, const ValueState* St, + SymbolID sid); public: @@ -1226,7 +1227,7 @@ public: GRExprEngine& Engine, GRStmtNodeBuilder& Builder, Expr* E, ExplodedNode* Pred, - ValueState* St, RVal TargetLV, RVal Val); + const ValueState* St, RVal TargetLV, RVal Val); // End-of-path. virtual void EvalEndPath(GRExprEngine& Engine, @@ -1237,7 +1238,7 @@ public: GRStmtNodeBuilder& Builder, ExplodedNode* Pred, Stmt* S, - ValueState* St, + const ValueState* St, const ValueStateManager::DeadSymbolsTy& Dead); // Return statements. @@ -1249,8 +1250,9 @@ public: // Assumptions. - virtual ValueState* EvalAssume(GRExprEngine& Engine, ValueState* St, - RVal Cond, bool Assumption, bool& isFeasible); + virtual const ValueState* EvalAssume(GRExprEngine& Engine, + const ValueState* St, RVal Cond, + bool Assumption, bool& isFeasible); // Error iterators. @@ -1304,7 +1306,7 @@ void CFRefCount::ProcessNonLeakError(ExplodedNodeSet& Dst, GRStmtNodeBuilder& Builder, Expr* NodeExpr, Expr* ErrorExpr, ExplodedNode* Pred, - ValueState* St, + const ValueState* St, RefVal::Kind hasErr, SymbolID Sym) { Builder.BuildSinks = true; GRExprEngine::NodeTy* N = Builder.MakeNode(Dst, NodeExpr, Pred, St); @@ -1368,7 +1370,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, // Get the state. ValueStateManager& StateMgr = Eng.getStateManager(); - ValueState* St = Builder.GetState(Pred); + const ValueState* St = Builder.GetState(Pred); // Evaluate the effect of the arguments. ValueState StVals = *St; @@ -1429,7 +1431,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet& Dst, unsigned Count = Builder.getCurrentBlockCount(); SymbolID NewSym = Eng.getSymbolManager().getConjuredSymbol(*I, Count); - StateMgr.BindVar(StVals, DV->getDecl(), + StateMgr.SetRVal(StVals, *DV, LVal::IsLValType(DV->getDecl()->getType()) ? cast(lval::SymbolVal(NewSym)) : cast(nonlval::SymbolVal(NewSym))); @@ -1596,7 +1598,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet& Dst, // FIXME: Wouldn't it be great if this code could be reduced? It's just // a chain of lookups. - ValueState* St = Builder.GetState(Pred); + const ValueState* St = Builder.GetState(Pred); RVal V = Eng.getStateManager().GetRVal(St, Receiver ); if (isa(V)) { @@ -1630,7 +1632,7 @@ void CFRefCount::EvalStore(ExplodedNodeSet& Dst, GRExprEngine& Eng, GRStmtNodeBuilder& Builder, Expr* E, ExplodedNode* Pred, - ValueState* St, RVal TargetLV, RVal Val) { + const ValueState* St, RVal TargetLV, RVal Val) { // Check if we have a binding for "Val" and if we are storing it to something // we don't understand or otherwise the value "escapes" the function. @@ -1663,8 +1665,9 @@ void CFRefCount::EvalStore(ExplodedNodeSet& Dst, } -ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St, - SymbolID sid) { +const ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, + const ValueState* St, + SymbolID sid) { ValueState StImpl = *St; RefBindings B = GetRefBindings(StImpl); StImpl.CheckerState = RefBFactory.Remove(B, sid).getRoot(); @@ -1673,8 +1676,8 @@ ValueState* CFRefCount::NukeBinding(ValueStateManager& VMgr, ValueState* St, // End-of-path. -ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr, - ValueState* St, SymbolID sid, +const ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr, + const ValueState* St, SymbolID sid, RefVal V, bool& hasLeak) { hasLeak = V.isOwned() || @@ -1693,7 +1696,7 @@ ValueState* CFRefCount::HandleSymbolDeath(ValueStateManager& VMgr, void CFRefCount::EvalEndPath(GRExprEngine& Eng, GREndPathNodeBuilder& Builder) { - ValueState* St = Builder.getState(); + const ValueState* St = Builder.getState(); RefBindings B = GetRefBindings(*St); llvm::SmallVector Leaked; @@ -1731,7 +1734,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet& Dst, GRStmtNodeBuilder& Builder, ExplodedNode* Pred, Stmt* S, - ValueState* St, + const ValueState* St, const ValueStateManager::DeadSymbolsTy& Dead) { // FIXME: a lot of copy-and-paste from EvalEndPath. Refactor. @@ -1784,7 +1787,7 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst, if (!RetE) return; ValueStateManager& StateMgr = Eng.getStateManager(); - ValueState* St = Builder.GetState(Pred); + const ValueState* St = Builder.GetState(Pred); RVal V = StateMgr.GetRVal(St, RetE); if (!isa(V)) @@ -1831,9 +1834,10 @@ void CFRefCount::EvalReturn(ExplodedNodeSet& Dst, // Assumptions. -ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, ValueState* St, - RVal Cond, bool Assumption, - bool& isFeasible) { +const ValueState* CFRefCount::EvalAssume(GRExprEngine& Eng, + const ValueState* St, + RVal Cond, bool Assumption, + bool& isFeasible) { // FIXME: We may add to the interface of EvalAssume the list of symbols // whose assumptions have changed. For now we just iterate through the @@ -2136,8 +2140,8 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode* N, // Check if the type state has changed. - ValueState* PrevSt = PrevN->getState(); - ValueState* CurrSt = N->getState(); + const ValueState* PrevSt = PrevN->getState(); + const ValueState* CurrSt = N->getState(); CFRefCount::RefBindings PrevB = CFRefCount::GetRefBindings(*PrevSt); CFRefCount::RefBindings CurrB = CFRefCount::GetRefBindings(*CurrSt); @@ -2275,7 +2279,7 @@ GetAllocationSite(ExplodedNode* N, SymbolID Sym) { VarDecl* FirstDecl = 0; while (N) { - ValueState* St = N->getState(); + const ValueState* St = N->getState(); RefBindings B = RefBindings((RefBindings::TreeTy*) St->CheckerState); if (!B.lookup(Sym)) diff --git a/lib/Analysis/GRCoreEngine.cpp b/lib/Analysis/GRCoreEngine.cpp index a4bb7fa631..548c4bf161 100644 --- a/lib/Analysis/GRCoreEngine.cpp +++ b/lib/Analysis/GRCoreEngine.cpp @@ -255,8 +255,8 @@ void GRCoreEngineImpl::HandlePostStmt(const PostStmt& L, CFGBlock* B, /// GenerateNode - Utility method to generate nodes, hook up successors, /// and add nodes to the worklist. -void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc, void* State, - ExplodedNodeImpl* Pred) { +void GRCoreEngineImpl::GenerateNode(const ProgramPoint& Loc, const void* State, + ExplodedNodeImpl* Pred) { bool IsNew; ExplodedNodeImpl* Node = G->getNodeImpl(Loc, State, &IsNew); @@ -321,7 +321,7 @@ static inline ProgramPoint GetPostLoc(Stmt* S, ProgramPoint::Kind K) { } ExplodedNodeImpl* -GRStmtNodeBuilderImpl::generateNodeImpl(Stmt* S, void* State, +GRStmtNodeBuilderImpl::generateNodeImpl(Stmt* S, const void* State, ExplodedNodeImpl* Pred, ProgramPoint::Kind K) { @@ -342,7 +342,7 @@ GRStmtNodeBuilderImpl::generateNodeImpl(Stmt* S, void* State, return NULL; } -ExplodedNodeImpl* GRBranchNodeBuilderImpl::generateNodeImpl(void* State, +ExplodedNodeImpl* GRBranchNodeBuilderImpl::generateNodeImpl(const void* State, bool branch) { bool IsNew; @@ -374,7 +374,7 @@ GRBranchNodeBuilderImpl::~GRBranchNodeBuilderImpl() { ExplodedNodeImpl* GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Iterator& I, - void* St, + const void* St, bool isSink) { bool IsNew; @@ -399,7 +399,8 @@ GRIndirectGotoNodeBuilderImpl::generateNodeImpl(const Iterator& I, ExplodedNodeImpl* -GRSwitchNodeBuilderImpl::generateCaseStmtNodeImpl(const Iterator& I, void* St) { +GRSwitchNodeBuilderImpl::generateCaseStmtNodeImpl(const Iterator& I, + const void* St) { bool IsNew; @@ -418,7 +419,8 @@ GRSwitchNodeBuilderImpl::generateCaseStmtNodeImpl(const Iterator& I, void* St) { ExplodedNodeImpl* -GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(void* St, bool isSink) { +GRSwitchNodeBuilderImpl::generateDefaultCaseNodeImpl(const void* St, + bool isSink) { // Get the block for the default case. assert (Src->succ_rbegin() != Src->succ_rend()); @@ -448,7 +450,7 @@ GREndPathNodeBuilderImpl::~GREndPathNodeBuilderImpl() { if (!HasGeneratedNode) generateNodeImpl(Pred->State); } -ExplodedNodeImpl* GREndPathNodeBuilderImpl::generateNodeImpl(void* State) { +ExplodedNodeImpl* GREndPathNodeBuilderImpl::generateNodeImpl(const void* State){ HasGeneratedNode = true; bool IsNew; diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index c4eddb9993..96e7fae7e3 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -18,6 +18,8 @@ #include "clang/Basic/SourceManager.h" #include "llvm/Support/Streams.h" +#include "clang/Analysis/PathSensitive/BasicStore.h" + #ifndef NDEBUG #include "llvm/Support/GraphWriter.h" #include @@ -44,7 +46,8 @@ GRExprEngine::GRExprEngine(CFG& cfg, Decl& CD, ASTContext& Ctx, G(CoreEngine.getGraph()), Liveness(L), Builder(NULL), - StateMgr(G.getContext(), G.getAllocator()), + StateMgr(G.getContext(), CreateBasicStoreManager(G.getAllocator()), + G.getAllocator()), BasicVals(StateMgr.getBasicValueFactory()), TF(NULL), // FIXME SymMgr(StateMgr.getSymbolManager()), @@ -127,7 +130,7 @@ void GRExprEngine::AddObjCMessageExprCheck(GRSimpleAPICheck* A) { MsgExprChecks.push_back(A); } -ValueState* GRExprEngine::getInitialState() { +const ValueState* GRExprEngine::getInitialState() { // The LiveVariables information already has a compilation of all VarDecls // used in the function. Iterate through this set, and "symbolicate" @@ -144,11 +147,11 @@ ValueState* GRExprEngine::getInitialState() { if (VarDecl* VD = dyn_cast(SD)) { if (VD->hasGlobalStorage() || isa(VD)) { RVal X = RVal::GetSymbolValue(SymMgr, VD); - StateMgr.BindVar(StateImpl, VD, X); + StateMgr.SetRVal(StateImpl, lval::DeclVal(VD), X); } } else if (ImplicitParamDecl *IPD = dyn_cast(SD)) { RVal X = RVal::GetSymbolValue(SymMgr, IPD); - StateMgr.BindVar(StateImpl, IPD, X); + StateMgr.SetRVal(StateImpl, lval::DeclVal(IPD), X); } @@ -157,7 +160,8 @@ ValueState* GRExprEngine::getInitialState() { return StateMgr.getPersistentState(StateImpl); } -ValueState* GRExprEngine::SetRVal(ValueState* St, Expr* Ex, RVal V) { +const ValueState* GRExprEngine::SetRVal(const ValueState* St, Expr* Ex, + RVal V) { bool isBlkExpr = false; @@ -285,7 +289,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) { break; } else if (B->getOpcode() == BinaryOperator::Comma) { - ValueState* St = GetState(Pred); + const ValueState* St = GetState(Pred); MakeNode(Dst, B, Pred, SetRVal(St, B, GetRVal(St, B->getRHS()))); break; } @@ -364,7 +368,7 @@ void GRExprEngine::Visit(Stmt* S, NodeTy* Pred, NodeSet& Dst) { case Stmt::StmtExprClass: { StmtExpr* SE = cast(S); - ValueState* St = GetState(Pred); + const ValueState* St = GetState(Pred); // FIXME: Not certain if we can have empty StmtExprs. If so, we should // probably just remove these from the CFG. @@ -420,7 +424,7 @@ void GRExprEngine::VisitLVal(Expr* Ex, NodeTy* Pred, NodeSet& Dst) { // Block entrance. (Update counters). //===----------------------------------------------------------------------===// -bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, ValueState*, +bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, const ValueState*, GRBlockCounter BC) { return BC.getNumVisited(B->getBlockID()) < 3; @@ -430,8 +434,9 @@ bool GRExprEngine::ProcessBlockEntrance(CFGBlock* B, ValueState*, // Branch processing. //===----------------------------------------------------------------------===// -ValueState* GRExprEngine::MarkBranch(ValueState* St, Stmt* Terminator, - bool branchTaken) { +const ValueState* GRExprEngine::MarkBranch(const ValueState* St, + Stmt* Terminator, + bool branchTaken) { switch (Terminator->getStmtClass()) { default: @@ -488,7 +493,8 @@ void GRExprEngine::ProcessBranch(Expr* Condition, Stmt* Term, BranchNodeBuilder& builder) { // Remove old bindings for subexpressions. - ValueState* PrevState = StateMgr.RemoveSubExprBindings(builder.getState()); + const ValueState* PrevState = + StateMgr.RemoveSubExprBindings(builder.getState()); // Check for NULL conditions; e.g. "for(;;)" if (!Condition) { @@ -523,7 +529,7 @@ void GRExprEngine::ProcessBranch(Expr* Condition, Stmt* Term, // Process the true branch. bool isFeasible = false; - ValueState* St = Assume(PrevState, V, true, isFeasible); + const ValueState* St = Assume(PrevState, V, true, isFeasible); if (isFeasible) builder.generateNode(MarkBranch(St, Term, true), true); @@ -545,7 +551,7 @@ void GRExprEngine::ProcessBranch(Expr* Condition, Stmt* Term, /// nodes by processing the 'effects' of a computed goto jump. void GRExprEngine::ProcessIndirectGoto(IndirectGotoNodeBuilder& builder) { - ValueState* St = builder.getState(); + const ValueState* St = builder.getState(); RVal V = GetRVal(St, builder.getTarget()); // Three possibilities: @@ -592,7 +598,7 @@ void GRExprEngine::VisitGuardedExpr(Expr* Ex, Expr* L, Expr* R, assert (Ex == CurrentStmt && getCFG().isBlkExpr(Ex)); - ValueState* St = GetState(Pred); + const ValueState* St = GetState(Pred); RVal X = GetBlkExprRVal(St, Ex); assert (X.isUndef()); @@ -613,7 +619,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { typedef SwitchNodeBuilder::iterator iterator; - ValueState* St = builder.getState(); + const ValueState* St = builder.getState(); Expr* CondE = builder.getCondition(); RVal CondV = GetRVal(St, CondE); @@ -623,7 +629,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { return; } - ValueState* DefaultSt = St; + const ValueState* DefaultSt = St; // While most of this can be assumed (such as the signedness), having it // just computed makes sure everything makes the same assumptions end-to-end. @@ -670,7 +676,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { // Now "assume" that the case matches. bool isFeasible = false; - ValueState* StNew = Assume(St, Res, true, isFeasible); + const ValueState* StNew = Assume(St, Res, true, isFeasible); if (isFeasible) { builder.generateCaseStmtNode(I, StNew); @@ -720,7 +726,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, assert (B == CurrentStmt && getCFG().isBlkExpr(B)); - ValueState* St = GetState(Pred); + const ValueState* St = GetState(Pred); RVal X = GetBlkExprRVal(St, B); assert (X.isUndef()); @@ -748,7 +754,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, // the payoff is not likely to be large. Instead, we do eager evaluation. bool isFeasible = false; - ValueState* NewState = Assume(St, X, true, isFeasible); + const ValueState* NewState = Assume(St, X, true, isFeasible); if (isFeasible) MakeNode(Dst, B, Pred, @@ -778,7 +784,7 @@ void GRExprEngine::VisitLogicalExpr(BinaryOperator* B, NodeTy* Pred, void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst, bool asLVal) { - ValueState* St = GetState(Pred); + const ValueState* St = GetState(Pred); RVal X = RVal::MakeVal(BasicVals, D); if (asLVal) @@ -814,7 +820,7 @@ void GRExprEngine::VisitArraySubscriptExpr(ArraySubscriptExpr* A, NodeTy* Pred, for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2!=E2; ++I2) { - ValueState* St = GetState(*I2); + const ValueState* St = GetState(*I2); RVal BaseV = GetRVal(St, Base); RVal IdxV = GetRVal(St, Idx); @@ -853,7 +859,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, VisitLVal(Base, Pred, Tmp); for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); RVal BaseV = GetRVal(St, Base); RVal V = lval::FieldOffset::Make(BasicVals, GetRVal(St, Base), @@ -871,7 +877,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); RVal BaseV = GetRVal(St, Base); if (LVal::IsLValType(Base->getType())) { @@ -900,7 +906,7 @@ void GRExprEngine::VisitMemberExpr(MemberExpr* M, NodeTy* Pred, } void GRExprEngine::EvalStore(NodeSet& Dst, Expr* Ex, NodeTy* Pred, - ValueState* St, RVal location, RVal Val) { + const ValueState* St, RVal location, RVal Val) { assert (Builder && "GRStmtNodeBuilder must be defined."); @@ -930,7 +936,8 @@ void GRExprEngine::EvalStore(NodeSet& Dst, Expr* Ex, NodeTy* Pred, } void GRExprEngine::EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred, - ValueState* St, RVal location, bool CheckOnly) { + const ValueState* St, RVal location, + bool CheckOnly) { // Evaluate the location (checks for bad dereferences). @@ -958,9 +965,9 @@ void GRExprEngine::EvalLoad(NodeSet& Dst, Expr* Ex, NodeTy* Pred, Ex->getType()))); } -ValueState* GRExprEngine::EvalLocation(Expr* Ex, NodeTy* Pred, - ValueState* St, RVal location, - bool isLoad) { +const ValueState* GRExprEngine::EvalLocation(Expr* Ex, NodeTy* Pred, + const ValueState* St, + RVal location, bool isLoad) { // Check for loads/stores from/to undefined values. if (location.isUndef()) { @@ -990,12 +997,12 @@ ValueState* GRExprEngine::EvalLocation(Expr* Ex, NodeTy* Pred, // "Assume" that the pointer is not NULL. bool isFeasibleNotNull = false; - ValueState* StNotNull = Assume(St, LV, true, isFeasibleNotNull); + const ValueState* StNotNull = Assume(St, LV, true, isFeasibleNotNull); // "Assume" that the pointer is NULL. bool isFeasibleNull = false; - ValueState* StNull = Assume(St, LV, false, isFeasibleNull); + const ValueState* StNull = Assume(St, LV, false, isFeasibleNull); if (isFeasibleNull) { @@ -1053,7 +1060,7 @@ void GRExprEngine::VisitCall(CallExpr* CE, NodeTy* Pred, // Finally, evaluate the function call. for (NodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end(); DI!=DE; ++DI) { - ValueState* St = GetState(*DI); + const ValueState* St = GetState(*DI); RVal L = GetRVal(St, Callee); // FIXME: Add support for symbolic function calls (calls involving @@ -1246,7 +1253,7 @@ void GRExprEngine::VisitObjCMessageExprDispatchHelper(ObjCMessageExpr* ME, // FIXME: More logic for the processing the method call. - ValueState* St = GetState(Pred); + const ValueState* St = GetState(Pred); bool RaisesException = false; @@ -1391,7 +1398,7 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){ for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) { NodeTy* N = *I1; - ValueState* St = GetState(N); + const ValueState* St = GetState(N); RVal V = GetRVal(St, Ex); // Unknown? @@ -1470,7 +1477,7 @@ void GRExprEngine::VisitDeclStmtAux(DeclStmt* DS, ScopedDecl* D, for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); if (!Ex && VD->hasGlobalStorage()) { @@ -1601,7 +1608,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); RVal location = GetRVal(St, Ex); if (asLVal) @@ -1630,7 +1637,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, // For all other types, UnaryOperator::Real is an identity operation. assert (U->getType() == Ex->getType()); - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); MakeNode(Dst, U, *I, SetRVal(St, U, GetRVal(St, Ex))); } @@ -1653,7 +1660,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, // For all other types, UnaryOperator::Float returns 0. assert (Ex->getType()->isIntegerType()); - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); RVal X = NonLVal::MakeVal(BasicVals, 0, Ex->getType()); MakeNode(Dst, U, *I, SetRVal(St, U, X)); } @@ -1679,7 +1686,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, Visit(Ex, Pred, Tmp); for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); MakeNode(Dst, U, *I, SetRVal(St, U, GetRVal(St, Ex))); } @@ -1694,7 +1701,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, VisitLVal(Ex, Pred, Tmp); for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); RVal V = GetRVal(St, Ex); St = SetRVal(St, U, V); MakeNode(Dst, U, *I, St); @@ -1713,7 +1720,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, Visit(Ex, Pred, Tmp); for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); RVal V = GetRVal(St, Ex); if (V.isUnknownOrUndef()) { @@ -1771,7 +1778,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, return; uint64_t size = getContext().getTypeSize(T) / 8; - ValueState* St = GetState(Pred); + const ValueState* St = GetState(Pred); St = SetRVal(St, U, NonLVal::MakeVal(BasicVals, size, U->getType())); MakeNode(Dst, U, Pred, St); @@ -1788,7 +1795,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, for (NodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) { - ValueState* St = GetState(*I); + const ValueState* St = GetState(*I); RVal V1 = GetRVal(St, Ex); // Perform a load. @@ -1855,7 +1862,7 @@ void GRExprEngine::VisitAsmStmtHelperInputs(AsmStmt* A, // which interprets the inline asm and stores proper results in the // outputs. - ValueState* St = GetState(Pred); + const ValueState* St = GetState(Pred); for (AsmStmt::outputs_iterator OI = A->begin_outputs(), OE = A->end_outputs(); OI != OE; ++OI) { @@ -1949,7 +1956,7 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) { // Transfer functions: Binary operators. //===----------------------------------------------------------------------===// -bool GRExprEngine::CheckDivideZero(Expr* Ex, ValueState* St, +bool GRExprEngine::CheckDivideZero(Expr* Ex, const ValueState* St, NodeTy* Pred, RVal Denom) { // Divide by undefined? (potentially zero) @@ -1969,7 +1976,7 @@ bool GRExprEngine::CheckDivideZero(Expr* Ex, ValueState* St, // First, "assume" that the denominator is 0 or undefined. bool isFeasibleZero = false; - ValueState* ZeroSt = Assume(St, Denom, false, isFeasibleZero); + const ValueState* ZeroSt = Assume(St, Denom, false, isFeasibleZero); // Second, "assume" that the denominator cannot be 0. @@ -2018,7 +2025,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, for (NodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end(); I2 != E2; ++I2) { - ValueState* St = GetState(*I2); + const ValueState* St = GetState(*I2); RVal RightV = GetRVal(St, RHS); BinaryOperator::Opcode Op = B->getOpcode(); @@ -2175,8 +2182,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // "Assume" logic. //===----------------------------------------------------------------------===// -ValueState* GRExprEngine::Assume(ValueState* St, LVal Cond, - bool Assumption, bool& isFeasible) { +const ValueState* GRExprEngine::Assume(const ValueState* St, LVal Cond, + bool Assumption, bool& isFeasible) { St = AssumeAux(St, Cond, Assumption, isFeasible); @@ -2184,8 +2191,8 @@ ValueState* GRExprEngine::Assume(ValueState* St, LVal Cond, : St; } -ValueState* GRExprEngine::AssumeAux(ValueState* St, LVal Cond, - bool Assumption, bool& isFeasible) { +const ValueState* GRExprEngine::AssumeAux(const ValueState* St, LVal Cond, + bool Assumption, bool& isFeasible) { switch (Cond.getSubKind()) { default: @@ -2224,8 +2231,8 @@ ValueState* GRExprEngine::AssumeAux(ValueState* St, LVal Cond, } } -ValueState* GRExprEngine::Assume(ValueState* St, NonLVal Cond, - bool Assumption, bool& isFeasible) { +const ValueState* GRExprEngine::Assume(const ValueState* St, NonLVal Cond, + bool Assumption, bool& isFeasible) { St = AssumeAux(St, Cond, Assumption, isFeasible); @@ -2233,8 +2240,8 @@ ValueState* GRExprEngine::Assume(ValueState* St, NonLVal Cond, : St; } -ValueState* GRExprEngine::AssumeAux(ValueState* St, NonLVal Cond, - bool Assumption, bool& isFeasible) { +const ValueState* GRExprEngine::AssumeAux(const ValueState* St, NonLVal Cond, + bool Assumption, bool& isFeasible) { switch (Cond.getSubKind()) { default: assert (false && "'Assume' not implemented for this NonLVal."); @@ -2272,9 +2279,9 @@ ValueState* GRExprEngine::AssumeAux(ValueState* St, NonLVal Cond, } } -ValueState* -GRExprEngine::AssumeSymNE(ValueState* St, SymbolID sym, - const llvm::APSInt& V, bool& isFeasible) { +const ValueState* GRExprEngine::AssumeSymNE(const ValueState* St, + SymbolID sym, const llvm::APSInt& V, + bool& isFeasible) { // First, determine if sym == X, where X != V. if (const llvm::APSInt* X = St->getSymVal(sym)) { @@ -2295,9 +2302,8 @@ GRExprEngine::AssumeSymNE(ValueState* St, SymbolID sym, return StateMgr.AddNE(St, sym, V); } -ValueState* -GRExprEngine::AssumeSymEQ(ValueState* St, SymbolID sym, - const llvm::APSInt& V, bool& isFeasible) { +const ValueState* GRExprEngine::AssumeSymEQ(const ValueState* St, SymbolID sym, + const llvm::APSInt& V, bool& isFeasible) { // First, determine if sym == X, where X != V. if (const llvm::APSInt* X = St->getSymVal(sym)) { @@ -2318,9 +2324,10 @@ GRExprEngine::AssumeSymEQ(ValueState* St, SymbolID sym, return StateMgr.AddEQ(St, sym, V); } -ValueState* -GRExprEngine::AssumeSymInt(ValueState* St, bool Assumption, - const SymIntConstraint& C, bool& isFeasible) { +const ValueState* GRExprEngine::AssumeSymInt(const ValueState* St, + bool Assumption, + const SymIntConstraint& C, + bool& isFeasible) { switch (C.getOpcode()) { default: diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index 926bcc8e58..7d7afe39af 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -265,9 +265,9 @@ namespace { struct VISIBILITY_HIDDEN FindUndefExpr { ValueStateManager& VM; - ValueState* St; + const ValueState* St; - FindUndefExpr(ValueStateManager& V, ValueState* S) : VM(V), St(S) {} + FindUndefExpr(ValueStateManager& V, const ValueState* S) : VM(V), St(S) {} Expr* FindExpr(Expr* Ex) { @@ -319,7 +319,7 @@ void UndefBranch::EmitWarnings(BugReporter& BR) { ExplodedNode *N = *(*I)->pred_begin(); ProgramPoint P = N->getLocation(); - ValueState* St = (*I)->getState(); + const ValueState* St = (*I)->getState(); if (PostStmt* PS = dyn_cast(&P)) if (PS->getStmt() == Ex) @@ -652,7 +652,7 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet& Dst, ExplodedNode* Pred) { ValueStateManager& StateMgr = Eng.getStateManager(); - ValueState* St = Builder.GetState(Pred); + const ValueState* St = Builder.GetState(Pred); // Invalidate all arguments passed in by reference (LVals). @@ -700,7 +700,7 @@ void GRSimpleVals::EvalObjCMessageExpr(ExplodedNodeSet& Dst, // We just invalidate all arguments passed in by references. ValueStateManager& StateMgr = Eng.getStateManager(); - ValueState* St = Builder.GetState(Pred); + const ValueState* St = Builder.GetState(Pred); for (ObjCMessageExpr::arg_iterator I = ME->arg_begin(), E = ME->arg_end(); I != E; ++I) { diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp index 9c96e3d981..a31f8aaa1b 100644 --- a/lib/Analysis/GRTransferFuncs.cpp +++ b/lib/Analysis/GRTransferFuncs.cpp @@ -23,7 +23,7 @@ void GRTransferFuncs::EvalStore(ExplodedNodeSet& Dst, GRExprEngine& Eng, GRStmtNodeBuilder& Builder, Expr* E, ExplodedNode* Pred, - ValueState* St, RVal TargetLV, RVal Val) { + const ValueState* St, RVal TargetLV, RVal Val) { // This code basically matches the "safety-net" logic of GRExprEngine: // bind Val to TargetLV, and create a new node. We replicate it here diff --git a/lib/Analysis/ValueState.cpp b/lib/Analysis/ValueState.cpp index cc77edc826..72ff498adb 100644 --- a/lib/Analysis/ValueState.cpp +++ b/lib/Analysis/ValueState.cpp @@ -30,8 +30,8 @@ const llvm::APSInt* ValueState::getSymVal(SymbolID sym) const { return T ? *T : NULL; } -ValueState* -ValueStateManager::RemoveDeadBindings(ValueState* St, Stmt* Loc, +const ValueState* +ValueStateManager::RemoveDeadBindings(const ValueState* St, Stmt* Loc, const LiveVariables& Liveness, DeadSymbolsTy& DeadSymbols) { @@ -126,7 +126,7 @@ ValueStateManager::RemoveDeadBindings(ValueState* St, Stmt* Loc, for (ValueState::vb_iterator I = St->vb_begin(), E = St->vb_end(); I!=E ; ++I) if (!Marked.count(I.getKey())) { - NewSt.VarBindings = Remove(NewSt, I.getKey()); + NewSt.St = StMgr->Remove(NewSt.St, lval::DeclVal(I.getKey())); RVal X = I.getData(); @@ -160,77 +160,35 @@ ValueStateManager::RemoveDeadBindings(ValueState* St, Stmt* Loc, return getPersistentState(NewSt); } - -RVal ValueStateManager::GetRVal(ValueState* St, LVal LV, QualType T) { +const ValueState* ValueStateManager::SetRVal(const ValueState* St, LVal LV, + RVal V) { - if (isa(LV)) - return UnknownVal(); + Store OldStore = St->getStore(); + Store NewStore = StMgr->SetRVal(OldStore, LV, V); - assert (!isa(LV)); + if (NewStore == OldStore) + return St; - switch (LV.getSubKind()) { - case lval::DeclValKind: { - ValueState::VarBindingsTy::data_type* T = - St->VarBindings.lookup(cast(LV).getDecl()); - - return T ? *T : UnknownVal(); - } - - // FIXME: We should limit how far a "ContentsOf" will go... - - case lval::SymbolValKind: { - - - // FIXME: This is a broken representation of memory, and is prone - // to crashing the analyzer when addresses to symbolic values are - // passed through casts. We need a better representation of symbolic - // memory (or just memory in general); probably we should do this - // as a plugin class (similar to GRTransferFuncs). - -#if 0 - const lval::SymbolVal& SV = cast(LV); - assert (T.getTypePtr()); - - // Punt on "symbolic" function pointers. - if (T->isFunctionType()) - return UnknownVal(); + ValueState NewSt = *St; + NewSt.St = NewStore; + return getPersistentState(NewSt); +} - if (T->isPointerType()) - return lval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol())); - else - return nonlval::SymbolVal(SymMgr.getContentsOfSymbol(SV.getSymbol())); -#endif - - return UnknownVal(); - } - - case lval::ConcreteIntKind: - // Some clients may call GetRVal with such an option simply because - // they are doing a quick scan through their LVals (potentially to - // invalidate their bindings). Just return Undefined. - return UndefinedVal(); - - case lval::ArrayOffsetKind: - case lval::FieldOffsetKind: - return UnknownVal(); - - case lval::FuncValKind: - return LV; - - case lval::StringLiteralValKind: - // FIXME: Implement better support for fetching characters from strings. - return UnknownVal(); - - default: - assert (false && "Invalid LVal."); - break; - } +const ValueState* ValueStateManager::Unbind(const ValueState* St, LVal LV) { + Store OldStore = St->getStore(); + Store NewStore = StMgr->Remove(OldStore, LV); - return UnknownVal(); + if (NewStore == OldStore) + return St; + + ValueState NewSt = *St; + NewSt.St = NewStore; + return getPersistentState(NewSt); } -ValueState* ValueStateManager::AddNE(ValueState* St, SymbolID sym, - const llvm::APSInt& V) { + +const ValueState* ValueStateManager::AddNE(const ValueState* St, SymbolID sym, + const llvm::APSInt& V) { // First, retrieve the NE-set associated with the given symbol. ValueState::ConstNotEqTy::data_type* T = St->ConstNotEq.lookup(sym); @@ -247,8 +205,8 @@ ValueState* ValueStateManager::AddNE(ValueState* St, SymbolID sym, return getPersistentState(NewSt); } -ValueState* ValueStateManager::AddEQ(ValueState* St, SymbolID sym, - const llvm::APSInt& V) { +const ValueState* ValueStateManager::AddEQ(const ValueState* St, SymbolID sym, + const llvm::APSInt& V) { // Create a new state with the old binding replaced. ValueState NewSt = *St; @@ -258,66 +216,17 @@ ValueState* ValueStateManager::AddEQ(ValueState* St, SymbolID sym, return getPersistentState(NewSt); } +const ValueState* ValueStateManager::getInitialState() { -ValueState* ValueStateManager::SetRVal(ValueState* St, LVal LV, RVal V) { - - switch (LV.getSubKind()) { - - case lval::DeclValKind: - return V.isUnknown() - ? UnbindVar(St, cast(LV).getDecl()) - : BindVar(St, cast(LV).getDecl(), V); - - default: - assert ("SetRVal for given LVal type not yet implemented."); - return St; - } -} - -void ValueStateManager::BindVar(ValueState& StImpl, VarDecl* D, RVal V) { - StImpl.VarBindings = VBFactory.Add(StImpl.VarBindings, D, V); -} - -ValueState* ValueStateManager::BindVar(ValueState* St, VarDecl* D, RVal V) { - - // Create a new state with the old binding removed. - ValueState NewSt = *St; - NewSt.VarBindings = VBFactory.Add(NewSt.VarBindings, D, V); - - // Get the persistent copy. - return getPersistentState(NewSt); -} - -ValueState* ValueStateManager::UnbindVar(ValueState* St, VarDecl* D) { - - // Create a new state with the old binding removed. - ValueState NewSt = *St; - NewSt.VarBindings = VBFactory.Remove(NewSt.VarBindings, D); - - // Get the persistent copy. - return getPersistentState(NewSt); -} - -void ValueStateManager::Unbind(ValueState& StImpl, LVal LV) { - - if (isa(LV)) - StImpl.VarBindings = VBFactory.Remove(StImpl.VarBindings, - cast(LV).getDecl()); - -} - -ValueState* ValueStateManager::getInitialState() { - - // Create a state with empty variable bindings. ValueState StateImpl(EnvMgr.getInitialEnvironment(), - VBFactory.GetEmptyMap(), + StMgr->getInitialStore(), CNEFactory.GetEmptyMap(), CEFactory.GetEmptyMap()); return getPersistentState(StateImpl); } -ValueState* ValueStateManager::getPersistentState(ValueState& State) { +const ValueState* ValueStateManager::getPersistentState(ValueState& State) { llvm::FoldingSetNodeID ID; State.Profile(ID);