Charusso created this revision.
Charusso added reviewers: NoQ, xazax.hun.
Charusso added a project: clang.
Herald added subscribers: cfe-commits, dkrupp, donat.nagy, Szelethus, 
mikhail.ramalho, a.sidorin, rnkovacs, szepet, baloghadamsoftware.

This patch generalizes the `AllocaRegion` to store metadata about the
expression of the allocation of a memory block. This information could be
used to apply fix-its to the size expression of the allocation when the
buffer would overflow.


Repository:
  rC Clang

https://reviews.llvm.org/D68725

Files:
  clang/include/clang/Analysis/AnalysisDeclContext.h
  clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
  clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
  clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
  clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
  clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
  clang/lib/StaticAnalyzer/Core/CallEvent.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
  clang/lib/StaticAnalyzer/Core/MemRegion.cpp
  clang/lib/StaticAnalyzer/Core/RegionStore.cpp
  clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
  clang/lib/StaticAnalyzer/Core/Store.cpp
  clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
  clang/test/Analysis/array-struct.c
  clang/test/Analysis/exercise-ps.c
  clang/test/Analysis/explain-svals.cpp
  clang/test/Analysis/pr22954.c
  clang/www/analyzer/implicit_checks.html

Index: clang/www/analyzer/implicit_checks.html
===================================================================
--- clang/www/analyzer/implicit_checks.html
+++ clang/www/analyzer/implicit_checks.html
@@ -84,10 +84,9 @@
 <td><div class="exampleContainer expandable">
 <div class="example"><pre>
 void test(int x) {
-  int *p = (int *)__builtin_alloca(8);
-    // evaluates to AllocaRegion
+  int *p = (int *)__builtin_alloca(8); // Evaluates to 'MemoryBlockRegion'.
 
-  if(__builtin_expect(x > 10, 0)) // evaluates to 'x > 10'
+  if(__builtin_expect(x > 10, 0))      // Evaluates to 'x > 10'.
     x = 0;
 }
 </pre></div></div></td></tr>
Index: clang/test/Analysis/pr22954.c
===================================================================
--- clang/test/Analysis/pr22954.c
+++ clang/test/Analysis/pr22954.c
@@ -625,9 +625,8 @@
   clang_analyzer_eval(m29[i].s3[2] == 1); // expected-warning{{UNKNOWN}}
   clang_analyzer_eval(m29[i].s3[3] == 1); // expected-warning{{UNKNOWN}}
   clang_analyzer_eval(m29[j].s3[k] == 1); // expected-warning{{TRUE}}
+  // expected-warning@-1 {{Potential leak of memory pointed to by field 's4'}}
   clang_analyzer_eval(l29->s1[m] == 2); // expected-warning{{UNKNOWN}}
-  // FIXME: Should warn that m29[i].s4 leaks. But not on the previous line,
-  // because l29 and m29 alias.
   return 0;
 }
 
Index: clang/test/Analysis/explain-svals.cpp
===================================================================
--- clang/test/Analysis/explain-svals.cpp
+++ clang/test/Analysis/explain-svals.cpp
@@ -87,7 +87,7 @@
   void test_5(int i) {
     clang_analyzer_explain(this); // expected-warning-re{{{{^pointer to 'this' object$}}}}
     clang_analyzer_explain(&x[i]); // expected-warning-re{{{{^pointer to element of type 'int' with index 'argument 'i'' of field 'x' of 'this' object$}}}}
-    clang_analyzer_explain(__builtin_alloca(i)); // expected-warning-re{{{{^pointer to region allocated by '__builtin_alloca\(i\)'$}}}}
+    clang_analyzer_explain(__builtin_alloca(i)); // expected-warning-re{{{{^pointer to memory block region allocated by '__builtin_alloca\(i\)'$}}}}
   }
 };
 } // end of anonymous namespace
Index: clang/test/Analysis/exercise-ps.c
===================================================================
--- clang/test/Analysis/exercise-ps.c
+++ clang/test/Analysis/exercise-ps.c
@@ -22,7 +22,7 @@
   // expected-note{{include the header <string.h> or explicitly provide a declaration for 'memcpy'}}
 }
 
-// AllocaRegion is untyped. Void pointer isn't of much help either. Before
+// MemoryBlockRegion is untyped. Void pointer isn't of much help either. Before
 // realizing that the value is undefined, we need to somehow figure out
 // what type of value do we expect.
 void f3(void *dest) {
Index: clang/test/Analysis/array-struct.c
===================================================================
--- clang/test/Analysis/array-struct.c
+++ clang/test/Analysis/array-struct.c
@@ -53,7 +53,7 @@
   g1(&data);
 }
 
