Enhance understanding of VarRegions referenced by a block whose declarations are outside the current stack frame.  Fixes <rdar://problem/7462324>.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@91107 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Analysis/AnalysisContext.cpp b/lib/Analysis/AnalysisContext.cpp
index 113587f..3a6cf42 100644
--- a/lib/Analysis/AnalysisContext.cpp
+++ b/lib/Analysis/AnalysisContext.cpp
@@ -179,6 +179,19 @@
   return NULL;
 }
 
+const StackFrameContext *
+LocationContext::getStackFrameForDeclContext(const DeclContext *DC) const {
+  const LocationContext *LC = this;
+  while (LC) {
+    if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
+      if (cast<DeclContext>(SFC->getDecl()) == DC)
+        return SFC;
+    }
+    LC = LC->getParent();
+  }
+  return NULL;
+}
+
 //===----------------------------------------------------------------------===//
 // Lazily generated map to query the external variables referenced by a Block.
 //===----------------------------------------------------------------------===//
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 3bf3e5b..da45c4d 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -381,13 +381,22 @@
 }
 
 const StackLocalsSpaceRegion*
-MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {  
-  return LazyAllocate(stackLocals, STC);
+MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
+  assert(STC);
+  if (STC == cachedStackLocalsFrame)
+    return cachedStackLocalsRegion;
+  cachedStackLocalsFrame = STC;
+  return LazyAllocate(cachedStackLocalsRegion, STC);
 }
 
 const StackArgumentsSpaceRegion *
 MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
-  return LazyAllocate(stackArguments, STC);
+  assert(STC);
+  if (STC == cachedStackArgumentsFrame)
+    return cachedStackArgumentsRegion;
+  
+  cachedStackArgumentsFrame = STC;
+  return LazyAllocate(cachedStackArgumentsRegion, STC);
 }
 
 const GlobalsSpaceRegion *MemRegionManager::getGlobalsRegion() {
@@ -418,15 +427,19 @@
                                                 const LocationContext *LC) {
   const MemRegion *sReg = 0;
 
-  if (D->hasLocalStorage()) {
+  if (D->hasLocalStorage()) {    
     // FIXME: Once we implement scope handling, we will need to properly lookup
     // 'D' to the proper LocationContext.
-    const StackFrameContext *STC = LC->getCurrentStackFrame();
+    const DeclContext *DC = D->getDeclContext();
+    const StackFrameContext *STC = LC->getStackFrameForDeclContext(DC);
 
-    assert(STC);
-    sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
-           ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
-           : static_cast<const MemRegion*>(getStackLocalsRegion(STC));
+    if (!STC)
+      sReg = getUnknownRegion();
+    else {
+      sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
+            ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
+            : static_cast<const MemRegion*>(getStackLocalsRegion(STC));
+    }
   }
   else {
     sReg = getGlobalsRegion();
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index c718f1f..b5eeb1e 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -728,6 +728,7 @@
     case MemRegion::StackArgumentsSpaceRegionKind:
     case MemRegion::HeapSpaceRegionKind:
     case MemRegion::GlobalsSpaceRegionKind:
+    case MemRegion::UnknownSpaceRegionKind:
       assert(0 && "Cannot index into a MemSpace");
       return UnknownVal();
 
@@ -881,6 +882,7 @@
     case MemRegion::StackArgumentsSpaceRegionKind:
     case MemRegion::HeapSpaceRegionKind:
     case MemRegion::GlobalsSpaceRegionKind:
+    case MemRegion::UnknownSpaceRegionKind:
       assert(0 && "Cannot perform pointer arithmetic on a MemSpace");
       return UnknownVal();
   }
@@ -1292,7 +1294,8 @@
   // Lazily derive a value for the VarRegion.
   const VarDecl *VD = R->getDecl();
 
-  if (R->hasGlobalsOrParametersStorage())
+  if (R->hasGlobalsOrParametersStorage() ||
+      isa<UnknownSpaceRegion>(R->getMemorySpace()))
     return ValMgr.getRegionValueSymbolValOrUnknown(R, VD->getType());
 
   return UndefinedVal();
diff --git a/lib/Analysis/Store.cpp b/lib/Analysis/Store.cpp
index be4ce2d..e6ff6e5 100644
--- a/lib/Analysis/Store.cpp
+++ b/lib/Analysis/Store.cpp
@@ -81,6 +81,7 @@
     case MemRegion::StackLocalsSpaceRegionKind:
     case MemRegion::StackArgumentsSpaceRegionKind:
     case MemRegion::HeapSpaceRegionKind:
+    case MemRegion::UnknownSpaceRegionKind:
     case MemRegion::GlobalsSpaceRegionKind: {
       assert(0 && "Invalid region cast");
       break;