]> granicus.if.org Git - clang/commitdiff
Refactored most of the "Store" piece of ValueState into a Store type. The
authorTed Kremenek <kremenek@apple.com>
Thu, 10 Jul 2008 22:03:41 +0000 (22:03 +0000)
committerTed Kremenek <kremenek@apple.com>
Thu, 10 Jul 2008 22:03:41 +0000 (22:03 +0000)
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

16 files changed:
include/clang/Analysis/PathSensitive/BasicStore.h [new file with mode: 0644]
include/clang/Analysis/PathSensitive/ExplodedGraph.h
include/clang/Analysis/PathSensitive/GRCoreEngine.h
include/clang/Analysis/PathSensitive/GRExprEngine.h
include/clang/Analysis/PathSensitive/GRTransferFuncs.h
include/clang/Analysis/PathSensitive/Store.h [new file with mode: 0644]
include/clang/Analysis/PathSensitive/ValueState.h
lib/Analysis/BasicObjCFoundationChecks.cpp
lib/Analysis/BasicStore.cpp [new file with mode: 0644]
lib/Analysis/BugReporter.cpp
lib/Analysis/CFRefCount.cpp
lib/Analysis/GRCoreEngine.cpp
lib/Analysis/GRExprEngine.cpp
lib/Analysis/GRSimpleVals.cpp
lib/Analysis/GRTransferFuncs.cpp
lib/Analysis/ValueState.cpp

diff --git a/include/clang/Analysis/PathSensitive/BasicStore.h b/include/clang/Analysis/PathSensitive/BasicStore.h
new file mode 100644 (file)
index 0000000..88ac9ce
--- /dev/null
@@ -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
index 39a064d4c609c17a4732d67cccf029e7612630cc..71043f0ef67eb7d7d6af32877a4a6d1dbf37a1a7 100644 (file)
@@ -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<StateTy*>(State);
+  inline const StateTy* getState() const {
+    return static_cast<const StateTy*>(State);
   }
   
   // Profiling (for FoldingSet).
   
   static inline void Profile(llvm::FoldingSetNodeID& ID,
                              const ProgramPoint& Loc,
-                             StateTy* state) {
+                             const StateTy* state) {
     ID.Add(Loc);
     GRTrait<StateTy>::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<StateTy*>(State), IsNew);