-// AllocaRegion test.
+// MemoryBlockRegion test.
 void f6() {
   char *p;
   p = __builtin_alloca(10); 
Index: clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
+++ clang/lib/StaticAnalyzer/Core/SymbolManager.cpp
@@ -442,9 +442,9 @@
 
   // FIXME: This is a gross over-approximation. What we really need is a way to
   // tell if anything still refers to this region. Unlike SymbolicRegions,
-  // AllocaRegions don't have associated symbols, though, so we don't actually
-  // have a way to track their liveness.
-  if (isa<AllocaRegion>(MR))
+  // MemoryBlockRegions don't have associated symbols, though, so we don't
+  // actually have a way to track their liveness.
+  if (isa<MemoryBlockRegion>(MR))
     return true;
 
   if (isa<CXXThisRegion>(MR))
Index: clang/lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/Store.cpp
+++ clang/lib/StaticAnalyzer/Core/Store.cpp
@@ -129,7 +129,7 @@
     case MemRegion::StringRegionKind:
       // FIXME: Need to handle arbitrary downcasts.
     case MemRegion::SymbolicRegionKind:
-    case MemRegion::AllocaRegionKind:
+    case MemRegion::MemoryBlockRegionKind:
     case MemRegion::CompoundLiteralRegionKind:
     case MemRegion::FieldRegionKind:
     case MemRegion::ObjCIvarRegionKind:
@@ -502,7 +502,7 @@
     //   char *p = __builtin_alloc(10);
     //   p[1] = 8;
     //
-    //  Observe that 'p' binds to an AllocaRegion.
+    //  Observe that 'p' binds to a 'MemoryBlockRegion'.
     return loc::MemRegionVal(MRMgr.getElementRegion(elementType, Offset,
                                                     BaseRegion, Ctx));
   }
Index: clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -187,18 +187,28 @@
   return nonloc::SymbolVal(sym);
 }
 
-DefinedOrUnknownSVal
-SValBuilder::getConjuredHeapSymbolVal(const Expr *E,
-                                      const LocationContext *LCtx,
-                                      unsigned VisitCount) {
-  QualType T = E->getType();
-  assert(Loc::isLocType(T));
-  assert(SymbolManager::canSymbolicate(T));
-  if (T->isNullPtrType())
-    return makeZeroVal(T);
+DefinedOrUnknownSVal SValBuilder::getConjuredHeapSymbolVal(
+    const Expr *AllocExpr, const Decl *AllocDecl, const Expr *SizeExpr,
+    DefinedOrUnknownSVal Size, const LocationContext *LCtx,
+    unsigned BlockCount) {
+  QualType Ty = AllocExpr->getType();
+  assert(Loc::isLocType(Ty));
+  assert(SymbolManager::canSymbolicate(Ty));
+  if (Ty->isNullPtrType())
+    return makeZeroVal(Ty);
+
+  SymbolRef Sym = SymMgr.conjureSymbol(AllocExpr, LCtx, Ty, BlockCount);
+  return loc::MemRegionVal(MemMgr.getSymbolicHeapMemoryBlock(
+      Sym, AllocExpr, AllocDecl, SizeExpr, Size, BlockCount));
+}
 
-  SymbolRef sym = SymMgr.conjureSymbol(E, LCtx, T, VisitCount);
-  return loc::MemRegionVal(MemMgr.getSymbolicHeapRegion(sym));
+DefinedOrUnknownSVal
+SValBuilder::getStackSymbolVal(const Expr *AllocExpr, const Decl *AllocDecl,
+                               const Expr *SizeExpr, DefinedOrUnknownSVal Size,
+                               const LocationContext *LCtx, unsigned BlockCount,
+                               bool IsArgument) {
+  return loc::MemRegionVal(MemMgr.getStackMemoryBlockRegion(
+      AllocExpr, AllocDecl, SizeExpr, Size, LCtx, BlockCount, IsArgument));
 }
 
 DefinedSVal SValBuilder::getMetadataSymbolVal(const void *symbolTag,
Index: clang/lib/StaticAnalyzer/Core/RegionStore.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/RegionStore.cpp
+++ clang/lib/StaticAnalyzer/Core/RegionStore.cpp
@@ -1144,7 +1144,7 @@
   if (Regions)
     Regions->push_back(baseR);
 
-  if (isa<AllocaRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
+  if (isa<MemoryBlockRegion>(baseR) || isa<SymbolicRegion>(baseR)) {
     // Invalidate the region by setting its default value to
     // conjured symbol. The type of the symbol is irrelevant.
     DefinedOrUnknownSVal V =
Index: clang/lib/StaticAnalyzer/Core/MemRegion.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/MemRegion.cpp
+++ clang/lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -62,53 +62,16 @@
 // MemRegion Construction.
 //===----------------------------------------------------------------------===//
 
-template <typename RegionTy, typename SuperTy, typename Arg1Ty>
-RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1,
-                                         const SuperTy *superRegion) {
+template <typename RegionTy, typename... ArgsTy>
+RegionTy *MemRegionManager::getSubRegion(ArgsTy &&... Args) {
   llvm::FoldingSetNodeID ID;
-  RegionTy::ProfileRegion(ID, arg1, superRegion);
+  RegionTy::ProfileRegion(ID, std::forward<ArgsTy>(Args)...);
   void *InsertPos;
   auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
 
   if (!R) {
     R = A.Allocate<RegionTy>();
-    new (R) RegionTy(arg1, superRegion);
-    Regions.InsertNode(R, InsertPos);
-  }
-
-  return R;
-}
-
-template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty>
-RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
-                                         const SuperTy *superRegion) {
-  llvm::FoldingSetNodeID ID;
-  RegionTy::ProfileRegion(ID, arg1, arg2, superRegion);
-  void *InsertPos;
-  auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
-
-  if (!R) {
-    R = A.Allocate<RegionTy>();
-    new (R) RegionTy(arg1, arg2, superRegion);
-    Regions.InsertNode(R, InsertPos);
-  }
-
-  return R;
-}
-
-template <typename RegionTy, typename SuperTy,
-          typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
-RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
-                                         const Arg3Ty arg3,
-                                         const SuperTy *superRegion) {
-  llvm::FoldingSetNodeID ID;
-  RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion);
-  void *InsertPos;
-  auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
-
-  if (!R) {
-    R = A.Allocate<RegionTy>();
-    new (R) RegionTy(arg1, arg2, arg3, superRegion);
+    new (R) RegionTy(std::forward<ArgsTy>(Args)...);
     Regions.InsertNode(R, InsertPos);
   }
 
@@ -196,10 +159,6 @@
   return Extent;
 }
 
-DefinedOrUnknownSVal AllocaRegion::getExtent(SValBuilder &svalBuilder) const {
-  return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
-}
-
 DefinedOrUnknownSVal SymbolicRegion::getExtent(SValBuilder &svalBuilder) const {
   return nonloc::SymbolVal(svalBuilder.getSymbolManager().getExtentSymbol(this));
 }
@@ -262,17 +221,22 @@
   ID.AddPointer(superRegion);
 }
 
