[cfe-commits] r57042 - in /cfe/trunk: include/clang/Analysis/PathSensitive/ lib/Analysis/

Ted Kremenek kremenek at apple.com
Fri Oct 3 22:50:14 PDT 2008


Author: kremenek
Date: Sat Oct  4 00:50:14 2008
New Revision: 57042

URL: http://llvm.org/viewvc/llvm-project?rev=57042&view=rev
Log:
This is a big patch, but the functionality change is small and the rest of the patch consists of deltas due to API changes.

This patch overhauls the "memory region" abstraction that was prototyped (but never really used) as part of the Store.h.  This patch adds MemRegion.h and MemRegion.cpp, which defines the class MemRegion and its subclasses.  This classes serve to define an abstract representation of memory, with regions being layered on other regions to to capture the relationships between fields and variables, variables and the address space they are allocated in, and so on.  

The main motivation of this patch is that key parts of the analyzer assumed that all value bindings were to VarDecls.  In the future this won't be the case, and this patch removes lval::DeclVal and replaces it with lval::MemRegionVal.  Now all pieces of the analyzer must reason about abstract memory blocks instead of just variables.

There should be no functionality change from this patch, but it opens the door for significant improvements to the analyzer such as field-sensitivity and object-sensitivity, both which were on hold until the memory abstraction got generalized.

The memory region abstraction also allows type-information to literally be affixed to a memory region.  This will allow the some now redundant logic to be removed from the retain/release checker.

Added:
    cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h
    cfe/trunk/lib/Analysis/MemRegion.cpp
Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h
    cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
    cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
    cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
    cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
    cfe/trunk/lib/Analysis/BasicConstraintManager.cpp
    cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
    cfe/trunk/lib/Analysis/BasicStore.cpp
    cfe/trunk/lib/Analysis/BugReporter.cpp
    cfe/trunk/lib/Analysis/CFRefCount.cpp
    cfe/trunk/lib/Analysis/CheckNSError.cpp
    cfe/trunk/lib/Analysis/Environment.cpp
    cfe/trunk/lib/Analysis/GRExprEngine.cpp
    cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
    cfe/trunk/lib/Analysis/GRSimpleVals.cpp
    cfe/trunk/lib/Analysis/GRState.cpp
    cfe/trunk/lib/Analysis/RValues.cpp

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Environment.h Sat Oct  4 00:50:14 2008
@@ -19,6 +19,7 @@
 #include "clang/Analysis/PathSensitive/Store.h"
 
 #include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/SmallVector.h"
 #include "clang/Analysis/PathSensitive/RValues.h"
 #include "llvm/Support/Allocator.h"
 #include "llvm/ADT/FoldingSet.h"
@@ -138,11 +139,10 @@
   Environment SetRVal(const Environment& Env, Expr* E, RVal V,
                       bool isBlkExpr, bool Invalidate);
 
-  Environment RemoveDeadBindings(Environment Env, 
-                                 Stmt* Loc,
-                                 const LiveVariables& Liveness,
-                                 StoreManager::DeclRootsTy& DRoots,
-                                 StoreManager::LiveSymbolsTy& LSymbols);
+  Environment RemoveDeadBindings(Environment Env, Stmt* Loc,
+                              const LiveVariables& Liveness,
+                              llvm::SmallVectorImpl<const MemRegion*>& DRoots,
+                              StoreManager::LiveSymbolsTy& LSymbols);
 };
   
 } // end clang namespace

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Sat Oct  4 00:50:14 2008
@@ -410,6 +410,10 @@
     return SetRVal(St, const_cast<Expr*>(Ex), V);
   }
   
+  LVal getLVal(VarDecl* V) {
+    return getStateManager().getLVal(V);
+  }    
+  
 protected:
  
   const GRState* SetBlkExprRVal(const GRState* St, Expr* Ex, RVal V) {

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h Sat Oct  4 00:50:14 2008
@@ -19,6 +19,7 @@
 #include "clang/Analysis/PathSensitive/Environment.h"
 #include "clang/Analysis/PathSensitive/Store.h"
 #include "clang/Analysis/PathSensitive/ConstraintManager.h"
+#include "clang/Analysis/PathSensitive/MemRegion.h"
 #include "clang/Analysis/PathSensitive/RValues.h"
 #include "clang/Analysis/PathSensitive/GRCoreEngine.h"
 #include "clang/AST/Expr.h"
@@ -133,20 +134,6 @@
   }
   
   // 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 {
-    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(); }
   seb_iterator seb_end() const { return Env.beb_end(); }
@@ -249,6 +236,7 @@
   EnvironmentManager                   EnvMgr;
   llvm::OwningPtr<StoreManager>        StMgr;
   llvm::OwningPtr<ConstraintManager>   ConstraintMgr;
+  MemRegionManager                     MRMgr;
   GRState::IntSetTy::Factory           ISetFactory;
   
   GRState::GenericDataMap::Factory     GDMFactory;
@@ -273,10 +261,6 @@
   /// Alloc - A BumpPtrAllocator to allocate states.
   llvm::BumpPtrAllocator& Alloc;
   
-  /// DRoots - A vector to hold of worklist used by RemoveDeadSymbols.
-  ///  This vector is persistent because it is reused over and over.
-  StoreManager::DeclRootsTy DRoots;
-  
   /// CurrentStmt - The block-level statement currently being visited.  This
   ///  is set by GRExprEngine.
   Stmt* CurrentStmt;
@@ -297,10 +281,10 @@
   Environment RemoveBlkExpr(const Environment& Env, Expr* E) {
     return EnvMgr.RemoveBlkExpr(Env, E);
   }
-   
+  
   // FIXME: Remove when we do lazy initializaton of variable bindings.
   const GRState* BindVar(const GRState* St, VarDecl* D, RVal V) {
-    return SetRVal(St, lval::DeclVal(D), V);
+    return SetRVal(St, getLVal(D), V);
   }
     
 public:
@@ -313,7 +297,8 @@
                  ConstraintManagerCreator CreateConstraintManager,
                  llvm::BumpPtrAllocator& alloc, CFG& c, LiveVariables& L) 
   : EnvMgr(alloc),
-    ISetFactory(alloc), 
+    MRMgr(alloc),
+    ISetFactory(alloc),
     GDMFactory(alloc),
     BasicVals(Ctx, alloc),
     SymMgr(alloc),
@@ -334,6 +319,7 @@
   SymbolManager& getSymbolManager() { return SymMgr; }
   LiveVariables& getLiveVariables() { return Liveness; }
   llvm::BumpPtrAllocator& getAllocator() { return Alloc; }
+  MemRegionManager& getRegionManager() { return MRMgr; }
 
   typedef StoreManager::DeadSymbolsTy DeadSymbolsTy;
 
@@ -350,6 +336,17 @@
     return getPersistentState(NewSt);
   }
 
