[cfe-commits] r78268 - in /cfe/trunk: include/clang/Analysis/PathSensitive/BasicValueFactory.h include/clang/Analysis/PathSensitive/MemRegion.h include/clang/Analysis/PathSensitive/SVals.h include/clang/Analysis/PathSensitive/ValueManager.h lib/Analysis/BasicValueFactory.cpp lib/Analysis/RegionStore.cpp lib/Analysis/SVals.cpp

Ted Kremenek kremenek at apple.com
Wed Aug 5 18:21:10 PDT 2009


Author: kremenek
Date: Wed Aug  5 20:20:57 2009
New Revision: 78268

URL: http://llvm.org/viewvc/llvm-project?rev=78268&view=rev
Log:
Implement lazy "copying" of structures and arrays in RegionStore. While
RegionStore already lazily abstracted the contents of arrays and structs, when
doing an assignment from one array/struct to another we did an explicit
element-wise copy, which resulted in a loss of laziness and huge performance
problem when analyzing many code bases.

Now RegionStoreManager handles such assignments using a new SVal could
'LazyCompoundSVal', which basically means the value of a given struct or array
(a MemRegion*) in a specific state (GRState). When we do a load from a field
whose encompassing struct binds to a LazyCompoundSVal, we essentially do a field
lookup in the original structure. This means we have essentially zero copying of
data for structs/arrays and everything stays lazy.

Modified:
    cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h
    cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h
    cfe/trunk/include/clang/Analysis/PathSensitive/SVals.h
    cfe/trunk/include/clang/Analysis/PathSensitive/ValueManager.h
    cfe/trunk/lib/Analysis/BasicValueFactory.cpp
    cfe/trunk/lib/Analysis/RegionStore.cpp
    cfe/trunk/lib/Analysis/SVals.cpp

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/BasicValueFactory.h Wed Aug  5 20:20:57 2009
@@ -25,6 +25,8 @@
 
 namespace clang {
   
+  class GRState;
+
 class CompoundValData : public llvm::FoldingSetNode {
   QualType T;
   llvm::ImmutableList<SVal> L;
@@ -43,6 +45,22 @@
   void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, T, L); }
 };
 
+class LazyCompoundValData : public llvm::FoldingSetNode {
+  const GRState *state;
+  const TypedRegion *region;
+public:
+  LazyCompoundValData(const GRState *st, const TypedRegion *r)
+    : state(st), region(r) {}
+  
+  const GRState *getState() const { return state; }
+  const TypedRegion *getRegion() const { return region; }
+    
+  static void Profile(llvm::FoldingSetNodeID& ID, const GRState *state,
+                      const TypedRegion *region);
+  
+  void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, state, region); }
+};
+  
 class BasicValueFactory {
   typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> >
           APSIntSetTy;
@@ -56,6 +74,7 @@
 
   llvm::ImmutableList<SVal>::Factory SValListFactory;
   llvm::FoldingSet<CompoundValData>  CompoundValDataSet;
+  llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet;
 
 public:
   BasicValueFactory(ASTContext& ctx, llvm::BumpPtrAllocator& Alloc) 
@@ -138,9 +157,12 @@
     return getTruthValue(b, Ctx.IntTy);
   }
   
