Index: include/clang/Analysis/AnalysisContext.h
===================================================================
--- include/clang/Analysis/AnalysisContext.h
+++ include/clang/Analysis/AnalysisContext.h
@@ -33,6 +33,7 @@
 class PseudoConstantAnalysis;
 class LocationContextManager;
 class StackFrameContext;
+class ScopeContext;
 class BlockInvocationContext;
 class AnalysisDeclContextManager;
 class LocationContext;
@@ -83,6 +84,7 @@
   llvm::BumpPtrAllocator A;
 
   llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars;
+  llvm::DenseMap<const Stmt *, void *> *DeclaredVars;
 
   void *ManagedAnalyses;
 
@@ -163,10 +165,14 @@
   PseudoConstantAnalysis *getPseudoConstantAnalysis();
 
   typedef const VarDecl * const * referenced_decls_iterator;
+  typedef const VarDecl * const * declared_vars_iterator;
 
   std::pair<referenced_decls_iterator, referenced_decls_iterator>
     getReferencedBlockVars(const BlockDecl *BD);
 
+  std::pair<declared_vars_iterator, declared_vars_iterator>
+    getDeclaredVars(const Stmt *Scope);
+
   /// Return the ImplicitParamDecl* associated with 'self' if this
   /// AnalysisDeclContext wraps an ObjCMethodDecl.  Returns NULL otherwise.
   const ImplicitParamDecl *getSelfDecl() const;
@@ -175,6 +181,9 @@
                                          const Stmt *S, const CFGBlock *Blk,
                                          unsigned Idx, unsigned Cnt);
 
+  const ScopeContext *getScope(LocationContext const *Parent, const Stmt *S,
+                               unsigned BlockCount);
+
   const BlockInvocationContext *
   getBlockInvocationContext(const LocationContext *parent,
                             const BlockDecl *BD,
@@ -315,20 +324,29 @@
 
 class ScopeContext : public LocationContext {
   const Stmt *Enter;
+  // The block count to discriminate between scopes of the same statement.
+  unsigned BlockCount;
 
   friend class LocationContextManager;
-  ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent,
-               const Stmt *s)
-    : LocationContext(Scope, ctx, parent), Enter(s) {}
+  ScopeContext(AnalysisDeclContext *ctx, const LocationContext *Parent,
+               const Stmt *S, unsigned BlockCount)
+    : LocationContext(Scope, ctx, Parent), Enter(S), BlockCount(BlockCount) {
+    assert(Parent);
+    assert(S);
+  }
 
 public:
   ~ScopeContext() {}
 
+  const Stmt *getTriggerStmt() const { return Enter; }
+
   void Profile(llvm::FoldingSetNodeID &ID);
 
   static void Profile(llvm::FoldingSetNodeID &ID, AnalysisDeclContext *ctx,
-                      const LocationContext *parent, const Stmt *s) {
+                      const LocationContext *parent, const Stmt *s,
+                      unsigned BlockCount) {
     ProfileCommon(ID, Scope, ctx, parent, s);
+    ID.AddInteger(BlockCount);
   }
 
   static bool classof(const LocationContext *Ctx) {
@@ -382,7 +400,7 @@
 
   const ScopeContext *getScope(AnalysisDeclContext *ctx,
                                const LocationContext *parent,
-                               const Stmt *s);
+                               const Stmt *s, unsigned BlockCount);
   
   const BlockInvocationContext *
   getBlockInvocationContext(AnalysisDeclContext *ctx,
Index: include/clang/Analysis/ProgramPoint.h
===================================================================
--- include/clang/Analysis/ProgramPoint.h
+++ include/clang/Analysis/ProgramPoint.h
@@ -60,6 +60,8 @@
               PostImplicitCallKind,
               MinImplicitCallKind = PreImplicitCallKind,
               MaxImplicitCallKind = PostImplicitCallKind,
+              ScopeEnterKind,
+              ScopeExitKind,
               EpsilonKind};
 
 private:
@@ -556,6 +558,52 @@
   }
 };
 
+/// Represents a point where a new scope is being entered.
+class ScopeEnter : public ProgramPoint {
+public:
+  ScopeEnter(const Stmt *TriggerStmt, const ScopeContext *ScopeCtx,
+             const LocationContext *CurrCtx)
+    : ProgramPoint(TriggerStmt, CurrCtx, ScopeEnterKind, ScopeCtx) {}
+
+  const Stmt *getTriggerStmt() const {
+    return static_cast<const Stmt *>(getData1());
+  }
+
+  const LocationContext *getParentContext() const {
+    return static_cast<const LocationContext *>(getData2());
+  }
+
+private:
+  ScopeEnter() {}
+  friend class ProgramPoint;
+  static bool isKind(const ProgramPoint &Location) {
+    return Location.getKind() == ScopeEnterKind;
+  }
+};
+
+/// Represents a point where a scope is being exited.
+class ScopeExit : public ProgramPoint {
+public:
+  ScopeExit(const Stmt *TriggerStmt, const ScopeContext *ScopeCtx,
+            const LocationContext *TargetCtx)
+    : ProgramPoint(TriggerStmt, ScopeCtx, ScopeExitKind, TargetCtx) {}
+
+  const Stmt *getTriggerStmt() const {
+    return static_cast<const Stmt *>(getData1());
+  }
+
+  const LocationContext *getScopeContext() const {
+    return static_cast<const LocationContext *>(getData2());
+  }
+
+private:
+  ScopeExit() {}
+  friend class ProgramPoint;
+  static bool isKind(const ProgramPoint &Location) {
+    return Location.getKind() == ScopeExitKind;
+  }
+};
+
 /// Represents a point when we begin processing an inlined call.
 /// CallEnter uses the caller's location context.
 class CallEnter : public ProgramPoint {
Index: include/clang/StaticAnalyzer/Core/Checker.h
===================================================================
--- include/clang/StaticAnalyzer/Core/Checker.h
+++ include/clang/StaticAnalyzer/Core/Checker.h
@@ -196,6 +196,34 @@
   }
 };
 