+  
+  // Utility methods for getting regions.
+  
+  VarRegion* getRegion(const VarDecl* D) {
+    return MRMgr.getVarRegion(D);
+  }
+  
+  lval::MemRegionVal getLVal(const VarDecl* D) {
+    return lval::MemRegionVal(getRegion(D));
+  }
+  
   // Methods that query & manipulate the Environment.
   
   RVal GetRVal(const GRState* St, Expr* Ex) {
@@ -394,19 +391,17 @@
   // Methods that manipulate the GDM.
   const GRState* addGDM(const GRState* St, void* Key, void* Data);
   
-  // Methods that query & manipulate the Store.
-  
-  /// getBindings - Returns all store bindings in the specified state that bind
-  ///  to the specified symbolic value.
-  void getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
-                   const GRState* St, SymbolID Sym) {
-    StMgr->getBindings(bindings, St->getStore(), Sym);    
+  // Methods that query or create regions.
+  bool hasStackStorage(const MemRegion* R) {
+    return getRegionManager().hasStackStorage(R);
   }
   
-  /// BindingAsString - Returns a string representing the given store binding.
-  std::string BindingAsString(store::Binding binding) {
-    return StMgr->BindingAsString(binding);
+  // Methods that query & manipulate the Store.
+
+  void iterBindings(const GRState* state, StoreManager::BindingsHandler& F) {
+    StMgr->iterBindings(state->getStore(), F);
   }
+    
   
   RVal GetRVal(const GRState* St, LVal LV, QualType T = QualType()) {
     return StMgr->GetRVal(St->getStore(), LV, T);

Added: cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h?rev=57042&view=auto

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h (added)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h Sat Oct  4 00:50:14 2008
@@ -0,0 +1,267 @@
+//== MemRegion.h - Abstract memory regions for static analysis --*- C++ -*--==//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines MemRegion and its subclasses.  MemRegion defines a
+//  partially-typed abstraction of memory useful for path-sensitive dataflow
+//  analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_ANALYSIS_MEMREGION_H
+#define LLVM_CLANG_ANALYSIS_MEMREGION_H
+
+#include "llvm/Support/Casting.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/Support/Allocator.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include <string>
+
+namespace llvm { class raw_ostream; }
+
+namespace clang {
+ 
+class MemRegionManager;
+  
+      
+/// MemRegion - The root abstract class for all memory regions.
+class MemRegion : public llvm::FoldingSetNode {
+public:
+  enum Kind { MemSpaceRegionKind,
+              // Typed regions.
+              BEG_TYPED_REGIONS,
+              VarRegionKind, FieldRegionKind, ObjCIvarRegionKind,
+              AnonTypedRegionKind,
+              END_TYPED_REGIONS };  
+private:
+  const Kind kind;
+  
+protected:
+  MemRegion(Kind k) : kind(k) {}
+  virtual ~MemRegion();
+
+public:
+  // virtual MemExtent getExtent(MemRegionManager& mrm) const = 0;
+  virtual const MemRegion* getSuperRegion() const = 0;
+  virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
+  
+  std::string getString() const;
+  virtual void print(llvm::raw_ostream& os) const;  
+  
+  Kind getKind() const { return kind; }  
+  static bool classof(const MemRegion*) { return true; }
+};
+  
+/// MemSpaceRegion - A memory region that represents and "memory space";
+///  for example, the set of global variables, the stack frame, etc.
+class MemSpaceRegion : public MemRegion {
+  friend class MemRegionManager;
+  MemSpaceRegion() : MemRegion(MemSpaceRegionKind) {}
+  
+public:
+  //RegionExtent getExtent() const { return UndefinedExtent(); }
+
+  const MemRegion* getSuperRegion() const {
+    return 0;
+  }
+    
+  //static void ProfileRegion(llvm::FoldingSetNodeID& ID);
+  void Profile(llvm::FoldingSetNodeID& ID) const;
+
+  static bool classof(const MemRegion* R) {
+    return R->getKind() == MemSpaceRegionKind;
+  }
+};
+
+/// TypedRegion - An abstract class representing regions that are typed.
+class TypedRegion : public MemRegion {
+protected:
+  const MemRegion* superRegion;
+
+  TypedRegion(const MemRegion* sReg, Kind k)
+    : MemRegion(k), superRegion(sReg) {};
+  
+public:
+  virtual QualType getType() const = 0;
+  
+  // MemExtent getExtent(MemRegionManager& mrm) const;
+  const MemRegion* getSuperRegion() const {
+    return superRegion;
+  }
+  
+  static bool classof(const MemRegion* R) {
+    unsigned k = R->getKind();
+    return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS;
+  }
+};
+
+/// AnonTypedRegion - An "anonymous" region that simply types a chunk
+///  of memory.
+class AnonTypedRegion : public TypedRegion {
+  QualType T;
+
+  friend class MemRegionManager;
+  
+  AnonTypedRegion(QualType t, MemRegion* sreg)
+    : TypedRegion(sreg, AnonTypedRegionKind), T(t) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
+                      const MemRegion* superRegion);
+  
+public:
+  QualType getType() const { return T; }
+  
+
+  void Profile(llvm::FoldingSetNodeID& ID) const;
+  
+  static bool classof(const MemRegion* R) {
+    return R->getKind() == AnonTypedRegionKind;
+  }
+};
+
+class DeclRegion : public TypedRegion {
+protected:
+  const Decl* D;
+
+  DeclRegion(const Decl* d, MemRegion* sReg, Kind k)
+    : TypedRegion(sReg, k), D(d) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
+                      const MemRegion* superRegion, Kind k);
+  
+public:  
+  void Profile(llvm::FoldingSetNodeID& ID) const;
+};
+  
+class VarRegion : public DeclRegion {
+  friend class MemRegionManager;
+  
+  VarRegion(const VarDecl* vd, MemRegion* sReg)
+    : DeclRegion(vd, sReg, VarRegionKind) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID& ID, VarDecl* VD,
+                      const MemRegion* superRegion) {
+    DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
+  }
+  
+public:  
+  const VarDecl* getDecl() const { return cast<VarDecl>(D); }
+  QualType getType() const { return getDecl()->getType(); }
+  
+  void print(llvm::raw_ostream& os) const;
+  
+  static bool classof(const MemRegion* R) {
+    return R->getKind() == VarRegionKind;
+  }  
+};
+
+class FieldRegion : public DeclRegion {
+  friend class MemRegionManager;
+
+  FieldRegion(const FieldDecl* fd, MemRegion* sReg)
+    : DeclRegion(fd, sReg, FieldRegionKind) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID& ID, FieldDecl* FD,
+                      const MemRegion* superRegion) {
+    DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
+  }
+  
+public:
+  const FieldDecl* getDecl() const { return cast<FieldDecl>(D); }
+  QualType getType() const { return getDecl()->getType(); }
+    
+  static bool classof(const MemRegion* R) {
+    return R->getKind() == FieldRegionKind;
+  }
+};
+  
+class ObjCIvarRegion : public DeclRegion {
+  
+  friend class MemRegionManager;
+  
+  ObjCIvarRegion(const ObjCIvarDecl* ivd, MemRegion* sReg)
+    : DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
+
+  static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCIvarDecl* ivd,
+                      const MemRegion* superRegion) {
+    DeclRegion::ProfileRegion(ID, ivd, superRegion, ObjCIvarRegionKind);
+  }
+  
+public:
+  const ObjCIvarDecl* getDecl() const { return cast<ObjCIvarDecl>(D); }
+  QualType getType() const { return getDecl()->getType(); }
+  
+  static bool classof(const MemRegion* R) {
+    return R->getKind() == ObjCIvarRegionKind;
+  }
+};
+  
+//===----------------------------------------------------------------------===//
+// MemRegionManager - Factory object for creating regions.
+//===----------------------------------------------------------------------===//
+
+class MemRegionManager {
+  llvm::BumpPtrAllocator& A;
+  llvm::FoldingSet<MemRegion> Regions;
+  
+  MemSpaceRegion* globals;
+  MemSpaceRegion* stack;
+  MemSpaceRegion* heap;
+  
+public:
+  MemRegionManager(llvm::BumpPtrAllocator& a)
+  : A(a), globals(0), stack(0), heap(0) {}
+  
+  ~MemRegionManager() {}
+  
+  /// getStackRegion - Retrieve the memory region associated with the
+  ///  current stack frame.
+  MemSpaceRegion* getStackRegion();
+  
+  /// getGlobalsRegion - Retrieve the memory region associated with
+  ///  all global variables.
+  MemSpaceRegion* getGlobalsRegion();
+  
+  /// getHeapRegion - Retrieve the memory region associated with the
+  ///  generic "heap".
+  MemSpaceRegion* getHeapRegion();
+  
+  /// getVarRegion - Retrieve or create the memory region associated with
+  ///  a specified VarDecl.  'superRegion' corresponds to the containing
+  ///  memory region, and 'off' is the offset within the containing region.
+  VarRegion* getVarRegion(const VarDecl* vd, MemRegion* superRegion);
+  
+  VarRegion* getVarRegion(const VarDecl* vd) {
+    return getVarRegion(vd, vd->hasLocalStorage() ? getStackRegion() 
+                        : getGlobalsRegion());
+  }
+  
+  /// getFieldRegion - Retrieve or create the memory region associated with
+  ///  a specified FieldDecl.  'superRegion' corresponds to the containing
+  ///  memory region (which typically represents the memory representing
+  ///  a structure or class).
+  FieldRegion* getFieldRegion(const FieldDecl* fd, MemRegion* superRegion);
+  
+  /// getObjCIvarRegion - Retrieve or create the memory region associated with
+  ///   a specified Objective-c instance variable.  'superRegion' corresponds
+  ///   to the containing region (which typically represents the Objective-C
+  ///   object).
+  ObjCIvarRegion* getObjCIvarRegion(const ObjCIvarDecl* ivd,
+                                    MemRegion* superRegion);
+  
+  bool hasStackStorage(const MemRegion* R);
+  
+private:
+  MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
+};
+
+
+  
+} // end clang namespace
+#endif

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Sat Oct  4 00:50:14 2008
@@ -24,6 +24,9 @@
 
 namespace clang {
   
+class MemRegion;
+class GRStateManager;
+  
 class RVal {
 public:
   enum BaseKind { UndefinedKind, UnknownKind, LValKind, NonLValKind };
@@ -92,7 +95,7 @@
   symbol_iterator symbol_begin() const;
   symbol_iterator symbol_end() const;  
   
-  static RVal MakeVal(BasicValueFactory& BasicVals, DeclRefExpr* E);
+  static RVal MakeVal(GRStateManager& SMgr, DeclRefExpr* E);
   
   // Implement isa<T> support.
   static inline bool classof(const RVal*) { return true; }
@@ -285,7 +288,7 @@
 
 namespace lval {
   
-enum Kind { SymbolValKind, GotoLabelKind, DeclValKind, FuncValKind,
+enum Kind { SymbolValKind, GotoLabelKind, MemRegionKind, FuncValKind,
             ConcreteIntKind, StringLiteralValKind, FieldOffsetKind,
             ArrayOffsetKind };
 
@@ -327,30 +330,30 @@
 };
   
 
-class DeclVal : public LVal {
+class MemRegionVal : public LVal {
 public:
-  DeclVal(const VarDecl* vd) : LVal(DeclValKind, vd) {}
-  
-  VarDecl* getDecl() const {
-    return static_cast<VarDecl*>(Data);
+  MemRegionVal(const MemRegion* r) : LVal(MemRegionKind, r) {}
+
+  MemRegion* getRegion() const {
+    return static_cast<MemRegion*>(Data);
   }
   
-  inline bool operator==(const DeclVal& R) const {
-    return getDecl() == R.getDecl();
+  inline bool operator==(const MemRegionVal& R) const {
+    return getRegion() == R.getRegion();
   }
   
-  inline bool operator!=(const DeclVal& R) const {
-    return getDecl() != R.getDecl();
+  inline bool operator!=(const MemRegionVal& R) const {
+    return getRegion() != R.getRegion();
   }
   
   // Implement isa<T> support.
   static inline bool classof(const RVal* V) {
     return V->getBaseKind() == LValKind &&
-           V->getSubKind() == DeclValKind;
+           V->getSubKind() == MemRegionKind;
   }
   
   static inline bool classof(const LVal* V) {
-    return V->getSubKind() == DeclValKind;
+    return V->getSubKind() == MemRegionKind;
   }    
 };
 

Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Store.h?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Store.h Sat Oct  4 00:50:14 2008
@@ -19,127 +19,21 @@
 #include "llvm/ADT/SmallSet.h"
 #include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/SmallVector.h"
-#include <vector>
 #include <iosfwd>
 
 namespace clang {
   
 typedef const void* Store;
   
-namespace store {
-  /// Region - A region represents an abstract chunk of memory.  Subclasses
-  ///  of StoreManager are responsible for defining the particular semantics
-  ///  of Region for the store they represent.
-  class Region {
-  protected:
-    const void* Data;
-    Region(const void* data) : Data(data) {}
-  public:
-    Region() : Data(0) {}
-  };
-  
-  /// Binding - A "binding" represents a binding of a value to an abstract
-  ///  chunk of memory (which is represented by a region).  Subclasses of
-  ///  StoreManager are responsible for defining the particular semantics
-  ///  of a Binding.
-  class Binding {
-  protected:
-    const void* first;
-    const void* second;
-    Binding(const void* f, const void* s = 0) : first(f), second(s) {}
-  public:
-    Binding() : first(0), second(0) {}
-    operator bool() const { return first || second; }
-  };
-  
-  /// RegionExtent - Represents the size, or extent, or an abstract memory
-  ///  chunk (a region).  Sizes are in bits.  RegionExtent is essentially a
-  ///  variant with three subclasses: UnknownExtent, FixedExtent,
-  ///  and SymbolicExtent.  
-  class RegionExtent {
-  public:
-    enum Kind { Unknown = 0, Fixed = 0, Sym = 1 };
-    
-  protected:
-    const uintptr_t Raw;
-    RegionExtent(uintptr_t raw, Kind k) : Raw(raw | k) {}
-    uintptr_t getData() const { return Raw & ~0x1; }
-    
-  public:
-    // Folding-set profiling.
-    void Profile(llvm::FoldingSetNodeID& ID) const {
-      ID.AddPointer((void*) Raw);
-    }  
-    // Comparing extents.
-    bool operator==(const RegionExtent& R) const {
-      return Raw == R.Raw;
-    }
-    bool operator!=(const RegionExtent& R) const {
-      return Raw != R.Raw;
-    }  
-    // Implement isa<T> support.
-    Kind getKind() const { return Kind(Raw & 0x1); }
-    uintptr_t getRaw() const { return Raw; }
-    
-    static inline bool classof(const RegionExtent*) {
-      return true;
-    }
-  };
-  
-  /// UnknownExtent - Represents a region extent with no available information
-  ///  about the size of the region.
-  class UnknownExtent : public RegionExtent {
-  public:
-    UnknownExtent() : RegionExtent(0,Unknown) {}
-    
-    // Implement isa<T> support.
-    static inline bool classof(const RegionExtent* E) {
-      return E->getRaw() == 0;
-    }  
-  };
-  
-  /// FixedExtent - Represents a region extent with a known fixed size.
-  ///  Typically FixedExtents are used to represent the size of variables, but
-  ///  they can also be used to represent the size of a constant-sized array.
-  class FixedExtent : public RegionExtent {
-  public:
-    FixedExtent(const llvm::APSInt& X) : RegionExtent((uintptr_t) &X, Fixed) {}
-    
-    const llvm::APSInt& getInt() const {
-      return *((llvm::APSInt*) getData());
-    }
-    
-    // Implement isa<T> support.
-    static inline bool classof(const RegionExtent* E) {
-      return E->getKind() == Fixed && E->getRaw() != 0;
-    }
-  };
-  
-  /// SymbolicExtent - Represents the extent of a region where the extent
-  ///  itself is a symbolic value.  These extents can be used to represent
-  ///  the sizes of dynamically allocated chunks of memory with variable size.
-  class SymbolicExtent : public RegionExtent {
-  public:
-    SymbolicExtent(SymbolID S) : RegionExtent(S.getNumber() << 1, Sym) {}
-    
-    SymbolID getSymbol() const { return SymbolID(getData() >> 1); }
-    
-    // Implement isa<T> support.
-    static inline bool classof(const RegionExtent* E) {
-      return E->getKind() == Sym;
-    }  
-  };
-} // end store namespace
-  
 class GRStateManager;
 class LiveVariables;
 class Stmt;
+class MemRegion;
   
 class StoreManager {
 public:
   typedef llvm::SmallSet<SymbolID, 20>      LiveSymbolsTy;
   typedef llvm::DenseSet<SymbolID>          DeadSymbolsTy;
-  typedef std::vector<ValueDecl*>           DeclRootsTy;
   
   virtual ~StoreManager() {}
   virtual RVal GetRVal(Store St, LVal LV, QualType T = QualType()) = 0;
@@ -147,10 +41,10 @@
   virtual Store Remove(Store St, LVal LV) = 0;
   virtual Store getInitialStore(GRStateManager& StateMgr) = 0;
   
-  virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
-                                   const LiveVariables& Live,
-                                   DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,                                  
-                                   DeadSymbolsTy& DSymbols) = 0;
+  virtual Store
+  RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live,
+                     llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
+                     LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) = 0;
 
   virtual Store AddDecl(Store store, GRStateManager& StMgr,
                         const VarDecl* VD, Expr* Ex, 
@@ -163,29 +57,14 @@
   public:    
     virtual ~BindingsHandler();
     virtual bool HandleBinding(StoreManager& SMgr, Store store,
-                               store::Binding binding) = 0;
+                               MemRegion* R, RVal val) = 0;
   };
   
   /// iterBindings - Iterate over the bindings in the Store.
-  virtual void iterBindings(Store store, BindingsHandler& f) = 0;
-  
-  /// getBindings - Returns all bindings in the specified store that bind
-  ///  to the specified symbolic value.
-  void getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
-                   Store store, SymbolID Sym);
-  
-  /// BindingAsString - Returns a string representing the given binding.
-  virtual std::string BindingAsString(store::Binding binding) = 0;
-  
-  /// getExtent - Returns the size of the region in bits.
-  virtual store::RegionExtent getExtent(store::Region R) = 0;
-
-  /// getRVal - Returns the bound RVal for a given binding.
-  virtual RVal getRVal(Store store, store::Binding binding) = 0;
+  virtual void iterBindings(Store store, BindingsHandler& f) = 0;  
 };
   
 StoreManager* CreateBasicStoreManager(GRStateManager& StMgr);
-
   
 } // end clang namespace
 

Modified: cfe/trunk/lib/Analysis/BasicConstraintManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicConstraintManager.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/BasicConstraintManager.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicConstraintManager.cpp Sat Oct  4 00:50:14 2008
@@ -129,7 +129,7 @@
       return AssumeSymEQ(St, cast<lval::SymbolVal>(Cond).getSymbol(),
                          BasicVals.getZeroWithPtrWidth(), isFeasible);
 
-  case lval::DeclValKind:
+  case lval::MemRegionKind:
   case lval::FuncValKind:
   case lval::GotoLabelKind:
   case lval::StringLiteralValKind:

Modified: cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp Sat Oct  4 00:50:14 2008
@@ -20,6 +20,7 @@
 #include "clang/Analysis/PathSensitive/GRExprEngine.h"
 #include "clang/Analysis/PathSensitive/GRState.h"
 #include "clang/Analysis/PathSensitive/BugReporter.h"
+#include "clang/Analysis/PathSensitive/MemRegion.h"
 #include "clang/Analysis/PathDiagnostic.h"
 #include "clang/Analysis/LocalCheckers.h"
 
@@ -366,7 +367,7 @@
   
 private:
   
-  void AddError(VarDecl* V, Expr* Ex, ExplodedNode<GRState> *N,
+  void AddError(TypedRegion* R, Expr* Ex, ExplodedNode<GRState> *N,
                 uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);  
 };
 } // end anonymous namespace
@@ -497,12 +498,17 @@
   
   // FIXME: Eventually we should handle arbitrary locations.  We can do this
   //  by having an enhanced memory model that does low-level typing.
-  lval::DeclVal* LV = dyn_cast<lval::DeclVal>(&TheValueExpr);
+  lval::MemRegionVal* LV = dyn_cast<lval::MemRegionVal>(&TheValueExpr);
 
   if (!LV)
     return false;
   
-  QualType T = Ctx.getCanonicalType(LV->getDecl()->getType());
+  TypedRegion* R = dyn_cast<TypedRegion>(LV->getRegion());
+  if (!R)
+    return false;
+  
+  
+  QualType T = Ctx.getCanonicalType(R->getType());
   
   // FIXME: If the pointee isn't an integer type, should we flag a warning?
   //  People can do weird stuff with pointers.
@@ -517,14 +523,14 @@
   if (SourceSize == TargetSize)
     return false;
     
-  AddError(LV->getDecl(), CE->getArg(2), N, SourceSize, TargetSize, NumberKind);
+  AddError(R, CE->getArg(2), N, SourceSize, TargetSize, NumberKind);
   
   // FIXME: We can actually create an abstract "CFNumber" object that has
   //  the bits initialized to the provided values.
   return SourceSize < TargetSize;
 }
 
-void AuditCFNumberCreate::AddError(VarDecl* V, Expr* Ex,
+void AuditCFNumberCreate::AddError(TypedRegion* R, Expr* Ex,
                                    ExplodedNode<GRState> *N,
                                    uint64_t SourceSize, uint64_t TargetSize,
                                    uint64_t NumberKind) {

Modified: cfe/trunk/lib/Analysis/BasicStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicStore.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/BasicStore.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicStore.cpp Sat Oct  4 00:50:14 2008
@@ -18,10 +18,8 @@
 #include "llvm/Support/Streams.h"
 
 using namespace clang;
-using store::Region;
-using store::RegionExtent;
 
-typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;  
+typedef llvm::ImmutableMap<const VarDecl*,RVal> VarBindingsTy;  
 
 namespace {
   
@@ -40,10 +38,10 @@
 
   virtual Store getInitialStore(GRStateManager& StateMgr);
   
-  virtual Store RemoveDeadBindings(Store store, Stmt* Loc,
-                                   const LiveVariables& Live,
-                                   DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
-                                   DeadSymbolsTy& DSymbols);
+  virtual Store
+  RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live,
+                     llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
+                     LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols);
 
   virtual void iterBindings(Store store, BindingsHandler& f);
 
@@ -57,42 +55,9 @@
 
   virtual void print(Store store, std::ostream& Out,
                      const char* nl, const char *sep);
-  
-  virtual RegionExtent getExtent(Region R);
-  
-  /// BindingAsString - Returns a string representing the given binding.
-  virtual std::string BindingAsString(store::Binding binding);
-  
-  /// getRVal - Returns the bound RVal for a given binding.
-  virtual RVal getRVal(Store store, store::Binding binding);
-};
-  
-class VISIBILITY_HIDDEN VarRegion : public store::Region {
-public:
-  VarRegion(VarDecl* VD) : Region(VD) {}  
-  VarDecl* getDecl() const { return (VarDecl*) Data; }    
-  static bool classof(const store::Region*) { return true; }
-};
-
-class VISIBILITY_HIDDEN VarBinding : public store::Binding {
-public:
-  VarBinding(VarBindingsTy::value_type* T) : store::Binding(T) {}
-  
-  const VarBindingsTy::value_type_ref getValue() const {
-    return *static_cast<const VarBindingsTy::value_type*>(first);
-  }
     
-  std::string getName() const {
-    return getValue().first->getName();
-  }
-  
-  RVal getRVal() const {
-    return getValue().second;
-  }
-  
-  static inline bool classof(const store::Binding*) { return true; }
 };
-  
+    
 } // end anonymous namespace
 
 
@@ -100,22 +65,6 @@
   return new BasicStoreManager(StMgr);
 }
 