-  const CompoundValData* getCompoundValData(QualType T, 
+  const CompoundValData *getCompoundValData(QualType T, 
                                             llvm::ImmutableList<SVal> Vals);
   
+  const LazyCompoundValData *getLazyCompoundValData(const GRState *state,
+                                                    const TypedRegion *region);
+  
   llvm::ImmutableList<SVal> getEmptySValList() {
     return SValListFactory.GetEmptyList();
   }

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h Wed Aug  5 20:20:57 2009
@@ -638,16 +638,27 @@
   
   /// getElementRegion - Retrieve the memory region associated with the
   ///  associated element type, index, and super region.
-  ElementRegion* getElementRegion(QualType elementType, SVal Idx,
+  ElementRegion *getElementRegion(QualType elementType, SVal Idx,
                                   const MemRegion* superRegion,ASTContext &Ctx);
+  
+  ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
+                                           const MemRegion *superRegion) {
+    return getElementRegion(ER->getElementType(), ER->getIndex(),
+                            superRegion, ER->getContext());
+  }
 
   /// 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,
+  FieldRegion *getFieldRegion(const FieldDecl* fd,
                               const MemRegion* superRegion);
   
+  FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
+                                       const MemRegion *superRegion) {
+    return getFieldRegion(FR->getDecl(), superRegion);
+  }
+  
   /// getObjCObjectRegion - Retrieve or create the memory region associated with
   ///  the instance of a specified Objective-C class.
   ObjCObjectRegion* getObjCObjectRegion(const ObjCInterfaceDecl* ID,

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/SVals.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/SVals.h Wed Aug  5 20:20:57 2009
@@ -30,8 +30,11 @@
 namespace clang {
 
 class CompoundValData;
+class LazyCompoundValData;
+class GRState;
 class BasicValueFactory;
 class MemRegion;
+class TypedRegion;
 class MemRegionManager;
 class GRStateManager;
 class ValueManager;
@@ -211,7 +214,7 @@
 namespace nonloc {
   
 enum Kind { ConcreteIntKind, SymbolValKind, SymExprValKind,
-            LocAsIntegerKind, CompoundValKind };
+            LocAsIntegerKind, CompoundValKind, LazyCompoundValKind };
 
 class SymbolVal : public NonLoc {
 public:
@@ -334,6 +337,24 @@
   }
 };
   
+class LazyCompoundVal : public NonLoc {
+  friend class clang::ValueManager;
+
+  LazyCompoundVal(const LazyCompoundValData *D)
+    : NonLoc(LazyCompoundValKind, D) {}
+public:
+  const GRState *getState() const;
+  const TypedRegion *getRegion() const;
+  
+  static bool classof(const SVal *V) {
+    return V->getBaseKind() == NonLocKind && 
+           V->getSubKind() == LazyCompoundValKind;
+  }
+  static bool classof(const NonLoc *V) {
+    return V->getSubKind() == LazyCompoundValKind;
+  }
+};
+  
 } // end namespace clang::nonloc
 
 //==------------------------------------------------------------------------==//

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

==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ValueManager.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ValueManager.h Wed Aug  5 20:20:57 2009
@@ -113,6 +113,10 @@
   NonLoc makeCompoundVal(QualType T, llvm::ImmutableList<SVal> Vals) {
     return nonloc::CompoundVal(BasicVals.getCompoundValData(T, Vals));
   }
+  
+  NonLoc makeLazyCompoundVal(const GRState *state, const TypedRegion *R) {
+    return nonloc::LazyCompoundVal(BasicVals.getLazyCompoundValData(state, R));
+  }
 
   NonLoc makeZeroArrayIndex() {
     return nonloc::ConcreteInt(BasicVals.getValue(0, ArrayIndexTy));

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

==============================================================================
--- cfe/trunk/lib/Analysis/BasicValueFactory.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicValueFactory.cpp Wed Aug  5 20:20:57 2009
@@ -23,6 +23,13 @@
   ID.AddPointer(L.getInternalPointer());
 }
 
+void LazyCompoundValData::Profile(llvm::FoldingSetNodeID& ID,
+                                  const GRState *state,
+                                  const TypedRegion *region) {
+  ID.AddPointer(state);
+  ID.AddPointer(region);
+}
+
 typedef std::pair<SVal, uintptr_t> SValData;
 typedef std::pair<SVal, SVal> SValPair;
 
@@ -116,6 +123,25 @@
   return D;
 }
 