+class ScopeEnter {
+  template <typename CHECKER>
+  static void _checkScopeEnter(void *checker, CheckerContext &C) {
+    ((const CHECKER *)checker)->checkScopeEnter(C);
+  }
+
+public:
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerForScopeEnter(
+     CheckerManager::CheckScopeFunc(checker, _checkScopeEnter<CHECKER>));
+  }
+};
+
+class ScopeExit {
+  template <typename CHECKER>
+  static void _checkScopeExit(void *checker, CheckerContext &C) {
+    ((const CHECKER *)checker)->checkScopeExit(C);
+  }
+
+public:
+  template <typename CHECKER>
+  static void _register(CHECKER *checker, CheckerManager &mgr) {
+    mgr._registerForScopeExit(
+     CheckerManager::CheckScopeFunc(checker, _checkScopeExit<CHECKER>));
+  }
+};
+
 class Location {
   template <typename CHECKER>
   static void _checkLocation(void *checker,
Index: include/clang/StaticAnalyzer/Core/CheckerManager.h
===================================================================
--- include/clang/StaticAnalyzer/Core/CheckerManager.h
+++ include/clang/StaticAnalyzer/Core/CheckerManager.h
@@ -293,6 +293,27 @@
                                const CallEvent &Call, ExprEngine &Eng,
                                bool wasInlined = false);
 
+  /// \brief Run checkers for entering scope.
+  void runCheckersForScopeEnter(ExplodedNodeSet &Dst,
+                                const ExplodedNodeSet &Src,
+                                ProgramPoint PP, ExprEngine &Eng) {
+    runCheckersForScope(/*isEnter=*/true, Dst, Src, PP, Eng);
+  }
+
+  /// \brief Run checkers for exiting scope.
+  void runCheckersForScopeExit(ExplodedNodeSet &Dst,
+                               const ExplodedNodeSet &Src,
+                               ProgramPoint PP,
+                               ExprEngine &Eng) {
+    runCheckersForScope(/*isEnter=*/false, Dst, Src, PP, Eng);
+  }
+
+  /// \brief Run checkers for scope enter/exit event.
+  void runCheckersForScope(bool IsEnter, ExplodedNodeSet &Dst,
+                           const ExplodedNodeSet &Src,
+                           ProgramPoint PP,
+                           ExprEngine &Eng);
+
   /// \brief Run checkers for load/store of a location.
   void runCheckersForLocation(ExplodedNodeSet &Dst,
                               const ExplodedNodeSet &Src,
@@ -467,7 +488,9 @@
 
   typedef CheckerFn<void (const CallEvent &, CheckerContext &)>
       CheckCallFunc;
-  
+
+  typedef CheckerFn<void (CheckerContext &)> CheckScopeFunc;
+
   typedef CheckerFn<void (const SVal &location, bool isLoad,
                           const Stmt *S,
                           CheckerContext &)>
@@ -538,6 +561,9 @@
   void _registerForPreCall(CheckCallFunc checkfn);
   void _registerForPostCall(CheckCallFunc checkfn);
 
+  void _registerForScopeEnter(CheckScopeFunc checkfn);
+  void _registerForScopeExit(CheckScopeFunc checkfn);
+
   void _registerForLocation(CheckLocationFunc checkfn);
 
   void _registerForBind(CheckBindFunc checkfn);
@@ -647,6 +673,9 @@
   std::vector<CheckCallFunc> PreCallCheckers;
   std::vector<CheckCallFunc> PostCallCheckers;
 
+  std::vector<CheckScopeFunc> ScopeEnterCheckers;
+  std::vector<CheckScopeFunc> ScopeExitCheckers;
+
   std::vector<CheckLocationFunc> LocationCheckers;
 
   std::vector<CheckBindFunc> BindCheckers;
Index: include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h
@@ -31,8 +31,8 @@
 /// This allows the environment to manage context-sensitive bindings,
 /// which is essentially for modeling recursive function analysis, among
 /// other things.
-class EnvironmentEntry : public std::pair<const Stmt*,
-                                          const StackFrameContext *> {
+class EnvironmentEntry
+    : public std::pair<const Stmt*, const LocationContext *> {
 public:
   EnvironmentEntry(const Stmt *s, const LocationContext *L);
 
Index: include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h
@@ -201,6 +201,10 @@
 
   void ProcessInitializer(const CFGInitializer I, ExplodedNode *Pred);
 
+  void ProcessScopeEnter(const CFGScopeBegin SC, ExplodedNode *Pred);
+
+  void ProcessScopeExit(const CFGScopeEnd SE, ExplodedNode *Pred);
+
   void ProcessImplicitDtor(const CFGImplicitDtor D, ExplodedNode *Pred);
 
   void ProcessAutomaticObjDtor(const CFGAutomaticObjDtor D, 
Index: include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -404,6 +404,67 @@
   }
 };
 
+class ScopeLocalSpaceRegion : public MemSpaceRegion {
+  const ScopeContext *ScopeCtx;
+  void *DeclaredVars;
+
+  virtual void anchor();
+  friend class MemRegionManager;
+  ScopeLocalSpaceRegion(MemRegionManager *Mgr, const ScopeContext *ScopeCtx)
+    : MemSpaceRegion(Mgr, ScopeLocalSpaceRegionKind),
+      ScopeCtx(ScopeCtx),
+      DeclaredVars(nullptr) {}
+
+  void LazyInitializeDeclaredVars();
+  const VarRegion *getScopedRegion(const VarDecl *VD);
+
+public:
+  const ScopeContext *getScopeContext() const { return ScopeCtx; }
+
+  void Profile(llvm::FoldingSetNodeID &ID) const;
+
+  class declared_vars_iterator {
+    const MemRegion *const *MR;
+  public:
+    explicit declared_vars_iterator(const MemRegion *const *MR) : MR(MR) {}
+
+    const VarRegion *getDeclaredRegion() const {
+      return cast<VarRegion>(*MR);
+    }
+
+    const VarRegion *operator *() const {
+      return getDeclaredRegion();
+    }
+
+    const VarRegion *operator ->() const {
+      return getDeclaredRegion();
+    }
+
+    bool operator==(const declared_vars_iterator &I) const {
+      assert((MR == nullptr) == (I.MR == nullptr));
+      return I.MR == MR;
+    }
+
+    bool operator!=(const declared_vars_iterator &I) const {
+      assert((MR == nullptr) == (I.MR == nullptr));
+      return I.MR != MR;
+    }
+    declared_vars_iterator &operator++() {
+      ++MR;
+      return *this;
+    }
+  };
+
+  declared_vars_iterator declared_vars_begin() const;
+  declared_vars_iterator declared_vars_end() const;
+
+  void dumpToStream(raw_ostream &os) const;
+
+  static bool classof(const MemRegion *R) {
+    return R->getKind() == ScopeLocalSpaceRegionKind;
+  }
+};
+
 
 /// SubRegion - A region that subsets another larger region.  Most regions
 ///  are subclasses of SubRegion.
@@ -1124,17 +1185,24 @@
   GlobalImmutableSpaceRegion *ImmutableGlobals;
 
   
-  llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *> 
+  llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
     StackLocalsSpaceRegions;
   llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
     StackArgumentsSpaceRegions;
   llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *>
     StaticsGlobalSpaceRegions;
+  llvm::DenseMap<const ScopeContext *, ScopeLocalSpaceRegion *>
+    ScopeLocalSpaceRegions;
 
   HeapSpaceRegion *heap;
   UnknownSpaceRegion *unknown;
   CodeSpaceRegion *code;
 
+  llvm::PointerUnion<const StackFrameContext *, const VarRegion *>
+  getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
+                                        const DeclContext *DC,
+                                        const VarDecl *VD);
+
 public:
   MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator& a)
     : C(c), A(a), InternalGlobals(0), SystemGlobals(0), ImmutableGlobals(0),
@@ -1156,6 +1224,11 @@
   const StackArgumentsSpaceRegion *
   getStackArgumentsRegion(const StackFrameContext *STC);
 
+  /// getScopeLocalSpaceRegion - Retrieve the memory region associated with
+  /// the given scope.
+  const ScopeLocalSpaceRegion *
+  getScopeLocalSpaceRegion(const ScopeContext *ScopeCtx);
+
   /// getGlobalsRegion - Retrieve the memory region associated with
   ///  global variables.
   const GlobalsSpaceRegion *getGlobalsRegion(
Index: include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
+++ include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def
@@ -52,6 +52,7 @@
     REGION(StackLocalsSpaceRegion, StackSpaceRegion)
     REGION_RANGE(STACK_MEMSPACES, StackArgumentsSpaceRegionKind,
                                   StackLocalsSpaceRegionKind)
+  REGION(ScopeLocalSpaceRegion, MemSpaceRegion)
   REGION(UnknownSpaceRegion, MemSpaceRegion)
   REGION_RANGE(MEMSPACES, CodeSpaceRegionKind,
                           UnknownSpaceRegionKind)
Index: include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
===================================================================
--- include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
+++ include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h
@@ -674,7 +674,7 @@
 
   RegionSetTy RegionRoots;
   
-  const StackFrameContext *LCtx;
+  const LocationContext *LCtx;
   const Stmt *Loc;
   SymbolManager& SymMgr;
   StoreRef reapedStore;
@@ -688,7 +688,7 @@
   /// considered live.
   /// If the stack frame context is NULL, everything on stack is considered
   /// dead.
-  SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr,
+  SymbolReaper(const LocationContext *Ctx, const Stmt *s, SymbolManager& symmgr,
                StoreManager &storeMgr)
    : LCtx(Ctx), Loc(s), SymMgr(symmgr),
      reapedStore(0, storeMgr) {}
Index: lib/Analysis/AnalysisDeclContext.cpp
===================================================================
--- lib/Analysis/AnalysisDeclContext.cpp
+++ lib/Analysis/AnalysisDeclContext.cpp
@@ -45,6 +45,7 @@
     builtCFG(false),
     builtCompleteCFG(false),
     ReferencedBlockVars(0),
+    DeclaredVars(nullptr),
     ManagedAnalyses(0)
 {  
   cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
@@ -58,6 +59,7 @@
   builtCFG(false),
   builtCompleteCFG(false),
   ReferencedBlockVars(0),
+  DeclaredVars(nullptr),
   ManagedAnalyses(0)
 {  
   cfgBuildOptions.forcedBlkExprs = &forcedBlkExprs;
@@ -279,6 +281,12 @@
                                                    Cnt);
 }
 
+const ScopeContext *
+AnalysisDeclContext::getScope(const LocationContext *Parent, const Stmt *S,
+                              unsigned BlockCount) {
+  return getLocationContextManager().getScope(this, Parent, S, BlockCount);
+}
+
 const BlockInvocationContext *
 AnalysisDeclContext::getBlockInvocationContext(const LocationContext *parent,
                                                const clang::BlockDecl *BD,
@@ -329,7 +337,7 @@
 }
 
 void ScopeContext::Profile(llvm::FoldingSetNodeID &ID) {
-  Profile(ID, getAnalysisDeclContext(), getParent(), Enter);
+  Profile(ID, getAnalysisDeclContext(), getParent(), Enter, BlockCount);
 }
 
 void BlockInvocationContext::Profile(llvm::FoldingSetNodeID &ID) {
@@ -376,8 +384,17 @@
 const ScopeContext *
 LocationContextManager::getScope(AnalysisDeclContext *ctx,
                                  const LocationContext *parent,
-                                 const Stmt *s) {
-  return getLocationContext<ScopeContext, Stmt>(ctx, parent, s);
+                                 const Stmt *s, unsigned BlockCount) {
+  llvm::FoldingSetNodeID ID;
+  ScopeContext::Profile(ID, ctx, parent, s, BlockCount);
+  void *InsertPos;
+  ScopeContext *L =
+   cast_or_null<ScopeContext>(Contexts.FindNodeOrInsertPos(ID, InsertPos));
+  if (!L) {
+    L = new ScopeContext(ctx, parent, s, BlockCount);
+    Contexts.InsertNode(L, InsertPos);
+  }
+  return L;
 }
 
 const BlockInvocationContext *
@@ -537,6 +554,52 @@
   return BV;
 }
 
+static DeclVec *LazyInitializeDeclaredVars(const Stmt *Scope, void *&Vec,
+                                           llvm::BumpPtrAllocator &A) {
+  if (Vec)
+    return (DeclVec*) Vec;
+
+  BumpVectorContext BC(A);
+  DeclVec *Declared = (DeclVec*) A.Allocate<DeclVec>();
+  new (Declared) DeclVec(BC, 10);
+
+  if (const IfStmt *IfS = dyn_cast<IfStmt>(Scope)) {
+    if (const VarDecl *VD = IfS->getConditionVariable())
+      Declared->push_back(VD, BC);
+
+  } else if (const WhileStmt *WS = dyn_cast<WhileStmt>(Scope)) {
+    if (const VarDecl *VD = WS->getConditionVariable())
+      Declared->push_back(VD, BC);
+
+  } else if (const SwitchStmt *SS = dyn_cast<SwitchStmt>(Scope)) {
+    if (const VarDecl *VD = SS->getConditionVariable())
+      Declared->push_back(VD, BC);
+
+  } else if (const ForStmt *FS = dyn_cast<ForStmt>(Scope)) {
+    if (const VarDecl *VD = FS->getConditionVariable())
+      Declared->push_back(VD, BC);
+
+  } else if (const CXXForRangeStmt *CFR = dyn_cast<CXXForRangeStmt>(Scope)) {
+    if (const VarDecl *VD = CFR->getLoopVariable())
+      Declared->push_back(VD, BC);
+
+  } else if (const CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Scope)) {
+    if (const VarDecl *VD = CS->getExceptionDecl())
+      Declared->push_back(VD, BC);
+
+  } else {
+    for (const Stmt *Child : Scope->children())
+      if (const DeclStmt *DS = dyn_cast<DeclStmt>(Child))
+        for (DeclStmt::const_decl_iterator I = DS->decl_begin(),
+             E = DS->decl_end(); I != E; ++I)
+          if (const VarDecl *VD = dyn_cast<VarDecl>(*I))
+            Declared->push_back(VD, BC);
+  }
+
+  Vec = Declared;
+  return Declared;
+}
+
 std::pair<AnalysisDeclContext::referenced_decls_iterator,
           AnalysisDeclContext::referenced_decls_iterator>
 AnalysisDeclContext::getReferencedBlockVars(const BlockDecl *BD) {
@@ -547,6 +610,16 @@
   return std::make_pair(V->begin(), V->end());
 }
 
+std::pair<AnalysisDeclContext::referenced_decls_iterator,
+          AnalysisDeclContext::referenced_decls_iterator>
+AnalysisDeclContext::getDeclaredVars(const Stmt *Scope) {
+  if (!DeclaredVars)
+    DeclaredVars = new llvm::DenseMap<const Stmt *, void *>();
+
+  DeclVec *V = LazyInitializeDeclaredVars(Scope, (*DeclaredVars)[Scope], A);
+  return std::make_pair(V->begin(), V->end());
+}
+
 ManagedAnalysis *&AnalysisDeclContext::getAnalysisImpl(const void *tag) {
   if (!ManagedAnalyses)
     ManagedAnalyses = new ManagedAnalysisMap();
Index: lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
+++ lib/StaticAnalyzer/Checkers/CheckerDocumentation.cpp
@@ -44,6 +44,8 @@
                                        check::Location,
                                        check::Bind,
                                        check::DeadSymbols,
+                                       check::ScopeEnter,
+                                       check::ScopeExit,
                                        check::EndFunction,
                                        check::EndAnalysis,
                                        check::EndOfTranslationUnit,
@@ -154,6 +156,22 @@
   /// check::DeadSymbols
   void checkDeadSymbols(SymbolReaper &SR, CheckerContext &C) const {}
 
+  /// \brief Called when a scope is being entered.
+  ///
+  /// This callback may be used by the checkers to determine variables that
+  /// become alive in some scope and perform necessary actions.
+  ///
+  /// check::ScopeEnter
+  void checkScopeEnter(CheckerContext &C) const {}
+
+  /// \brief Called when a scope is being leaved.
+  ///
+  /// This callback may be used by the checkers to determine variables whose
+  /// lifetime ends.
+  ///
+  /// check::ScopeExit
+  void checkScopeExit(CheckerContext &C) const {}
+
   /// \brief Called when the analyzer core reaches the end of a
   /// function being analyzed.
   ///
Index: lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp
@@ -89,7 +89,8 @@
     os << " stack allocated memory";
   os << " for the predicate value.  Using such transient memory for "
         "the predicate is potentially dangerous.";
-  if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
+  if (isa<VarRegion>(R) && (isa<StackLocalsSpaceRegion>(R->getMemorySpace()) ||
+                            isa<ScopeLocalSpaceRegion>(R->getMemorySpace())))
     os << "  Perhaps you intended to declare the variable as 'static'?";
 
   BugReport *report = new BugReport(*BT_dispatchOnce, os.str(), N);
Index: lib/StaticAnalyzer/Checkers/MallocChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/MallocChecker.cpp
+++ lib/StaticAnalyzer/Checkers/MallocChecker.cpp
@@ -1172,6 +1172,22 @@
       return true;
     }
 
+    if (isa<ScopeLocalSpaceRegion>(MS)) {
+      const VarRegion *VR = dyn_cast<VarRegion>(MR);
+      const VarDecl *VD;
+      if (VR)
+        VD = VR->getDecl();
+      else
+        VD = NULL;
+
+      if (VD)
+        os << "the address of the scope-local variable '" << VD->getName()
+           << "'";
+      else
+        os << "the address of a scope-local variable";
+      return true;
+    }
+
     if (isa<StackArgumentsSpaceRegion>(MS)) {
       const VarRegion *VR = dyn_cast<VarRegion>(MR);
       const VarDecl *VD;
Index: lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
+++ lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp
@@ -176,7 +176,8 @@
     os << " stack allocated memory";
   os << " for the \"control\" value.  Using such transient memory for "
   "the control value is potentially dangerous.";
-  if (isa<VarRegion>(R) && isa<StackLocalsSpaceRegion>(R->getMemorySpace()))
+  if (isa<VarRegion>(R) && (isa<StackLocalsSpaceRegion>(R->getMemorySpace()) ||
+                            isa<ScopeLocalSpaceRegion>(R->getMemorySpace())))
     os << "  Perhaps you intended to declare the variable as 'static'?";
 
   LazyInitialize(BT_pthreadOnce, "Improper use of 'pthread_once'");
Index: lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
===================================================================
--- lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
+++ lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
@@ -434,7 +434,9 @@
 
   const MemSpaceRegion *VarSpace = VR->getMemorySpace();
   const StackSpaceRegion *FrameSpace = dyn_cast<StackSpaceRegion>(VarSpace);
-  if (!FrameSpace) {
+  const ScopeLocalSpaceRegion *ScopeSpace =
+      dyn_cast<ScopeLocalSpaceRegion>(VarSpace);
+  if (!FrameSpace && !ScopeSpace) {
     // If we ever directly evaluate global DeclStmts, this assertion will be
     // invalid, but this still seems preferable to silently accepting an
     // initialization that may be for a path-sensitive variable.
@@ -444,7 +446,9 @@
 
   assert(VR->getDecl()->hasLocalStorage());
   const LocationContext *LCtx = N->getLocationContext();
-  return FrameSpace->getStackFrame() == LCtx->getCurrentStackFrame();
+  return FrameSpace
+      ? FrameSpace->getStackFrame() == LCtx->getCurrentStackFrame()
+      : ScopeSpace->getScopeContext() == LCtx;
 }
 
 PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ,
Index: lib/StaticAnalyzer/Core/CheckerManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/CheckerManager.cpp
+++ lib/StaticAnalyzer/Core/CheckerManager.cpp
@@ -273,6 +273,41 @@
 }
 
 namespace {
+  struct CheckScopeContext {
+    typedef std::vector<CheckerManager::CheckScopeFunc> CheckersTy;
+    bool IsEnter;
+    const CheckersTy &Checkers;
+    ProgramPoint PP;
+    ExprEngine &Eng;
+
+    CheckersTy::const_iterator checkers_begin() { return Checkers.begin(); }
+    CheckersTy::const_iterator checkers_end() { return Checkers.end(); }
+
+    CheckScopeContext(bool IsEnter, const CheckersTy &Checkers,
+                      ProgramPoint PP, ExprEngine &Eng)
+      : IsEnter(IsEnter), Checkers(Checkers), PP(PP), Eng(Eng) {}
+
+    void runChecker(CheckerManager::CheckScopeFunc checkFn,
+                    NodeBuilder &Bldr, ExplodedNode *Pred) {
+      CheckerContext C(Bldr, Eng, Pred, PP.withTag(checkFn.Checker));
+      checkFn(C);
+    }
+  };
+}
+
+/// \brief Run checkers for entering/leaving a scope.
+void CheckerManager::runCheckersForScope(bool IsEnter,
+                                         ExplodedNodeSet &Dst,
+                                         const ExplodedNodeSet &Src,
+                                         ProgramPoint PP,
+                                         ExprEngine &Eng) {
+  CheckScopeContext C(IsEnter,
+                     IsEnter ? ScopeEnterCheckers : ScopeExitCheckers,
+                     PP, Eng);
+  expandGraphWithCheckers(C, Dst, Src);
+}
+
+namespace {
   struct CheckLocationContext {
     typedef std::vector<CheckerManager::CheckLocationFunc> CheckersTy;
     const CheckersTy &Checkers;
@@ -694,6 +729,14 @@
   PostCallCheckers.push_back(checkfn);
 }
 
+void CheckerManager::_registerForScopeEnter(CheckScopeFunc checkfn) {
+  ScopeEnterCheckers.push_back(checkfn);
+}
+
+void CheckerManager::_registerForScopeExit(CheckScopeFunc checkfn) {
+  ScopeExitCheckers.push_back(checkfn);
+}
+
 void CheckerManager::_registerForLocation(CheckLocationFunc checkfn) {
   LocationCheckers.push_back(checkfn);
 }
Index: lib/StaticAnalyzer/Core/CoreEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/CoreEngine.cpp
+++ lib/StaticAnalyzer/Core/CoreEngine.cpp
@@ -271,7 +271,9 @@
       assert(Loc.getAs<PostStmt>() ||
              Loc.getAs<PostInitializer>() ||
              Loc.getAs<PostImplicitCall>() ||
-             Loc.getAs<CallExitEnd>());
+             Loc.getAs<CallExitEnd>() ||
+             Loc.getAs<ScopeEnter>() ||
+             Loc.getAs<ScopeExit>());
       HandlePostStmt(WU.getBlock(), WU.getIndex(), Pred);
       break;
   }
@@ -525,7 +527,9 @@
 
   // Do not create extra nodes. Move to the next CFG element.
   if (N->getLocation().getAs<PostInitializer>() ||
-      N->getLocation().getAs<PostImplicitCall>()) {
+      N->getLocation().getAs<PostImplicitCall>() ||
+      N->getLocation().getAs<ScopeEnter>() ||
+      N->getLocation().getAs<ScopeExit>()) {
     WList->enqueue(N, Block, Idx+1);
     return;
   }
Index: lib/StaticAnalyzer/Core/Environment.cpp
===================================================================
--- lib/StaticAnalyzer/Core/Environment.cpp
+++ lib/StaticAnalyzer/Core/Environment.cpp
@@ -52,9 +52,8 @@
 }
 
 EnvironmentEntry::EnvironmentEntry(const Stmt *S, const LocationContext *L)