-RegionExtent BasicStoreManager::getExtent(Region R) {
-  QualType T = cast<VarRegion>(&R)->getDecl()->getType();
-  
-  // FIXME: Add support for VLAs.  This may require passing in additional
-  //  information, or tracking a different region type.
-  if (!T.getTypePtr()->isConstantSizeType())
-    return store::UnknownExtent();
-  
-  ASTContext& C = StMgr.getContext();
-  assert (!T->isObjCInterfaceType()); // @interface not a possible VarDecl type.
-  assert (T != C.VoidTy); // void not a possible VarDecl type.  
-  return store::FixedExtent(StMgr.getBasicVals().getValue(C.getTypeSize(T),
-                                                          C.VoidPtrTy));
-}
-
-
 RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
   
   if (isa<UnknownVal>(LV))
@@ -125,9 +74,15 @@
   
   switch (LV.getSubKind()) {
 
-    case lval::DeclValKind: {      
+    case lval::MemRegionKind: {
+      VarRegion* R =
+        dyn_cast<VarRegion>(cast<lval::MemRegionVal>(LV).getRegion());
+      
+      if (!R)
+        return UnknownVal();
+        
       VarBindingsTy B(static_cast<const VarBindingsTy::TreeTy*>(St));      
-      VarBindingsTy::data_type* T = B.lookup(cast<lval::DeclVal>(LV).getDecl());      
+      VarBindingsTy::data_type* T = B.lookup(R->getDecl());      
       return T ? *T : UnknownVal();
     }
       
@@ -161,11 +116,17 @@
 
 Store BasicStoreManager::SetRVal(Store store, LVal LV, RVal V) {    
   switch (LV.getSubKind()) {      
-    case lval::DeclValKind: {
+    case lval::MemRegionKind: {
+      VarRegion* R =
+        dyn_cast<VarRegion>(cast<lval::MemRegionVal>(LV).getRegion());
+      
+      if (!R)
+        return store;
+      
       VarBindingsTy B = GetVarBindings(store);
       return V.isUnknown()
-        ? VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot()
-        : VBFactory.Add(B, cast<lval::DeclVal>(LV).getDecl(), V).getRoot();
+        ? VBFactory.Remove(B, R->getDecl()).getRoot()
+        : VBFactory.Add(B, R->getDecl(), V).getRoot();
     }
     default:
       assert ("SetRVal for given LVal type not yet implemented.");
@@ -175,9 +136,15 @@
 
 Store BasicStoreManager::Remove(Store store, LVal LV) {
   switch (LV.getSubKind()) {
-    case lval::DeclValKind: {
+    case lval::MemRegionKind: {
+      VarRegion* R =
+      dyn_cast<VarRegion>(cast<lval::MemRegionVal>(LV).getRegion());
+      
+      if (!R)
+        return store;
+      
       VarBindingsTy B = GetVarBindings(store);
-      return VBFactory.Remove(B,cast<lval::DeclVal>(LV).getDecl()).getRoot();
+      return VBFactory.Remove(B,R->getDecl()).getRoot();
     }
     default:
       assert ("Remove for given LVal type not yet implemented.");
@@ -185,12 +152,11 @@
   }
 }
 
-Store BasicStoreManager::RemoveDeadBindings(Store store,
-                                            Stmt* Loc,
-                                            const LiveVariables& Liveness,
-                                            DeclRootsTy& DRoots,
-                                            LiveSymbolsTy& LSymbols,
-                                            DeadSymbolsTy& DSymbols) {
+Store
+BasicStoreManager::RemoveDeadBindings(Store store, Stmt* Loc,
+                          const LiveVariables& Liveness,
+                          llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
+                          LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) {
   
   VarBindingsTy B = GetVarBindings(store);
   typedef RVal::symbol_iterator symbol_iterator;
@@ -198,7 +164,7 @@
   // Iterate over the variable bindings.
   for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
     if (Liveness.isLive(Loc, I.getKey())) {
-      DRoots.push_back(I.getKey());      
+      RegionRoots.push_back(StMgr.getRegion(I.getKey()));      
       RVal X = I.getData();
       
       for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
@@ -206,39 +172,43 @@
     }
   
   // Scan for live variables and live symbols.
-  llvm::SmallPtrSet<ValueDecl*, 10> Marked;
+  llvm::SmallPtrSet<const VarRegion*, 10> Marked;
   
-  while (!DRoots.empty()) {
-    ValueDecl* V = DRoots.back();
-    DRoots.pop_back();
+  while (!RegionRoots.empty()) {
+    const VarRegion* R = cast<VarRegion>(RegionRoots.back());
+    RegionRoots.pop_back();
     
-    if (Marked.count(V))
+    if (Marked.count(R))
       continue;
     
-    Marked.insert(V);
-    
-    RVal X = GetRVal(store, lval::DeclVal(cast<VarDecl>(V)), QualType());      
+    Marked.insert(R);    
+    // FIXME: Do we need the QualType here, since regions are partially
+    // typed?
+    RVal X = GetRVal(store, lval::MemRegionVal(R), QualType());      
     
     for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
       LSymbols.insert(*SI);
     
-    if (!isa<lval::DeclVal>(X))
+    if (!isa<lval::MemRegionVal>(X))
       continue;
     
-    const lval::DeclVal& LVD = cast<lval::DeclVal>(X);
-    DRoots.push_back(LVD.getDecl());
+    const lval::MemRegionVal& LVD = cast<lval::MemRegionVal>(X);
+    RegionRoots.push_back(cast<VarRegion>(LVD.getRegion()));
   }
   
   // Remove dead variable bindings.  
-  for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I)
-    if (!Marked.count(I.getKey())) {
-      store = Remove(store, lval::DeclVal(I.getKey()));
+  for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I!=E ; ++I) {
+    const VarRegion* R = cast<VarRegion>(StMgr.getRegion(I.getKey()));
+    
+    if (!Marked.count(R)) {
+      store = Remove(store, lval::MemRegionVal(R));
       RVal X = I.getData();
       
       for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
         if (!LSymbols.count(*SI)) DSymbols.insert(*SI);
     }
-
+  }
+  
   return store;
 }
 
@@ -270,7 +240,7 @@
                  ? RVal::GetSymbolValue(StateMgr.getSymbolManager(), VD)
                  : UndefinedVal();
 
-        St = SetRVal(St, lval::DeclVal(VD), X);
+        St = SetRVal(St, StMgr.getLVal(VD), X);
       }
     }
   }
@@ -310,16 +280,16 @@
       if (!Ex) {
         QualType T = VD->getType();
         if (LVal::IsLValType(T))
-          store = SetRVal(store, lval::DeclVal(VD),
+          store = SetRVal(store, StMgr.getLVal(VD),
                           lval::ConcreteInt(BasicVals.getValue(0, T)));
         else if (T->isIntegerType())
-          store = SetRVal(store, lval::DeclVal(VD),
+          store = SetRVal(store, StMgr.getLVal(VD),
                           nonlval::ConcreteInt(BasicVals.getValue(0, T)));
         else {
           // assert(0 && "ignore other types of variables");
         }
       } else {
-        store = SetRVal(store, lval::DeclVal(VD), InitVal);
+        store = SetRVal(store, StMgr.getLVal(VD), InitVal);
       }
     }
   } else {
@@ -337,7 +307,7 @@
           : cast<RVal>(nonlval::SymbolVal(Sym));
       }
 
-      store = SetRVal(store, lval::DeclVal(VD), V);
+      store = SetRVal(store, StMgr.getLVal(VD), V);
     }
   }
 
@@ -366,57 +336,9 @@
   VarBindingsTy B = GetVarBindings(store);
   
   for (VarBindingsTy::iterator I=B.begin(), E=B.end(); I != E; ++I) {
-    VarBinding binding(&(*I));
-    f.HandleBinding(*this, store, binding);
-  }
-}
-
-
-std::string BasicStoreManager::BindingAsString(store::Binding binding) {
-  return cast<VarBinding>(binding).getName();
-}
-
-RVal BasicStoreManager::getRVal(Store store, store::Binding binding) {
-  return cast<VarBinding>(binding).getRVal();
-}
 
-//==------------------------------------------------------------------------==//
-// Generic store operations.
-//==------------------------------------------------------------------------==//
-
-namespace {
-class VISIBILITY_HIDDEN GetBindingsIterator : public StoreManager::BindingsHandler {
-  SymbolID Sym;
-  llvm::SmallVectorImpl<store::Binding>& bindings;
-public:
-  GetBindingsIterator(SymbolID s, llvm::SmallVectorImpl<store::Binding>& b)
-  : Sym(s), bindings(b) {}
-  
-  virtual bool HandleBinding(StoreManager& SMgr, Store store,
-                             store::Binding binding) {
-    
-    RVal V = SMgr.getRVal(store, binding);
-    
-    if (const lval::SymbolVal* SV=dyn_cast<lval::SymbolVal>(&V)) {
-      if (SV->getSymbol() == Sym) 
-        bindings.push_back(binding);      
-    }    
-    else if (const nonlval::SymbolVal* SV=dyn_cast<nonlval::SymbolVal>(&V)){
-      if (SV->getSymbol() == Sym) 
-        bindings.push_back(binding);
-    }
-    
-    return true;
+    f.HandleBinding(*this, store, StMgr.getRegion(I.getKey()),I.getData());
   }
-}; 
-} // end anonymous namespace
-
-void StoreManager::getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
-                               Store store, SymbolID Sym) {
-  
-  GetBindingsIterator BI(Sym, bindings);
-  iterBindings(store, BI);
 }
 
 StoreManager::BindingsHandler::~BindingsHandler() {}