+const LazyCompoundValData*
+BasicValueFactory::getLazyCompoundValData(const GRState *state,
+                                          const TypedRegion *region) {
+  llvm::FoldingSetNodeID ID;
+  LazyCompoundValData::Profile(ID, state, region);
+  void* InsertPos;
+  
+  LazyCompoundValData *D =
+    LazyCompoundValDataSet.FindNodeOrInsertPos(ID, InsertPos);
+  
+  if (!D) {
+    D = (LazyCompoundValData*) BPAlloc.Allocate<LazyCompoundValData>();
+    new (D) LazyCompoundValData(state, region);
+    LazyCompoundValDataSet.InsertNode(D, InsertPos);
+  }
+  
+  return D;
+}
+
 const llvm::APSInt*
 BasicValueFactory::EvaluateAPSInt(BinaryOperator::Opcode Op,
                              const llvm::APSInt& V1, const llvm::APSInt& V2) {

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

==============================================================================
--- cfe/trunk/lib/Analysis/RegionStore.cpp (original)
+++ cfe/trunk/lib/Analysis/RegionStore.cpp Wed Aug  5 20:20:57 2009
@@ -28,6 +28,7 @@
 using namespace clang;
 
 #define HEAP_UNDEFINED 0
+#define USE_EXPLICIT_COMPOUND 0
 
 // Actual Store type.
 typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
@@ -130,6 +131,8 @@
     I->second = F.Add(I->second, SubRegion);
     return false;
   }
+  
+  void process(llvm::SmallVectorImpl<const SubRegion*> &WL, const SubRegion *R);
     
   ~RegionStoreSubRegionMap() {}
   
@@ -246,9 +249,11 @@
                                   const Expr *E, unsigned Count);
   
 private:
-  RegionBindingsTy RemoveSubRegionBindings(RegionBindingsTy B,
-                                           const MemRegion *R,
-                                           RegionStoreSubRegionMap &M);
+  void RemoveSubRegionBindings(RegionBindingsTy &B,
+                               RegionDefaultValue::MapTy &DVM,
+                               RegionDefaultValue::MapTy::Factory &DVMFactory,
+                               const MemRegion *R,
+                               RegionStoreSubRegionMap &M);
   
 public:  
   const GRState *Bind(const GRState *state, Loc LV, SVal V);
@@ -313,6 +318,13 @@
   SVal RetrieveStruct(const GRState *St, const TypedRegion* R);
   
   SVal RetrieveArray(const GRState *St, const TypedRegion* R);
+  
+  std::pair<const GRState*, const MemRegion*>
+  GetLazyBinding(RegionBindingsTy B, const MemRegion *R);
+  
+  const GRState* CopyLazyBindings(nonloc::LazyCompoundVal V,
+                                  const GRState *state,
+                                  const TypedRegion *R);
 
   //===------------------------------------------------------------------===//
   // State pruning.
@@ -381,37 +393,38 @@
   return new RegionStoreManager(StMgr, F);
 }
 
+void
+RegionStoreSubRegionMap::process(llvm::SmallVectorImpl<const SubRegion*> &WL,
+                                 const SubRegion *R) {  
+  const MemRegion *superR = R->getSuperRegion();
+  if (add(superR, R))
+    if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
+      WL.push_back(sr);  
+}
+
 RegionStoreSubRegionMap*
 RegionStoreManager::getRegionStoreSubRegionMap(const GRState *state) {
   RegionBindingsTy B = GetRegionBindings(state->getStore());
   RegionStoreSubRegionMap *M = new RegionStoreSubRegionMap();
   
-  llvm::SmallPtrSet<const MemRegion*, 10> Marked;
   llvm::SmallVector<const SubRegion*, 10> WL;
 
   for (RegionBindingsTy::iterator I=B.begin(), E=B.end(); I!=E; ++I)
-    if (const SubRegion* R = dyn_cast<SubRegion>(I.getKey()))
-      WL.push_back(R);
-  
+    if (const SubRegion *R = dyn_cast<SubRegion>(I.getKey()))
+      M->process(WL, R);
+    
   RegionDefaultValue::MapTy DVM = state->get<RegionDefaultValue>();
   for (RegionDefaultValue::MapTy::iterator I = DVM.begin(), E = DVM.end();
-       I != E; ++I)    
-    if (const SubRegion* R = dyn_cast<SubRegion>(I.getKey()))
-      WL.push_back(R);
+       I != E; ++I) 
+    if (const SubRegion *R = dyn_cast<SubRegion>(I.getKey()))
+      M->process(WL, R);
 
   // We also need to record in the subregion map "intermediate" regions that  
   // don't have direct bindings but are super regions of those that do.
   while (!WL.empty()) {
     const SubRegion *R = WL.back();
     WL.pop_back();
-
-    if (Marked.count(R))
-      continue;
-
-    const MemRegion *superR = R->getSuperRegion();
-    if (M->add(superR, R))
-      if (const SubRegion *sr = dyn_cast<SubRegion>(superR))
-        WL.push_back(sr);
+    M->process(WL, R);
   }
 
   return M;