-  : std::pair<const Stmt *,
-              const StackFrameContext *>(ignoreTransparentExprs(S),
-                                         L ? L->getCurrentStackFrame() : 0) {}
+  : std::pair<const Stmt *, const LocationContext *>(
+      ignoreTransparentExprs(S), L) {}
 
 SVal Environment::lookupExpr(const EnvironmentEntry &E) const {
   const SVal* X = ExprBindings.lookup(E);
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -296,6 +296,12 @@
     case CFGElement::Initializer:
       ProcessInitializer(E.castAs<CFGInitializer>().getInitializer(), Pred);
       return;
+    case CFGElement::ScopeBegin:
+      ProcessScopeEnter(E.castAs<CFGScopeBegin>(), Pred);
+      return;
+    case CFGElement::ScopeEnd:
+      ProcessScopeExit(E.castAs<CFGScopeEnd>(), Pred);
+      return;
     case CFGElement::AutomaticObjectDtor:
     case CFGElement::DeleteDtor:
     case CFGElement::BaseDtor:
@@ -361,7 +367,7 @@
   }
 
   const StackFrameContext *SFC = LC ? LC->getCurrentStackFrame() : 0;
-  SymbolReaper SymReaper(SFC, ReferenceStmt, SymMgr, getStoreManager());
+  SymbolReaper SymReaper(LC, ReferenceStmt, SymMgr, getStoreManager());
 
   getCheckerManager().runCheckersForLiveSymbols(CleanedState, SymReaper);
 