-

Modified: cfe/trunk/lib/Analysis/BugReporter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BugReporter.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/BugReporter.cpp (original)
+++ cfe/trunk/lib/Analysis/BugReporter.cpp Sat Oct  4 00:50:14 2008
@@ -322,32 +322,27 @@
   return 0;
 }
 
+namespace {
+class VISIBILITY_HIDDEN NotableSymbolHandler 
+  : public StoreManager::BindingsHandler {
+    
+  SymbolID Sym;
+  const GRState* PrevSt;
+  Stmt* S;
+  GRStateManager& VMgr;
+  ExplodedNode<GRState>* Pred;
+  PathDiagnostic& PD; 
+  BugReporter& BR;
+    
+public:
+  
+  NotableSymbolHandler(SymbolID sym, const GRState* prevst, Stmt* s,
+                       GRStateManager& vmgr, ExplodedNode<GRState>* pred,
+                       PathDiagnostic& pd, BugReporter& br)
+    : Sym(sym), PrevSt(prevst), S(s), VMgr(vmgr), Pred(pred), PD(pd), BR(br) {}
+                        
+  bool HandleBinding(StoreManager& SMgr, Store store, MemRegion* R, RVal V) {
 
-static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
-                                SymbolID Sym, BugReporter& BR,
-                                PathDiagnostic& PD) {
-  
-  ExplodedNode<GRState>* Pred = N->pred_empty() ? 0 : *N->pred_begin();
-  const GRState* PrevSt = Pred ? Pred->getState() : 0;
-  
-  if (!PrevSt)
-    return;
-  
-  // Look at the variable bindings of the current state that map to the
-  // specified symbol.  Are any of them not in the previous state.
-  
-  const GRState* St = N->getState();
-  GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
-  
-  // FIXME: Later generalize for a broader memory model.
-
-  // FIXME: This is quadratic, since its nested in another loop.  Probably
-  //   doesn't matter, but keep an eye out for performance issues.  It's
-  //   also a bunch of copy-paste.  Bad.  Cleanup later.
-  
-  for (GRState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I){
-    
-    RVal V = I.getData();
     SymbolID ScanSym;
     
     if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
@@ -355,18 +350,17 @@
     else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
       ScanSym = SV->getSymbol();
     else
-      continue;
+      return true;
     
     if (ScanSym != Sym)
-      continue;
-    
-    // Check if the previous state has this binding.
+      return true;
     
-    RVal X = VMgr.GetRVal(PrevSt, lval::DeclVal(I.getKey()));
+    // Check if the previous state has this binding.    
+    RVal X = VMgr.GetRVal(PrevSt, lval::MemRegionVal(R));
     
     if (X == V) // Same binding?
-      continue;
-
+      return true;
+    
     // Different binding.  Only handle assignments for now.  We don't pull
     // this check out of the loop because we will eventually handle other 
     // cases.
@@ -375,41 +369,102 @@
     
     if (BinaryOperator* B = dyn_cast<BinaryOperator>(S)) {
       if (!B->isAssignmentOp())
-        continue;
+        return true;
       
       // What variable did we assign to?
       DeclRefExpr* DR = dyn_cast<DeclRefExpr>(B->getLHS()->IgnoreParenCasts());
       
       if (!DR)
-        continue;
+        return true;
       
       VD = dyn_cast<VarDecl>(DR->getDecl());
     }
     else if (DeclStmt* DS = dyn_cast<DeclStmt>(S))
       VD = dyn_cast<VarDecl>(DS->getDecl());
-      
+    
     if (!VD)
-      continue;
-      
+      return true;
+    
     // What is the most recently referenced variable with this binding?
     VarDecl* MostRecent = GetMostRecentVarDeclBinding(Pred, VMgr, V);
-        
+    
     if (!MostRecent)
-      continue;
-
+      return true;
+    
     // Create the diagnostic.
     
     FullSourceLoc L(S->getLocStart(), BR.getSourceManager());
-      
+    
     if (VD->getType()->isPointerLikeType()) {
       std::string msg = "'" + std::string(VD->getName()) +
-                        "' now aliases '" + MostRecent->getName() + "'";
+      "' now aliases '" + MostRecent->getName() + "'";
       
       PD.push_front(new PathDiagnosticPiece(L, msg));
     }
-  }
+    
+    return true;
+  }  
+};
+}
+
+static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
+                                SymbolID Sym, BugReporter& BR,
+                                PathDiagnostic& PD) {
+  
+  ExplodedNode<GRState>* Pred = N->pred_empty() ? 0 : *N->pred_begin();
+  const GRState* PrevSt = Pred ? Pred->getState() : 0;
+  
+  if (!PrevSt)
+    return;
+  
+  // Look at the region bindings of the current state that map to the
+  // specified symbol.  Are any of them not in the previous state?
+  GRStateManager& VMgr = cast<GRBugReporter>(BR).getStateManager();
+  NotableSymbolHandler H(Sym, PrevSt, S, VMgr, Pred, PD, BR);
+  cast<GRBugReporter>(BR).getStateManager().iterBindings(N->getState(), H);
 }
 