-void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
-                                 const Expr *Ex, unsigned cnt,
-                                 const MemRegion *superRegion) {
-  ID.AddInteger(static_cast<unsigned>(AllocaRegionKind));
-  ID.AddPointer(Ex);
-  ID.AddInteger(cnt);
+void MemoryBlockRegion::ProfileRegion(
+    llvm::FoldingSetNodeID &ID, const Expr *AllocExpr, const Decl *AllocDecl,
+    const Expr *SizeExpr, DefinedOrUnknownSVal Size, unsigned BlockCount,
+    const MemRegion *superRegion) {
+  ID.AddInteger(static_cast<unsigned>(MemoryBlockRegionKind));
+  ID.AddPointer(AllocExpr);
+  ID.AddPointer(AllocDecl);
+  ID.AddPointer(SizeExpr);
+  ID.Add(Size);
+  ID.AddInteger(BlockCount);
   ID.AddPointer(superRegion);
 }
 
-void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
-  ProfileRegion(ID, Ex, Cnt, superRegion);
+void MemoryBlockRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+  ProfileRegion(ID, AllocExpr, AllocDecl, SizeExpr, Size, BlockCount,
+                superRegion);
 }
 
 void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
@@ -455,8 +419,21 @@
   os << "<Unknown Region>";
 }
 
-void AllocaRegion::dumpToStream(raw_ostream &os) const {
-  os << "alloca{S" << Ex->getID(getContext()) << ',' << Cnt << '}';
+void MemoryBlockRegion::dumpToStream(raw_ostream &os) const {
+  os << "memory_block{";
+
+  if (AllocExpr)
+    os << 'S' << AllocExpr->getID(getContext());
+  else
+    os << "no stmt";
+  os << ',';
+
+  if (AllocDecl)
+    os << 'D' << AllocDecl->getID();
+  else
+    os << "no decl";
+
+  os << ',' << Size << ',' << BlockCount << '}';
 }
 
 void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
@@ -524,7 +501,7 @@
 }
 
 void SymbolicRegion::dumpToStream(raw_ostream &os) const {
-  if (isa<HeapSpaceRegion>(getSuperRegion()))
+  if (isa<HeapSpaceRegion>(getSuperRegion()->getMemorySpace()))
     os << "Heap";
   os << "SymRegion{" << sym << '}';
 }
@@ -848,7 +825,6 @@
   const MemRegion *sReg = nullptr;
 
   if (D->hasGlobalStorage() && !D->isStaticLocal()) {
-
     // First handle the globals defined in system headers.
     if (C.getSourceManager().isInSystemHeader(D->getLocation())) {
       // Whitelist the system globals which often DO GET modified, assume the
@@ -889,11 +865,26 @@
       sReg = getUnknownRegion();
     } else {
       if (D->hasLocalStorage()) {
-        sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
-               ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
-               : static_cast<const MemRegion*>(getStackLocalsRegion(STC));
-      }
-      else {
+        const Expr *SizeExpr = nullptr;
+        if (D->getType()->isArrayType())
+          if (const TypeSourceInfo *TSI = D->getTypeSourceInfo())
+            if (const auto ATL = TSI->getTypeLoc().getAs<ArrayTypeLoc>())
+              SizeExpr = ATL.getSizeExpr();
+
+        bool IsArgument = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D);
+        if (IsArgument)
+          sReg = getStackArgumentsRegion(STC);
+        else
+          sReg = getStackLocalsRegion(STC);
+
+        if (SizeExpr) {
+          // Create a temporary 'VarRegion' to obtain the extent.
+          const VarRegion *TempVR = getSubRegion<VarRegion>(D, sReg);
+          sReg = getStackMemoryBlockRegion(nullptr, D, SizeExpr,
+                                           TempVR->getExtent(SVB), STC,
+                                           STC->getBlockCount(), IsArgument);
+        }
+      } else {
         assert(D->isStaticLocal());
         const Decl *STCD = STC->getDecl();
         if (isa<FunctionDecl>(STCD) || isa<ObjCMethodDecl>(STCD))
@@ -1028,6 +1019,31 @@
   return getSubRegion<SymbolicRegion>(Sym, getHeapRegion());
 }
 
+const SymbolicRegion *MemRegionManager::getSymbolicHeapMemoryBlock(
+    SymbolRef Sym, const Expr *AllocExpr, const Decl *AllocDecl,
+    const Expr *SizeExpr, DefinedOrUnknownSVal Size, unsigned BlockCount) {
+  return getSubRegion<SymbolicRegion>(
+      Sym, getSubRegion<MemoryBlockRegion>(AllocExpr, AllocDecl, SizeExpr, Size,
+                                           BlockCount, getHeapRegion()));
+}
+
+const MemoryBlockRegion *MemRegionManager::getStackMemoryBlockRegion(
+    const Expr *AllocExpr, const Decl *AllocDecl, const Expr *SizeExpr,
+    DefinedOrUnknownSVal Size, const LocationContext *LCtx, unsigned BlockCount,
+    bool IsArgument) {
+  const StackFrameContext *STC = LCtx->getStackFrame();
+  assert(STC);
+
+  const MemSpaceRegion *SuperR = nullptr;
+  if (IsArgument)
+    SuperR = getStackArgumentsRegion(STC);
+  else
+    SuperR = getStackLocalsRegion(STC);
+
+  return getSubRegion<MemoryBlockRegion>(AllocExpr, AllocDecl, SizeExpr, Size,
+                                         BlockCount, SuperR);
+}
+
 const FieldRegion*
 MemRegionManager::getFieldRegion(const FieldDecl *d,
                                  const SubRegion* superRegion){
@@ -1117,14 +1133,6 @@
   return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC));
 }
 
