Enhances SCA to process untyped region to typed region conversion.
 - RegionView and RegionViewMap is introduced to assist back-mapping from
   super region to subregions.
 - GDM is used to carry RegionView information.
 - AnonTypedRegion is added to represent a typed region introduced by pointer
   casting. Later AnonTypedRegion can be used in other similar cases, e.g.,
   malloc()'ed region.
 - The specific conversion is delegated to store manager.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@59382 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index f1c57b3..732785c 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -16,26 +16,46 @@
 //===----------------------------------------------------------------------===//
 #include "clang/Analysis/PathSensitive/MemRegion.h"
 #include "clang/Analysis/PathSensitive/GRState.h"
+#include "clang/Analysis/PathSensitive/GRStateTrait.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
 
 #include "llvm/ADT/ImmutableMap.h"
+#include "llvm/ADT/ImmutableList.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Compiler.h"
 
 using namespace clang;
 
 typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
+typedef llvm::ImmutableList<const MemRegion*> RegionViewTy;
+typedef llvm::ImmutableMap<const MemRegion*, RegionViewTy> RegionViewMapTy;
+
+static int RegionViewMapTyIndex = 0;
+
+namespace clang {
+template<> struct GRStateTrait<RegionViewMapTy> 
+  : public GRStatePartialTrait<RegionViewMapTy> {
+  static void* GDMIndex() { return &RegionViewMapTyIndex; }
+};
+}
 
 namespace {
 
 class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
   RegionBindingsTy::Factory RBFactory;
+  RegionViewTy::Factory RVFactory;
+  RegionViewMapTy::Factory RVMFactory;
+
   GRStateManager& StateMgr;
   MemRegionManager MRMgr;
 
 public:
   RegionStoreManager(GRStateManager& mgr) 
-    : StateMgr(mgr), MRMgr(StateMgr.getAllocator()) {}
+    : RBFactory(mgr.getAllocator()),
+      RVFactory(mgr.getAllocator()),
+      RVMFactory(mgr.getAllocator()),
+      StateMgr(mgr), 
+      MRMgr(StateMgr.getAllocator()) {}
 
   virtual ~RegionStoreManager() {}
 
@@ -62,6 +82,9 @@
 
   SVal ArrayToPointer(SVal Array);
 
+  const GRState* CastRegion(const GRState* St, SVal VoidPtr, 
+                            QualType CastToTy, Stmt* CastE);
+
   SVal Retrieve(Store S, Loc L, QualType T = QualType());
 
   Store Bind(Store St, Loc LV, SVal V);
@@ -112,6 +135,9 @@
   // Utility methods.
   BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
   ASTContext& getContext() { return StateMgr.getContext(); }
+
+  const GRState* AddRegionView(const GRState* St,
+                               const MemRegion* View, const MemRegion* Base);
 };
 
 } // end anonymous namespace
@@ -238,6 +264,30 @@
   return loc::MemRegionVal(ER);                    
 }
 
+const GRState* 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);
+
+    St = StateMgr.BindExpr(St, CastE, loc::MemRegionVal(ER));
+
+    // Add a RegionView to base region.
+    return AddRegionView(St, TR, AR);
+  }
+
+  // Default case.
+  return St;
+}
+
 SVal RegionStoreManager::Retrieve(Store S, Loc L, QualType T) {
   assert(!isa<UnknownVal>(L) && "location unknown");
   assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -600,3 +650,19 @@
 
   return store;
 }
+
+const GRState* RegionStoreManager::AddRegionView(const GRState* St,
+                                                 const MemRegion* View,
+                                                 const MemRegion* Base) {
+  GRStateRef state(St, StateMgr);
+
+  // First, retrieve the region view of the base region.
+  RegionViewMapTy::data_type* d = state.get<RegionViewMapTy>(Base);
+  RegionViewTy L = d ? *d : RVFactory.GetEmptyList();
+
+  // Now add View to the region view.
+  L = RVFactory.Add(View, L);
+
+  // Create a new state with the new region view.
+  return state.set<RegionViewMapTy>(Base, L);
+}