@@ -530,6 +536,66 @@
   Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
 }
 
+
+void ExprEngine::ProcessScopeEnter(const CFGScopeBegin SC, ExplodedNode *Pred) {
+  const Stmt *TriggerStmt = SC.getTriggerStmt();
+  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+                                TriggerStmt->getLocStart(),
+                                "Error evaluating scope enter");
+
+  const LocationContext *ParentCtx = Pred->getLocationContext();
+  // We don't clean up dead bindings here.
+  const StackFrameContext *StackFrame = ParentCtx->getCurrentStackFrame();
+
+  // Construct a new scope frame for the statement.
+  AnalysisDeclContext *ADC = AMgr.getAnalysisDeclContext(StackFrame->getDecl());
+  const ScopeContext *ScopeCtx = ADC->getScope(ParentCtx, TriggerStmt,
+                                               currBldrCtx->blockCount());
+
+  ScopeEnter Enter(TriggerStmt, ScopeCtx, ParentCtx);
+  ExplodedNodeSet Src(Pred);
+  ExplodedNodeSet Tmp, Dst;
+  getCheckerManager().runCheckersForScopeEnter(Tmp, Src, Enter, *this);
+  if (Tmp.empty())
+    Tmp.Add(Pred);
+
+  NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
+  for (auto *Node : Tmp)
+    Bldr.generateNode(Enter, Node->getState(), Node);
+
+  // Enqueue the new nodes onto the work list.
+  Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
+}
+
+void ExprEngine::ProcessScopeExit(const CFGScopeEnd SE, ExplodedNode *Pred) {
+  const Stmt *TriggerStmt = SE.getTriggerStmt();
+  PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
+                                TriggerStmt->getLocEnd(),
+                                "Error evaluating scope exit");
+
+  // Construct a new scope frame for the statement.
+  const ScopeContext *ScopeCtx = cast<ScopeContext>(Pred->getLocationContext());
+
+  const LocationContext *TargetCtx = isa<ReturnStmt>(SE.getTriggerStmt())
+      ? ScopeCtx->getCurrentStackFrame()
+      : ScopeCtx->getParent();
+
+  ScopeExit Exit(TriggerStmt, ScopeCtx, TargetCtx);
+  ExplodedNodeSet Src(Pred);
+  ExplodedNodeSet Tmp, Dst;
+  getCheckerManager().runCheckersForScopeExit(Tmp, Src, Exit, *this);
+  if (Tmp.empty())
+    Tmp.Add(Pred);
+
+  NodeBuilder Bldr(Tmp, Dst, *currBldrCtx);
+  for (auto *Node : Tmp)
+    Bldr.generateNode(Exit, Node->getState(), Node);
+
+  // Enqueue the new nodes onto the work list.
+  Engine.enqueue(Dst, currBldrCtx->getBlock(), currStmtIdx);
+}
+
+
 void ExprEngine::ProcessImplicitDtor(const CFGImplicitDtor D,
                                      ExplodedNode *Pred) {
   ExplodedNodeSet Dst;
@@ -2425,6 +2491,20 @@
         break;
       }
 
