diff --git a/INPUTS/cfg-nested-var-scopes.cpp b/INPUTS/cfg-nested-var-scopes.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0944ec268f1b667298be51da7019e72d4e2fb4ad
--- /dev/null
+++ b/INPUTS/cfg-nested-var-scopes.cpp
@@ -0,0 +1,59 @@
+// Hammer the CFG with large numbers of overlapping variable scopes, which
+// implicit destructors triggered at each edge.
+
+#define EXPAND_BASIC_STRUCT(i) struct X##i { X##i(int); ~X##i(); };
+#define EXPAND_NORET_STRUCT(i) struct X##i { X##i(int); ~X##i() __attribute__((noreturn)); };
+EXPAND_BASIC_STRUCT(0000); EXPAND_NORET_STRUCT(0001);
+EXPAND_BASIC_STRUCT(0010); EXPAND_BASIC_STRUCT(0011);
+EXPAND_BASIC_STRUCT(0100); EXPAND_NORET_STRUCT(0101);
+EXPAND_NORET_STRUCT(0110); EXPAND_BASIC_STRUCT(0111);
+EXPAND_BASIC_STRUCT(1000); EXPAND_NORET_STRUCT(1001);
+EXPAND_BASIC_STRUCT(1010); EXPAND_BASIC_STRUCT(1011);
+EXPAND_NORET_STRUCT(1100); EXPAND_NORET_STRUCT(1101);
+EXPAND_BASIC_STRUCT(1110); EXPAND_BASIC_STRUCT(1111);
+
+#define EXPAND_2_VARS(c, i, x)  const X##i var_##c##_##i##0(x), &var_##c##_##i##1 = X##i(x)
+#define EXPAND_4_VARS(c, i, x)  EXPAND_2_VARS(c, i##0, x);  EXPAND_2_VARS(c, i##1, x)
+#define EXPAND_8_VARS(c, i, x)  EXPAND_4_VARS(c, i##0, x);  EXPAND_4_VARS(c, i##1, x)
+#define EXPAND_16_VARS(c, i, x) EXPAND_8_VARS(c, i##0, x);  EXPAND_8_VARS(c, i##1, x)
+#define EXPAND_32_VARS(c, x)    EXPAND_16_VARS(c, 0, x);    EXPAND_16_VARS(c, 1, x)
+
+#define EXPAND_2_INNER_CASES(i, x, y)    INNER_CASE(i, x, y);             INNER_CASE(i + 1, x, y);
+#define EXPAND_4_INNER_CASES(i, x, y)    EXPAND_2_INNER_CASES(i, x, y)    EXPAND_2_INNER_CASES(i + 2, x, y)
+#define EXPAND_8_INNER_CASES(i, x, y)    EXPAND_4_INNER_CASES(i, x, y)    EXPAND_4_INNER_CASES(i + 4, x, y)
+#define EXPAND_16_INNER_CASES(i, x, y)   EXPAND_8_INNER_CASES(i, x, y)    EXPAND_8_INNER_CASES(i + 8, x, y)
+#define EXPAND_32_INNER_CASES(i, x, y)   EXPAND_16_INNER_CASES(i, x, y)   EXPAND_16_INNER_CASES(i + 16, x, y)
+
+#define EXPAND_2_OUTER_CASES(i, x, y)    OUTER_CASE(i, x, y);             OUTER_CASE(i + 1, x, y);
+#define EXPAND_4_OUTER_CASES(i, x, y)    EXPAND_2_OUTER_CASES(i, x, y)    EXPAND_2_OUTER_CASES(i + 2, x, y)
+#define EXPAND_8_OUTER_CASES(i, x, y)    EXPAND_4_OUTER_CASES(i, x, y)    EXPAND_4_OUTER_CASES(i + 4, x, y)
+#define EXPAND_16_OUTER_CASES(i, x, y)   EXPAND_8_OUTER_CASES(i, x, y)    EXPAND_8_OUTER_CASES(i + 8, x, y)
+#define EXPAND_32_OUTER_CASES(i, x, y)   EXPAND_16_OUTER_CASES(i, x, y)   EXPAND_16_OUTER_CASES(i + 16, x, y)
+
+unsigned cfg_nested_vars(int x) {
+  int y = 0;
+  while (x > 0) {
+    EXPAND_32_VARS(a, x);
+    switch (x) {
+#define INNER_CASE(i, x, y) \
+          case i: { \
+            int case_var = 3*x + i; \
+            EXPAND_32_VARS(c, case_var); \
+            y += case_var - 1; \
+            break; \
+          }
+#define OUTER_CASE(i, x, y) \
+      case i: { \
+        int case_var = y >> 8; \
+        EXPAND_32_VARS(b, y); \
+        switch (case_var) { \
+          EXPAND_32_INNER_CASES(0, x, y); \
+        } \
+        break; \
+      }
+EXPAND_32_OUTER_CASES(0, x, y);
+    }
+    --x;
+  }
+  return y;
+}
diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h
index d395e0078a18f161207198bb5a79707083814dfd..f380012080d5e418621ca6db4b60f1a1e441beaf 100644
--- a/include/clang/Analysis/CFG.h
+++ b/include/clang/Analysis/CFG.h
@@ -506,6 +506,10 @@ public:
     Elements.push_back(CFGTemporaryDtor(E), C);
   }
 
