[cfe-commits] r55688 - in /cfe/trunk: include/clang/Analysis/PathSensitive/Store.h lib/Analysis/BasicStore.cpp lib/Analysis/CFRefCount.cpp

Ted Kremenek kremenek at apple.com
Tue Sep 2 20:06:12 PDT 2008


Author: kremenek
Date: Tue Sep  2 22:06:11 2008
New Revision: 55688

URL: http://llvm.org/viewvc/llvm-project?rev=55688&view=rev
Log:
Store: (static analyzer)
- Change definition of store::Region and store::Binding (once again) to make
  them real classes that just wrap pointers. This makes them more strictly
  typed, and allows specific implementations of Regions/Bindings to just
  subclass them.
- minor renamings to RegionExtent and its subclasses
- added a bunch of doxygen comments

StoreManager: (static analyzer)
- added 'iterBindings', an iteration method for iterating over the bindings of a
  store. It that takes a callback object (acting like a poor man's closure).
- added 'getRVal' version for store::Binding. Will potentially phase the other
  versions of GetRVal in StoreManager out.
- reimplemented 'getBindings' to be non-virtual and to use 'iterBindings'

BasicStoreManager: (static analyzer)
- implemented 'iterBindings' for BasicStoreManager


Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
    cfe/trunk/lib/Analysis/BasicStore.cpp
    cfe/trunk/lib/Analysis/CFRefCount.cpp

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=55688&r1=55687&r2=55688&view=diff

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Store.h Tue Sep  2 22:06:11 2008
@@ -27,12 +27,38 @@
 typedef const void* Store;
   
 namespace store {
-  typedef const void* Binding;
-  typedef const void* Region;
+  /// 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, Int = 0, Sym = 1 };
+    enum Kind { Unknown = 0, Fixed = 0, Sym = 1 };
     
   protected:
     const uintptr_t Raw;
@@ -60,6 +86,8 @@
     }
   };
   
+  /// UnknownExtent - Represents a region extent with no available information
+  ///  about the size of the region.
   class UnknownExtent : public RegionExtent {
   public:
     UnknownExtent() : RegionExtent(0,Unknown) {}
@@ -70,9 +98,12 @@
     }  
   };
   
-  class IntExtent : public RegionExtent {
+  /// 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:
-    IntExtent(const llvm::APSInt& X) : RegionExtent((uintptr_t) &X, Int) {}
+    FixedExtent(const llvm::APSInt& X) : RegionExtent((uintptr_t) &X, Fixed) {}
     
     const llvm::APSInt& getInt() const {
       return *((llvm::APSInt*) getData());
@@ -80,13 +111,16 @@
     
     // Implement isa<T> support.
     static inline bool classof(const RegionExtent* E) {
-      return E->getKind() == Int && E->getRaw() != 0;
+      return E->getKind() == Fixed && E->getRaw() != 0;
     }
   };
   
-  class SymExtent : public RegionExtent {
+  /// 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:
-    SymExtent(SymbolID S) : RegionExtent(S.getNumber() << 1, Sym) {}
+    SymbolicExtent(SymbolID S) : RegionExtent(S.getNumber() << 1, Sym) {}
     
     SymbolID getSymbol() const { return SymbolID(getData() >> 1); }
     
@@ -124,17 +158,30 @@
 
   virtual void print(Store store, std::ostream& Out,
                      const char* nl, const char *sep) = 0;
-    
+      
+  class BindingsHandler {
+  public:    
+    virtual ~BindingsHandler();
+    virtual bool HandleBinding(StoreManager& SMgr, Store store,
+                               store::Binding binding) = 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.
-  virtual void getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
-                           Store store, SymbolID Sym) = 0;
+  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;
+  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;
 };
   
 StoreManager* CreateBasicStoreManager(GRStateManager& StMgr);

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

==============================================================================
--- cfe/trunk/lib/Analysis/BasicStore.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicStore.cpp Tue Sep  2 22:06:11 2008
@@ -21,10 +21,11 @@
 using store::Region;
 using store::RegionExtent;
 
+typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;  
+
 namespace {
   
 class VISIBILITY_HIDDEN BasicStoreManager : public StoreManager {
-  typedef llvm::ImmutableMap<VarDecl*,RVal> VarBindingsTy;  
   VarBindingsTy::Factory VBFactory;
   GRStateManager& StMgr;
   
@@ -44,6 +45,8 @@
                                    DeclRootsTy& DRoots, LiveSymbolsTy& LSymbols,
                                    DeadSymbolsTy& DSymbols);
 
+  virtual void iterBindings(Store store, BindingsHandler& f);
+
   virtual Store AddDecl(Store store, GRStateManager& StateMgr,
                         const VarDecl* VD, Expr* Ex, 
                         RVal InitVal = UndefinedVal(), unsigned Count = 0);
@@ -57,14 +60,38 @@
   
   virtual RegionExtent getExtent(Region R);
   
-  /// getBindings - Returns all bindings in the specified store that bind
-  ///  to the specified symbolic value.
-  virtual 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);
-};  
+  
+  /// 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
 
