Improve RegionStoreManager::getSizeInElements()
 - add a static function getTypeWidth(), which computes the width of a type
   with the help of TargetInfo.
 - no-outofbounds.c now passes for region store.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@71080 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index 043fc95..5f987fd 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -18,6 +18,7 @@
 #include "clang/Analysis/PathSensitive/GRState.h"
 #include "clang/Analysis/PathSensitive/GRStateTrait.h"
 #include "clang/Analysis/Analyses/LiveVariables.h"
+#include "clang/Basic/TargetInfo.h"
 
 #include "llvm/ADT/ImmutableMap.h"
 #include "llvm/ADT/ImmutableList.h"
@@ -296,6 +297,7 @@
   // Utility methods.
   BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
   ASTContext& getContext() { return StateMgr.getContext(); }
+  TargetInfo& getTargetInfo() { return getContext().getTargetInfo(); }
   SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
 
   const GRState* AddRegionView(const GRState* St,
@@ -310,6 +312,45 @@
   return new RegionStoreManager(StMgr);
 }
 
+// getTypeWidth - compute the width of the type. Should pass in
+// canonical type.
+static unsigned getTypeWidth(ASTContext& Ctx, QualType T) {
+  TargetInfo& Target = Ctx.getTargetInfo();
+  QualType CanT = Ctx.getCanonicalType(T);
+
+  if (CanT->isPointerType())
+    return Target.getPointerWidth(0);
+
+  if (CanT->isCharType())
+    return Target.getCharWidth();
+
+  if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanT)) {
+    switch (BT->getKind()) {
+    case BuiltinType::Char_U:
+    case BuiltinType::UChar:
+    case BuiltinType::Char_S:
+    case BuiltinType::SChar:
+      return Target.getCharWidth();
+
+    case BuiltinType::UShort:
+    case BuiltinType::Short:
+      return Target.getShortWidth();
+
+    case BuiltinType::UInt:
+    case BuiltinType::Int:
+      return Target.getIntWidth();
+
+    case BuiltinType::ULong:
+    case BuiltinType::Long:
+      return Target.getLongWidth();
+    default:
+      assert(0 && "Unprocessed builtin type.");
+    }
+  }
+
+  assert(0 && "Unprocessed type.");
+}
+
 SubRegionMap* RegionStoreManager::getSubRegionMap(const GRState *state) {
   RegionBindingsTy B = GetRegionBindings(state->getStore());
   RegionStoreSubRegionMap *M = new RegionStoreSubRegionMap();
@@ -503,7 +544,17 @@
 
     // If the VarRegion is cast to other type, compute the size with respect to
     // that type.
-    
+    GRStateRef state(St, StateMgr);
+    const QualType* CastTy = state.get<RegionCasts>(VR);
+
+    if (CastTy) {
+      QualType EleTy =cast<PointerType>(CastTy->getTypePtr())->getPointeeType();
+      QualType VarTy = VR->getRValueType(getContext());
+      unsigned EleWidth = getTypeWidth(getContext(), EleTy);
+      unsigned VarWidth = getTypeWidth(getContext(), VarTy);
+      return NonLoc::MakeIntVal(getBasicVals(), VarWidth / EleWidth, false);
+    }
+
     // Clients can use ordinary variables as if they were arrays.  These
     // essentially are arrays of size 1.
     return NonLoc::MakeIntVal(getBasicVals(), 1, false);
@@ -613,7 +664,7 @@
 
 RegionStoreManager::CastResult
 RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
-                         QualType CastToTy) {
+                               QualType CastToTy) {
   
   ASTContext& Ctx = StateMgr.getContext();