+  void appendAutomaticObjDtor(VarDecl *VD, Stmt *S, BumpVectorContext &C) {
+    Elements.push_back(CFGAutomaticObjDtor(VD, S), C);
+  }
+
   // Destructors must be inserted in reversed order. So insertion is in two
   // steps. First we prepare space for some number of elements, then we insert
   // the elements beginning at the last position in prepared space.
diff --git a/lib/Analysis/CFG.cpp b/lib/Analysis/CFG.cpp
index d385420a56770e3211df6461996995646bea2c7a..69399f3bcd36107e0acc28daadcff7ed1252ff2c 100644
--- a/lib/Analysis/CFG.cpp
+++ b/lib/Analysis/CFG.cpp
@@ -413,11 +413,10 @@ private:
   void appendTemporaryDtor(CFGBlock *B, CXXBindTemporaryExpr *E) {
     B->appendTemporaryDtor(E, cfg->getBumpVectorContext());
   }
+  void appendAutomaticObjDtor(CFGBlock *B, VarDecl *VD, Stmt *S) {
+    B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());
+  }
 
-  void insertAutomaticObjDtors(CFGBlock *Blk, CFGBlock::iterator I,
-    LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt *S);
-  void appendAutomaticObjDtors(CFGBlock *Blk, LocalScope::const_iterator B,
-      LocalScope::const_iterator E, Stmt *S);
   void prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk,
       LocalScope::const_iterator B, LocalScope::const_iterator E);
 
@@ -647,8 +646,40 @@ void CFGBuilder::addAutomaticObjDtors(LocalScope::const_iterator B,
   if (B == E)
     return;
 
-  autoCreateBlock();
-  appendAutomaticObjDtors(Block, B, E, S);
+  CFGBlock::iterator InsertPos;
+
+  // We need to append the destructors in reverse order, but any one of them
+  // may be a no-return destructor which changes the CFG. As a result, buffer
+  // this sequence up and replay them in reverse order when appending onto the
+  // CFGBlock(s).
+  SmallVector<VarDecl*, 10> Decls;
+  Decls.reserve(B.distance(E));
+  for (LocalScope::const_iterator I = B; I != E; ++I)
+    Decls.push_back(*I);
+
+  for (SmallVectorImpl<VarDecl*>::reverse_iterator I = Decls.rbegin(),
+                                                   E = Decls.rend();
+       I != E; ++I) {
+    // If this destructor is marked as a no-return destructor, we need to
+    // create a new block for the destructor which does not have as a successor
+    // anything built thus far: control won't flow out of this block.
+    QualType Ty = (*I)->getType().getNonReferenceType();
+    if (const ArrayType *AT = Context->getAsArrayType(Ty))
+      Ty = AT->getElementType();
+    const CXXDestructorDecl *Dtor = Ty->getAsCXXRecordDecl()->getDestructor();
+    if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr()) {
+      Block = createBlock(/*add_successor=*/false);
+      // Wire up this block directly to the exit block if we're in the
+      // no-return case. We pruned any other successors because control flow
+      // won't actually exit this block, but we want to be able to find all of
+      // these entries in the CFG when doing analyses.
+      addSuccessor(Block, &cfg->getExit());
+    } else {
+      autoCreateBlock();
+    }
+
+    appendAutomaticObjDtor(Block, *I, S);
+  }
 }
 
 /// addImplicitDtorsForDestructor - Add implicit destructors generated for
@@ -807,34 +838,21 @@ void CFGBuilder::addLocalScopeAndDtors(Stmt *S) {
   addAutomaticObjDtors(ScopePos, scopeBeginPos, S);
 }
 
-/// insertAutomaticObjDtors - Insert destructor CFGElements for variables with
-/// automatic storage duration to CFGBlock's elements vector. Insertion will be
-/// performed in place specified with iterator.
-void CFGBuilder::insertAutomaticObjDtors(CFGBlock *Blk, CFGBlock::iterator I,
-    LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt *S) {
-  BumpVectorContext &C = cfg->getBumpVectorContext();
-  I = Blk->beginAutomaticObjDtorsInsert(I, B.distance(E), C);
-  while (B != E)
-    I = Blk->insertAutomaticObjDtor(I, *B++, S);
-}
-
-/// appendAutomaticObjDtors - Append destructor CFGElements for variables with
-/// automatic storage duration to CFGBlock's elements vector. Elements will be
-/// appended to physical end of the vector which happens to be logical
-/// beginning.
-void CFGBuilder::appendAutomaticObjDtors(CFGBlock *Blk,
-    LocalScope::const_iterator B, LocalScope::const_iterator E, Stmt *S) {
-  insertAutomaticObjDtors(Blk, Blk->begin(), B, E, S);
-}
-
 /// prependAutomaticObjDtorsWithTerminator - Prepend destructor CFGElements for
 /// variables with automatic storage duration to CFGBlock's elements vector.
 /// Elements will be prepended to physical beginning of the vector which
 /// happens to be logical end. Use blocks terminator as statement that specifies
 /// destructors call site.
+/// FIXME: This mechanism for adding automatic destructors doesn't handle
+/// no-return destructors properly.
 void CFGBuilder::prependAutomaticObjDtorsWithTerminator(CFGBlock *Blk,
     LocalScope::const_iterator B, LocalScope::const_iterator E) {
-  insertAutomaticObjDtors(Blk, Blk->end(), B, E, Blk->getTerminator());
+  BumpVectorContext &C = cfg->getBumpVectorContext();
+  CFGBlock::iterator InsertPos
+    = Blk->beginAutomaticObjDtorsInsert(Blk->end(), B.distance(E), C);
+  for (LocalScope::const_iterator I = B; I != E; ++I)
+    InsertPos = Blk->insertAutomaticObjDtor(InsertPos, *I,
+                                            Blk->getTerminator());
 }
 
 /// Visit - Walk the subtree of a statement and add extra
@@ -2861,7 +2879,22 @@ CFGBlock *CFGBuilder::VisitCXXBindTemporaryExprForTemporaryDtors(
   if (!BindToTemporary) {
     // If lifetime of temporary is not prolonged (by assigning to constant
     // reference) add destructor for it.
-    autoCreateBlock();
+
+    // If the destructor is marked as a no-return destructor, we need to create
+    // a new block for the destructor which does not have as a successor
+    // anything built thus far. Control won't flow out of this block.
+    const CXXDestructorDecl *Dtor = E->getTemporary()->getDestructor();
+    if (cast<FunctionType>(Dtor->getType())->getNoReturnAttr()) {
+      Block = createBlock(/*add_successor=*/false);
+      // Wire up this block directly to the exit block if we're in the
+      // no-return case. We pruned any other successors because control flow
+      // won't actually exit this block, but we want to be able to find all of
+      // these entries in the CFG when doing analyses.
+      addSuccessor(Block, &cfg->getExit());
+    } else {
+      autoCreateBlock();
+    }
+
     appendTemporaryDtor(Block, E);
     B = Block;
   }
diff --git a/test/SemaCXX/return-noreturn.cpp b/test/SemaCXX/return-noreturn.cpp
index 1a10c2aa1687cbb81649c6b10ff804b5303a8a91..2109efc19eb8d12dbc19b1af95a44cadc9be5aef 100644
--- a/test/SemaCXX/return-noreturn.cpp
+++ b/test/SemaCXX/return-noreturn.cpp
@@ -8,6 +8,8 @@ struct pr6884_abort_struct {
   ~pr6884_abort_struct() __attribute__((noreturn)) { pr6884_abort(); }
 };
 
+struct other { ~other() {} };
+
 // Ensure that destructors from objects are properly modeled in the CFG despite
 // the presence of switches, case statements, labels, and blocks. These tests
 // try to cover bugs reported in both PR6884 and PR10063.
@@ -37,9 +39,63 @@ namespace abort_struct_complex_cfgs {
     switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
   }
 
-  int h(int x) {
+  // Test that these constructs work even when extraneous blocks are created
+  // before and after the switch due to implicit destructors.
+  int g1(int x) {
+    other o;
+    switch (x) default: pr6884_abort_struct();
+  }
+  int g2(int x) {
+    other o;
+    switch (x) { default: pr6884_abort_struct(); }
+  }
+  int g2_positive(int x) {
+    other o;
+    switch (x) { default: ; }
+  } // expected-warning {{control reaches end of non-void function}}
+  int g3(int x) {
+    other o;
+    switch (x) { default: { pr6884_abort_struct(); } }
+  }
+  int g4(int x) {
+    other o;
+    switch (x) default: L1: L2: case 4: pr6884_abort_struct();
+  }
+  int g5(int x) {
+    other o;
+    switch (x) default: L1: { L2: case 4: pr6884_abort_struct(); }
+  }
+  int g6(int x) {
+    other o;
+    switch (x) default: L1: L2: case 4: { pr6884_abort_struct(); }
+  }
+
+  // Test that these constructs work even with variables carrying the no-return
+  // destructor instead of temporaries.
+  int h1(int x) {
+    other o;
+    switch (x) default: pr6884_abort_struct a;
+  }
+  int h2(int x) {
+    other o;
+    switch (x) { default: pr6884_abort_struct a; }
+  }
+  int h3(int x) {
+    other o;
     switch (x) { default: { pr6884_abort_struct a; } }
   }
+  int h4(int x) {
+    other o;
+    switch (x) default: L1: L2: case 4: pr6884_abort_struct a;
+  }
+  int h5(int x) {
+    other o;
+    switch (x) default: L1: { L2: case 4: pr6884_abort_struct a; }
+  }
+  int h6(int x) {
+    other o;
+    switch (x) default: L1: L2: case 4: { pr6884_abort_struct a; }
+  }
 }
 
 // PR9380