@@ -425,17 +438,20 @@
 // Binding invalidation.
 //===----------------------------------------------------------------------===//
 
-RegionBindingsTy
-RegionStoreManager::RemoveSubRegionBindings(RegionBindingsTy B,
-                                            const MemRegion *R,
-                                            RegionStoreSubRegionMap &M) {
+void
+RegionStoreManager::RemoveSubRegionBindings(RegionBindingsTy &B,
+                                 RegionDefaultValue::MapTy &DVM,
+                                 RegionDefaultValue::MapTy::Factory &DVMFactory,
+                                 const MemRegion *R,
+                                 RegionStoreSubRegionMap &M) {
   
   RegionStoreSubRegionMap::iterator I, E;
 
   for (llvm::tie(I, E) = M.begin_end(R); I != E; ++I)
-    B = RemoveSubRegionBindings(B, *I, M);
+    RemoveSubRegionBindings(B, DVM, DVMFactory, *I, M);
     
-  return RBFactory.Remove(B, R);
+  B = RBFactory.Remove(B, R);
+  DVM = DVMFactory.Remove(DVM, R);
 }
 
 
@@ -448,15 +464,21 @@
   // Strip away casts.
   R = R->getBaseRegion();
 
-  // Get the mapping of regions -> subregions.
-  llvm::OwningPtr<RegionStoreSubRegionMap>
-  SubRegions(getRegionStoreSubRegionMap(state));
-  
   // Remove the bindings to subregions.
-  RegionBindingsTy B = GetRegionBindings(state->getStore());
-  B = RemoveSubRegionBindings(B, R, *SubRegions.get());
-  state = state->makeWithStore(B.getRoot());
-  
+  { 
+    // Get the mapping of regions -> subregions.
+    llvm::OwningPtr<RegionStoreSubRegionMap>
+      SubRegions(getRegionStoreSubRegionMap(state));
+    
+    RegionBindingsTy B = GetRegionBindings(state->getStore());
+    RegionDefaultValue::MapTy DVM = state->get<RegionDefaultValue>();  
+    RegionDefaultValue::MapTy::Factory &DVMFactory =
+      state->get_context<RegionDefaultValue>();
+    
+    RemoveSubRegionBindings(B, DVM, DVMFactory, R, *SubRegions.get());    
+    state = state->makeWithStore(B.getRoot())->set<RegionDefaultValue>(DVM);
+  }
+
   if (!R->isBoundable())
     return state;
   
@@ -975,7 +997,32 @@
                                ValMgr.getRegionValueSymbolValOrUnknown(R, RTy));
 }
   
+std::pair<const GRState*, const MemRegion*>
+RegionStoreManager::GetLazyBinding(RegionBindingsTy B, const MemRegion *R) {
 
+  if (const nonloc::LazyCompoundVal *V =
+        dyn_cast_or_null<nonloc::LazyCompoundVal>(B.lookup(R)))
+    return std::make_pair(V->getState(), V->getRegion());
+  
+  if (const ElementRegion *ER = dyn_cast<ElementRegion>(R)) {
+    const std::pair<const GRState *, const MemRegion *> &X =
+      GetLazyBinding(B, ER->getSuperRegion());
+    
+    if (X.first)
+      return std::make_pair(X.first,
+                            MRMgr.getElementRegionWithSuper(ER, X.second));
+  } 
+  else if (const FieldRegion *FR = dyn_cast<FieldRegion>(R)) {
+    const std::pair<const GRState *, const MemRegion *> &X =
+      GetLazyBinding(B, FR->getSuperRegion());
+    
+    if (X.first)
+      return std::make_pair(X.first,
+                            MRMgr.getFieldRegionWithSuper(FR, X.second));
+  }
+
+  return std::make_pair((const GRState*) 0, (const MemRegion *) 0);
+}
 
 SVal RegionStoreManager::RetrieveElement(const GRState* state,
                                          const ElementRegion* R) {
@@ -1039,10 +1086,30 @@
     if (V->isUnknownOrUndef())
       return *V;
     
+    // Handle LazyCompoundVals below.
+    if (const nonloc::LazyCompoundVal *LVC =
+          dyn_cast<nonloc::LazyCompoundVal>(V)) {
+      return RetrieveElement(LVC->getState(),
+                             MRMgr.getElementRegionWithSuper(R,
+                                                             LVC->getRegion()));
+    }
+      
     // Other cases: give up.
     return UnknownVal();
   }
   