@@ -74,8 +101,7 @@
 }
 
 RegionExtent BasicStoreManager::getExtent(Region R) {
-  VarDecl* VD = (VarDecl*) R;
-  QualType T = VD->getType();
+  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.
@@ -85,8 +111,8 @@
   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::IntExtent(StMgr.getBasicVals().getValue(C.getTypeSize(T),
-                                                        C.VoidPtrTy));
+  return store::FixedExtent(StMgr.getBasicVals().getValue(C.getTypeSize(T),
+                                                          C.VoidPtrTy));
 }
 
 
@@ -335,28 +361,62 @@
   }
 }
 
-void
-BasicStoreManager::getBindings(llvm::SmallVectorImpl<store::Binding>& bindings,
-                               Store store, SymbolID Sym) {
+
+void BasicStoreManager::iterBindings(Store store, BindingsHandler& f) {
+  VarBindingsTy B = GetVarBindings(store);
   
-  VarBindingsTy VB((VarBindingsTy::TreeTy*) 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) {}
   
-  for (VarBindingsTy::iterator I=VB.begin(), E=VB.end(); I!=E; ++I) {
-    if (const lval::SymbolVal* SV=dyn_cast<lval::SymbolVal>(&I->second)) {
-      if (SV->getSymbol() == Sym) 
-        bindings.push_back(I->first);
-      
-      continue;
-    }
+  virtual bool HandleBinding(StoreManager& SMgr, Store store,
+                             store::Binding binding) {
+    
+    RVal V = SMgr.getRVal(store, binding);
     
-    if (const nonlval::SymbolVal* SV=dyn_cast<nonlval::SymbolVal>(&I->second)){
+    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(I->first);
+        bindings.push_back(binding);
     }
+    
+    return true;
   }
-}
+}; 
+} // end anonymous namespace
 
-std::string BasicStoreManager::BindingAsString(store::Binding binding) {
-  // A binding is just an VarDecl*.
-  return ((VarDecl*) binding)->getName();
+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/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=55688&r1=55687&r2=55688&view=diff

==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Tue Sep  2 22:06:11 2008
@@ -2308,7 +2308,7 @@
   // 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 = 0;  
+  store::Binding FirstBinding;  
   
   while (N) {
     const GRState* St = N->getState();
@@ -2351,7 +2351,7 @@
   // symbol appeared, and also get the first VarDecl that tracked object
   // is stored to.
   ExplodedNode<GRState>* AllocNode = 0;
-  store::Binding FirstBinding = 0;
+  store::Binding FirstBinding;
 
   llvm::tie(AllocNode, FirstBinding) =
     GetAllocationSite(&BR.getStateManager(), EndN, Sym);





More information about the cfe-commits mailing list