- constify some uses of MemRegion* (MemRegion should be immutable).
- Added new region "SymbolicRegion", which maps symbol values to the region domain.
- Enhanced BasicStore::getFieldLValue() to return a FieldRegion (using SymbolicRegion)
- Added some utility methods to GRState for fetch svals from the store.
- Fixed regression in CheckNSError (we weren't getting the value bound to the parameter)


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57717 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index 8e32218..96a7ea1 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -367,7 +367,7 @@
   
 private:
   
-  void AddError(TypedRegion* R, Expr* Ex, ExplodedNode<GRState> *N,
+  void AddError(const TypedRegion* R, Expr* Ex, ExplodedNode<GRState> *N,
                 uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);  
 };
 } // end anonymous namespace
@@ -503,7 +503,7 @@
   if (!LV)
     return false;
   
-  TypedRegion* R = dyn_cast<TypedRegion>(LV->getRegion());
+  const TypedRegion* R = dyn_cast<TypedRegion>(LV->getRegion());
   if (!R)
     return false;
   
@@ -530,7 +530,7 @@
   return SourceSize < TargetSize;
 }
 
-void AuditCFNumberCreate::AddError(TypedRegion* R, Expr* Ex,
+void AuditCFNumberCreate::AddError(const TypedRegion* R, Expr* Ex,
                                    ExplodedNode<GRState> *N,
                                    uint64_t SourceSize, uint64_t TargetSize,
                                    uint64_t NumberKind) {
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 7998ef4..e1220ce 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -90,7 +90,41 @@
   
 SVal BasicStoreManager::getLValueField(const GRState* St, const FieldDecl* D,
                                        SVal Base) {
-  return UnknownVal();
+
+  if (Base.isUnknownOrUndef())
+    return Base;
+  
+  Loc BaseL = cast<Loc>(Base);  
+  const MemRegion* BaseR = 0;
+  
+  switch(BaseL.getSubKind()) {
+    case loc::SymbolValKind:
+      BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
+      break;
+      
+    case loc::GotoLabelKind:
+    case loc::FuncValKind:
+      // Technically we can get here if people do funny things with casts.
+      return UndefinedVal();
+
+    case loc::MemRegionKind:
+      BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
+      break;
+      
+    case loc::ConcreteIntKind:
+    case loc::StringLiteralValKind:
+      // While these seem funny, this can happen through casts.
+      // FIXME: What we should return is the field offset.  For example,
+      //  add the field offset to the integer value.  That way funny things
+      //  like this work properly:  &(((struct foo *) 0xa)->f)
+      return Base;
+
+    default:
+      assert ("Unhandled Base.");
+      return Base;
+  }
+  
+  return loc::MemRegionVal(MRMgr.getFieldRegion(D, BaseR));
 }
 
 SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
@@ -108,7 +142,7 @@
   switch (LV.getSubKind()) {
 
     case loc::MemRegionKind: {
-      VarRegion* R =
+      const VarRegion* R =
         dyn_cast<VarRegion>(cast<loc::MemRegionVal>(LV).getRegion());
       
       if (!R)
@@ -145,7 +179,7 @@
 Store BasicStoreManager::SetSVal(Store store, Loc LV, SVal V) {    
   switch (LV.getSubKind()) {      
     case loc::MemRegionKind: {
-      VarRegion* R =
+      const VarRegion* R =
         dyn_cast<VarRegion>(cast<loc::MemRegionVal>(LV).getRegion());
       
       if (!R)
@@ -165,8 +199,8 @@
 Store BasicStoreManager::Remove(Store store, Loc LV) {
   switch (LV.getSubKind()) {
     case loc::MemRegionKind: {
-      VarRegion* R =
-      dyn_cast<VarRegion>(cast<loc::MemRegionVal>(LV).getRegion());
+      const VarRegion* R =
+        dyn_cast<VarRegion>(cast<loc::MemRegionVal>(LV).getRegion());
       
       if (!R)
         return store;
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index 9d63231..e720096 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -1513,7 +1513,7 @@
           state = state.remove<RefBindings>(Sym);
         }
         
-        TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion());
+        const TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion());
         if (R) {
           // Set the value of the variable to be a conjured symbol.
           unsigned Count = Builder.getCurrentBlockCount();
@@ -1717,7 +1717,7 @@
   if (!isa<loc::MemRegionVal>(TargetLV))
     escapes = true;
   else {
-    MemRegion* R = cast<loc::MemRegionVal>(TargetLV).getRegion();
+    const MemRegion* R = cast<loc::MemRegionVal>(TargetLV).getRegion();
     escapes = !Eng.getStateManager().hasStackStorage(R);
   }
   
diff --git a/lib/Analysis/CheckNSError.cpp b/lib/Analysis/CheckNSError.cpp
index 38d32a7..f76b601 100644
--- a/lib/Analysis/CheckNSError.cpp
+++ b/lib/Analysis/CheckNSError.cpp
@@ -216,7 +216,11 @@
                                    GRExprEngine& Eng, GRBugReporter& BR,
                                    bool isNSErrorWarning) {
   
-  SVal ParamSVal = rootState.GetLValue(Param);
+  SVal ParamL = rootState.GetLValue(Param);
+  const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>();
+  assert (ParamR && "Parameters always have VarRegions.");
+  SVal ParamSVal = rootState.GetSVal(ParamR);
+  
 
   // FIXME: For now assume that ParamSVal is symbolic.  We need to generalize
   // this later.
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 747d2f6..97a4fbc 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -56,6 +56,15 @@
   DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
 }
 
+void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolID sym) {
+  ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
+  ID.AddInteger(sym.getNumber());
+}
+
+void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+  SymbolicRegion::ProfileRegion(ID, sym);
+}
+
 //===----------------------------------------------------------------------===//
 // Region pretty-printing.
 //===----------------------------------------------------------------------===//
@@ -75,6 +84,10 @@
   os << cast<VarDecl>(D)->getName();
 }
 
+void SymbolicRegion::print(llvm::raw_ostream& os) const {
+  os << "$" << sym.getNumber();
+}
+
 //===----------------------------------------------------------------------===//
 // MemRegionManager methods.
 //===----------------------------------------------------------------------===//
@@ -106,7 +119,7 @@
 }
 
 VarRegion* MemRegionManager::getVarRegion(const VarDecl* d,
-                                          MemRegion* superRegion) {
+                                          const MemRegion* superRegion) {
   llvm::FoldingSetNodeID ID;
   DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
   
@@ -123,8 +136,27 @@
   return R;
 }
 
+/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
+SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolID sym) {
+  
+  llvm::FoldingSetNodeID ID;
+  SymbolicRegion::ProfileRegion(ID, sym);
+  
+  void* InsertPos;
+  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
+  SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
+  
+  if (!R) {
+    R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
+    new (R) SymbolicRegion(sym);
+    Regions.InsertNode(R, InsertPos);
+  }
+  
+  return R;  
+}
+
 FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
-                                              MemRegion* superRegion) {
+                                              const MemRegion* superRegion) {
   llvm::FoldingSetNodeID ID;
   DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
   
@@ -141,8 +173,9 @@
   return R;
 }
 
-ObjCIvarRegion* MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
-                                                    MemRegion* superRegion) {
+ObjCIvarRegion*
+MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
+                                    const MemRegion* superRegion) {
   llvm::FoldingSetNodeID ID;
   DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
   
@@ -181,11 +214,20 @@
 }
 
 bool MemRegionManager::hasStackStorage(const MemRegion* R) {
+  const SubRegion* SR = dyn_cast<SubRegion>(R);
+
+  // Only subregions can have stack storage.
+  if (!SR)
+    return false;
+  
   MemSpaceRegion* S = getStackRegion();
   
-  while (R) {
-    if (R == S) return true;
-    R = R->getSuperRegion();
+  while (SR) {
+    R = SR->getSuperRegion();
+    if (R == S)
+      return true;
+    
+    SR = dyn_cast<SubRegion>(R);    
   }
   
   return false;
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 6757f43..48706ce 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -52,7 +52,7 @@
 Store RegionStoreManager::SetSVal(Store store, Loc LV, SVal V) {
   assert(LV.getSubKind() == loc::MemRegionKind);
 
-  MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
+  const MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
   
   if (!R)
     return store;