+    return getNode(L, static_cast<const StateTy*>(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;    
index 19028ee8751abc8f240de3ef77755f5759345fc9..32fe9d3342af514e35875ada9ddeb5eda9731db3 100644 (file)
@@ -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<StateTy>   NodeTy;
   
   GRStmtNodeBuilderImpl& NB;
-  StateTy* CleanedState;
+  const StateTy* CleanedState;
   
   GRAuditor<StateTy> **CallExprAuditBeg, **CallExprAuditEnd;
   GRAuditor<StateTy> **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<StateTy>& Dst, Stmt* S,
-                 NodeTy* Pred, StateTy* St) {    
+                   NodeTy* Pred, const StateTy* St) {    
     
-    StateTy* PredState = GetState(Pred);
+    const StateTy* PredState = GetState(Pred);
     
     GRAuditor<StateTy> **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<NodeTy*>(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<NodeTy*>(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<typename STATE>
@@ -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<NodeTy*>(NB.generateNodeImpl(I, St, isSink));
   }
   
-  StateTy* getState() const {
-    return static_cast<StateTy*>(NB.getState());
+  const StateTy* getState() const {
+    return static_cast<const StateTy*>(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<typename STATE>
@@ -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<NodeTy*>(NB.generateCaseStmtNodeImpl(I, St));
   }
   
-  NodeTy* generateDefaultCaseNode(StateTy* St, bool isSink = false) {    
+  NodeTy* generateDefaultCaseNode(const StateTy* St, bool isSink = false) {    
     return static_cast<NodeTy*>(NB.generateDefaultCaseNodeImpl(St, isSink));
   }
   
-  StateTy* getState() const {
-    return static_cast<StateTy*>(NB.getState());
+  const StateTy* getState() const {
+    return static_cast<const StateTy*>(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<NodeTy*>(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<StateTy*>(State),BC);
+    return SubEngine.ProcessBlockEntrance(Blk,
+                                          static_cast<const StateTy*>(State),
+                                          BC);
   }
 
   virtual void ProcessBranch(Expr* Condition, Stmt* Terminator,
index 6dfd428bf4fdbf7646c7a6efa84f4100dd6ea036..97699ca902df934180b30e25cec74e14e594a9b4 100644 (file)
@@ -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<Expr*>(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<Expr*>(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<NonLVal>(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
index 323358e0c3b7227845d07d6067cd4d6d90949b3b..4e267f8859e6c234a8c900a8ca44c35bb4cbc2fd 100644 (file)
@@ -82,7 +82,7 @@ public:
                          GRExprEngine& Engine,
                          GRStmtNodeBuilder<ValueState>& Builder,
                          Expr* E, ExplodedNode<ValueState>* 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<ValueState>& Builder,
                                ExplodedNode<ValueState>* 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 (file)
index 0000000..adf9cf8
--- /dev/null
@@ -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
index ab9b4a8b324ae02034f0a13c5dd3744c6bc7a0f3..36bfdff5b936ba1614083ab038aa7a15d2f7c6bb 100644 (file)
@@ -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<llvm::APSInt*>                IntSetTy;
-  typedef llvm::ImmutableMap<VarDecl*,RVal>                VarBindingsTy;  
   typedef llvm::ImmutableMap<SymbolID,IntSetTy>            ConstNotEqTy;
   typedef llvm::ImmutableMap<SymbolID,const llvm::APSInt*> 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<VarDecl*,RVal> 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<const VarBindingsTy::TreeTy*>(St));
+    return B.begin();
+  }
+  vb_iterator vb_end() const {
+    VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(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<ValueState*> {
 class ValueStateManager {
 private:
   EnvironmentManager                   EnvMgr;
+  llvm::OwningPtr<StoreManager>        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<SymbolID> 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
index 1667a21494e76d6eb3e9f12c41056e5b96100359..4475ed2bc5b8667518b39da0808a05931bcc490e 100644 (file)
@@ -107,7 +107,7 @@ class VISIBILITY_HIDDEN BasicObjCFoundationChecks : public GRSimpleAPICheck {
   typedef std::vector<BugReport*> 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 (file)
index 0000000..38c1db7
--- /dev/null
@@ -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<VarDecl*,RVal> 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<UnknownVal>(LV))
+    return UnknownVal();
+  
+  assert (!isa<UndefinedVal>(LV));
+  
+  switch (LV.getSubKind()) {
+
+    case lval::DeclValKind: {      
+      VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));      
+      VarBindingsTy::data_type* T = B.lookup(cast<lval::DeclVal>(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<lval::SymbolVal>(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<const VarBindingsTy::TreeTy*>(St));
+  
+  switch (LV.getSubKind()) {
+      
+    case lval::DeclValKind:        
+      return V.isUnknown()
+        ? VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot()
+        : VBFactory.Add(B, cast<lval::DeclVal>(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<const VarBindingsTy::TreeTy*>(St));
+  
+  switch (LV.getSubKind()) {
+      
+    case lval::DeclValKind:
+      return VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot();
+
+    default:
+      assert ("Remove for given LVal type not yet implemented.");
+      return St;
+  }
+}
index fba31f81af3aa77f52976a78bc64d9cc42552bcb..081e7925eed50534ff425dee7377fe643930da2b 100644 (file)
@@ -327,7 +327,7 @@ static void HandleNotableSymbol(ExplodedNode<ValueState>* N, Stmt* S,
                                 PathDiagnostic& PD) {
   
   ExplodedNode<ValueState>* 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<ValueState>* 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<GRBugReporter>(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<PostStmt>(&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.
index 1a57306f86ae5fb4b15ed9b973e2cc990c436dd5..4de91daa1b83186b3f28806543e6d9fa486cd125 100644 (file)
@@ -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<ValueState>& Builder,
                            Expr* NodeExpr, Expr* ErrorExpr,                        
                            ExplodedNode<ValueState>* 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<ValueState>& Builder,
                          Expr* E, ExplodedNode<ValueState>* 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<ValueState>& Builder,
                                ExplodedNode<ValueState>* 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<ValueState>& Dst,
                                      GRStmtNodeBuilder<ValueState>& Builder,
                                      Expr* NodeExpr, Expr* ErrorExpr,                        
                                      ExplodedNode<ValueState>* 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<ValueState>& 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<ValueState>& 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<RVal>(lval::SymbolVal(NewSym))
                          : cast<RVal>(nonlval::SymbolVal(NewSym)));
@@ -1596,7 +1598,7 @@ void CFRefCount::EvalObjCMessageExpr(ExplodedNodeSet<ValueState>& 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<lval::SymbolVal>(V)) {
@@ -1630,7 +1632,7 @@ void CFRefCount::EvalStore(ExplodedNodeSet<ValueState>& Dst,
                            GRExprEngine& Eng,
                            GRStmtNodeBuilder<ValueState>& Builder,
                            Expr* E, ExplodedNode<ValueState>* 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<ValueState>& 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<ValueState>& Builder) {
   
-  ValueState* St = Builder.getState();
+  const ValueState* St = Builder.getState();
   RefBindings B = GetRefBindings(*St);
   
   llvm::SmallVector<SymbolID, 10> Leaked;
@@ -1731,7 +1734,7 @@ void CFRefCount::EvalDeadSymbols(ExplodedNodeSet<ValueState>& Dst,
                                  GRStmtNodeBuilder<ValueState>& Builder,
                                  ExplodedNode<ValueState>* 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<ValueState>& 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<lval::SymbolVal>(V))
@@ -1831,9 +1834,10 @@ void CFRefCount::EvalReturn(ExplodedNodeSet<ValueState>& 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<ValueState>* 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<ValueState>* 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))
index a4bb7fa63117ccda2c13d917b46f928a3a31f96e..548c4bf161c9bc5777b83e4b1c1528d607426b96 100644 (file)
@@ -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;
index c4eddb9993605d5a23ccbfa553b8c0b85f182dbe..96e7fae7e37f3a000d48c28ea42c8709d0c440fc 100644 (file)
@@ -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 <sstream>
@@ -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<VarDecl>(SD)) {
       if (VD->hasGlobalStorage() || isa<ParmVarDecl>(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<ImplicitParamDecl>(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<StmtExpr>(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:
index 926bcc8e5819bf9e052758d45f9281c675d5540e..7d7afe39afaa8a7468687846c51c975e1cc2038d 100644 (file)
@@ -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<ValueState> *N = *(*I)->pred_begin();
     ProgramPoint P = N->getLocation();
 
-    ValueState* St = (*I)->getState();
+    const ValueState* St = (*I)->getState();
     
     if (PostStmt* PS = dyn_cast<PostStmt>(&P))
       if (PS->getStmt() == Ex)
@@ -652,7 +652,7 @@ void GRSimpleVals::EvalCall(ExplodedNodeSet<ValueState>& Dst,
                             ExplodedNode<ValueState>* 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<ValueState>& 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) {
index 9c96e3d9817e7b1d6a5acdaba9c182365afd0219..a31f8aaa1b2e1a827b54a8d19859047226fd67ea 100644 (file)
@@ -23,7 +23,7 @@ void GRTransferFuncs::EvalStore(ExplodedNodeSet<ValueState>& Dst,
                                 GRExprEngine& Eng,
                                 GRStmtNodeBuilder<ValueState>& Builder,
                                 Expr* E, ExplodedNode<ValueState>* 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
index cc77edc82687536093cfe3576fb2debf219d76a0..72ff498adbe234ef71dd5be8247f177e17a0d6ac 100644 (file)
@@ -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<UnknownVal>(LV))
-    return UnknownVal();
+  Store OldStore = St->getStore();
+  Store NewStore = StMgr->SetRVal(OldStore, LV, V);
   
-  assert (!isa<UndefinedVal>(LV));
+  if (NewStore == OldStore)
+    return St;
   
-  switch (LV.getSubKind()) {
-    case lval::DeclValKind: {
-      ValueState::VarBindingsTy::data_type* T =
-        St->VarBindings.lookup(cast<lval::DeclVal>(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<lval::SymbolVal>(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<lval::DeclVal>(LV).getDecl())
-             : BindVar(St, cast<lval::DeclVal>(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<lval::DeclVal>(LV))
-    StImpl.VarBindings = VBFactory.Remove(StImpl.VarBindings,
-                                          cast<lval::DeclVal>(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);