+  // Lazy binding?
+  const GRState *lazyBindingState = NULL;
+  const MemRegion *LazyBindingRegion = NULL;
+  llvm::tie(lazyBindingState, LazyBindingRegion) = GetLazyBinding(B, R);
+  
+  if (lazyBindingState) {
+    assert(LazyBindingRegion && "Lazy-binding region not set");
+    return RetrieveElement(lazyBindingState,
+                           cast<ElementRegion>(LazyBindingRegion));
+  }
+
+  // Default value cases.
 #if 0
   if (R->hasHeapStorage()) {
       // FIXME: If the region has heap storage and we know nothing special
@@ -1093,12 +1160,25 @@
 
       if (D->isZeroConstant())
         return ValMgr.makeZeroVal(Ty);
+      
+      if (const nonloc::LazyCompoundVal *LCV =
+            dyn_cast<nonloc::LazyCompoundVal>(D)) {
+        const FieldRegion *FR =
+          MRMgr.getFieldRegionWithSuper(R, LCV->getRegion());
+        return RetrieveField(LCV->getState(), FR);
+      }
 
       if (D->isUnknown())
         return *D;
 
       assert(0 && "Unknown default value");
     }
+    
+    if (const SVal *V = B.lookup(superR)) {
+      // Handle LazyCompoundVals below.
+      if (isa<nonloc::CompoundVal>(*V))
+        break;
+    }
    
     // If our super region is a field or element itself, walk up the region
     // hierarchy to see if there is a default value installed in an ancestor.
@@ -1108,7 +1188,18 @@
     }
     
     break;
-  }    
+  }
+  
+  // Lazy binding?
+  const GRState *lazyBindingState = NULL;
+  const MemRegion *LazyBindingRegion = NULL;
+  llvm::tie(lazyBindingState, LazyBindingRegion) = GetLazyBinding(B, R);
+  
+  if (lazyBindingState) {
+    assert(LazyBindingRegion && "Lazy-binding region not set");
+    return RetrieveField(lazyBindingState,
+                        cast<FieldRegion>(LazyBindingRegion));
+  }
 
 #if HEAP_UNDEFINED
   // FIXME: Is this correct?  Should it be UnknownVal?
@@ -1206,7 +1297,7 @@
   const RecordType* RT = T->getAsStructureType();
   RecordDecl* RD = RT->getDecl();
   assert(RD->isDefinition());
-
+#if USE_EXPLICIT_COMPOUND
   llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
 
   // FIXME: We shouldn't use a std::vector.  If RecordDecl doesn't have a
@@ -1223,11 +1314,14 @@
   }
 
   return ValMgr.makeCompoundVal(T, StructVal);
+#else
+  return ValMgr.makeLazyCompoundVal(state, R);
+#endif
 }
 
 SVal RegionStoreManager::RetrieveArray(const GRState *state,
                                        const TypedRegion * R) {
-
+#if USE_EXPLICIT_COMPOUND
   QualType T = R->getValueType(getContext());
   ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
 
@@ -1243,6 +1337,10 @@
   }
 
   return ValMgr.makeCompoundVal(T, ArrayVal);
