MemRegion:
- Overhauled the notion of "types" for TypedRegions.  We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()).  Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs.
- Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type.  We can add it back once there is a need for it and we can resolve its role with these concepts.

StoreManager:
- Overhauled StoreManager::CastRegion.  It expects an *lvalue* type for a region.  This is actually what motivated the overhaul to the MemRegion type mechanism.  It also no longer returns an SVal; we can just return a MemRegion*.
- BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts.  This matches with the MemRegion changes.
- Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion().

AuditCFNumberCreate check:
- Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type.  This change was needed to work with the changes to StoreManager::CastRegion.

GRExprEngine::VisitCast:
- Conform to the new interface of StoreManager::CastRegion.

Tests:
- None of the analysis tests fail now for using the "basic store".
- Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@60995 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index d81b334..be729be 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -504,11 +504,14 @@
     return false;
   
   const TypedRegion* R = dyn_cast<TypedRegion>(LV->getRegion());
-  if (!R)
-    return false;
+  if (!R) return false;
   
+  while (const AnonTypedRegion* ATR = dyn_cast<AnonTypedRegion>(R)) {
+    R = dyn_cast<TypedRegion>(ATR->getSuperRegion());
+    if (!R) return false;
+  }
   
-  QualType T = Ctx.getCanonicalType(R->getType(Ctx));
+  QualType T = Ctx.getCanonicalType(R->getRValueType(Ctx));
   
   // FIXME: If the pointee isn't an integer type, should we flag a warning?
   //  People can do weird stuff with pointers.
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 91d85c4..1febba6 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -66,11 +66,11 @@
   ///  conversions between arrays and pointers.
   SVal ArrayToPointer(SVal Array) { return Array; }
 
-  std::pair<const GRState*, SVal> 
-  CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE) {
-    return std::make_pair(St, UnknownVal());
-  }
-
+  /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+  ///  a MemRegion* to a specific location type.  'R' is the region being
+  ///  casted and 'CastToTy' the result type of the cast.
+  CastResult CastRegion(const GRState* state, const MemRegion* R,
+                        QualType CastToTy);
   
   /// getSelfRegion - Returns the region for the 'self' (Objective-C) or
   ///  'this' object (C++).  When used when analyzing a normal function this
@@ -124,6 +124,25 @@
   return UnknownVal();
 }
   
+/// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+///  a MemRegion* to a specific location type.  'R' is the region being
+///  casted and 'CastToTy' the result type of the cast.
+StoreManager::CastResult
+BasicStoreManager::CastRegion(const GRState* state, const MemRegion* R,
+                              QualType CastToTy) {
+
+  // Return the same region if the region types are compatible.
+  if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
+    ASTContext& Ctx = StateMgr.getContext();
+    QualType Ta = Ctx.getCanonicalType(TR->getLValueType(Ctx));
+    QualType Tb = Ctx.getCanonicalType(CastToTy);
+    
+    if (Ta == Tb)
+      return CastResult(state, R);
+  }
+
+  return CastResult(state, MRMgr.getAnonTypedRegion(CastToTy, R));
+}
   
 SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
                                        const FieldDecl* D) {
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index cb0cbd1..e044d1d 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -1602,7 +1602,7 @@
         if (R) {
           // Set the value of the variable to be a conjured symbol.
           unsigned Count = Builder.getCurrentBlockCount();
-          QualType T = R->getType(Ctx);
+          QualType T = R->getRValueType(Ctx);
           
           // FIXME: handle structs.
           if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 74e1a07..d6b15b1 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1465,7 +1465,7 @@
       // FIXME: The proper thing to do is to really iterate over the
       //  container.  We will do this with dispatch logic to the store.
       //  For now, just 'conjure' up a symbolic value.
-      QualType T = R->getType(getContext());
+      QualType T = R->getRValueType(getContext());
       assert (Loc::IsLocType(T));
       unsigned Count = Builder->getCurrentBlockCount();
       loc::SymbolVal SymV(SymMgr.getConjuredSymbol(elem, T, Count));
@@ -1731,16 +1731,25 @@
       continue;
     }
 
-    // Check for casts from a pointer to a region to typed pointer.
-    if (isa<loc::MemRegionVal>(V)) {
+    // Check for casts from a region to a specific type.
+    if (loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(&V)) {
       assert(Loc::IsLocType(T));
       assert(Loc::IsLocType(ExTy));
 
-      // Delegate to store manager.
-      std::pair<const GRState*, SVal> Res =  
-        getStoreManager().CastRegion(St, V, T, CastE);
-
-      MakeNode(Dst, CastE, N, BindExpr(Res.first, CastE, Res.second));
+      const MemRegion* R = RV->getRegion();
+      StoreManager& StoreMgr = getStoreManager();
+      
+      // Delegate to store manager to get the result of casting a region
+      // to a different type.
+      const StoreManager::CastResult& Res = StoreMgr.CastRegion(St, R, T);
+      
+      // Inspect the result.  If the MemRegion* returned is NULL, this
+      // expression evaluates to UnknownVal.
+      R = Res.getRegion();
+      if (R) { V = loc::MemRegionVal(R); } else { V = UnknownVal(); }
+      
+      // Generate the new node in the ExplodedGraph.
+      MakeNode(Dst, CastE, N, BindExpr(Res.getState(), CastE, V));
       continue;
     }
 
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 94ffb3f..898aff0 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -51,18 +51,6 @@
   ID.AddPointer(superRegion);
 }
 
-QualType AnonPointeeRegion::getType(ASTContext& C) const {
-  return C.getCanonicalType(T);
-}
-
-void AnonPointeeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, 
-                                      SymbolRef Sym,
-                                      const MemRegion* superRegion) {
-  ID.AddInteger((unsigned) AnonPointeeRegionKind);
-  Sym.Profile(ID);
-  ID.AddPointer(superRegion);
-}
-
 void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
   CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
 }