-const AllocaRegion*
-MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt,
-                                  const LocationContext *LC) {
-  const StackFrameContext *STC = LC->getStackFrame();
-  assert(STC);
-  return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC));
-}
-
 const MemSpaceRegion *MemRegion::getMemorySpace() const {
   const MemRegion *R = this;
   const auto *SR = dyn_cast<SubRegion>(this);
@@ -1320,7 +1328,7 @@
       goto Finish;
 
     case MemRegion::SymbolicRegionKind:
-    case MemRegion::AllocaRegionKind:
+    case MemRegion::MemoryBlockRegionKind:
     case MemRegion::CompoundLiteralRegionKind:
     case MemRegion::CXXThisRegionKind:
     case MemRegion::StringRegionKind:
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -654,15 +654,26 @@
     // See if we need to conjure a heap pointer instead of
     // a regular unknown pointer.
     bool IsHeapPointer = false;
-    if (const auto *CNE = dyn_cast<CXXNewExpr>(E))
-      if (CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
-        // FIXME: Delegate this to evalCall in MallocChecker?
-        IsHeapPointer = true;
+    const auto *CNE = dyn_cast<CXXNewExpr>(E);
+    if (CNE && CNE->getOperatorNew()->isReplaceableGlobalAllocationFunction()) {
+      // FIXME: Delegate this to evalCall in MallocChecker?
+      IsHeapPointer = true;
+    }
+
+    DefinedOrUnknownSVal Size = UnknownVal();
+    const Expr *SizeExpr = nullptr;
+    if (CNE) {
+      if (Optional<const Expr *> TempSizeExpr = CNE->getArraySize()) {
+        SizeExpr = *TempSizeExpr;
+        Size = State->getSVal(SizeExpr, LCtx).castAs<DefinedOrUnknownSVal>();
       }
+    }
 
-    R = IsHeapPointer ? svalBuilder.getConjuredHeapSymbolVal(E, LCtx, Count)
-                      : svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy,
-                                                     Count);
+    R = IsHeapPointer
+            ? svalBuilder.getConjuredHeapSymbolVal(
+                  E, CNE ? CNE->getOperatorNew() : nullptr, SizeExpr, Size,
+                  LCtx, Count)
+            : svalBuilder.conjureSymbolVal(nullptr, E, LCtx, ResultTy, Count);
   }
   return State->BindExpr(E, LCtx, R);
 }
Index: clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -761,11 +761,20 @@
   // heap. We realize this is an approximation that might not correctly model
   // a custom global allocator.
   if (symVal.isUnknown()) {
-    if (IsStandardGlobalOpNewFunction)
-      symVal = svalBuilder.getConjuredHeapSymbolVal(CNE, LCtx, blockCount);
-    else
+    if (IsStandardGlobalOpNewFunction) {
+      DefinedOrUnknownSVal Size = UnknownVal();
+      const Expr *SizeExpr = nullptr;
+      if (Optional<const Expr *> TempSizeExpr = CNE->getArraySize()) {
+        SizeExpr = *TempSizeExpr;
+        Size = State->getSVal(SizeExpr, LCtx).castAs<DefinedOrUnknownSVal>();
+      }
+
+      symVal = svalBuilder.getConjuredHeapSymbolVal(
+          CNE, CNE->getOperatorNew(), SizeExpr, Size, LCtx, blockCount);
+    } else {
       symVal = svalBuilder.conjureSymbolVal(nullptr, CNE, LCtx, CNE->getType(),
                                             blockCount);
+    }
   }
 
   CallEventManager &CEMgr = getStateManager().getCallEventManager();