+namespace {
+class VISIBILITY_HIDDEN ScanNotableSymbols
+  : public StoreManager::BindingsHandler {
+    
+  llvm::SmallSet<SymbolID, 10> AlreadyProcessed;
+  ExplodedNode<GRState>* N;
+  Stmt* S;
+  GRBugReporter& BR;
+  PathDiagnostic& PD;
+    
+public:
+  ScanNotableSymbols(ExplodedNode<GRState>* n, Stmt* s, GRBugReporter& br,
+                     PathDiagnostic& pd)
+    : N(n), S(s), BR(br), PD(pd) {}
+  
+  bool HandleBinding(StoreManager& SMgr, Store store, MemRegion* R, RVal V) {
+    SymbolID ScanSym;
+  
+    if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
+      ScanSym = SV->getSymbol();
+    else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
+      ScanSym = SV->getSymbol();
+    else
+      return true;
+  
+    assert (ScanSym.isInitialized());
+  
+    if (!BR.isNotable(ScanSym))
+      return true;
+  
+    if (AlreadyProcessed.count(ScanSym))
+      return true;
+  
+    AlreadyProcessed.insert(ScanSym);
+  
+    HandleNotableSymbol(N, S, ScanSym, BR, PD);
+    return true;
+  }
+};
+} // end anonymous namespace
+
 void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
                                            BugReport& R) {
 
@@ -633,42 +688,11 @@
     if (PathDiagnosticPiece* p = R.VisitNode(N, NextNode, *ReportGraph, *this))
       PD.push_front(p);
     
-    if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {
-      
-      const GRState* St = N->getState();
-      
-      // Scan the lval bindings, and see if a "notable" symbol has a new
+    if (const PostStmt* PS = dyn_cast<PostStmt>(&P)) {      
+      // Scan the region bindings, and see if a "notable" symbol has a new
       // lval binding.
-      
-      // FIXME: In the future, when we generalize the memory model, we'll
-      //  need a way to iterate over binded locations.
-      
-      llvm::SmallSet<SymbolID, 10> AlreadyProcessed;
-      
-      for (GRState::vb_iterator I=St->vb_begin(), E=St->vb_end(); I!=E; ++I){
-        
-        RVal V = I.getData();
-        SymbolID ScanSym;
-        
-        if (lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&V))
-          ScanSym = SV->getSymbol();
-        else if (nonlval::SymbolVal* SV = dyn_cast<nonlval::SymbolVal>(&V))
-          ScanSym = SV->getSymbol();
-        else
-          continue;
-        
-        assert (ScanSym.isInitialized());
-        
-        if (!isNotable(ScanSym))
-          continue;
-        
-        if (AlreadyProcessed.count(ScanSym))
-          continue;
-        
-        AlreadyProcessed.insert(ScanSym);
-        
-        HandleNotableSymbol(N, PS->getStmt(), ScanSym, *this, PD);        
-      }
+      ScanNotableSymbols SNS(N, PS->getStmt(), *this, PD);
+      getStateManager().iterBindings(N->getState(), SNS);
     }
   }
 }

Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Sat Oct  4 00:50:14 2008
@@ -1489,7 +1489,7 @@
       // Nuke all arguments passed by reference.
       StateMgr.Unbind(StVals, cast<LVal>(V));
 #else
