Index: test/tools/llvm-ar/Inputs/a-plus-b.a
===================================================================
--- /dev/null
+++ test/tools/llvm-ar/Inputs/a-plus-b.a
@@ -0,0 +1,6 @@
+!<thin>
+//                                              14        `
+a.txt/
+b.txt/
+/0              0           0     0     644     11        `
+/7              0           0     0     644     11        `
Index: test/tools/llvm-ar/Inputs/a.txt
===================================================================
--- /dev/null
+++ test/tools/llvm-ar/Inputs/a.txt
@@ -0,0 +1 @@
+a-contents
Index: test/tools/llvm-ar/Inputs/b.txt
===================================================================
--- /dev/null
+++ test/tools/llvm-ar/Inputs/b.txt
@@ -0,0 +1 @@
+b-contents
Index: test/tools/llvm-ar/Inputs/c.txt
===================================================================
--- /dev/null
+++ test/tools/llvm-ar/Inputs/c.txt
@@ -0,0 +1 @@
+c-contents
Index: test/tools/llvm-ar/Inputs/d.txt
===================================================================
--- /dev/null
+++ test/tools/llvm-ar/Inputs/d.txt
@@ -0,0 +1 @@
+d-contents
Index: test/tools/llvm-ar/Inputs/nested-thin-archive.a
===================================================================
--- /dev/null
+++ test/tools/llvm-ar/Inputs/nested-thin-archive.a
@@ -0,0 +1,7 @@
+!<thin>
+//                                              20        `
+a-plus-b.a/
+c.txt/
+
+/0              0           0     0     644     202       `
+/12             0           0     0     644     11        `
Index: test/tools/llvm-ar/flatten-thin-archive-recursive.test
===================================================================
--- /dev/null
+++ test/tools/llvm-ar/flatten-thin-archive-recursive.test
@@ -0,0 +1,13 @@
+# Since llvm-ar cannot create thin archives that contain any thin archives,
+# nested-thin-archive.a is a manually constructed thin archive that contains
+# another (unflattened) thin archive.
+# This test ensures that flat archives are recursively flattened.
+
+RUN: rm -f %t.a
+RUN: llvm-ar rcsT %t.a %S/Inputs/nested-thin-archive.a %S/Inputs/d.txt
+RUN: llvm-ar t %t.a | FileCheck %s
+
+CHECK:      a.txt
+CHECK-NEXT: b.txt
+CHECK-NEXT: c.txt
+CHECK-NEXT: d.txt
Index: test/tools/llvm-ar/flatten-thin-archive.test
===================================================================
--- /dev/null
+++ test/tools/llvm-ar/flatten-thin-archive.test
@@ -0,0 +1,18 @@
+# This test creates a thin archive that contains a thin archive, a regular
+# archive, and a file.
+#
+# The inner thin archive should be flattened, but the regular archive should
+# not. The order of members in the archive should match the input order, with
+# flattened members appearing together.
+
+RUN: touch %t-a.txt %t-b.txt %t-c.txt %t-d.txt %t-e.txt
+RUN: rm -f %t-a-plus-b.a %t.a
+RUN: llvm-ar rcsT %t-a-plus-b.a %t-a.txt %t-b.txt
+RUN: llvm-ar rcs %t-d-plus-e.a %t-d.txt %t-e.txt
+RUN: llvm-ar rcsT %t.a %t-a-plus-b.a %t-c.txt %t-d-plus-e.a
+RUN: llvm-ar t %t.a | FileCheck %s
+
+CHECK:      a.txt
+CHECK-NEXT: b.txt
+CHECK-NEXT: c.txt
+CHECK-NEXT: -d-plus-e.a
Index: tools/llvm-ar/llvm-ar.cpp
===================================================================
--- tools/llvm-ar/llvm-ar.cpp
+++ tools/llvm-ar/llvm-ar.cpp
@@ -536,52 +536,53 @@
   exit(1);
 }
 