@@ -106,9 +94,9 @@
   ElementRegion::ProfileRegion(ID, Index, superRegion);
 }
 
-QualType ElementRegion::getType(ASTContext& C) const {
-  QualType T = getArrayRegion()->getType(C);
-
+QualType ElementRegion::getRValueType(ASTContext& C) const {
+  QualType T = getArrayRegion()->getLValueType(C);
+  // FIXME: Should ArrayType be considered an LValue or RValue type?
   if (isa<ArrayType>(T.getTypePtr())) {
     ArrayType* AT = cast<ArrayType>(T.getTypePtr());
     return AT->getElementType();
@@ -121,6 +109,14 @@
 }
 
 //===----------------------------------------------------------------------===//
+// getLValueType() and getRValueType()
+//===----------------------------------------------------------------------===//
+
+QualType StringRegion::getRValueType(ASTContext& C) const {
+  return Str->getType();
+}
+
+//===----------------------------------------------------------------------===//
 // Region pretty-printing.
 //===----------------------------------------------------------------------===//
 
@@ -390,26 +386,6 @@
   return R;
 }
 
-AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(SymbolRef Sym,
-                                                          QualType T) {
-  llvm::FoldingSetNodeID ID;
-  MemRegion* superRegion = getUnknownRegion();
-
-  AnonPointeeRegion::ProfileRegion(ID, Sym, superRegion);
-
-  void* InsertPos;
-  MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
-  AnonPointeeRegion* R = cast_or_null<AnonPointeeRegion>(data);
-
-  if (!R) {
-    R = (AnonPointeeRegion*) A.Allocate<AnonPointeeRegion>();
-    new (R) AnonPointeeRegion(Sym, T, superRegion);
-    Regions.InsertNode(R, InsertPos);
-  }
-
-  return R;
-}
-
 AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
   llvm::FoldingSetNodeID ID;
   AllocaRegion::ProfileRegion(ID, E, cnt);
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index defa80f..af1bebf 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -101,8 +101,11 @@
 
   SVal ArrayToPointer(SVal Array);
 
-  std::pair<const GRState*, SVal>
-  CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE);
+  /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+  ///  a MemRegion* to a specific location type.  'R' is the region being
+  ///  casted and 'CastToTy' the result type of the cast.  
+  CastResult CastRegion(const GRState* state, const MemRegion* R,
+                        QualType CastToTy);
 
   SVal Retrieve(const GRState* state, Loc L, QualType T = QualType());
 
@@ -297,7 +300,7 @@
                                            const MemRegion* R) {
   if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
     // Get the type of the variable.
-    QualType T = VR->getType(getContext());
+    QualType T = VR->getRValueType(getContext());
 
     // It must be of array type. 
     const ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
@@ -326,8 +329,8 @@
     llvm::APSInt SSize = cast<nonloc::ConcreteInt>(*T).getValue();
 
     // Get the size of the element in bits.
-    QualType ElemTy = cast<PointerType>(ATR->getType(getContext()).getTypePtr())
-                      ->getPointeeType();
+    QualType LvT = ATR->getLValueType(getContext());
+    QualType ElemTy = cast<PointerType>(LvT.getTypePtr())->getPointeeType();
 
     uint64_t X = getContext().getTypeSize(ElemTy);
 
@@ -378,25 +381,22 @@
   return loc::MemRegionVal(ER);                    
 }
 