-      if (lval::DeclVal* DV = dyn_cast<lval::DeclVal>(&V)) {
+      if (lval::MemRegionVal* MR = dyn_cast<lval::MemRegionVal>(&V)) {
 
         if (GetArgE(Summ, idx) == DoNothingByRef)
           continue;
@@ -1506,23 +1506,28 @@
         //  disambiguate conjured symbols. 
 
         // Is the invalidated variable something that we were tracking?
-        RVal X = state.GetRVal(*DV);
+        RVal X = state.GetRVal(*MR);
         
         if (isa<lval::SymbolVal>(X)) {
           SymbolID Sym = cast<lval::SymbolVal>(X).getSymbol();
           state = state.remove<RefBindings>(Sym);
         }
-
-        // Set the value of the variable to be a conjured symbol.
-        unsigned Count = Builder.getCurrentBlockCount();
-        SymbolID NewSym =
-          Eng.getSymbolManager().getConjuredSymbol(*I, DV->getDecl()->getType(),
-                                                   Count);
-
-        state = state.SetRVal(*DV,
-                              LVal::IsLValType(DV->getDecl()->getType())
-                              ? cast<RVal>(lval::SymbolVal(NewSym))
-                              : cast<RVal>(nonlval::SymbolVal(NewSym)));
+        
+        TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion());
+        if (R) {
+          // Set the value of the variable to be a conjured symbol.
+          unsigned Count = Builder.getCurrentBlockCount();
+          QualType T = R->getType();
+          SymbolID NewSym =
+            Eng.getSymbolManager().getConjuredSymbol(*I, T, Count);
+          
+          state = state.SetRVal(*MR,
+                                LVal::IsLValType(T)
+                                ? cast<RVal>(lval::SymbolVal(NewSym))
+                                : cast<RVal>(nonlval::SymbolVal(NewSym)));
+        }
+        else
+          state = state.SetRVal(*MR, UnknownVal());
       }
       else {
         // Nuke all other arguments passed by reference.
@@ -1709,10 +1714,12 @@
   
   bool escapes = false;
   
-  if (!isa<lval::DeclVal>(TargetLV))
+  if (!isa<lval::MemRegionVal>(TargetLV))
     escapes = true;
-  else
-    escapes = cast<lval::DeclVal>(TargetLV).getDecl()->hasGlobalStorage();
+  else {
+    MemRegion* R = cast<lval::MemRegionVal>(TargetLV).getRegion();
+    escapes = !Eng.getStateManager().hasStackStorage(R);
+  }
   
   if (!escapes)
     return;
@@ -2307,14 +2314,51 @@
   return P;
 }
 
