Make StoreManager::InvalidateRegion() virtual, move the current implementation
in StoreManager to RegionStoreManager, and create a special, highly reduced
version in BasicStoreManager.

These changes are in preparation for future RegionStore-specific changes to
InvalidateRegion.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@77483 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index dc0cac8..c533a7e 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -244,6 +244,9 @@
   // Binding values to regions.
   //===-------------------------------------------------------------------===//
 
+  const GRState *InvalidateRegion(const GRState *state, const MemRegion *R,
+                                  const Expr *E, unsigned Count);
+  
   const GRState *Bind(const GRState *state, Loc LV, SVal V);
 
   const GRState *BindCompoundLiteral(const GRState *state,
@@ -415,6 +418,103 @@
 }
 
 //===----------------------------------------------------------------------===//
+// Binding invalidation.
+//===----------------------------------------------------------------------===//
+
+const GRState *RegionStoreManager::InvalidateRegion(const GRState *state,
+                                                    const MemRegion *R,
+                                                    const Expr *E,
+                                                    unsigned Count) {
+  ASTContext& Ctx = StateMgr.getContext();
+  
+  if (!R->isBoundable())
+    return state;
+  
+  if (isa<AllocaRegion>(R) || isa<SymbolicRegion>(R) 
+      || isa<ObjCObjectRegion>(R)) {
+    // Invalidate the alloca region by setting its default value to 
+    // conjured symbol. The type of the symbol is irrelavant.
+    SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count);
+    state = setDefaultValue(state, R, V);
+    
+    // FIXME: This form of invalidation is a little bogus; we actually need
+    // to invalidate all subregions as well.
+    return state;
+  }
+  
+  const TypedRegion *TR = cast<TypedRegion>(R);
+  QualType T = TR->getValueType(Ctx);
+  
+  // FIXME: The code causes a crash when using RegionStore on the test case
+  // 'test_invalidate_cast_int' (misc-ps.m).  Consider removing it
+  // permanently.  Region casts are probably not too strict to handle
+  // the transient interpretation of memory.  Instead we can use the QualType
+  // passed to 'Retrieve' and friends to determine the most current
+  // interpretation of memory when it is actually used.
+#if 0
+  // If the region is cast to another type, use that type.  
+  if (const QualType *CastTy = getCastType(state, R)) {
+    assert(!(*CastTy)->isObjCObjectPointerType());
+    QualType NewT = (*CastTy)->getAsPointerType()->getPointeeType();    
+    
+    // The only exception is if the original region had a location type as its
+    // value type we always want to treat the region as binding to a location.
+    // This issue can arise when pointers are casted to integers and back.
+    
+    if (!(Loc::IsLocType(T) && !Loc::IsLocType(NewT)))
+      T = NewT;
+  }
+#endif
+  
+  if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
+    SVal V = ValMgr.getConjuredSymbolVal(E, T, Count);
+    return Bind(state, ValMgr.makeLoc(TR), V);
+  }
+  else if (const RecordType *RT = T->getAsStructureType()) {
+    // FIXME: handle structs with default region value.
+    const RecordDecl *RD = RT->getDecl()->getDefinition(Ctx);
+    
+    // No record definition.  There is nothing we can do.
+    if (!RD)
+      return state;
+    
+    // Iterate through the fields and construct new symbols.
+    for (RecordDecl::field_iterator FI=RD->field_begin(),
+         FE=RD->field_end(); FI!=FE; ++FI) {
+      
+      // For now just handle scalar fields.
+      FieldDecl *FD = *FI;
+      QualType FT = FD->getType();
+      const FieldRegion* FR = MRMgr.getFieldRegion(FD, TR);
+      
+      if (Loc::IsLocType(FT) || 
+          (FT->isIntegerType() && FT->isScalarType())) {
+        SVal V = ValMgr.getConjuredSymbolVal(E, FT, Count);
+        state = state->bindLoc(ValMgr.makeLoc(FR), V);
+      }
+      else if (FT->isStructureType()) {
+        // set the default value of the struct field to conjured
+        // symbol. Note that the type of the symbol is irrelavant.
+        // We cannot use the type of the struct otherwise ValMgr won't
+        // give us the conjured symbol.
+        SVal V = ValMgr.getConjuredSymbolVal(E, Ctx.IntTy, Count);
+        state = setDefaultValue(state, FR, V);
+      }
+    }
+  } else if (const ArrayType *AT = Ctx.getAsArrayType(T)) {
+    // Set the default value of the array to conjured symbol.
+    SVal V = ValMgr.getConjuredSymbolVal(E, AT->getElementType(),
+                                         Count);
+    state = setDefaultValue(state, TR, V);
+  } else {
+    // Just blast away other values.
+    state = Bind(state, ValMgr.makeLoc(TR), UnknownVal());
+  }
+  
+  return state;
+}
+
+//===----------------------------------------------------------------------===//
 // getLValueXXX methods.
 //===----------------------------------------------------------------------===//