Index: clang/lib/StaticAnalyzer/Core/CallEvent.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/CallEvent.cpp
+++ clang/lib/StaticAnalyzer/Core/CallEvent.cpp
@@ -1210,7 +1210,7 @@
 
       DynamicTypeInfo DTI = getDynamicTypeInfo(getState(), Receiver);
       if (!DTI.isValid()) {
-        assert(isa<AllocaRegion>(Receiver) &&
+        assert(isa<MemoryBlockRegion>(Receiver) &&
                "Unhandled untyped region class!");
         return {};
       }
Index: clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -2039,7 +2039,7 @@
     if (const auto *SR = L->getRegionAs<SymbolicRegion>()) {
       if (SR->getSymbol()->getType()->getPointeeType()->isVoidType())
         CanDereference = false;
-    } else if (L->getRegionAs<AllocaRegion>())
+    } else if (L->getRegionAs<MemoryBlockRegion>())
       CanDereference = false;
 
     // At this point we are dealing with the region's LValue.
Index: clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp
@@ -69,6 +69,9 @@
                                             ASTContext &Ctx) {
   // Get the base region, stripping away fields and elements.
   R = R->getBaseRegion();
+  if (const SymbolicRegion *SR = R->getSymbolicBase())
+    R = SR->getSuperRegion();
+
   SourceManager &SM = Ctx.getSourceManager();
   SourceRange range;
   os << "Address of ";
@@ -80,10 +83,10 @@
           "declared on line "
        << SM.getExpansionLineNumber(CL->getBeginLoc()) << " returned to caller";
     range = CL->getSourceRange();
-  } else if (const auto *AR = dyn_cast<AllocaRegion>(R)) {
-    const Expr *ARE = AR->getExpr();
-    SourceLocation L = ARE->getBeginLoc();
-    range = ARE->getSourceRange();
+  } else if (const auto *MBR = dyn_cast<MemoryBlockRegion>(R)) {
+    const Expr *AllocExpr = MBR->getAllocExpr();
+    SourceLocation L = AllocExpr->getBeginLoc();
+    range = AllocExpr->getSourceRange();
     os << "stack memory allocated by call to alloca() on line "
        << SM.getExpansionLineNumber(L);
   } else if (const auto *BR = dyn_cast<BlockDataRegion>(R)) {
Index: clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -461,8 +461,8 @@
   /// \param [in] State The \c ProgramState right before allocation.
   /// \returns The ProgramState right after allocation.
   static ProgramStateRef MallocMemAux(CheckerContext &C, const CallExpr *CE,
-                                      SVal Size, SVal Init,
-                                      ProgramStateRef State,
+                                      const Expr *SizeExpr, SVal Size,
+                                      SVal Init, ProgramStateRef State,
                                       AllocationFamily Family = AF_Malloc);
 
   static ProgramStateRef addExtentSize(CheckerContext &C, const CXXNewExpr *NE,
@@ -1162,7 +1162,7 @@
     } else if (FunI == MemFunctionInfo.II_if_nameindex) {
       // Should we model this differently? We can allocate a fixed number of
       // elements with zeros in the last one.
-      State = MallocMemAux(C, CE, UnknownVal(), UnknownVal(), State,
+      State = MallocMemAux(C, CE, /*SizeExpr=*/nullptr, UnknownVal(), UnknownVal(), State,
                            AF_IfNameIndex);
     } else if (FunI == MemFunctionInfo.II_if_freenameindex) {
       State = FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocatedMemory);
@@ -1192,7 +1192,7 @@
         Init = SB.makeZeroVal(SB.getContext().CharTy);
       }
       SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1));
-      State = MallocMemAux(C, CE, TotalSize, Init, State);
+      State = MallocMemAux(C, CE, CE->getArg(0), TotalSize, Init, State);
       State = ProcessZeroAllocCheck(C, CE, 0, State);
       State = ProcessZeroAllocCheck(C, CE, 1, State);
     } else if (FunI == MemFunctionInfo.II_g_realloc_n ||
@@ -1493,7 +1493,7 @@
     return MallocMemAux(C, CE, CE->getArg(I->getASTIndex()), UndefinedVal(),
                         State);
   }
-  return MallocMemAux(C, CE, UnknownVal(), UndefinedVal(), State);
+  return MallocMemAux(C, CE, /*SizeExpr=*/nullptr, UnknownVal(), UndefinedVal(), State);
 }
 
 ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
@@ -1504,14 +1504,14 @@
   if (!State)
     return nullptr;
 
-  return MallocMemAux(C, CE, C.getSVal(SizeEx), Init, State, Family);
+  return MallocMemAux(C, CE, SizeEx, C.getSVal(SizeEx), Init, State, Family);
 }
 
 ProgramStateRef MallocChecker::MallocMemAux(CheckerContext &C,
-                                           const CallExpr *CE,
-                                           SVal Size, SVal Init,
-                                           ProgramStateRef State,
-                                           AllocationFamily Family) {
+                                            const CallExpr *CE,
+                                            const Expr *SizeExpr, SVal Size,
+                                            SVal Init, ProgramStateRef State,
+                                            AllocationFamily Family) {
   if (!State)
     return nullptr;
 
@@ -1525,8 +1525,11 @@
   unsigned Count = C.blockCount();
   SValBuilder &svalBuilder = C.getSValBuilder();
   const LocationContext *LCtx = C.getPredecessor()->getLocationContext();
-  DefinedSVal RetVal = svalBuilder.getConjuredHeapSymbolVal(CE, LCtx, Count)
-      .castAs<DefinedSVal>();
+  DefinedSVal RetVal = svalBuilder
+                           .getConjuredHeapSymbolVal(
+                               CE, /*AllocDecl=*/nullptr, SizeExpr,
+                               Size.castAs<DefinedOrUnknownSVal>(), LCtx, Count)
+                           .castAs<DefinedSVal>();
   State = State->BindExpr(CE, C.getLocationContext(), RetVal);
 
   // Fill the region with the initialization value.
@@ -1804,7 +1807,7 @@
     // function, so UnknownSpaceRegion is always a possibility.
     // False negatives are better than false positives.
 
-    if (isa<AllocaRegion>(R))
+    if (isa<MemoryBlockRegion>(R))
       ReportFreeAlloca(C, ArgVal, ArgExpr->getSourceRange());
     else
       ReportBadFree(C, ArgVal, ArgExpr->getSourceRange(), ParentExpr);
@@ -2440,7 +2443,7 @@
   // If the ptr is NULL and the size is not 0, the call is equivalent to
   // malloc(size).
   if (PrtIsNull && !SizeIsZero) {
-    ProgramStateRef stateMalloc = MallocMemAux(C, CE, TotalSize,
+    ProgramStateRef stateMalloc = MallocMemAux(C, CE, Arg1, TotalSize,
                                                UndefinedVal(), StatePtrIsNull);
     return stateMalloc;
   }
@@ -2472,7 +2475,7 @@
   if (ProgramStateRef stateFree =
           FreeMemAux(C, CE, State, 0, false, IsKnownToBeAllocated)) {
 
-    ProgramStateRef stateRealloc = MallocMemAux(C, CE, TotalSize,
+    ProgramStateRef stateRealloc = MallocMemAux(C, CE, Arg1, TotalSize,
                                                 UnknownVal(), stateFree);
     if (!stateRealloc)
       return nullptr;
@@ -2506,7 +2509,7 @@
   SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy);
   SVal TotalSize = evalMulForBufferSize(C, CE->getArg(0), CE->getArg(1));
 
-  return MallocMemAux(C, CE, TotalSize, zeroVal, State);
+  return MallocMemAux(C, CE, CE->getArg(0), TotalSize, zeroVal, State);
 }
 
 MallocChecker::LeakInfo MallocChecker::getAllocationSite(const ExplodedNode *N,
Index: clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp
@@ -199,7 +199,7 @@
 static bool isBadDeallocationArgument(const MemRegion *Arg) {
   if (!Arg)
     return false;
-  return isa<AllocaRegion>(Arg) || isa<BlockDataRegion>(Arg) ||
+  return isa<MemoryBlockRegion>(Arg) || isa<BlockDataRegion>(Arg) ||
          isa<TypedRegion>(Arg);
 }
 
Index: clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp
@@ -724,7 +724,7 @@
     return state;
 
   case MemRegion::SymbolicRegionKind:
-  case MemRegion::AllocaRegionKind:
+  case MemRegion::MemoryBlockRegionKind:
   case MemRegion::VarRegionKind:
   case MemRegion::FieldRegionKind:
   case MemRegion::ObjCIvarRegionKind:
@@ -829,7 +829,7 @@
     return svalBuilder.makeIntVal(strLit->getByteLength(), sizeTy);
   }
   case MemRegion::SymbolicRegionKind:
-  case MemRegion::AllocaRegionKind:
+  case MemRegion::MemoryBlockRegionKind:
   case MemRegion::VarRegionKind:
   case MemRegion::FieldRegionKind:
   case MemRegion::ObjCIvarRegionKind:
Index: clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
===================================================================
--- clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
+++ clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp
@@ -77,11 +77,6 @@
 
   case Builtin::BI__builtin_alloca_with_align:
   case Builtin::BI__builtin_alloca: {
-    // FIXME: Refactor into StoreManager itself?
-    MemRegionManager& RM = C.getStoreManager().getRegionManager();
-    const AllocaRegion* R =
-      RM.getAllocaRegion(CE, C.blockCount(), C.getLocationContext());
-
     // Set the extent of the region in bytes. This enables us to use the
     // SVal of the argument directly. If we save the extent in bits, we
     // cannot represent values like symbol*8.
@@ -89,14 +84,12 @@
     if (Size.isUndef())
       return true; // Return true to model purity.
 
-    SValBuilder& svalBuilder = C.getSValBuilder();
-    DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder);
-    DefinedOrUnknownSVal extentMatchesSizeArg =
-      svalBuilder.evalEQ(state, Extent, Size.castAs<DefinedOrUnknownSVal>());
-    state = state->assume(extentMatchesSizeArg, true);
-    assert(state && "The region should not have any previous constraints");
+    SVal V = C.getSValBuilder().getStackSymbolVal(
+        CE, Call.getDecl(), Call.getArgExpr(0),
+        Size.castAs<DefinedOrUnknownSVal>(), C.getLocationContext(),
+        C.blockCount(), /*IsArgument=*/false);
 
-    C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R)));
+    C.addTransition(state->BindExpr(CE, LCtx, V));
     return true;
   }
 
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h
@@ -84,7 +84,7 @@
   SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context,
               ProgramStateManager &stateMgr)
       : Context(context), BasicVals(context, alloc),
-        SymMgr(context, BasicVals, alloc), MemMgr(context, alloc),
+        SymMgr(context, BasicVals, alloc), MemMgr(context, alloc, *this),
         StateMgr(stateMgr), ArrayIndexTy(context.LongLongTy),
         ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {}
 
@@ -217,12 +217,21 @@
                                         QualType type,
                                         unsigned visitCount);
 