-static std::pair<ExplodedNode<GRState>*,store::Binding>
+namespace {
+class VISIBILITY_HIDDEN FindUniqueBinding :
+  public StoreManager::BindingsHandler {
+    SymbolID Sym;
+    MemRegion* Binding;
+    bool First;
+    
+  public:
+    FindUniqueBinding(SymbolID sym) : Sym(sym), Binding(0), First(true) {}
+    
+  bool HandleBinding(StoreManager& SMgr, Store store, MemRegion* R, RVal val) {
+    if (const lval::SymbolVal* SV = dyn_cast<lval::SymbolVal>(&val)) {
+      if (SV->getSymbol() != Sym) 
+        return true;
+    }
+    else if (const nonlval::SymbolVal* SV=dyn_cast<nonlval::SymbolVal>(&val)) {
+      if (SV->getSymbol() != Sym)
+        return true;
+    }
+    else
+      return true;
+
+    if (Binding) {
+      First = false;
+      return false;
+    }
+    else
+      Binding = R;
+    
+    return true;    
+  }
+    
+  operator bool() { return First && Binding; }
+  MemRegion* getRegion() { return Binding; }
+};  
+}
+
+static std::pair<ExplodedNode<GRState>*,MemRegion*>
 GetAllocationSite(GRStateManager* StateMgr, ExplodedNode<GRState>* N,
                   SymbolID Sym) {
 
   // Find both first node that referred to the tracked symbol and the
   // memory location that value was store to.
   ExplodedNode<GRState>* Last = N;
-  store::Binding FirstBinding;  
+  MemRegion* FirstBinding = 0;  
   
   while (N) {
     const GRState* St = N->getState();
@@ -2324,11 +2368,9 @@
       break;
 
     if (StateMgr) {
-      llvm::SmallVector<store::Binding, 5> Bindings;
-      StateMgr->getBindings(Bindings, St, Sym);
-
-      if (Bindings.size() == 1)
-        FirstBinding = Bindings[0];
+      FindUniqueBinding FB(Sym);
+      StateMgr->iterBindings(St, FB);      
+      if (FB) FirstBinding = FB.getRegion();      
     }
     
     Last = N;
@@ -2357,7 +2399,7 @@
   // symbol appeared, and also get the first VarDecl that tracked object
   // is stored to.
   ExplodedNode<GRState>* AllocNode = 0;
-  store::Binding FirstBinding;
+  MemRegion* FirstBinding = 0;
 
   llvm::tie(AllocNode, FirstBinding) =
     GetAllocationSite(&BR.getStateManager(), EndN, Sym);
@@ -2413,8 +2455,8 @@
   os << "Object allocated on line " << AllocLine;
   
   if (FirstBinding)
-    os << " and stored into '" 
-       << BR.getStateManager().BindingAsString(FirstBinding) << '\'';    
+    os << " and stored into '" << FirstBinding->getString() << '\'';  
+  
   os << " is no longer referenced after this point and has a retain count of +"
      << RetCount << " (object leaked).";
   

Modified: cfe/trunk/lib/Analysis/CheckNSError.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CheckNSError.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CheckNSError.cpp (original)
+++ cfe/trunk/lib/Analysis/CheckNSError.cpp Sat Oct  4 00:50:14 2008
@@ -216,7 +216,7 @@
                                    GRExprEngine& Eng, GRBugReporter& BR,
                                    bool isNSErrorWarning) {
   
-  RVal ParamRVal = rootState.GetRVal(lval::DeclVal(Param));
+  RVal ParamRVal = rootState.GetRVal(Eng.getLVal(Param));
 
   // FIXME: For now assume that ParamRVal is symbolic.  We need to generalize
   // this later.

Modified: cfe/trunk/lib/Analysis/Environment.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/Environment.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/Environment.cpp (original)
+++ cfe/trunk/lib/Analysis/Environment.cpp Sat Oct  4 00:50:14 2008
@@ -107,11 +107,11 @@
 }
 
 Environment 
-EnvironmentManager::RemoveDeadBindings(Environment Env, 
-                                       Stmt* Loc,
-                                       const LiveVariables& Liveness,
-                                       StoreManager::DeclRootsTy& DRoots,
-                                       StoreManager::LiveSymbolsTy& LSymbols) {
+EnvironmentManager::RemoveDeadBindings(Environment Env, Stmt* Loc,
+                                const LiveVariables& Liveness,
+                                llvm::SmallVectorImpl<const MemRegion*>& DRoots,
+                                StoreManager::LiveSymbolsTy& LSymbols) {
+  
   // Drop bindings for subexpressions.
   Env = RemoveSubExprBindings(Env);
 
@@ -123,12 +123,10 @@
     if (Liveness.isLive(Loc, BlkExpr)) {
       RVal X = I.getData();
 
-      // If the block expr's value is the address of some Decl, then mark that
-      // Decl.
-      if (isa<lval::DeclVal>(X)) {
-        lval::DeclVal LV = cast<lval::DeclVal>(X);
-        DRoots.push_back(LV.getDecl());
-      }
+      // If the block expr's value is a memory region, then mark that region.
+      if (isa<lval::MemRegionVal>(X))
+        DRoots.push_back(cast<lval::MemRegionVal>(X).getRegion());
+
 
       // Mark all symbols in the block expr's value.
       for (RVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();

Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Sat Oct  4 00:50:14 2008
@@ -792,12 +792,12 @@
                                     bool asLVal) {
   
   const GRState* St = GetState(Pred);
-  RVal X = RVal::MakeVal(getBasicVals(), D);
+  RVal X = RVal::MakeVal(getStateManager(), D);
   
   if (asLVal)
     MakeNode(Dst, D, Pred, SetRVal(St, D, cast<LVal>(X)));
   else {
-    RVal V = isa<lval::DeclVal>(X) ? GetRVal(St, cast<LVal>(X)) : X;
+    RVal V = isa<lval::MemRegionVal>(X) ? GetRVal(St, cast<LVal>(X)) : X;
     MakeNode(Dst, D, Pred, SetRVal(St, D, V));
   }
 }
@@ -1900,9 +1900,12 @@
     for (NodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
       RVal X = GetRVal((*I)->getState(), R);
 
-      if (isa<lval::DeclVal>(X)) {
+      if (isa<lval::MemRegionVal>(X)) {
         
-        if (cast<lval::DeclVal>(X).getDecl()->hasLocalStorage()) {
+        // Determine if the value is on the stack.
+        const MemRegion* R = cast<lval::MemRegionVal>(&X)->getRegion();
+
+        if (R && getStateManager().hasStackStorage(R)) {
         
           // Create a special node representing the v
           

Modified: cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngineInternalChecks.cpp Sat Oct  4 00:50:14 2008
@@ -194,13 +194,14 @@
       assert (E && "Return expression cannot be NULL");
       
       // Get the value associated with E.
-      lval::DeclVal V =
-        cast<lval::DeclVal>(Eng.getStateManager().GetRVal(N->getState(), E));
+      lval::MemRegionVal V =
+        cast<lval::MemRegionVal>(Eng.getStateManager().GetRVal(N->getState(),
+                                                               E));
       
       // Generate a report for this bug.
       std::ostringstream os;
       os << "Address of stack memory associated with local variable '"
-         << V.getDecl()->getName() << "' returned.";
+         << V.getRegion()->getString() << "' returned.";
       
       std::string s = os.str();
       

Modified: cfe/trunk/lib/Analysis/GRSimpleVals.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRSimpleVals.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRSimpleVals.cpp (original)
+++ cfe/trunk/lib/Analysis/GRSimpleVals.cpp Sat Oct  4 00:50:14 2008
@@ -287,7 +287,7 @@
     case lval::FieldOffsetKind:
       // Fall-through.
       
-    case lval::DeclValKind:
+    case lval::MemRegionKind:
     case lval::FuncValKind:
     case lval::GotoLabelKind:
     case lval::StringLiteralValKind:
@@ -351,7 +351,7 @@
     case lval::FieldOffsetKind:
       // Fall-through.
       
-    case lval::DeclValKind:
+    case lval::MemRegionKind:
     case lval::FuncValKind:
     case lval::GotoLabelKind:
     case lval::StringLiteralValKind:

Modified: cfe/trunk/lib/Analysis/GRState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRState.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/GRState.cpp (original)
+++ cfe/trunk/lib/Analysis/GRState.cpp Sat Oct  4 00:50:14 2008
@@ -42,19 +42,18 @@
   // tells us are live.  We then see what Decls they may reference, and keep
   // those around.  This code more than likely can be made faster, and the
   // frequency of which this method is called should be experimented with
-  // for optimum performance.  
-  DRoots.clear();
+  // for optimum performance.
+  llvm::SmallVector<const MemRegion*, 10> RegionRoots;
   StoreManager::LiveSymbolsTy LSymbols;
-  
   GRState NewSt = *St;
 
-  NewSt.Env = EnvMgr.RemoveDeadBindings(NewSt.Env, Loc, Liveness, 
-                                        DRoots, LSymbols);
+  NewSt.Env =
+    EnvMgr.RemoveDeadBindings(NewSt.Env, Loc, Liveness, RegionRoots, LSymbols);
 
   // Clean up the store.
   DSymbols.clear();
-  NewSt.St = StMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness, DRoots,
-                                       LSymbols, DSymbols);
+  NewSt.St = StMgr->RemoveDeadBindings(St->getStore(), Loc, Liveness,
+                                       RegionRoots, LSymbols, DSymbols);
 
   return ConstraintMgr->RemoveDeadBindings(getPersistentState(NewSt), 
                                            LSymbols, DSymbols);

Added: cfe/trunk/lib/Analysis/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/MemRegion.cpp?rev=57042&view=auto

==============================================================================
--- cfe/trunk/lib/Analysis/MemRegion.cpp (added)
+++ cfe/trunk/lib/Analysis/MemRegion.cpp Sat Oct  4 00:50:14 2008
@@ -0,0 +1,158 @@
+//== MemRegion.cpp - Abstract memory regions for static analysis --*- C++ -*--//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  This file defines MemRegion and its subclasses.  MemRegion defines a
+//  partially-typed abstraction of memory useful for path-sensitive dataflow
+//  analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/raw_ostream.h"
+#include "clang/Analysis/PathSensitive/MemRegion.h"
+
+using namespace clang;
+
+
+MemRegion::~MemRegion() {}
+
+void MemSpaceRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+  ID.AddInteger((unsigned)getKind());
+}
+
+void AnonTypedRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
+                                    const MemRegion* superRegion) {
+  ID.AddInteger((unsigned) AnonTypedRegionKind);
+  ID.Add(T);
+  ID.AddPointer(superRegion);
+}
+
+void AnonTypedRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+  AnonTypedRegion::ProfileRegion(ID, T, superRegion);
+}
+
+void DeclRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
+                               const MemRegion* superRegion, Kind k) {
+  ID.AddInteger((unsigned) k);
+  ID.AddPointer(D);
+  ID.AddPointer(superRegion);
+}
+
+void DeclRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+  DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
+}
+
+//===----------------------------------------------------------------------===//
+// Region pretty-printing.
+//===----------------------------------------------------------------------===//
+
+std::string MemRegion::getString() const {
+  std::string s;
+  llvm::raw_string_ostream os(s);
+  print(os);
+  return os.str();
+}
+
+void MemRegion::print(llvm::raw_ostream& os) const {
+  os << "<Unknown Region>";
+}
+
+void VarRegion::print(llvm::raw_ostream& os) const {
+  os << cast<VarDecl>(D)->getName();
+}
+
+//===----------------------------------------------------------------------===//
+// MemRegionManager methods.
+//===----------------------------------------------------------------------===//
+  
+MemSpaceRegion* MemRegionManager::LazyAllocate(MemSpaceRegion*& region) {
+  
+  if (!region) {  
+    region = (MemSpaceRegion*) A.Allocate<MemSpaceRegion>();
+    new (region) MemSpaceRegion();
+  }
+  
+  return region;
+}
+
+MemSpaceRegion* MemRegionManager::getStackRegion() {
+  return LazyAllocate(stack);
+}
+
+MemSpaceRegion* MemRegionManager::getGlobalsRegion() {
+  return LazyAllocate(globals);
+}
+
+MemSpaceRegion* MemRegionManager::getHeapRegion() {
+  return LazyAllocate(heap);
+}
+
+VarRegion* MemRegionManager::getVarRegion(const VarDecl* d,
+                                          MemRegion* superRegion) {
+  llvm::FoldingSetNodeID ID;
+  DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
+  
+  void* InsertPos;
+  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
+  VarRegion* R = cast_or_null<VarRegion>(data);
+  
+  if (!R) {
+    R = (VarRegion*) A.Allocate<VarRegion>();
+    new (R) VarRegion(d, superRegion);
+    Regions.InsertNode(R, InsertPos);
+  }
+  
+  return R;
+}
+
+FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
+                                              MemRegion* superRegion) {
+  llvm::FoldingSetNodeID ID;
+  DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
+  
+  void* InsertPos;
+  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
+  FieldRegion* R = cast_or_null<FieldRegion>(data);
+  
+  if (!R) {
+    R = (FieldRegion*) A.Allocate<FieldRegion>();
+    new (R) FieldRegion(d, superRegion);
+    Regions.InsertNode(R, InsertPos);
+  }
+  
+  return R;
+}
+
+ObjCIvarRegion* MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
+                                                    MemRegion* superRegion) {
+  llvm::FoldingSetNodeID ID;
+  DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
+  
+  void* InsertPos;
+  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
+  ObjCIvarRegion* R = cast_or_null<ObjCIvarRegion>(data);
+  
+  if (!R) {
+    R = (ObjCIvarRegion*) A.Allocate<FieldRegion>();
+    new (R) FieldRegion(d, superRegion);
+    Regions.InsertNode(R, InsertPos);
+  }
+  
+  return R;
+}
+
+bool MemRegionManager::hasStackStorage(const MemRegion* R) {
+  MemSpaceRegion* S = getStackRegion();
+  
+  while (R) {
+    if (R == S) return true;
+    R = R->getSuperRegion();
+  }
+  
+  return false;
+}

Modified: cfe/trunk/lib/Analysis/RValues.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RValues.cpp?rev=57042&r1=57041&r2=57042&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/RValues.cpp (original)
+++ cfe/trunk/lib/Analysis/RValues.cpp Sat Oct  4 00:50:14 2008
@@ -12,7 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Analysis/PathSensitive/RValues.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
 #include "clang/Basic/IdentifierTable.h"
 #include "llvm/Support/Streams.h"
 
@@ -163,9 +163,9 @@
         break;
       }
       