+    case ProgramPoint::ScopeEnterKind: {
+      const Stmt *Trigger = Loc.castAs<ScopeEnter>().getTriggerStmt();
+      Out <<"ScopeEnter: " << Trigger->getStmtClassName() << ' ' <<
+            (const void *)Trigger;
+      break;
+    }
+
+    case ProgramPoint::ScopeExitKind: {
+      const Stmt *Trigger = Loc.castAs<ScopeExit>().getTriggerStmt();
+      Out <<"ScopeExit: " << Trigger->getStmtClassName() << ' ' <<
+            (const void *)Trigger;
+      break;
+    }
+
       default: {
         const Stmt *S = Loc.castAs<StmtPoint>().getStmt();
 
Index: lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
+++ lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp
@@ -221,12 +221,11 @@
   PrettyStackTraceLocationContext CrashInfo(CEBNode->getLocationContext());
   const StackFrameContext *calleeCtx =
       CEBNode->getLocationContext()->getCurrentStackFrame();
-  
-  // The parent context might not be a stack frame, so make sure we
-  // look up the first enclosing stack frame.
-  const StackFrameContext *callerCtx =
-    calleeCtx->getParent()->getCurrentStackFrame();
-  
+
+  const LocationContext *CallerCtx = calleeCtx->getParent();
+  if (isa<BlockInvocationContext>(CallerCtx))
+    CallerCtx = CallerCtx->getParent();
+
   const Stmt *CE = calleeCtx->getCallSite();
   ProgramStateRef state = CEBNode->getState();
   // Find the last statement in the function and the corresponding basic block.
@@ -259,7 +258,7 @@
         }
       }
 
-      state = state->BindExpr(CE, callerCtx, V);
+      state = state->BindExpr(CE, CallerCtx, V);
     }
 
     // Bind the constructed object value to CXXConstructExpr.
@@ -272,7 +271,7 @@
       if (isTemporaryPRValue(CCE, ThisV))
         ThisV = state->getSVal(ThisV.castAs<Loc>());
 
-      state = state->BindExpr(CCE, callerCtx, ThisV);
+      state = state->BindExpr(CCE, CallerCtx, ThisV);
     }
   }
 
@@ -310,7 +309,7 @@
 
     // Step 4: Generate the CallExit and leave the callee's context.
     // CleanedNodes -> CEENode
-    CallExitEnd Loc(calleeCtx, callerCtx);
+    CallExitEnd Loc(calleeCtx, CallerCtx);
     bool isNew;
     ProgramStateRef CEEState = (*I == CEBNode) ? state : (*I)->getState();
     ExplodedNode *CEENode = G.getNode(Loc, CEEState, false, &isNew);
@@ -432,13 +431,12 @@
   assert(D);
 
   const LocationContext *CurLC = Pred->getLocationContext();
-  const StackFrameContext *CallerSFC = CurLC->getCurrentStackFrame();
-  const LocationContext *ParentOfCallee = CallerSFC;
+  const LocationContext *ParentOfCallee = CurLC;
   if (Call.getKind() == CE_Block) {
     const BlockDataRegion *BR = cast<BlockCall>(Call).getBlockRegion();
     assert(BR && "If we have the block definition we should have its region");
     AnalysisDeclContext *BlockCtx = AMgr.getAnalysisDeclContext(D);
-    ParentOfCallee = BlockCtx->getBlockInvocationContext(CallerSFC,
+    ParentOfCallee = BlockCtx->getBlockInvocationContext(CurLC,
                                                          cast<BlockDecl>(D),
                                                          BR);
   }
Index: lib/StaticAnalyzer/Core/MemRegion.cpp
===================================================================
--- lib/StaticAnalyzer/Core/MemRegion.cpp
+++ lib/StaticAnalyzer/Core/MemRegion.cpp
@@ -172,8 +172,15 @@
 }
 
 const StackFrameContext *VarRegion::getStackFrame() const {
-  const StackSpaceRegion *SSR = dyn_cast<StackSpaceRegion>(getMemorySpace());
-  return SSR ? SSR->getStackFrame() : NULL;
+  const MemSpaceRegion *Space = getMemorySpace();
+  if (const StackSpaceRegion *StackSpace = dyn_cast<StackSpaceRegion>(Space))
+    return StackSpace->getStackFrame();
+
+  else if (const ScopeLocalSpaceRegion *ScopeSpace =
+           dyn_cast<ScopeLocalSpaceRegion>(Space))
+    return ScopeSpace->getScopeContext()->getCurrentStackFrame();
+
+  return nullptr;
 }
 
 //===----------------------------------------------------------------------===//
@@ -259,6 +266,10 @@
   ID.AddPointer(getCodeRegion());
 }
 
+void ScopeLocalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
+  ID.AddPointer(ScopeCtx);
+}
+
 void StringRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
                                  const StringLiteral* Str,
                                  const MemRegion* superRegion) {
@@ -427,6 +438,7 @@
 void GlobalsSpaceRegion::anchor() { }
 void HeapSpaceRegion::anchor() { }
 void UnknownSpaceRegion::anchor() { }
+void ScopeLocalSpaceRegion::anchor() { }
 void StackLocalsSpaceRegion::anchor() { }
 void StackArgumentsSpaceRegion::anchor() { }
 void TypedRegion::anchor() { }
@@ -567,6 +579,10 @@
   os << "StackLocalsSpaceRegion";
 }
 
+void ScopeLocalSpaceRegion::dumpToStream(raw_ostream &OS) const {
+  OS << "ScopeLocalSpaceRegion";
+}
+
 bool MemRegion::canPrintPretty() const {
   return canPrintPrettyAsExpr();
 }
@@ -687,6 +703,19 @@
   return R;
 }
 
+const ScopeLocalSpaceRegion *
+MemRegionManager::getScopeLocalSpaceRegion(const ScopeContext *ScopeCtx) {
+  assert(ScopeCtx);
+  ScopeLocalSpaceRegion *&R = ScopeLocalSpaceRegions[ScopeCtx];
+
+  if (R)
+    return R;
+
+  R = A.Allocate<ScopeLocalSpaceRegion>();
+  new (R) ScopeLocalSpaceRegion(this, ScopeCtx);
+  return R;
+}
+
 const GlobalsSpaceRegion
 *MemRegionManager::getGlobalsRegion(MemRegion::Kind K,
                                     const CodeTextRegion *CR) {
@@ -734,12 +763,12 @@
 }
 
 /// Look through a chain of LocationContexts to either find the
-/// StackFrameContext that matches a DeclContext, or find a VarRegion
-/// for a variable captured by a block.
-static llvm::PointerUnion<const StackFrameContext *, const VarRegion *>
-getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
-                                      const DeclContext *DC,
-                                      const VarDecl *VD) {
+/// StackFrameContext that matches a DeclContext,
+/// or a ScopeContext where a variable was declared,
+/// or find a VarRegion for a variable captured by a block.
+llvm::PointerUnion<const StackFrameContext *, const VarRegion *>
+MemRegionManager::getStackOrCaptureRegionForDeclContext(
+    const LocationContext *LC, const DeclContext *DC, const VarDecl *VD) {
   while (LC) {
     if (const StackFrameContext *SFC = dyn_cast<StackFrameContext>(LC)) {
       if (cast<DeclContext>(SFC->getDecl()) == DC)
@@ -758,6 +787,14 @@
             return cast<VarRegion>(I.getCapturedRegion());
       }
     }
+    if (const ScopeContext *ScopeCtx = dyn_cast<ScopeContext>(LC)) {
+      const ScopeLocalSpaceRegion *Space = getScopeLocalSpaceRegion(ScopeCtx);
+      for (auto I = Space->declared_vars_begin(),
+           E = Space->declared_vars_end(); I != E; ++I) {
+        if (I->getDecl() == VD)
+          return *I;
+      }
+    }
     
     LC = LC->getParent();
   }
@@ -793,16 +830,14 @@
   
   // Finally handle static locals.  
   } else {
-    // FIXME: Once we implement scope handling, we will need to properly lookup
-    // 'D' to the proper LocationContext.
     const DeclContext *DC = D->getDeclContext();
     llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V =
       getStackOrCaptureRegionForDeclContext(LC, DC, D);
     
     if (V.is<const VarRegion*>())
       return V.get<const VarRegion*>();
-    
-    const StackFrameContext *STC = V.get<const StackFrameContext*>();
+
+    const StackFrameContext *STC = V.get<const StackFrameContext *>();
 
     if (!STC)
       sReg = getUnknownRegion();
@@ -810,9 +845,10 @@
       if (D->hasLocalStorage()) {
         sReg = isa<ParmVarDecl>(D) || isa<ImplicitParamDecl>(D)
                ? static_cast<const MemRegion*>(getStackArgumentsRegion(STC))
+                 // TODO: assert if 'cfg-scope-info=true'.
                : static_cast<const MemRegion*>(getStackLocalsRegion(STC));
-      }
-      else {
+
+      } else {
         assert(D->isStaticLocal());
         const Decl *STCD = STC->getDecl();
         if (isa<FunctionDecl>(STCD) || isa<ObjCMethodDecl>(STCD))
@@ -834,8 +870,8 @@
                                STC->getAnalysisDeclContext());
           sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
                                   BTR);
-        }
-        else {
+
+        } else {
           sReg = getGlobalsRegion();
         }
       }
@@ -1042,11 +1078,13 @@
 }
 
 bool MemRegion::hasStackStorage() const {
-  return isa<StackSpaceRegion>(getMemorySpace());
+  const MemSpaceRegion *MS = getMemorySpace();
+  return isa<StackSpaceRegion>(MS) || isa<ScopeLocalSpaceRegion>(MS);
 }
 
 bool MemRegion::hasStackNonParametersStorage() const {
-  return isa<StackLocalsSpaceRegion>(getMemorySpace());
+  const MemSpaceRegion *MS = getMemorySpace();
+  return isa<ScopeLocalSpaceRegion>(MS) || isa<StackLocalsSpaceRegion>(MS);
 }
 
 bool MemRegion::hasStackParametersStorage() const {
@@ -1192,6 +1230,7 @@
     case HeapSpaceRegionKind:
     case UnknownSpaceRegionKind:
     case StaticGlobalSpaceRegionKind:
+    case ScopeLocalSpaceRegionKind:
     case GlobalInternalSpaceRegionKind:
     case GlobalSystemSpaceRegionKind:
     case GlobalImmutableSpaceRegionKind:
@@ -1455,6 +1494,69 @@
 }
 
 //===----------------------------------------------------------------------===//
+// ScopeLocalRegionSpace
+//===----------------------------------------------------------------------===//
+
+const VarRegion *ScopeLocalSpaceRegion::getScopedRegion(const VarDecl *VD) {
+  MemRegionManager &MemMgr = *getMemRegionManager();
+
+  return VD->hasLocalStorage() ? MemMgr.getVarRegion(VD, this)
+                               : MemMgr.getVarRegion(VD, ScopeCtx);
+}
+
+void ScopeLocalSpaceRegion::LazyInitializeDeclaredVars() {
+  if (DeclaredVars)
+    return;
+
+  AnalysisDeclContext *ADC = ScopeCtx->getAnalysisDeclContext();
+  AnalysisDeclContext::declared_vars_iterator I, E;
+  llvm::tie(I, E) = ADC->getDeclaredVars(ScopeCtx->getTriggerStmt());
+
+  if (I == E) {
+    DeclaredVars = (void *)0x1;
+    return;
+  }
+
+  MemRegionManager &MemMgr = *getMemRegionManager();
+  llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
+  BumpVectorContext BC(A);
+
+  typedef BumpVector<const MemRegion*> VarVec;
+  VarVec *BV = (VarVec*) A.Allocate<VarVec>();
+  new (BV) VarVec(BC, E - I);
+  VarVec *BVOriginal = (VarVec*) A.Allocate<VarVec>();
+  new (BVOriginal) VarVec(BC, E - I);
+
+  for ( ; I != E; ++I) {
+    const VarRegion *VR = getScopedRegion(*I);
+    assert(VR);
+    BV->push_back(VR, BC);
+  }
+
+  DeclaredVars = BV;
+}
+
+ScopeLocalSpaceRegion::declared_vars_iterator
+ScopeLocalSpaceRegion::declared_vars_begin() const {
+  const_cast<ScopeLocalSpaceRegion*>(this)->LazyInitializeDeclaredVars();
+
+  BumpVector<const MemRegion *> *Vec =
+    static_cast<BumpVector<const MemRegion *> *>(DeclaredVars);
+
+  return declared_vars_iterator(Vec == (void *)0x1 ? nullptr : Vec->begin());
+}
+
+ScopeLocalSpaceRegion::declared_vars_iterator
+ScopeLocalSpaceRegion::declared_vars_end() const {
+  const_cast<ScopeLocalSpaceRegion*>(this)->LazyInitializeDeclaredVars();
+
+  BumpVector<const MemRegion *> *Vec =
+    static_cast<BumpVector<const MemRegion *> *>(DeclaredVars);
+
+  return declared_vars_iterator(Vec == (void *)0x1 ? nullptr : Vec->end());
+}
+
+//===----------------------------------------------------------------------===//
 // RegionAndSymbolInvalidationTraits
 //===----------------------------------------------------------------------===//
 
Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp
===================================================================
--- lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -554,6 +554,14 @@
     return PathDiagnosticLocation(Init.getInitializer()->getInit(),
                                   SM, CallerCtx);
   }
+  case CFGElement::ScopeBegin: {
+    const Stmt *TriggerStmt = Source.castAs<CFGScopeBegin>().getTriggerStmt();
+    return PathDiagnosticLocation(TriggerStmt, SM, CallerCtx);
+  }
+  case CFGElement::ScopeEnd: {
+    const Stmt *TriggerStmt = Source.castAs<CFGScopeEnd>().getTriggerStmt();
+    return PathDiagnosticLocation::createEnd(TriggerStmt, SM, CallerCtx);
+  }
   case CFGElement::AutomaticObjectDtor: {
     const CFGAutomaticObjDtor &Dtor = Source.castAs<CFGAutomaticObjDtor>();
     return PathDiagnosticLocation::createEnd(Dtor.getTriggerStmt(),
@@ -694,6 +702,10 @@
     return CEE->getCalleeContext()->getCallSite();
   if (Optional<PostInitializer> PIPP = P.getAs<PostInitializer>())
     return PIPP->getInitializer()->getInit();
+  if (Optional<ScopeExit> SE = P.getAs<ScopeExit>())
+    return SE->getTriggerStmt();
+  if (Optional<ScopeEnter> SEnt = P.getAs<ScopeEnter>())
+    return SEnt->getTriggerStmt();
 
   return 0;
 }
@@ -746,7 +758,7 @@
     if (const BinaryOperator *B = dyn_cast<BinaryOperator>(S))
       return PathDiagnosticLocation::createOperatorLoc(B, SM);
 
-    if (P.getAs<PostStmtPurgeDeadSymbols>())
+    if (P.getAs<PostStmtPurgeDeadSymbols>() || P.getAs<ScopeExit>())
       return PathDiagnosticLocation::createEnd(S, SM, LC);
 
     if (S->getLocStart().isValid())
Index: lib/StaticAnalyzer/Core/Store.cpp
===================================================================
--- lib/StaticAnalyzer/Core/Store.cpp
+++ lib/StaticAnalyzer/Core/Store.cpp
@@ -106,6 +106,7 @@
     case MemRegion::HeapSpaceRegionKind:
     case MemRegion::UnknownSpaceRegionKind:
     case MemRegion::StaticGlobalSpaceRegionKind:
+    case MemRegion::ScopeLocalSpaceRegionKind:
     case MemRegion::GlobalInternalSpaceRegionKind:
     case MemRegion::GlobalSystemSpaceRegionKind:
     case MemRegion::GlobalImmutableSpaceRegionKind: {
Index: test/Analysis/scope-context.cpp
===================================================================
--- /dev/null
+++ test/Analysis/scope-context.cpp
@@ -0,0 +1,24 @@
+// RUN: clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -analyzer-store=region -verify -analyzer-config cfg-scope-info=true %s
+
+void clang_analyzer_eval(bool);
+
+void testEq() {
+  void *a[2];
+  for (int i = 0; i < 2; ++i) {
+    int x[1];
+    a[i] = &x[0];
+  }
+  clang_analyzer_eval(a[0] == a[1]); // expected-warning{{FALSE}}
+}
+
+void testBreak() {
+  for (int i = 0; i < 3; ++i) {
+    {
+      int unused;
+      break;
+    }
+  }
+  {
+    int unused;
+  }
+}