Enhance RegionStore's reasoning about Objective-C ivars.  More testing to follow.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@75748 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 661f84f..fa355f5 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -281,9 +281,11 @@
   ///       return symbolic
   SVal Retrieve(const GRState *state, Loc L, QualType T = QualType());
 
-  SVal RetrieveElement(const GRState* state, const ElementRegion* R);
+  SVal RetrieveElement(const GRState *state, const ElementRegion *R);
 
-  SVal RetrieveField(const GRState* state, const FieldRegion* R);
+  SVal RetrieveField(const GRState *state, const FieldRegion *R);
+  
+  SVal RetrieveObjCIvar(const GRState *state, const ObjCIvarRegion *R);
 
   /// Retrieve the values in a struct and return a CompoundVal, used when doing
   /// struct copy: 
@@ -865,20 +867,8 @@
   if (V)
     return *V;
 
-  if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R)) {
-    const MemRegion *SR = IVR->getSuperRegion();
-
-    // If the super region is 'self' then return the symbol representing
-    // the value of the ivar upon entry to the method.
-    if (SR == SelfRegion) {
-      // FIXME: Do we need to handle the case where the super region
-      // has a view?  We want to canonicalize the bindings.
-      return ValMgr.getRegionValueSymbolVal(R);
-    }
-    
-    // Otherwise, we need a new symbol.  For now return Unknown.
-    return UnknownVal();
-  }
+  if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
+    return RetrieveObjCIvar(state, IVR);
 
   // The location does not have a bound value.  This means that it has
   // the value it had upon its creation and/or entry to the analyzed
@@ -1025,6 +1015,40 @@
   return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty);
 }
 
+SVal RegionStoreManager::RetrieveObjCIvar(const GRState* state, 
+                                          const ObjCIvarRegion* R) {
+
+  QualType Ty = R->getValueType(getContext());
+  
+    // Check if the region has a binding.
+  RegionBindingsTy B = GetRegionBindings(state->getStore());
+
+  if (const SVal* V = B.lookup(R))
+    return *V;
+  
+  const MemRegion *superR = R->getSuperRegion();
+
+  // Check if the super region has a binding.
+  if (const SVal *V = B.lookup(superR)) {
+    if (SymbolRef parentSym = V->getAsSymbol())
+      return ValMgr.getDerivedRegionValueSymbolVal(parentSym, R);
+    
+    // Other cases: give up.
+    return UnknownVal();
+  }
+  
+  // If the region is already cast to another type, use that type to create the
+  // symbol value.
+  if (const QualType *p = state->get<RegionCasts>(R)) {
+    QualType tmp = *p;
+    Ty = tmp->getAsPointerType()->getPointeeType();
+  }
+  
+  // All other values are symbolic.
+  return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty);
+}
+
+
 SVal RegionStoreManager::RetrieveStruct(const GRState *state, 
 					const TypedRegion* R){
   QualType T = R->getValueType(getContext());