]> granicus.if.org Git - clang/commitdiff
This is a big patch, but the functionality change is small and the rest of the patch...
authorTed Kremenek <kremenek@apple.com>
Sat, 4 Oct 2008 05:50:14 +0000 (05:50 +0000)
committerTed Kremenek <kremenek@apple.com>
Sat, 4 Oct 2008 05:50:14 +0000 (05:50 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57042 91177308-0d34-0410-b5e6-96231b3b80d8

19 files changed:
include/clang/Analysis/PathSensitive/Environment.h
include/clang/Analysis/PathSensitive/GRExprEngine.h
include/clang/Analysis/PathSensitive/GRState.h
include/clang/Analysis/PathSensitive/MemRegion.h [new file with mode: 0644]
include/clang/Analysis/PathSensitive/RValues.h
include/clang/Analysis/PathSensitive/Store.h
lib/Analysis/BasicConstraintManager.cpp
lib/Analysis/BasicObjCFoundationChecks.cpp
lib/Analysis/BasicStore.cpp
lib/Analysis/BugReporter.cpp
lib/Analysis/CFRefCount.cpp
lib/Analysis/CheckNSError.cpp
lib/Analysis/Environment.cpp
lib/Analysis/GRExprEngine.cpp
lib/Analysis/GRExprEngineInternalChecks.cpp
lib/Analysis/GRSimpleVals.cpp
lib/Analysis/GRState.cpp
lib/Analysis/MemRegion.cpp [new file with mode: 0644]
lib/Analysis/RValues.cpp

index 9c9dc54886ad0b7f047864e4daa8ca028448814e..8e1b97a3bec4d042b9cf78d5f06995cb965cad71 100644 (file)
@@ -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 @@ public:
   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
index 5b713d9c18a2d04b285c1f5dcb5b3fa5b1916261..0bcc13781f8f6ea4367eb309340a351a49e390bd 100644 (file)
@@ -410,6 +410,10 @@ public:
     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) {
index fd81a86946faa6c4e27919c1ff665122154aad7e..992174c2a33b22e5e8aa9b119dab7c620c50840d 100644 (file)
@@ -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 @@ 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 {
-    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 @@ private:
   EnvironmentManager                   EnvMgr;
   llvm::OwningPtr<StoreManager>        StMgr;
   llvm::OwningPtr<ConstraintManager>   ConstraintMgr;
+  MemRegionManager                     MRMgr;
   GRState::IntSetTy::Factory           ISetFactory;
   
   GRState::GenericDataMap::Factory     GDMFactory;
@@ -273,10 +261,6 @@ private:
   /// 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 @@ private:
   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 @@ public:
                  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 @@ public:
   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 @@ public:
     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 @@ public:
   // 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);
diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h
new file mode 100644 (file)
index 0000000..7970561
--- /dev/null
@@ -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
index 9034c0d4ae2a447b1e8e38032311594ef98321ac..82e511937399113c4f798c15f1890456ad1bf10a 100644 (file)
@@ -24,6 +24,9 @@
 
 namespace clang {
   
+class MemRegion;
+class GRStateManager;
+  
 class RVal {
 public:
   enum BaseKind { UndefinedKind, UnknownKind, LValKind, NonLValKind };
@@ -92,7 +95,7 @@ public:
   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 @@ public:
 
 namespace lval {
   
-enum Kind { SymbolValKind, GotoLabelKind, DeclValKind, FuncValKind,
+enum Kind { SymbolValKind, GotoLabelKind, MemRegionKind, FuncValKind,
             ConcreteIntKind, StringLiteralValKind, FieldOffsetKind,
             ArrayOffsetKind };
 
@@ -327,30 +330,30 @@ public:
 };
   
 
-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;
   }    
 };
 
index fc9b7f3d078c70d3cf63e69c4318e920128bc08c..4300954eac23903a65220b2ca79c6f74c5c63f92 100644 (file)
 #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 @@ public:
   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:
   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
 
index 0576eaf2a14cfeb1ed4a10c9f8bebc5990858a88..66bf082b136a556d0a8639d33ecf59e4b8a70646 100644 (file)
@@ -129,7 +129,7 @@ const GRState* BasicConstraintManager::AssumeAux(const GRState* St, LVal Cond,
       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:
index 521f317d631219c226e9f37ea292081a01e85edf..b3f534d1af01dfbea23dc7d2bf1211b84fc8ec99 100644 (file)
@@ -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 @@ public:
   
 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 @@ bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
   
   // 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 @@ bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
   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) {
index 97566798c0be6e18168e07b328227c57a2ede516..4616143d136ff38bf50c06e0c8e0ac38476218cc 100644 (file)
 #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 @@ public:
 
   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 @@ public:
 
   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 @@ StoreManager* clang::CreateBasicStoreManager(GRStateManager& StMgr) {
   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 @@ RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
   
   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 @@ RVal BasicStoreManager::GetRVal(Store St, LVal LV, QualType T) {
 
 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::SetRVal(Store store, LVal LV, RVal V) {
 
 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::Remove(Store store, LVal LV) {
   }
 }
 
-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 @@ Store BasicStoreManager::RemoveDeadBindings(Store store,
   // 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 @@ Store BasicStoreManager::RemoveDeadBindings(Store store,
     }
   
   // 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 @@ Store BasicStoreManager::getInitialStore(GRStateManager& StateMgr) {
                  ? RVal::GetSymbolValue(StateMgr.getSymbolManager(), VD)
                  : UndefinedVal();
 
-        St = SetRVal(St, lval::DeclVal(VD), X);
+        St = SetRVal(St, StMgr.getLVal(VD), X);
       }
     }
   }
@@ -310,16 +280,16 @@ Store BasicStoreManager::AddDecl(Store store, GRStateManager& StateMgr,
       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 @@ Store BasicStoreManager::AddDecl(Store store, GRStateManager& StateMgr,
           : cast<RVal>(nonlval::SymbolVal(Sym));
       }
 
-      store = SetRVal(store, lval::DeclVal(VD), V);
+      store = SetRVal(store, StMgr.getLVal(VD), V);
     }
   }
 
@@ -366,57 +336,9 @@ void BasicStoreManager::iterBindings(Store store, BindingsHandler& f) {
   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() {}
-
index 6a1478a9cbbc5b41a5b7174f095f41fcd472a8b0..e56da7b872d68b25cde380c24f0fd338c14c3177 100644 (file)
@@ -322,32 +322,27 @@ static VarDecl* GetMostRecentVarDeclBinding(ExplodedNode<GRState>* N,
   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 @@ static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
     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 @@ static void HandleNotableSymbol(ExplodedNode<GRState>* N, Stmt* S,
     
     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 @@ void GRBugReporter::GeneratePathDiagnostic(PathDiagnostic& PD,
     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);
     }
   }
 }
index 733cad18acf28b5fd7c7c35fbe23c1a64d928b52..c63529aa05598099ff918c13f3b5778fd3a5a9ea 100644 (file)
@@ -1489,7 +1489,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
       // 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 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
         //  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 @@ void CFRefCount::EvalStore(ExplodedNodeSet<GRState>& Dst,
   
   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 @@ PathDiagnosticPiece* CFRefReport::VisitNode(ExplodedNode<GRState>* N,
   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 @@ GetAllocationSite(GRStateManager* StateMgr, ExplodedNode<GRState>* N,
       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 @@ PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& br,
   // 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 @@ PathDiagnosticPiece* CFRefReport::getEndPath(BugReporter& br,
   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).";
   
index 5a1e7cb8f142aeeac5eb552f6b6163ed80b4725e..03c9af3a729cfb156e2ee5139643bb8efb97ce22 100644 (file)
@@ -216,7 +216,7 @@ void NSErrorCheck::CheckParamDeref(VarDecl* Param, GRStateRef rootState,
                                    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.
index 15a1d3659f8133fd587a227728583bb1bd582a90..f86c4fea71651738df7388581ee26461d89cc52a 100644 (file)
@@ -107,11 +107,11 @@ Environment EnvironmentManager::SetRVal(const Environment& Env, Expr* E, RVal V,
 }
 
 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 @@ EnvironmentManager::RemoveDeadBindings(Environment Env,
     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();
index 41bf98933efdbf64a2548ec4fa1974d814500ada..115d265dde451f6aaeb6849ed1d5704f276c228d 100644 (file)
@@ -792,12 +792,12 @@ void GRExprEngine::VisitDeclRefExpr(DeclRefExpr* D, NodeTy* Pred, NodeSet& Dst,
                                     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 @@ void GRExprEngine::VisitReturnStmt(ReturnStmt* S, NodeTy* Pred, NodeSet& Dst) {
     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
           
index e7e5f45d8a6c79307d4faddbd8b8a3534c5fd036..d61998c5a410f8adf0cb43b792c5c4fc9cf27476 100644 (file)
@@ -194,13 +194,14 @@ public:
       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();
       
index b33d5122b19db19237f9b1232178ea0b5606d657..44703163e06f2d98ff1deae57cc8092eebb2e2f6 100644 (file)
@@ -287,7 +287,7 @@ RVal GRSimpleVals::EvalEQ(GRExprEngine& Eng, LVal L, LVal R) {
     case lval::FieldOffsetKind:
       // Fall-through.
       
-    case lval::DeclValKind:
+    case lval::MemRegionKind:
     case lval::FuncValKind:
     case lval::GotoLabelKind:
     case lval::StringLiteralValKind:
@@ -351,7 +351,7 @@ RVal GRSimpleVals::EvalNE(GRExprEngine& Eng, LVal L, LVal R) {
     case lval::FieldOffsetKind:
       // Fall-through.
       
-    case lval::DeclValKind:
+    case lval::MemRegionKind:
     case lval::FuncValKind:
     case lval::GotoLabelKind:
     case lval::StringLiteralValKind:
index 67bff39fc8c83569332f6c9525181031abbe2466..2f829e65da847730d06bb502f37a11ca9928a45a 100644 (file)
@@ -42,19 +42,18 @@ GRStateManager::RemoveDeadBindings(const GRState* St, Stmt* Loc,
   // 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);
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
new file mode 100644 (file)
index 0000000..7c2af42
--- /dev/null
@@ -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;
+}
index 5dc9cd5fbe06b1cc9341237b61fb3ad8744bc86e..337d4792555548d4633ae1c3576191c5d36e3550 100644 (file)
@@ -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 @@ NonLVal LVal::EQ(BasicValueFactory& BasicVals, const LVal& R) const {
         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 @@ NonLVal LVal::NE(BasicValueFactory& BasicVals, const LVal& R) const {
         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 @@ LVal LVal::MakeVal(StringLiteral* S) {
 // 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 @@ RVal RVal::MakeVal(BasicValueFactory& BasicVals, DeclRefExpr* E) {
     // 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 @@ void LVal::print(std::ostream& Out) const {
           << 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: