Index: include/clang/Analysis/AnalysisContext.h
===================================================================
--- include/clang/Analysis/AnalysisContext.h
+++ include/clang/Analysis/AnalysisContext.h
@@ -425,6 +425,7 @@
                              bool addImplicitDtors = false,
                              bool addInitializers = false,
                              bool addTemporaryDtors = false,
+                             bool addScopeInfo = false,
                              bool synthesizeBodies = false,
                              bool addStaticInitBranches = false,
                              bool addCXXNewAllocator = true,
Index: include/clang/Analysis/CFG.h
===================================================================
--- include/clang/Analysis/CFG.h
+++ include/clang/Analysis/CFG.h
@@ -57,6 +57,8 @@
     Statement,
     Initializer,
     NewAllocator,
+    ScopeBegin,
+    ScopeEnd,
     // dtor kind
     AutomaticObjectDtor,
     DeleteDtor,
@@ -166,6 +168,48 @@
   }
 };
 
+/// Represents beginning of a scope implicitly generated
+/// by the compiler on encountering a CompoundStmt
+class CFGScopeBegin : public CFGElement {
+public:
+  CFGScopeBegin() {}
+  CFGScopeBegin(const Stmt *S)
+    : CFGElement(ScopeBegin, S) {}
+
+  // Get statement that triggered a new scope.
+  const Stmt *getTriggerStmt() const {
+    return static_cast<Stmt*>(Data1.getPointer());
+  }
+
+private:
+  friend class CFGElement;
+  static bool isKind(const CFGElement &E) {
+    Kind kind = E.getKind();
+    return kind == ScopeBegin;
+  }
+};
+
+/// Represents end of a scope implicitly generated by
+/// the compiler after the last Stmt in a CompoundStmt's body
+class CFGScopeEnd : public CFGElement {
+public:
+  CFGScopeEnd() {}
+  CFGScopeEnd(const Stmt *S)
+    : CFGElement(ScopeEnd, S) {}
+
+  // Get statement that triggered end of previously created scope.
+  const Stmt *getTriggerStmt() const {
+    return static_cast<Stmt*>(Data1.getPointer());
+  }
+
+private:
+  friend class CFGElement;
+  static bool isKind(const CFGElement &E) {
+    Kind kind = E.getKind();
+    return kind == ScopeEnd;
+  }
+};
+
 /// CFGImplicitDtor - Represents C++ object destructor implicitly generated
 /// by compiler on various occasions.
 class CFGImplicitDtor : public CFGElement {
@@ -666,6 +710,14 @@
     Elements.push_back(CFGNewAllocator(NE), C);
   }
 
+  void appendScopeBegin(Stmt *S, BumpVectorContext &C) {
+    Elements.push_back(CFGScopeBegin(S), C);
+  }
+
+  void appendScopeEnd(Stmt *S, BumpVectorContext &C) {
+    Elements.push_back(CFGScopeEnd(S), C);
+  }
+
   void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) {
     Elements.push_back(CFGBaseDtor(BS), C);
   }
@@ -735,6 +787,7 @@
     bool AddInitializers;
     bool AddImplicitDtors;
     bool AddTemporaryDtors;
+    bool AddScopes;
     bool AddStaticInitBranches;
     bool AddCXXNewAllocator;
     bool AddCXXDefaultInitExprInCtors;
@@ -757,8 +810,9 @@
       : forcedBlkExprs(nullptr), Observer(nullptr),
         PruneTriviallyFalseEdges(true), AddEHEdges(false),
         AddInitializers(false), AddImplicitDtors(false),
-        AddTemporaryDtors(false), AddStaticInitBranches(false),
-        AddCXXNewAllocator(false), AddCXXDefaultInitExprInCtors(false) {}
+        AddTemporaryDtors(false), AddScopes(false),
+        AddStaticInitBranches(false), AddCXXNewAllocator(false),
+        AddCXXDefaultInitExprInCtors(false) {}
   };
 
   /// \brief Provides a custom implementation of the iterator class to have the
Index: include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
===================================================================
--- include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
+++ include/clang/StaticAnalyzer/Core/AnalyzerOptions.h
@@ -204,6 +204,9 @@
   /// \sa includeTemporaryDtorsInCFG
   Optional<bool> IncludeTemporaryDtorsInCFG;
   
+  /// \sa includeScopesInCFG
+  Optional<bool> IncludeScopesInCFG;
+
   /// \sa mayInlineCXXStandardLibrary
   Optional<bool> InlineCXXStandardLibrary;
   
@@ -388,6 +391,12 @@
   /// accepts the values "true" and "false".
   bool includeTemporaryDtorsInCFG();
 
+  /// Returns whether or not scope information should be included in the CFG.
+  ///
+  /// This is controlled by the 'cfg-scope-info' config option, which accepts
+  /// the values "true" and "false".
+  bool includeScopesInCFG();
+
   /// Returns whether or not C++ standard library functions may be considered
   /// for inlining.
   ///
Index: lib/Analysis/AnalysisDeclContext.cpp
===================================================================
--- lib/Analysis/AnalysisDeclContext.cpp
+++ lib/Analysis/AnalysisDeclContext.cpp
@@ -67,6 +67,7 @@
                                                        bool addImplicitDtors,
                                                        bool addInitializers,
                                                        bool addTemporaryDtors,
+                                                       bool addScopes,
                                                        bool synthesizeBodies,
                                                        bool addStaticInitBranch,
                                                        bool addCXXNewAllocator,
@@ -77,6 +78,7 @@
   cfgBuildOptions.AddImplicitDtors = addImplicitDtors;
   cfgBuildOptions.AddInitializers = addInitializers;
   cfgBuildOptions.AddTemporaryDtors = addTemporaryDtors;
+  cfgBuildOptions.AddScopes = addScopes;
   cfgBuildOptions.AddStaticInitBranches = addStaticInitBranch;
   cfgBuildOptions.AddCXXNewAllocator = addCXXNewAllocator;
 }
Index: lib/Analysis/CFG.cpp
===================================================================
--- lib/Analysis/CFG.cpp
+++ lib/Analysis/CFG.cpp
@@ -245,11 +245,14 @@
   /// Iterator to variable in previous scope that was declared just before
   /// begin of this scope.
   const_iterator Prev;
+  /// Statement that triggered creation of this LocalScope object
+  const Stmt *TriggerScopeStmt;
 
 public:
   /// Constructs empty scope linked to previous scope in specified place.
-  LocalScope(BumpVectorContext ctx, const_iterator P)
-      : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P) {}
+  LocalScope(BumpVectorContext ctx, const_iterator P, Stmt *s)
+      : ctx(std::move(ctx)), Vars(this->ctx, 4), Prev(P),
+        TriggerScopeStmt(s) {}
 
   /// Begin of scope in direction of CFG building (backwards).
   const_iterator begin() const { return const_iterator(*this, Vars.size()); }
@@ -578,18 +581,23 @@
   }
   CFGBlock *addInitializer(CXXCtorInitializer *I);
   void addAutomaticObjDtors(LocalScope::const_iterator B,
-                            LocalScope::const_iterator E, Stmt *S);
+                            LocalScope::const_iterator E,
+                            Stmt *TriggerAutoObjDtorsStmt,
+                            Stmt *TriggerScopeStmt = nullptr,
+                            bool isScopeEnd = false);
   void addImplicitDtorsForDestructor(const CXXDestructorDecl *DD);
 
   // Local scopes creation.
-  LocalScope* createOrReuseLocalScope(LocalScope* Scope);
+  LocalScope* createOrReuseLocalScope(LocalScope* Scope,
+                                      Stmt *TriggerScopeStmt);
 
-  void addLocalScopeForStmt(Stmt *S);
-  LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS,
+  void addLocalScopeForStmt(Stmt *S, Stmt *TriggerScopeStmt);
+  LocalScope* addLocalScopeForDeclStmt(DeclStmt *DS, Stmt *TriggerScopeStmt,
                                        LocalScope* Scope = nullptr);
-  LocalScope* addLocalScopeForVarDecl(VarDecl *VD, LocalScope* Scope = nullptr);
+  LocalScope* addLocalScopeForVarDecl(VarDecl *VD, Stmt *TriggerScopeStmt,
+                                      LocalScope* Scope = nullptr);
 
-  void addLocalScopeAndDtors(Stmt *S);
+  void addLocalScopeAndDtors(Stmt *S, Stmt *TriggerScopeStmt);
 
   // Interface to CFGBlock - adding CFGElements.
   void appendStmt(CFGBlock *B, const Stmt *S) {
@@ -606,6 +614,12 @@
   void appendNewAllocator(CFGBlock *B, CXXNewExpr *NE) {
     B->appendNewAllocator(NE, cfg->getBumpVectorContext());
   }
+  void appendScopeBegin(CFGBlock *B, Stmt *S) {
+    B->appendScopeBegin(S, cfg->getBumpVectorContext());
+  }
+  void appendScopeEnd(CFGBlock *B, Stmt *S) {
+    B->appendScopeEnd(S, cfg->getBumpVectorContext());
+  }
   void appendBaseDtor(CFGBlock *B, const CXXBaseSpecifier *BS) {
     B->appendBaseDtor(BS, cfg->getBumpVectorContext());
   }
@@ -1208,10 +1222,20 @@
 }
   
 /// addAutomaticObjDtors - Add to current block automatic objects destructors
-/// for objects in range of local scope positions. Use S as trigger statement
-/// for destructors.
+/// for objects in range of local scope positions.
+/// Use `TriggerAutoObjDtorsStmt` as trigger statement for destructors, and
+/// `TriggerScopeStmt` as trigger statement for ending scope.
 void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
-                                      LocalScope::const_iterator E, Stmt *S) {
+                                      LocalScope::const_iterator E,
+                                      Stmt *TriggerAutoObjDtorsStmt,
+                                      Stmt *TriggerScopeStmt,
+                                      bool isScopeEnd) {
+  // Signal addition of ScopeEnd CFG Element, creating `Block` if necessary.
+  if (BuildOpts.AddScopes && isScopeEnd) {
+    autoCreateBlock();
+    appendScopeEnd(Block, TriggerScopeStmt);
+  }
+
   if (!BuildOpts.AddImplicitDtors)
     return;
 
@@ -1244,7 +1268,7 @@
     else
       autoCreateBlock();
 
-    appendAutomaticObjDtor(Block, *I, S);
+    appendAutomaticObjDtor(Block, *I, TriggerAutoObjDtorsStmt);
   }
 }
 
@@ -1295,17 +1319,20 @@
 
 /// createOrReuseLocalScope - If Scope is NULL create new LocalScope. Either
 /// way return valid LocalScope object.
-LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope) {
+LocalScope* CFGBuilder::createOrReuseLocalScope(LocalScope* Scope,
+                                                Stmt *TriggerScopeStmt) {
   if (Scope)
     return Scope;
+
   llvm::BumpPtrAllocator &alloc = cfg->getAllocator();
   return new (alloc.Allocate<LocalScope>())
-      LocalScope(BumpVectorContext(alloc), ScopePos);
+      LocalScope(BumpVectorContext(alloc), ScopePos, TriggerScopeStmt);
 }
 
 /// addLocalScopeForStmt - Add LocalScope to local scopes tree for statement
 /// that should create implicit scope (e.g. if/else substatements). 
-void CFGBuilder::addLocalScopeForStmt(Stmt *S) {
+void CFGBuilder::addLocalScopeForStmt(Stmt *S, Stmt *TriggerScopeStmt) {
+
   if (!BuildOpts.AddImplicitDtors)
     return;
 
@@ -1316,7 +1343,7 @@
     for (auto *BI : CS->body()) {
       Stmt *SI = BI->stripLabelLikeStatements();
       if (DeclStmt *DS = dyn_cast<DeclStmt>(SI))
-        Scope = addLocalScopeForDeclStmt(DS, Scope);
+        Scope = addLocalScopeForDeclStmt(DS, TriggerScopeStmt, Scope);
     }
     return;
   }
@@ -1324,19 +1351,20 @@
   // For any other statement scope will be implicit and as such will be
   // interesting only for DeclStmt.
   if (DeclStmt *DS = dyn_cast<DeclStmt>(S->stripLabelLikeStatements()))
-    addLocalScopeForDeclStmt(DS);
+    addLocalScopeForDeclStmt(DS, TriggerScopeStmt);
 }
 
 /// addLocalScopeForDeclStmt - Add LocalScope for declaration statement. Will
 /// reuse Scope if not NULL.
 LocalScope* CFGBuilder::addLocalScopeForDeclStmt(DeclStmt *DS,
+                                                 Stmt *TriggerScopeStmt,
                                                  LocalScope* Scope) {
   if (!BuildOpts.AddImplicitDtors)
     return Scope;
 
   for (auto *DI : DS->decls())
     if (VarDecl *VD = dyn_cast<VarDecl>(DI))
-      Scope = addLocalScopeForVarDecl(VD, Scope);
+      Scope = addLocalScopeForVarDecl(VD, TriggerScopeStmt, Scope);
   return Scope;
 }
 
@@ -1344,6 +1372,7 @@
 /// create add scope for automatic objects and temporary objects bound to
 /// const reference. Will reuse Scope if not NULL.
 LocalScope* CFGBuilder::addLocalScopeForVarDecl(VarDecl *VD,
+                                                Stmt *TriggerScopeStmt,
                                                 LocalScope* Scope) {
   if (!BuildOpts.AddImplicitDtors)
     return Scope;
@@ -1390,22 +1419,50 @@
   if (const CXXRecordDecl *CD = QT->getAsCXXRecordDecl())
     if (!CD->hasTrivialDestructor()) {
       // Add the variable to scope
-      Scope = createOrReuseLocalScope(Scope);
+      Scope = createOrReuseLocalScope(Scope, TriggerScopeStmt);
       Scope->addVar(VD);
       ScopePos = Scope->begin();
     }
   return Scope;
 }
 
-/// addLocalScopeAndDtors - For given statement add local scope for it and
-/// add destructors that will cleanup the scope. Will reuse Scope if not NULL.
-void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
+static bool deferAutomaticObjDtors(Stmt *S) {
+  if (isa<ReturnStmt>(S) || isa<BreakStmt>(S) || isa<ContinueStmt>(S))
+    return true;
+  return false;
+}
+
+/// addLocalScopeAndDtors - For given statements `TriggerAutoObjDtorsStmt`, and
+/// `TriggerScopeStmt`, add local scope for it and add destructors that will
+/// cleanup the scope. Will reuse Scope if not NULL.
+/// `TriggerAutoObjDtorsStmt` is the last statement in the present scope after
+/// which auto obj destructors (if any) will be added to cleanup scope.
+/// `TriggerScopeStmt` is the statement that led to the creation of the Scope
+/// object.
+///
+/// For example:
+///	if (condition) { // TriggerScopeStmt
+///		std::vector<int> IntVec;
+///		IntVec.push_back(0); // TriggerAutoObjDtorsStmt
+///	}
+///
+/// IfStmt is the `TriggerScopeStmt`; IntVec.push_back is
+/// `TriggerAutoObjDtorsStmt`.
+/// Eventually, `TriggerScopeStmt` is used inside CFGScopeBegin/End
+/// blocks. In the example above, we will have CFGScope blocks, like
+/// so: CFGScopeBegin(IfStmt) ... CFGScopeEnd(IfStmt).
+void CFGBuilder::addLocalScopeAndDtors(Stmt *TriggerAutoObjDtorsStmt,
+                                       Stmt *TriggerScopeStmt) {
   if (!BuildOpts.AddImplicitDtors)
     return;
 
   LocalScope::const_iterator scopeBeginPos = ScopePos;
-  addLocalScopeForStmt(S);
-  addAutomaticObjDtors(ScopePos, scopeBeginPos, S);
+  addLocalScopeForStmt(TriggerAutoObjDtorsStmt, TriggerScopeStmt);
+  // Disallow return statements from triggering end of scope because they
+  // directly invoke addAutomaticObjDtors that explicitly ends scope.
+  if (!deferAutomaticObjDtors(TriggerAutoObjDtorsStmt))
+    addAutomaticObjDtors(ScopePos, scopeBeginPos, TriggerAutoObjDtorsStmt,
+                         TriggerScopeStmt, true);
 }
 
 /// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for
@@ -1809,7 +1866,8 @@
   // If there is no target for the break, then we are looking at an incomplete
   // AST.  This means that the CFG cannot be constructed.
   if (BreakJumpTarget.block) {
-    addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B);
+    addAutomaticObjDtors(ScopePos, BreakJumpTarget.scopePosition, B, B,
+                         /*isScopeEnd=*/true);
     addSuccessor(Block, BreakJumpTarget.block);
   } else
     badCFG = true;
@@ -1938,15 +1996,14 @@
   return addStmt(C->getCond());
 }
 
-
 CFGBlock *CFGBuilder::VisitCompoundStmt(CompoundStmt *C) {
   LocalScope::const_iterator scopeBeginPos = ScopePos;
   if (BuildOpts.AddImplicitDtors) {
-    addLocalScopeForStmt(C);
+    addLocalScopeForStmt(C, C);
   }
-  if (!C->body_empty() && !isa<ReturnStmt>(*C->body_rbegin())) {
+  if (C->body_empty() || !deferAutomaticObjDtors(*C->body_rbegin())) {
     // If the body ends with a ReturnStmt, the dtors will be added in VisitReturnStmt
-    addAutomaticObjDtors(ScopePos, scopeBeginPos, C);
+    addAutomaticObjDtors(ScopePos, scopeBeginPos, C, C, /*isScopeEnd=*/true);
   }
 
   CFGBlock *LastBlock = Block;
@@ -1962,6 +2019,12 @@
       return nullptr;
   }
 
+  if (BuildOpts.AddScopes) {
+    if (!LastBlock)
+      LastBlock = createBlock();
+    appendScopeBegin(LastBlock, C);
+  }
+
   return LastBlock;
 }
 
@@ -2172,7 +2235,7 @@
   // Store scope position. Add implicit destructor.
   if (VarDecl *VD = I->getConditionVariable()) {
     LocalScope::const_iterator BeginScopePos = ScopePos;
-    addLocalScopeForVarDecl(VD);
+    addLocalScopeForVarDecl(VD, I);
     addAutomaticObjDtors(ScopePos, BeginScopePos, I);
   }
 
@@ -2197,7 +2260,7 @@
     // If branch is not a compound statement create implicit scope
     // and add destructors.
     if (!isa<CompoundStmt>(Else))
-      addLocalScopeAndDtors(Else);
+      addLocalScopeAndDtors(Else, I);
 
     ElseBlock = addStmt(Else);
 
@@ -2207,6 +2270,9 @@
       if (badCFG)
         return nullptr;
     }
+
+    if (BuildOpts.AddScopes && !isa<CompoundStmt>(Else))
+      appendScopeBegin(ElseBlock, I);
   }
 
   // Process the true branch.
@@ -2220,7 +2286,7 @@
     // If branch is not a compound statement create implicit scope
     // and add destructors.
     if (!isa<CompoundStmt>(Then))
-      addLocalScopeAndDtors(Then);
+      addLocalScopeAndDtors(Then, I);
 
     ThenBlock = addStmt(Then);
 
@@ -2234,6 +2300,9 @@
       if (badCFG)
         return nullptr;
     }
+
+    if (BuildOpts.AddScopes && !isa<CompoundStmt>(Then))
+      appendScopeBegin(ThenBlock, I);
   }
 
   // Specially handle "if (expr1 || ...)" and "if (expr1 && ...)" by
@@ -2290,7 +2359,8 @@
   // Create the new block.
   Block = createBlock(false);
 
-  addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R);
+  addAutomaticObjDtors(ScopePos, LocalScope::const_iterator(), R, R,
+                       /*isScopeEnd=*/true);
 
   // If the one of the destructors does not return, we already have the Exit
   // block as a successor.
@@ -2389,11 +2459,11 @@
   // Add destructor for init statement and condition variable.
   // Store scope position for continue statement.
   if (Stmt *Init = F->getInit())
-    addLocalScopeForStmt(Init);
+    addLocalScopeForStmt(Init, F);
   LocalScope::const_iterator LoopBeginScopePos = ScopePos;
 
   if (VarDecl *VD = F->getConditionVariable())
-    addLocalScopeForVarDecl(VD);
+    addLocalScopeForVarDecl(VD, F);
   LocalScope::const_iterator ContinueScopePos = ScopePos;
 
   addAutomaticObjDtors(ScopePos, save_scope_pos.get(), F);
@@ -2453,7 +2523,7 @@
     // If body is not a compound statement create implicit scope
     // and add destructors.
     if (!isa<CompoundStmt>(F->getBody()))
-      addLocalScopeAndDtors(F->getBody());
+      addLocalScopeAndDtors(F->getBody(), F);
 
     // Now populate the body block, and in the process create new blocks as we
     // walk the body of the loop.
@@ -2466,6 +2536,9 @@
     }
     else if (badCFG)
       return nullptr;
+
+    if (BuildOpts.AddScopes && !isa<CompoundStmt>(F->getBody()))
+      appendScopeBegin(BodyBlock, F);
   }
   
   // Because of short-circuit evaluation, the condition of the loop can span
@@ -2734,7 +2807,7 @@
   // Store scope position for continue statement.
   LocalScope::const_iterator LoopBeginScopePos = ScopePos;
   if (VarDecl *VD = W->getConditionVariable()) {
-    addLocalScopeForVarDecl(VD);
+    addLocalScopeForVarDecl(VD, W);
     addAutomaticObjDtors(ScopePos, LoopBeginScopePos, W);
   }
 
@@ -2775,7 +2848,7 @@
     // If body is not a compound statement create implicit scope
     // and add destructors.
     if (!isa<CompoundStmt>(W->getBody()))
-      addLocalScopeAndDtors(W->getBody());
+      addLocalScopeAndDtors(W->getBody(), W);
 
     // Create the body.  The returned block is the entry to the loop body.
     BodyBlock = addStmt(W->getBody());
@@ -2784,6 +2857,9 @@
       BodyBlock = ContinueJumpTarget.block; // can happen for "while(...) ;"
     else if (Block && badCFG)
       return nullptr;
+
+    if (BuildOpts.AddScopes && !isa<CompoundStmt>(W->getBody()))
+      appendScopeBegin(BodyBlock, W);
   }
 
   // Because of short-circuit evaluation, the condition of the loop can span
@@ -2957,7 +3033,7 @@
     // If body is not a compound statement create implicit scope
     // and add destructors.
     if (!isa<CompoundStmt>(D->getBody()))
-      addLocalScopeAndDtors(D->getBody());
+      addLocalScopeAndDtors(D->getBody(), D);
 
     // Create the body.  The returned block is the entry to the loop body.
     BodyBlock = addStmt(D->getBody());
@@ -2969,6 +3045,9 @@
         return nullptr;
     }
 
+    if (BuildOpts.AddScopes && !isa<CompoundStmt>(D->getBody()))
+      appendScopeBegin(BodyBlock, D);
+
     if (!KnownVal.isFalse()) {
       // Add an intermediate block between the BodyBlock and the
       // ExitConditionBlock to represent the "loop back" transition.  Create an
@@ -3013,7 +3092,8 @@
   // If there is no target for the continue, then we are looking at an
   // incomplete AST.  This means the CFG cannot be constructed.
   if (ContinueJumpTarget.block) {
-    addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C);
+    addAutomaticObjDtors(ScopePos, ContinueJumpTarget.scopePosition, C, C,
+                         /*isScopeEnd=*/true);
     addSuccessor(Block, ContinueJumpTarget.block);
   } else
     badCFG = true;
@@ -3063,7 +3143,7 @@
   // Store scope position. Add implicit destructor.
   if (VarDecl *VD = Terminator->getConditionVariable()) {
     LocalScope::const_iterator SwitchBeginScopePos = ScopePos;
-    addLocalScopeForVarDecl(VD);
+    addLocalScopeForVarDecl(VD, Terminator);
     addAutomaticObjDtors(ScopePos, SwitchBeginScopePos, Terminator);
   }
 
@@ -3112,7 +3192,7 @@
   // If body is not a compound statement create implicit scope
   // and add destructors.
   if (!isa<CompoundStmt>(Terminator->getBody()))
-    addLocalScopeAndDtors(Terminator->getBody());
+    addLocalScopeAndDtors(Terminator->getBody(), Terminator);
 
   addStmt(Terminator->getBody());
   if (Block) {
@@ -3346,7 +3426,7 @@
   // Store scope position. Add implicit destructor.
   if (VarDecl *VD = CS->getExceptionDecl()) {
     LocalScope::const_iterator BeginScopePos = ScopePos;
-    addLocalScopeForVarDecl(VD);
+    addLocalScopeForVarDecl(VD, CS);
     addAutomaticObjDtors(ScopePos, BeginScopePos, CS);
   }
 
@@ -3396,11 +3476,11 @@
 
   // Create local scopes and destructors for range, begin and end variables.
   if (Stmt *Range = S->getRangeStmt())
-    addLocalScopeForStmt(Range);
+    addLocalScopeForStmt(Range, S);
   if (Stmt *Begin = S->getBeginStmt())
-    addLocalScopeForStmt(Begin);
+    addLocalScopeForStmt(Begin, S);
   if (Stmt *End = S->getEndStmt())
-    addLocalScopeForStmt(End);
+    addLocalScopeForStmt(End, S);
   addAutomaticObjDtors(ScopePos, save_scope_pos.get(), S);
 
   LocalScope::const_iterator ContinueScopePos = ScopePos;
@@ -3470,7 +3550,7 @@
     Block = nullptr;
 
     // Add implicit scope and dtors for loop variable.
-    addLocalScopeAndDtors(S->getLoopVarStmt());
+    addLocalScopeAndDtors(S->getLoopVarStmt(), S);
 
     // Populate a new block to contain the loop body and loop variable.
     addStmt(S->getBody());
@@ -3868,6 +3948,8 @@
     case CFGElement::Statement:
     case CFGElement::Initializer:
     case CFGElement::NewAllocator:
+    case CFGElement::ScopeBegin:
+    case CFGElement::ScopeEnd:
       llvm_unreachable("getDestructorDecl should only be used with "
                        "ImplicitDtors");
     case CFGElement::AutomaticObjectDtor: {
@@ -4273,6 +4355,16 @@
     if (const CXXNewExpr *AllocExpr = NE->getAllocatorExpr())
       AllocExpr->getType().print(OS, PrintingPolicy(Helper.getLangOpts()));
     OS << ")\n";
+  } else if (Optional<CFGScopeBegin> SB = E.getAs<CFGScopeBegin>()) {
+    OS << "CFGScopeBegin(";
+    if (const Stmt *S = SB->getTriggerStmt())
+      OS << S->getStmtClassName();
+    OS << ")\n";
+  } else if (Optional<CFGScopeEnd> SE = E.getAs<CFGScopeEnd>()) {
+    OS << "CFGScopeEnd(";
+    if (const Stmt *S = SE->getTriggerStmt())
+      OS << S->getStmtClassName();
+    OS << ")\n";
   } else if (Optional<CFGDeleteDtor> DE = E.getAs<CFGDeleteDtor>()) {
     const CXXRecordDecl *RD = DE->getCXXRecordDecl();
     if (!RD)
Index: lib/StaticAnalyzer/Core/AnalysisManager.cpp
===================================================================
--- lib/StaticAnalyzer/Core/AnalysisManager.cpp
+++ lib/StaticAnalyzer/Core/AnalysisManager.cpp
@@ -26,6 +26,7 @@
               /*AddImplicitDtors=*/true,
               /*AddInitializers=*/true,
               Options.includeTemporaryDtorsInCFG(),
+              Options.includeScopesInCFG(),
               Options.shouldSynthesizeBodies(),
               Options.shouldConditionalizeStaticInitializers(),
               /*addCXXNewAllocator=*/true,
Index: lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
===================================================================
--- lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
+++ lib/StaticAnalyzer/Core/AnalyzerOptions.cpp
@@ -153,6 +153,12 @@
                           /* Default = */ false);
 }
 
+bool AnalyzerOptions::includeScopesInCFG() {
+  return getBooleanOption(IncludeScopesInCFG,
+                          "cfg-scopes",
+                          /* Default = */ false);
+}
+
 bool AnalyzerOptions::mayInlineCXXStandardLibrary() {
   return getBooleanOption(InlineCXXStandardLibrary,
                           "c++-stdlib-inlining",
Index: lib/StaticAnalyzer/Core/ExprEngine.cpp
===================================================================
--- lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -310,6 +310,9 @@
     case CFGElement::TemporaryDtor:
       ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
       return;
+    case CFGElement::ScopeBegin:
+    case CFGElement::ScopeEnd:
+      llvm_unreachable("Local scopes not yet implemented.");
   }
 }
 
Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp
===================================================================
--- lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -570,6 +570,8 @@
   }
   case CFGElement::TemporaryDtor:
   case CFGElement::NewAllocator:
+  case CFGElement::ScopeBegin:
+  case CFGElement::ScopeEnd:
     llvm_unreachable("not yet implemented!");
   }
 
Index: test/Analysis/analyzer-config.c
===================================================================
--- test/Analysis/analyzer-config.c
+++ test/Analysis/analyzer-config.c
@@ -12,6 +12,7 @@
 
 // CHECK: [config]
 // CHECK-NEXT: cfg-conditional-static-initializers = true
+// CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-temporary-dtors = false
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: graph-trim-interval = 1000
@@ -27,5 +28,5 @@
 // CHECK-NEXT: region-store-small-struct-limit = 2
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 15
+// CHECK-NEXT: num-entries = 16
 
Index: test/Analysis/analyzer-config.cpp
===================================================================
--- test/Analysis/analyzer-config.cpp
+++ test/Analysis/analyzer-config.cpp
@@ -23,6 +23,7 @@
 // CHECK-NEXT: c++-stdlib-inlining = true
 // CHECK-NEXT: c++-template-inlining = true
 // CHECK-NEXT: cfg-conditional-static-initializers = true
+// CHECK-NEXT: cfg-scopes = false
 // CHECK-NEXT: cfg-temporary-dtors = false
 // CHECK-NEXT: faux-bodies = true
 // CHECK-NEXT: graph-trim-interval = 1000
@@ -38,4 +39,4 @@
 // CHECK-NEXT: region-store-small-struct-limit = 2
 // CHECK-NEXT: widen-loops = false
 // CHECK-NEXT: [stats]
-// CHECK-NEXT: num-entries = 20
+// CHECK-NEXT: num-entries = 21
Index: test/Analysis/scopes-cfg-output.cpp
===================================================================
--- /dev/null
+++ test/Analysis/scopes-cfg-output.cpp
@@ -0,0 +1,696 @@
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -analyze -analyzer-checker=debug.DumpCFG -analyzer-config cfg-scopes=true %s > %t 2>&1
+// RUN: FileCheck --input-file=%t %s
+
+class A {
+public:
+// CHECK:      [B2 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B1]
+// CHECK-NEXT:   1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+  A() {}
+
+// CHECK:      [B2 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B1]
+// CHECK-NEXT:   1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+  ~A() {}
+
+// CHECK:      [B2 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B1]
+// CHECK-NEXT:   1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2: 1
+// CHECK-NEXT:   3: return [B1.2];
+// CHECK-NEXT:   4: CFGScopeEnd(ReturnStmt)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+  operator int() const { return 1; }
+};
+
+extern const bool UV;
+
+// CHECK:      [B2 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B1]
+// CHECK-NEXT:   1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   4: a
+// CHECK-NEXT:   5: [B1.4] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   6: const A &b = a;
+// CHECK-NEXT:   7: A() (CXXConstructExpr, class A)
+// CHECK-NEXT:   8: [B1.7] (BindTemporary)
+// CHECK-NEXT:   9: [B1.8] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   10: [B1.9]
+// CHECK:       11: const A &c = A();
+// CHECK:       12: [B1.11].~A() (Implicit destructor)
+// CHECK:       13: [B1.3].~A() (Implicit destructor)
+// CHECK:       14: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+void test_const_ref() {
+  A a;
+  const A& b = a;
+  const A& c = A();
+}
+
+// CHECK:      [B2 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B1]
+// CHECK-NEXT:   1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A [2])
+// CHECK-NEXT:   3: A a[2];
+// CHECK-NEXT:   4:  (CXXConstructExpr, class A [0])
+// CHECK-NEXT:   5: A b[0];
+// CHECK-NEXT:   6: [B1.3].~A() (Implicit destructor)
+// CHECK-NEXT:   7: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+void test_array() {
+  A a[2];
+  A b[0];
+}
+
+// CHECK:      [B2 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B1]
+// CHECK-NEXT:   1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   4: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   5:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   6: A c;
+// CHECK-NEXT:   7:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   8: A d;
+// CHECK-NEXT:   9: [B1.8].~A() (Implicit destructor)
+// CHECK-NEXT:   10: [B1.6].~A() (Implicit destructor)
+// CHECK-NEXT:   11: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   12:  (CXXConstructExpr, class A)
+// CHECK:       13: A b;
+// CHECK:       14: [B1.13].~A() (Implicit destructor)
+// CHECK:       15: [B1.3].~A() (Implicit destructor)
+// CHECK:	16: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+void test_scope() {
+  A a;
+  { A c;
+    A d;
+  }
+  A b;
+}
+
+// CHECK:      [B4 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B3
+// CHECK:      [B1]
+// CHECK-NEXT:   1:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   2: A c;
+// CHECK-NEXT:   3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B3.5].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 6: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: return;
+// CHECK-NEXT:   3: [B3.5].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(ReturnStmt)
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B3]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   4:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   5: A b;
+// CHECK-NEXT:   6: UV
+// CHECK-NEXT:   7: [B3.6] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B3.7]
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (2): B2 B1
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (2): B1 B2
+void test_return() {
+  A a;
+  A b;
+  if (UV) return;
+  A c;
+}
+
+// CHECK:      [B5 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B1]
+// CHECK-NEXT:   1: [B4.7].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 3: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (2): B2 B3
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A c;
+// CHECK-NEXT:   4: [B2.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(IfStmt)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B3]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A c;
+// CHECK-NEXT:   4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:   5: CFGScopeEnd(IfStmt)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B4]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   4: a
+// CHECK-NEXT:   5: [B4.4] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   6: [B4.5] (CXXConstructExpr, class A)
+// CHECK-NEXT:   7: A b = a;
+// CHECK-NEXT:   8: b
+// CHECK-NEXT:   9: [B4.8] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   10: [B4.9].operator int
+// CHECK:       11: [B4.9]
+// CHECK:       12: [B4.11] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:       13: [B4.12] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:   T: if [B4.13]
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (2): B3 B2
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+void test_if_implicit_scope() {
+  A a;
+  if (A b = a)
+    A c;
+  else A c;
+}
+
+// CHECK:      [B9 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B8
+// CHECK:      [B1]
+// CHECK-NEXT:   1: [B8.7].~A() (Implicit destructor)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A e;
+// CHECK-NEXT:   4: [B1.3].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 6: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (2): B2 B5
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:   1:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   2: A d;
+// CHECK-NEXT:   3: [B2.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B3]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: return;
+// CHECK-NEXT:   3: [B4.3].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B8.7].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 6: CFGScopeEnd(ReturnStmt)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B4]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A c;
+// CHECK-NEXT:   4: UV
+// CHECK-NEXT:   5: [B4.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B4.5]
+// CHECK-NEXT:   Preds (1): B8
+// CHECK-NEXT:   Succs (2): B3 B2
+// CHECK:      [B5]
+// CHECK-NEXT:   1:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   2: A d;
+// CHECK-NEXT:   3: [B5.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B7
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B6]
+// CHECK-NEXT: 	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: return;
+// CHECK-NEXT:   3: [B7.3].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B8.7].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B8.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 6: CFGScopeEnd(ReturnStmt)
+// CHECK-NEXT:   Preds (1): B7
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B7]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A c;
+// CHECK-NEXT:   4: UV
+// CHECK-NEXT:   5: [B7.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B7.5]
+// CHECK-NEXT:   Preds (1): B8
+// CHECK-NEXT:   Succs (2): B6 B5
+// CHECK:      [B8]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   4: a
+// CHECK-NEXT:   5: [B8.4] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   6: [B8.5] (CXXConstructExpr, class A)
+// CHECK-NEXT:   7: A b = a;
+// CHECK-NEXT:   8: b
+// CHECK-NEXT:   9: [B8.8] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   10: [B8.9].operator int
+// CHECK:       11: [B8.9]
+// CHECK:       12: [B8.11] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:       13: [B8.12] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:   T: if [B8.13]
+// CHECK-NEXT:   Preds (1): B9
+// CHECK-NEXT:   Succs (2): B7 B4
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (3): B1 B3 B6
+void test_if_jumps() {
+  A a;
+  if (A b = a) {
+    A c;
+    if (UV) return;
+    A d;
+  } else {
+    A c;
+    if (UV) return;
+    A d;
+  }
+  A e;
+}
+
+// CHECK:      [B6 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B5
+// CHECK:      [B1]
+// CHECK-NEXT:   1: [B4.4].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 3: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B3]
+// CHECK-NEXT:	 1: CFGScopeBegin(WhileStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A c;
+// CHECK-NEXT:   4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(WhileStmt)
+// CHECK-NEXT:   6: [B4.4].~A() (Implicit destructor)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B4]
+// CHECK-NEXT:   1: a
+// CHECK-NEXT:   2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   3: [B4.2] (CXXConstructExpr, class A)
+// CHECK-NEXT:   4: A b = a;
+// CHECK-NEXT:   5: b
+// CHECK-NEXT:   6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   7: [B4.6].operator int
+// CHECK-NEXT:   8: [B4.6]
+// CHECK-NEXT:   9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:       10: [B4.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:   T: while [B4.10]
+// CHECK-NEXT:   Preds (2): B2 B5
+// CHECK-NEXT:   Succs (2): B3 B1
+// CHECK:      [B5]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   Preds (1): B6
+// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+void test_while_implicit_scope() {
+  A a;
+  while (A b = a)
+    A c;
+}
+
+// CHECK:      [B12 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B11
+// CHECK:      [B1]
+// CHECK-NEXT:   1: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A e;
+// CHECK-NEXT:   4: [B1.3].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 6: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (2): B8 B10
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:   Preds (2): B3 B6
+// CHECK-NEXT:   Succs (1): B10
+// CHECK:      [B3]
+// CHECK-NEXT:   1:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   2: A d;
+// CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   6: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B4]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: return;
+// CHECK-NEXT:   3: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 6: CFGScopeEnd(ReturnStmt)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B5]
+// CHECK-NEXT:   1: UV
+// CHECK-NEXT:   2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B5.2]
+// CHECK-NEXT:   Preds (1): B7
+// CHECK-NEXT:   Succs (2): B4 B3
+// CHECK:      [B6]
+// CHECK-NEXT: 	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:   3: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:	 4: CFGScopeEnd(ContinueStmt)
+// CHECK-NEXT:   T: continue;
+// CHECK:        Preds (1): B7
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B7]
+// CHECK-NEXT:   1: UV
+// CHECK-NEXT:   2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B7.2]
+// CHECK-NEXT:   Preds (1): B9
+// CHECK-NEXT:   Succs (2): B6 B5
+// CHECK:      [B8]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 3: CFGScopeEnd(BreakStmt)
+// CHECK-NEXT:   T: break;
+// CHECK:        Preds (1): B9
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B9]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A c;
+// CHECK-NEXT:   4: UV
+// CHECK-NEXT:   5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B9.5]
+// CHECK-NEXT:   Preds (1): B10
+// CHECK-NEXT:   Succs (2): B8 B7
+// CHECK:      [B10]
+// CHECK-NEXT:   1: a
+// CHECK-NEXT:   2: [B10.1] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   3: [B10.2] (CXXConstructExpr, class A)
+// CHECK-NEXT:   4: A b = a;
+// CHECK-NEXT:   5: b
+// CHECK-NEXT:   6: [B10.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   7: [B10.6].operator int
+// CHECK-NEXT:   8: [B10.6]
+// CHECK-NEXT:   9: [B10.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:       10: [B10.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:   T: while [B10.10]
+// CHECK-NEXT:   Preds (2): B2 B11
+// CHECK-NEXT:   Succs (2): B9 B1
+// CHECK:      [B11]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   Preds (1): B12
+// CHECK-NEXT:   Succs (1): B10
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (2): B1 B4
+void test_while_jumps() {
+  A a;
+  while (A b = a) {
+    A c;
+    if (UV) break;
+    if (UV) continue;
+    if (UV) return;
+    A d;
+  }
+  A e;
+}
+
+// CHECK:      [B12 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B11
+// CHECK:      [B1]
+// CHECK-NEXT:   1:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   2: A d;
+// CHECK-NEXT:   3: [B1.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT: 	 5: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (2): B8 B2
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:   1: UV
+// CHECK-NEXT:   2: [B2.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: do ... while [B2.2]
+// CHECK-NEXT:   Preds (2): B3 B6
+// CHECK-NEXT:   Succs (2): B10 B1
+// CHECK:      [B3]
+// CHECK-NEXT:   1:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   2: A c;
+// CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B4]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: return;
+// CHECK-NEXT:   3: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(ReturnStmt)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B5]
+// CHECK-NEXT:   1: UV
+// CHECK-NEXT:   2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B5.2]
+// CHECK-NEXT:   Preds (1): B7
+// CHECK-NEXT:   Succs (2): B4 B3
+// CHECK:      [B6]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 3: CFGScopeEnd(ContinueStmt)
+// CHECK-NEXT:   T: continue;
+// CHECK:        Preds (1): B7
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B7]
+// CHECK-NEXT:   1: UV
+// CHECK-NEXT:   2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B7.2]
+// CHECK-NEXT:   Preds (1): B9
+// CHECK-NEXT:   Succs (2): B6 B5
+// CHECK:      [B8]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 3: CFGScopeEnd(BreakStmt)
+// CHECK-NEXT:   T: break;
+// CHECK:        Preds (1): B9
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B9]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A b;
+// CHECK-NEXT:   4: UV
+// CHECK-NEXT:   5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B9.5]
+// CHECK-NEXT:   Preds (2): B10 B11
+// CHECK-NEXT:   Succs (2): B8 B7
+// CHECK:      [B10]
+// CHECK-NEXT:   Preds (1): B2
+// CHECK-NEXT:   Succs (1): B9
+// CHECK:      [B11]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   Preds (1): B12
+// CHECK-NEXT:   Succs (1): B9
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (2): B1 B4
+void test_do_jumps() {
+  A a;
+  do {
+    A b;
+    if (UV) break;
+    if (UV) continue;
+    if (UV) return;
+    A c;
+  } while (UV);
+  A d;
+}
+
+// CHECK:      [B6 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B5
+// CHECK:      [B1]
+// CHECK-NEXT:   1: [B4.4].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B5.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 3: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:   Preds (1): B3
+// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B3]
+// CHECK-NEXT:	 1: CFGScopeBegin(ForStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A c;
+// CHECK-NEXT:   4: [B3.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(ForStmt)
+// CHECK-NEXT:   6: [B4.4].~A() (Implicit destructor)
+// CHECK-NEXT:   Preds (1): B4
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B4]
+// CHECK-NEXT:   1: a
+// CHECK-NEXT:   2: [B4.1] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   3: [B4.2] (CXXConstructExpr, class A)
+// CHECK-NEXT:   4: A b = a;
+// CHECK-NEXT:   5: b
+// CHECK-NEXT:   6: [B4.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   7: [B4.6].operator int
+// CHECK-NEXT:   8: [B4.6]
+// CHECK-NEXT:   9: [B4.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:       10: [B4.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:   T: for (...; [B4.10]; )
+// CHECK-NEXT:   Preds (2): B2 B5
+// CHECK-NEXT:   Succs (2): B3 B1
+// CHECK:      [B5]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   Preds (1): B6
+// CHECK-NEXT:   Succs (1): B4
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (1): B1
+void test_for_implicit_scope() {
+  for (A a; A b = a; )
+    A c;
+}
+
+// CHECK:      [B12 (ENTRY)]
+// CHECK-NEXT:   Succs (1): B11
+// CHECK:      [B1]
+// CHECK-NEXT:   1: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   2: [B11.5].~A() (Implicit destructor)
+// CHECK-NEXT:   3:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   4: A f;
+// CHECK-NEXT:   5: [B1.4].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 7: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   Preds (2): B8 B10
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B2]
+// CHECK-NEXT:   Preds (2): B3 B6
+// CHECK-NEXT:   Succs (1): B10
+// CHECK:      [B3]
+// CHECK-NEXT:   1:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   2: A e;
+// CHECK-NEXT:   3: [B3.2].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 5: CFGScopeEnd(CompoundStmt)
+// CHECK-NEXT:   6: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B4]
+// CHECK-NEXT: 	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: return;
+// CHECK-NEXT:   3: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:   4: [B10.4].~A() (Implicit destructor)
+// CHECK-NEXT:   5: [B11.5].~A() (Implicit destructor)
+// CHECK-NEXT:   6: [B11.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 7: CFGScopeEnd(ReturnStmt)
+// CHECK-NEXT:   Preds (1): B5
+// CHECK-NEXT:   Succs (1): B0
+// CHECK:      [B5]
+// CHECK-NEXT:   1: UV
+// CHECK-NEXT:   2: [B5.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B5.2]
+// CHECK-NEXT:   Preds (1): B7
+// CHECK-NEXT:   Succs (2): B4 B3
+// CHECK:      [B6]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 3: CFGScopeEnd(ContinueStmt)
+// CHECK-NEXT:   T: continue;
+// CHECK:        Preds (1): B7
+// CHECK-NEXT:   Succs (1): B2
+// CHECK:      [B7]
+// CHECK-NEXT:   1: UV
+// CHECK-NEXT:   2: [B7.1] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B7.2]
+// CHECK-NEXT:   Preds (1): B9
+// CHECK-NEXT:   Succs (2): B6 B5
+// CHECK:      [B8]
+// CHECK-NEXT:	 1: CFGScopeBegin(IfStmt)
+// CHECK-NEXT:   2: [B9.3].~A() (Implicit destructor)
+// CHECK-NEXT:	 3: CFGScopeEnd(BreakStmt)
+// CHECK-NEXT:   T: break;
+// CHECK:        Preds (1): B9
+// CHECK-NEXT:   Succs (1): B1
+// CHECK:      [B9]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A d;
+// CHECK-NEXT:   4: UV
+// CHECK-NEXT:   5: [B9.4] (ImplicitCastExpr, LValueToRValue, _Bool)
+// CHECK-NEXT:   T: if [B9.5]
+// CHECK-NEXT:   Preds (1): B10
+// CHECK-NEXT:   Succs (2): B8 B7
+// CHECK:      [B10]
+// CHECK-NEXT:   1: b
+// CHECK-NEXT:   2: [B10.1] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   3: [B10.2] (CXXConstructExpr, class A)
+// CHECK-NEXT:   4: A c = b;
+// CHECK-NEXT:   5: c
+// CHECK-NEXT:   6: [B10.5] (ImplicitCastExpr, NoOp, const class A)
+// CHECK-NEXT:   7: [B10.6].operator int
+// CHECK-NEXT:   8: [B10.6]
+// CHECK-NEXT:   9: [B10.8] (ImplicitCastExpr, UserDefinedConversion, int)
+// CHECK:       10: [B10.9] (ImplicitCastExpr, IntegralToBoolean, _Bool)
+// CHECK-NEXT:   T: for (...; [B10.10]; )
+// CHECK-NEXT:   Preds (2): B2 B11
+// CHECK-NEXT:   Succs (2): B9 B1
+// CHECK:      [B11]
+// CHECK-NEXT:	 1: CFGScopeBegin(CompoundStmt)
+// CHECK-NEXT:   2:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   3: A a;
+// CHECK-NEXT:   4:  (CXXConstructExpr, class A)
+// CHECK-NEXT:   5: A b;
+// CHECK-NEXT:   Preds (1): B12
+// CHECK-NEXT:   Succs (1): B10
+// CHECK:      [B0 (EXIT)]
+// CHECK-NEXT:   Preds (2): B1 B4
+void test_for_jumps() {
+  A a;
+  for (A b; A c = b; ) {
+    A d;
+    if (UV) break;
+    if (UV) continue;
+    if (UV) return;
+    A e;
+  }
+  A f;
+}