-static void addMember(std::vector<NewArchiveMember> &Members,
-                      StringRef FileName, int Pos = -1) {
-  Expected<NewArchiveMember> NMOrErr =
-      NewArchiveMember::getFile(FileName, Deterministic);
-  failIfError(NMOrErr.takeError(), FileName);
-
-  // Use the basename of the object path for the member name.
-  NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
-
-  if (Pos == -1)
-    Members.push_back(std::move(*NMOrErr));
-  else
-    Members[Pos] = std::move(*NMOrErr);
-}
-
-static void addMember(std::vector<NewArchiveMember> &Members,
-                      const object::Archive::Child &M, int Pos = -1) {
+static void addChildMember(std::vector<NewArchiveMember> &Members,
+                           const object::Archive::Child &M,
+                           bool FlattenArchive = false) {
   if (Thin && !M.getParent()->isThin())
     fail("Cannot convert a regular archive to a thin one");
   Expected<NewArchiveMember> NMOrErr =
       NewArchiveMember::getOldMember(M, Deterministic);
   failIfError(NMOrErr.takeError());
-  if (Pos == -1)
-    Members.push_back(std::move(*NMOrErr));
-  else
-    Members[Pos] = std::move(*NMOrErr);
+  if (FlattenArchive &&
+      identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
+    Expected<StringRef> FileNameOrErr = M.getName();
+    failIfError(FileNameOrErr.takeError());
+    object::Archive &Lib = readLibrary(*FileNameOrErr);
+    // When creating thin archives, only flatten if the member is also thin.
+    if (!Thin || Lib.isThin()) {
+      Error Err = Error::success();
+      // Only Thin archives are recursively flattened.
+      for (auto &Child : Lib.children(Err))
+        addChildMember(Members, Child, /*FlattenArchive=*/Thin);
+      failIfError(std::move(Err));
+      return;
+    }
+  }
+  Members.push_back(std::move(*NMOrErr));
 }
 
-static void addLibMember(std::vector<NewArchiveMember> &Members,
-                         StringRef FileName) {
+static void addMember(std::vector<NewArchiveMember> &Members,
+                      StringRef FileName, bool FlattenArchive = false) {
   Expected<NewArchiveMember> NMOrErr =
       NewArchiveMember::getFile(FileName, Deterministic);
   failIfError(NMOrErr.takeError(), FileName);
-  if (identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
+  if (FlattenArchive &&
+      identify_magic(NMOrErr->Buf->getBuffer()) == file_magic::archive) {
     object::Archive &Lib = readLibrary(FileName);
-    Error Err = Error::success();
-
-    for (auto &Child : Lib.children(Err))
-      addMember(Members, Child);
-
-    failIfError(std::move(Err));
-  } else {
-    // Use the basename of the object path for the member name.
-    NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
-    Members.push_back(std::move(*NMOrErr));
+    // When creating thin archives, only flatten if the member is also thin.
+    if (!Thin || Lib.isThin()) {
+      Error Err = Error::success();
+      // Only Thin archives are recursively flattened.
+      for (auto &Child : Lib.children(Err))
+        addChildMember(Members, Child, /*FlattenArchive=*/Thin);
+      failIfError(std::move(Err));
+      return;
+    }
   }
+  // Use the basename of the object path for the member name.
+  NMOrErr->MemberName = sys::path::filename(NMOrErr->MemberName);
+  Members.push_back(std::move(*NMOrErr));
 }
 
 enum InsertAction {
@@ -670,7 +671,7 @@
           computeInsertAction(Operation, Child, Name, MemberI);
       switch (Action) {
       case IA_AddOldMember:
-        addMember(Ret, Child);
+        addChildMember(Ret, Child);
         break;
       case IA_AddNewMember:
         addMember(Ret, *MemberI);
@@ -678,7 +679,7 @@
       case IA_Delete:
         break;
       case IA_MoveOldMember:
-        addMember(Moved, Child);
+        addChildMember(Moved, Child);
         break;
       case IA_MoveNewMember:
         addMember(Moved, *MemberI);
@@ -709,17 +710,16 @@
   if (AddLibrary) {
     assert(Operation == QuickAppend);
     for (auto &Member : Members)
-      addLibMember(Ret, Member);
+      addMember(Ret, Member, /*FlattenArchive=*/true);
     return Ret;
   }
 
-  for (unsigned I = 0; I != Members.size(); ++I)
-    Ret.insert(Ret.begin() + InsertPos, NewArchiveMember());
-  Pos = InsertPos;
-  for (auto &Member : Members) {
-    addMember(Ret, Member, Pos);
-    ++Pos;
-  }
+  std::vector<NewArchiveMember> NewMembers;
+  for (auto &Member : Members)
+    addMember(NewMembers, Member, /*FlattenArchive=*/Thin);
+  Ret.reserve(Ret.size() + NewMembers.size());
+  std::move(NewMembers.begin(), NewMembers.end(),
+            std::inserter(Ret, std::next(Ret.begin(), InsertPos)));
 
   return Ret;
 }
@@ -897,7 +897,7 @@
       {
         Error Err = Error::success();
         for (auto &Member : Lib.children(Err))
-          addMember(NewMembers, Member);
+          addChildMember(NewMembers, Member);
         failIfError(std::move(Err));
       }
       break;