-      case lval::DeclValKind:
-      if (isa<lval::DeclVal>(R)) {        
-        bool b = cast<lval::DeclVal>(*this) == cast<lval::DeclVal>(R);
+      case lval::MemRegionKind:
+      if (isa<lval::MemRegionVal>(R)) {        
+        bool b = cast<lval::MemRegionVal>(*this) == cast<lval::MemRegionVal>(R);
         return NonLVal::MakeIntTruthVal(BasicVals, b);
       }
       
@@ -216,9 +216,9 @@
         break;
       }
       
-      case lval::DeclValKind:
-        if (isa<lval::DeclVal>(R)) {        
-          bool b = cast<lval::DeclVal>(*this) == cast<lval::DeclVal>(R);
+      case lval::MemRegionKind:
+        if (isa<lval::MemRegionVal>(R)) {        
+          bool b = cast<lval::MemRegionVal>(*this)==cast<lval::MemRegionVal>(R);
           return NonLVal::MakeIntTruthVal(BasicVals, b);
         }
       
@@ -270,12 +270,12 @@
 // Utility methods for constructing RVals (both NonLVals and LVals).
 //===----------------------------------------------------------------------===//
 
-RVal RVal::MakeVal(BasicValueFactory& BasicVals, DeclRefExpr* E) {
+RVal RVal::MakeVal(GRStateManager& SMgr, DeclRefExpr* E) {
   
   ValueDecl* D = cast<DeclRefExpr>(E)->getDecl();
   
   if (VarDecl* VD = dyn_cast<VarDecl>(D)) {
-    return lval::DeclVal(VD);
+    return SMgr.getLVal(VD);
   }
   else if (EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
     
@@ -283,7 +283,7 @@
     // already has persistent storage?  We do this because we
     // are comparing states using pointer equality.  Perhaps there is
     // a better way, since APInts are fairly lightweight.
-    
+    BasicValueFactory& BasicVals = SMgr.getBasicVals();
     return nonlval::ConcreteInt(BasicVals.getValue(ED->getInitVal()));          
   }
   else if (FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
@@ -408,9 +408,8 @@
           << cast<lval::GotoLabel>(this)->getLabel()->getID()->getName();
       break;
 
-    case lval::DeclValKind:
-      Out << '&' 
-          << cast<lval::DeclVal>(this)->getDecl()->getIdentifier()->getName();
+    case lval::MemRegionKind:
+      Out << '&' << cast<lval::MemRegionVal>(this)->getRegion()->getString();
       break;
       
     case lval::FuncValKind:





More information about the cfe-commits mailing list