-  /// Conjure a symbol representing heap allocated memory region.
-  ///
-  /// Note, the expression should represent a location.
-  DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E,
-                                                const LocationContext *LCtx,
-                                                unsigned Count);
+  /// \returns A conjured symbol representing a heap allocated block of memory.
+  /// \note The expression \p AllocExpr should represent a location.
+  DefinedOrUnknownSVal
+  getConjuredHeapSymbolVal(const Expr *AllocExpr, const Decl *AllocDecl,
+                           const Expr *SizeExpr, DefinedOrUnknownSVal Size,
+                           const LocationContext *LCtx, unsigned BlockCount);
+
+  /// \returns A stack allocated block of memory.
+  /// \note The expression \p AllocExpr should represent a location.
+  DefinedOrUnknownSVal getStackSymbolVal(const Expr *AllocExpr,
+                                         const Decl *AllocDecl,
+                                         const Expr *SizeExpr,
+                                         DefinedOrUnknownSVal Size,
+                                         const LocationContext *LCtx,
+                                         unsigned BlockCount, bool IsArgument);
 
   DefinedOrUnknownSVal getDerivedRegionValueSymbolVal(
       SymbolRef parentSymbol, const TypedValueRegion *region);
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
@@ -55,7 +55,7 @@
   REGION_RANGE(MEMSPACES, CodeSpaceRegionKind,
                           UnknownSpaceRegionKind)
 ABSTRACT_REGION(SubRegion, MemRegion)
-  REGION(AllocaRegion, SubRegion)
+  REGION(MemoryBlockRegion, SubRegion)
   REGION(SymbolicRegion, SubRegion)
   ABSTRACT_REGION(TypedRegion, SubRegion)
     REGION(BlockDataRegion, TypedRegion)
Index: clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -128,6 +128,14 @@
 
   const MemRegion *StripCasts(bool StripBaseAndDerivedCasts = true) const;
 
+  /// getExtent - Returns the size of the region in bytes.
+  virtual DefinedOrUnknownSVal getExtent() const { return UnknownVal(); }
+
+  /// getExtent - Returns the size of the region in bytes.
+  virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
+    return UnknownVal();
+  }
+
   /// If this is a symbolic region, returns the region. Otherwise,
   /// goes up the base chain looking for the first symbolic base region.
   const SymbolicRegion *getSymbolicBase() const;
@@ -449,11 +457,6 @@
     return superRegion;
   }
 
-  /// getExtent - Returns the size of the region in bytes.
-  virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
-    return UnknownVal();
-  }
-
   MemRegionManager* getMemRegionManager() const override;
 
   bool isSubRegionOf(const MemRegion* R) const override;
@@ -467,39 +470,48 @@
 // MemRegion subclasses.
 //===----------------------------------------------------------------------===//
 
-/// AllocaRegion - A region that represents an untyped blob of bytes created
-///  by a call to 'alloca'.
-class AllocaRegion : public SubRegion {
-  friend class MemRegionManager;
-
-  // Block counter. Used to distinguish different pieces of memory allocated by
-  // alloca at the same call site.
-  unsigned Cnt;
-
-  const Expr *Ex;
-
-  AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion)
-      : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {
-    assert(Ex);
-  }
-
-  static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
-                            unsigned Cnt, const MemRegion *superRegion);
-
+/// A region that represents a block of memory.
+class MemoryBlockRegion : public SubRegion {
 public:
-  const Expr *getExpr() const { return Ex; }
+  const Expr *getAllocExpr() const { return AllocExpr; }
+  const Decl *getAllocDecl() const { return AllocDecl; }
+  const Expr *getSizeExpr() const { return SizeExpr; }
+
+  DefinedOrUnknownSVal getExtent() const override { return Size; }
+  DefinedOrUnknownSVal getExtent(SValBuilder &) const override { return Size; }
 
   bool isBoundable() const override { return true; }
 
-  DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+  void Profile(llvm::FoldingSetNodeID &ID) const override;
 
-  void Profile(llvm::FoldingSetNodeID& ID) const override;
+  static bool classof(const MemRegion *R) {
+    return R->getKind() == MemoryBlockRegionKind;
+  }
 
   void dumpToStream(raw_ostream &os) const override;
 
-  static bool classof(const MemRegion* R) {
-    return R->getKind() == AllocaRegionKind;
-  }
+private:
+  MemoryBlockRegion(const Expr *AllocExpr, const Decl *AllocDecl,
+                    const Expr *SizeExpr, DefinedOrUnknownSVal Size,
+                    unsigned BlockCount, const MemSpaceRegion *superRegion)
+      : SubRegion(superRegion, MemoryBlockRegionKind), AllocExpr(AllocExpr),
+        AllocDecl(AllocDecl), SizeExpr(SizeExpr), Size(Size),
+        BlockCount(BlockCount) {
+    assert(AllocExpr || AllocDecl);
+  }
+
+  static void ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *AllocExpr,
+                            const Decl *AllocDecl, const Expr *SizeExpr,
+                            DefinedOrUnknownSVal Size, unsigned BlockCount,
+                            const MemRegion *superRegion);
+
+  const Expr *AllocExpr;
+  const Decl *AllocDecl;
+  const Expr *SizeExpr;
+  DefinedOrUnknownSVal Size;
+  unsigned BlockCount;
+
+  friend class MemRegionManager;
 };
 
 /// TypedRegion - An abstract class representing regions that are typed.
@@ -766,7 +778,7 @@
 
   const SymbolRef sym;
 