+#else
+  assert(isa<ConstantArrayType>(R->getValueType(getContext())));
+  return ValMgr.makeLazyCompoundVal(state, R);
+#endif
 }
 
 SValuator::CastResult RegionStoreManager::CastRetrievedVal(SVal V,
@@ -1311,8 +1409,7 @@
   
   // Perform the binding.
   RegionBindingsTy B = GetRegionBindings(state->getStore());
-  B = RBFactory.Add(B, R, V);  
-  return state->makeWithStore(B.getRoot());
+  return state->makeWithStore(RBFactory.Add(B, R, V).getRoot());
 }
 
 const GRState *RegionStoreManager::BindDecl(const GRState *state, 
@@ -1375,6 +1472,11 @@
     return state;
   }
 
+  // Handle lazy compound values.
+  if (nonloc::LazyCompoundVal *LCV = dyn_cast<nonloc::LazyCompoundVal>(&Init))
+    return CopyLazyBindings(*LCV, state, R);
+  
+  // Remaining case: explicit compound values.  
   nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
   nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
   uint64_t i = 0;
@@ -1421,6 +1523,10 @@
   if (!RD->isDefinition())
     return state;
 
+  // Handle lazy compound values.
+  if (const nonloc::LazyCompoundVal *LCV = dyn_cast<nonloc::LazyCompoundVal>(&V))
+    return CopyLazyBindings(*LCV, state, R);
+  
   // We may get non-CompoundVal accidentally due to imprecise cast logic.
   // Ignore them and kill the field values.
   if (V.isUnknown() || !isa<nonloc::CompoundVal>(V))
@@ -1477,7 +1583,29 @@
                                                const MemRegion* R, SVal V) {
   return state->set<RegionDefaultValue>(R, V);
 }
+  
+const GRState*
+RegionStoreManager::CopyLazyBindings(nonloc::LazyCompoundVal V,
+                                     const GRState *state,
+                                     const TypedRegion *R) {
 
+  // Nuke the old bindings stemming from R.
+  RegionBindingsTy B = GetRegionBindings(state->getStore());
+  RegionDefaultValue::MapTy DVM = state->get<RegionDefaultValue>();
+  RegionDefaultValue::MapTy::Factory &DVMFactory =
+    state->get_context<RegionDefaultValue>();
+
+  llvm::OwningPtr<RegionStoreSubRegionMap> 
+    SubRegions(getRegionStoreSubRegionMap(state));
+
+  // B and DVM are updated after the call to RemoveSubRegionBindings.    
+  RemoveSubRegionBindings(B, DVM, DVMFactory, R, *SubRegions.get());
+  
+  // Now copy the bindings.  This amounts to just binding 'V' to 'R'.  This
+  // results in a zero-copy algorithm.
+  return state->makeWithStore(RBFactory.Add(B, R, V).getRoot());
+}
+  
 //===----------------------------------------------------------------------===//
 // State pruning.
 //===----------------------------------------------------------------------===//
@@ -1666,6 +1794,9 @@
       SymReaper.maybeDead(*SI);
   }
   
+  // FIXME: Do a pass over nonloc::LazyCompoundVals and the symbols
+  // that they reference.
+  
   // Write the store back.
   state.setStore(store);
   

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

==============================================================================
--- cfe/trunk/lib/Analysis/SVals.cpp (original)
+++ cfe/trunk/lib/Analysis/SVals.cpp Wed Aug  5 20:20:57 2009
@@ -158,6 +158,14 @@
   assert(false && "unhandled expansion case");
 }
 
+const GRState *nonloc::LazyCompoundVal::getState() const {
+  return static_cast<const LazyCompoundValData*>(Data)->getState();
+}
+
+const TypedRegion *nonloc::LazyCompoundVal::getRegion() const {
+  return static_cast<const LazyCompoundValData*>(Data)->getRegion();
+}
+
 //===----------------------------------------------------------------------===//
 // Other Iterators.
 //===----------------------------------------------------------------------===//
@@ -289,7 +297,13 @@
       }
       os << "}";
       break;
-    }      
+    }
+    case nonloc::LazyCompoundValKind: {
+      const nonloc::LazyCompoundVal &C = *cast<nonloc::LazyCompoundVal>(this);
+      os << "lazyCompoundVal{" << (void*) C.getState() << ',' << C.getRegion()
+         << '}';
+      break;
+    }            
     default:
       assert (false && "Pretty-printed not implemented for this NonLoc.");
       break;





More information about the cfe-commits mailing list