Merge remote-tracking branch 'origin/swift-4.1-branch' into stable
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index 7a46d26..239017d 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -10499,6 +10499,36 @@
   SmallVector<CXXRecordDecl*, 4> DelayedDllExportClasses;
 
 private:
+  class SavePendingParsedClassStateRAII {
+  public:
+    SavePendingParsedClassStateRAII(Sema &S) : S(S) { swapSavedState(); }
+
+    ~SavePendingParsedClassStateRAII() {
+      assert(S.DelayedExceptionSpecChecks.empty() &&
+             "there shouldn't be any pending delayed exception spec checks");
+      assert(S.DelayedDefaultedMemberExceptionSpecs.empty() &&
+             "there shouldn't be any pending delayed defaulted member "
+             "exception specs");
+      assert(S.DelayedDllExportClasses.empty() &&
+             "there shouldn't be any pending delayed DLL export classes");
+      swapSavedState();
+    }
+
+  private:
+    Sema &S;
+    decltype(DelayedExceptionSpecChecks) SavedExceptionSpecChecks;
+    decltype(DelayedDefaultedMemberExceptionSpecs)
+        SavedDefaultedMemberExceptionSpecs;
+    decltype(DelayedDllExportClasses) SavedDllExportClasses;
+
+    void swapSavedState() {
+      SavedExceptionSpecChecks.swap(S.DelayedExceptionSpecChecks);
+      SavedDefaultedMemberExceptionSpecs.swap(
+          S.DelayedDefaultedMemberExceptionSpecs);
+      SavedDllExportClasses.swap(S.DelayedDllExportClasses);
+    }
+  };
+
   /// \brief Helper class that collects misaligned member designations and
   /// their location info for delayed diagnostics.
   struct MisalignedMember {
diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp
index f4f0c80..643e018 100644
--- a/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2030,12 +2030,11 @@
   bool MergeWithParentScope = !Instantiation->isDefinedOutsideFunctionOrMethod();
   LocalInstantiationScope Scope(*this, MergeWithParentScope);
 
-  // All dllexported classes created during instantiation should be fully
-  // emitted after instantiation completes. We may not be ready to emit any
-  // delayed classes already on the stack, so save them away and put them back
-  // later.
-  decltype(DelayedDllExportClasses) ExportedClasses;
-  std::swap(ExportedClasses, DelayedDllExportClasses);
+  // Some class state isn't processed immediately but delayed till class
+  // instantiation completes. We may not be ready to handle any delayed state
+  // already on the stack as it might correspond to a different class, so save
+  // it now and put it back later.
+  SavePendingParsedClassStateRAII SavedPendingParsedClassState(*this);
 
   // Pull attributes from the pattern onto the instantiation.
   InstantiateAttrs(TemplateArgs, Pattern, Instantiation);
@@ -2122,9 +2121,6 @@
   // default arg exprs for default constructors if necessary now.
   ActOnFinishCXXNonNestedClass(Instantiation);
 
-  // Put back the delayed exported classes that we moved out of the way.
-  std::swap(ExportedClasses, DelayedDllExportClasses);
-
   // Instantiate late parsed attributes, and attach them to their decls.
   // See Sema::InstantiateAttrs
   for (LateInstantiatedAttrVec::iterator I = LateAttrs.begin(),
diff --git a/lib/Sema/TreeTransform.h b/lib/Sema/TreeTransform.h
index 91da9f8..a8b4c7a 100644
--- a/lib/Sema/TreeTransform.h
+++ b/lib/Sema/TreeTransform.h
@@ -6585,8 +6585,7 @@
 
   // Rebuild the switch statement.
   StmtResult Switch
-    = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(),
-                                          S->getInit(), Cond);
+    = getDerived().RebuildSwitchStmtStart(S->getSwitchLoc(), Init.get(), Cond);
   if (Switch.isInvalid())
     return StmtError();
 
diff --git a/test/SemaCXX/cxx1z-init-statement-template.cpp b/test/SemaCXX/cxx1z-init-statement-template.cpp
new file mode 100644
index 0000000..cedd2c7
--- /dev/null
+++ b/test/SemaCXX/cxx1z-init-statement-template.cpp
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -std=c++1z -verify -emit-llvm-only %s
+// expected-no-diagnostics
+
+// rdar://problem/33888545
+template <unsigned int BUFFER_SIZE> class Buffer {};
+
+class A {
+public:
+  int status;
+};
+
+template <unsigned int N> A parse(Buffer<N> buffer);
+
+template<unsigned int N>
+void init_in_if(Buffer<N> buffer) {
+  if (A a = parse(buffer); a.status > 0) {
+  }
+}
+
+template<unsigned int N>
+void init_in_switch(Buffer<N> buffer) {
+  switch (A a = parse(buffer); a.status) {
+    default:
+      break;
+  }
+}
+
+void test() {
+  Buffer<10> buffer;
+  init_in_if(buffer);
+  init_in_switch(buffer);
+}
diff --git a/test/SemaTemplate/crash-unparsed-exception.cpp b/test/SemaTemplate/crash-unparsed-exception.cpp
index 1226b35..3137d3f 100644
--- a/test/SemaTemplate/crash-unparsed-exception.cpp
+++ b/test/SemaTemplate/crash-unparsed-exception.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify -fcxx-exceptions -fexceptions %s
+// expected-no-diagnostics
 
 struct A {
   virtual ~A();
@@ -11,7 +12,7 @@
     ~D() throw();
   };
   struct E : A {
-    D<int> d; //expected-error{{exception specification is not available until end of class definition}}
+    D<int> d;
   };
-  B<int> b; //expected-note{{in instantiation of template class 'B<int>' requested here}}
+  B<int> b;
 };
diff --git a/test/SemaTemplate/default-arguments-cxx0x.cpp b/test/SemaTemplate/default-arguments-cxx0x.cpp
index d9fa2b4..c24ed12 100644
--- a/test/SemaTemplate/default-arguments-cxx0x.cpp
+++ b/test/SemaTemplate/default-arguments-cxx0x.cpp
@@ -87,3 +87,30 @@
     A<1> m_target;
   };
 }
+
+// rdar://problem/34167492
+// Template B is instantiated during checking if defaulted A copy constructor
+// is constexpr. For this we check if S<int> copy constructor is constexpr. And
+// for this we check S constructor template with default argument that mentions
+// template B. In  turn, template instantiation triggers checking defaulted
+// members exception spec. The problem is that it checks defaulted members not
+// for instantiated class only, but all defaulted members so far. In this case
+// we try to check exception spec for A default constructor which requires
+// initializer for the field _a. But initializers are added after constexpr
+// check so we reject the code because cannot find _a initializer.
+namespace rdar34167492 {
+  template <typename T> struct B { using type = bool; };
+
+  template <typename T> struct S {
+    S() noexcept;
+
+    template <typename U, typename B<U>::type = true>
+    S(const S<U>&) noexcept;
+  };
+
+  class A {
+    A() noexcept = default;
+    A(const A&) noexcept = default;
+    S<int> _a{};
+  };
+}