Improve flat store: MemRegion::getAsOffset() computes a region's offset within
the top-level object. FlatStore now can bind and retrieve element and field
regions.
PR7297 is fixed by flat store.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@110020 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Checker/FlatStore.cpp b/lib/Checker/FlatStore.cpp
index 64575b3..51c537e 100644
--- a/lib/Checker/FlatStore.cpp
+++ b/lib/Checker/FlatStore.cpp
@@ -74,7 +74,14 @@
     return RegionBindings(static_cast<const RegionBindings::TreeTy*>(store));
   }
 
-  Interval RegionToInterval(const MemRegion *R);
+  class RegionInterval {
+  public:
+    const MemRegion *R;
+    Interval I;
+    RegionInterval(const MemRegion *r, uint64_t s, uint64_t e) : R(r), I(s, e){}
+  };
+
+  RegionInterval RegionToInterval(const MemRegion *R);
 
   SVal RetrieveRegionWithNoBinding(const MemRegion *R, QualType T);
 };
@@ -86,11 +93,14 @@
 
 SVal FlatStoreManager::Retrieve(Store store, Loc L, QualType T) {
   const MemRegion *R = cast<loc::MemRegionVal>(L).getRegion();
-  Interval I = RegionToInterval(R);
+  RegionInterval RI = RegionToInterval(R);
+
+  assert(RI.R && "should handle regions with unknown interval");
+
   RegionBindings B = getRegionBindings(store);
-  const BindingVal *BV = B.lookup(R);
+  const BindingVal *BV = B.lookup(RI.R);
   if (BV) {
-    const SVal *V = BVFactory.Lookup(*BV, I);
+    const SVal *V = BVFactory.Lookup(*BV, RI.I);
     if (V)
       return *V;
     else
@@ -116,9 +126,10 @@
   if (V)
     BV = *V;
 
-  Interval I = RegionToInterval(R);
-  BV = BVFactory.Add(BV, I, val);
-  B = RBFactory.Add(B, R, BV);
+  RegionInterval RI = RegionToInterval(R);
+  assert(RI.R && "should handle regions with unknown interval");
+  BV = BVFactory.Add(BV, RI.I, val);
+  B = RBFactory.Add(B, RI.R, BV);
   return B.getRoot();
 }
 
@@ -139,7 +150,7 @@
 
 Store FlatStoreManager::BindDecl(Store store, const VarRegion *VR, 
                                  SVal initVal) {
-  return store;
+  return Bind(store, ValMgr.makeLoc(VR), initVal);
 }
 
 Store FlatStoreManager::BindDeclWithNoInit(Store store, const VarRegion *VR) {
@@ -170,15 +181,30 @@
 void FlatStoreManager::iterBindings(Store store, BindingsHandler& f) {
 }
 
-Interval FlatStoreManager::RegionToInterval(const MemRegion *R) { 
+FlatStoreManager::RegionInterval 
+FlatStoreManager::RegionToInterval(const MemRegion *R) { 
   switch (R->getKind()) {
   case MemRegion::VarRegionKind: {
     QualType T = cast<VarRegion>(R)->getValueType(Ctx);
     uint64_t Size = Ctx.getTypeSize(T);
-    return Interval(0, Size-1);
+    return RegionInterval(R, 0, Size-1);
   }
+
+  case MemRegion::ElementRegionKind: 
+  case MemRegion::FieldRegionKind: {
+    const TypedRegion *TR = cast<TypedRegion>(R);
+    RegionOffset Offset = TR->getAsOffset();
+    // We cannot compute offset for all ElementRegions, for example, elements
+    // with symbolic offsets.
+    if (!Offset.getRegion())
+      return RegionInterval(0, 0, 0);
+    uint64_t Start = Offset.getOffset();
+    uint64_t Size = Ctx.getTypeSize(TR->getValueType(Ctx));
+    return RegionInterval(Offset.getRegion(), Start, Start+Size);
+  }
+
   default:
     llvm_unreachable("Region kind unhandled.");
-    return Interval(0, 0);
+    return RegionInterval(0, 0, 0);
   }
 }