-  SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg)
+  SymbolicRegion(const SymbolRef s, const MemRegion *sreg)
       : SubRegion(sreg, SymbolicRegionKind), sym(s) {
     // Because pointer arithmetic is represented by ElementRegion layers,
     // the base symbol here should not contain any arithmetic.
@@ -774,7 +786,8 @@
     assert(s->getType()->isAnyPointerType() ||
            s->getType()->isReferenceType() ||
            s->getType()->isBlockPointerType());
-    assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg));
+    assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg) ||
+           isa<MemoryBlockRegion>(sreg));
   }
 
 public:
@@ -936,7 +949,8 @@
     // Other block variables appear within block data regions,
     // which, unlike everything else on this list, are not memory spaces.
     assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||
-           isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
+           isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg) ||
+           isa<MemoryBlockRegion>(sReg));
   }
 
   static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD,
@@ -1244,6 +1258,7 @@
 class MemRegionManager {
   ASTContext &C;
   llvm::BumpPtrAllocator& A;
+  SValBuilder &SVB;
   llvm::FoldingSet<MemRegion> Regions;
 
   GlobalInternalSpaceRegion *InternalGlobals = nullptr;
@@ -1262,7 +1277,9 @@
   CodeSpaceRegion *code = nullptr;
 
 public:
-  MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : C(c), A(a) {}
+  MemRegionManager(ASTContext &Ctx, llvm::BumpPtrAllocator &Alloc,
+                   SValBuilder &SVB)
+      : C(Ctx), A(Alloc), SVB(SVB) {}
   ~MemRegionManager();
 
   ASTContext &getContext() { return C; }
@@ -1295,10 +1312,6 @@
 
   const CodeSpaceRegion *getCodeRegion();
 
-  /// getAllocaRegion - Retrieve a region associated with a call to alloca().
-  const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
-                                      const LocationContext *LC);
-
   /// getCompoundLiteralRegion - Retrieve the region associated with a
   ///  given CompoundLiteral.
   const CompoundLiteralRegion*
@@ -1313,9 +1326,22 @@
   /// Retrieve or create a "symbolic" memory region.
   const SymbolicRegion* getSymbolicRegion(SymbolRef Sym);
 
-  /// Return a unique symbolic region belonging to heap memory space.
+  /// \returns A unique symbolic region belonging to the generic "heap".
   const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym);
 
+  /// \returns A unique symbolic region to a memory block on the heap.
+  const SymbolicRegion *
+  getSymbolicHeapMemoryBlock(SymbolRef Sym, const Expr *AllocExpr,
+                             const Decl *AllocDecl, const Expr *SizeExpr,
+                             DefinedOrUnknownSVal Size, unsigned BlockCount);
+
+  /// \returns A region associated with a block of memory on the stack.
+  const MemoryBlockRegion *
+  getStackMemoryBlockRegion(const Expr *AllocExpr, const Decl *AllocDecl,
+                            const Expr *SizeExpr, DefinedOrUnknownSVal Size,
+                            const LocationContext *LCtx, unsigned BlockCount,
+                            bool IsArgument);
+
   const StringRegion *getStringRegion(const StringLiteral *Str);
 
   const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str);
@@ -1406,21 +1432,8 @@
   const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
 
 private:
-  template <typename RegionTy, typename SuperTy,
-            typename Arg1Ty>
-  RegionTy* getSubRegion(const Arg1Ty arg1,
-                         const SuperTy* superRegion);
-
-  template <typename RegionTy, typename SuperTy,
-            typename Arg1Ty, typename Arg2Ty>
-  RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
-                         const SuperTy* superRegion);
-
-  template <typename RegionTy, typename SuperTy,
-            typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
-  RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
-                         const Arg3Ty arg3,
-                         const SuperTy* superRegion);
+  template <typename RegionTy, typename... ArgsTy>
+  RegionTy *getSubRegion(ArgsTy &&... Args);
 
   template <typename REG>
   const REG* LazyAllocate(REG*& region);
Index: clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
===================================================================
--- clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
+++ clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h
@@ -152,8 +152,9 @@
     return "pointee of " + Visit(R->getSymbol());
   }
 
-  std::string VisitAllocaRegion(const AllocaRegion *R) {
-    return "region allocated by '" + printStmt(R->getExpr()) + "'";
+  std::string VisitMemoryBlockRegion(const MemoryBlockRegion *R) {
+    return "memory block region allocated by '" + printStmt(R->getAllocExpr()) +
+           "'";
   }
 
   std::string VisitCompoundLiteralRegion(const CompoundLiteralRegion *R) {
Index: clang/include/clang/Analysis/AnalysisDeclContext.h
===================================================================
--- clang/include/clang/Analysis/AnalysisDeclContext.h
+++ clang/include/clang/Analysis/AnalysisDeclContext.h
@@ -323,11 +323,13 @@
 
   const CFGBlock *getCallSiteBlock() const { return Block; }
 
-  /// Return true if the current LocationContext has no caller context.
-  bool inTopFrame() const override { return getParent() == nullptr;  }
+  unsigned getBlockCount() const { return BlockCount; }
 
   unsigned getIndex() const { return Index; }
 
+  /// Return true if the current LocationContext has no caller context.
+  bool inTopFrame() const override { return getParent() == nullptr; }
+
   void Profile(llvm::FoldingSetNodeID &ID) override;
 
   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to