-std::pair<const GRState*, SVal>
-RegionStoreManager::CastRegion(const GRState* St, SVal VoidPtr, 
-                               QualType CastToTy, Stmt* CastE) {
-  if (const AllocaRegion* AR =
-      dyn_cast<AllocaRegion>(cast<loc::MemRegionVal>(VoidPtr).getRegion())) {
-
-    // Create a new region to attach type information to it.
-    const AnonTypedRegion* TR = MRMgr.getAnonTypedRegion(CastToTy, AR);
-
-    // Get the pointer to the first element.
-    nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
-    const ElementRegion* ER = MRMgr.getElementRegion(Idx, TR);
-
-    // Add a RegionView to base region.
-    return std::make_pair(AddRegionView(St, TR, AR), loc::MemRegionVal(ER));
+StoreManager::CastResult
+RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
+                               QualType CastToTy) {
+  
+  // Return the same region if the region types are compatible.
+  if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
+    ASTContext& Ctx = StateMgr.getContext();
+    QualType Ta = Ctx.getCanonicalType(TR->getLValueType(Ctx));
+    QualType Tb = Ctx.getCanonicalType(CastToTy);
+    
+    if (Ta == Tb)
+      return CastResult(state, R);
   }
-
-  // Default case.
-  return std::make_pair(St, UnknownVal());
+  
+  const MemRegion* ViewR = MRMgr.getAnonTypedRegion(CastToTy, R);  
+  return CastResult(AddRegionView(state, ViewR, R), ViewR);
 }
 
 SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) {
@@ -410,7 +410,7 @@
     assert(R && "bad region");
 
     if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
-      if (TR->getType(getContext())->isStructureType())
+      if (TR->getRValueType(getContext())->isStructureType())
         return RetrieveStruct(S, TR);
 
     RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(S));
@@ -434,7 +434,8 @@
 }
 
 SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
-  QualType T = R->getType(getContext());
+  // FIXME: Verify we want getRValueType instead of getLValueType.
+  QualType T = R->getRValueType(getContext());
   assert(T->isStructureType());
 
   const RecordType* RT = cast<RecordType>(T.getTypePtr());
@@ -471,7 +472,8 @@
   assert(R);
 
   if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
-    if (TR->getType(getContext())->isStructureType())
+    // FIXME: Verify we want getRValueType().
+    if (TR->getRValueType(getContext())->isStructureType())
       return BindStruct(store, TR, V);
 
   RegionBindingsTy B = GetRegionBindings(store);
@@ -481,7 +483,8 @@
 }
 
 Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R, SVal V){
-  QualType T = R->getType(getContext());
+  // Verify we want getRValueType.
+  QualType T = R->getRValueType(getContext());
   assert(T->isStructureType());
 
   const RecordType* RT = cast<RecordType>(T.getTypePtr());
@@ -774,7 +777,9 @@
 
 Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R, 
                                           SVal Init) {
-  QualType T = R->getType(getContext());
+  
+  // FIXME: Verify we should use getLValueType or getRValueType.
+  QualType T = R->getLValueType(getContext());
   assert(T->isArrayType());
 
   ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
@@ -829,7 +834,9 @@
 // Bind all elements of the array to some value.
 Store RegionStoreManager::BindArrayToVal(Store store, const TypedRegion* BaseR,
                                          SVal V){
-  QualType T = BaseR->getType(getContext());
+  
+  // FIXME: Verify we want getRValueType.
+  QualType T = BaseR->getRValueType(getContext());
   assert(T->isArrayType());
 
   // Only handle constant size array for now.
@@ -855,7 +862,9 @@
 
 Store RegionStoreManager::BindArrayToSymVal(Store store, 
                                             const TypedRegion* BaseR) {
-  QualType T = BaseR->getType(getContext());
+  
+  // FIXME: Verify we want getRValueType.
+  QualType T = BaseR->getRValueType(getContext());
   assert(T->isArrayType());
 
   if (ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(T.getTypePtr())) {
@@ -882,7 +891,9 @@
 
 Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R, 
                                            SVal Init) {
-  QualType T = R->getType(getContext());
+  
+  // FIXME: Verify that we should use getRValueType or getLValueType.
+  QualType T = R->getRValueType(getContext());
   assert(T->isStructureType());
 
   RecordType* RT = cast<RecordType>(T.getTypePtr());
@@ -925,7 +936,9 @@
 // Bind all fields of the struct to some value.
 Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
                                           SVal V) {
-  QualType T = BaseR->getType(getContext());
+  
+  // FIXME: Verify that we should use getLValueType or getRValueType.
+  QualType T = BaseR->getRValueType(getContext());
   assert(T->isStructureType());
 
   const RecordType* RT = cast<RecordType>(T.getTypePtr());
@@ -955,7 +968,9 @@
 
 Store RegionStoreManager::BindStructToSymVal(Store store, 
                                              const TypedRegion* BaseR) {
-  QualType T = BaseR->getType(getContext());
+  
+  // FIXME: Verify that we should use getLValueType or getRValueType
+  QualType T = BaseR->getRValueType(getContext());
   assert(T->isStructureType());
 
   const RecordType* RT = cast<RecordType>(T.getTypePtr());