diff --git a/lld/test/MachO/Inputs/libStubLink.tbd b/lld/test/MachO/Inputs/libStubLink.tbd
--- a/lld/test/MachO/Inputs/libStubLink.tbd
+++ b/lld/test/MachO/Inputs/libStubLink.tbd
@@ -22,3 +22,4 @@
 exports:
   - targets:         [ arm64-ios-simulator ]
     symbols:         [ _arm64_sim_only ]
+...
diff --git a/lld/test/MachO/invalid/invalid-stub.s b/lld/test/MachO/invalid/invalid-stub.s
--- a/lld/test/MachO/invalid/invalid-stub.s
+++ b/lld/test/MachO/invalid/invalid-stub.s
@@ -7,9 +7,8 @@
 # RUN: not %lld -L%t -linvalidYAML %t/test.o -o %t/test 2>&1 | FileCheck %s -DDIR=%t
 # RUN: not %lld -F%t -framework invalidYAML %t/test.o -o %t/test 2>&1 | FileCheck %s -DDIR=%t --check-prefix=CHECK-FRAMEWORK
 
-# CHECK: could not load TAPI file at [[DIR]]{{[\\/]}}libinvalidYAML.tbd: malformed file
-# CHECK-FRAMEWORK: could not load TAPI file at [[DIR]]{{[\\/]}}invalidYAML.framework{{[\\/]}}invalidYAML.tbd: malformed file
-
+# CHECK: could not load TAPI file at [[DIR]]{{[\\/]}}libinvalidYAML.tbd: unsupported file type  
+# CHECK-FRAMEWORK: could not load TAPI file at [[DIR]]{{[\\/]}}invalidYAML.framework{{[\\/]}}invalidYAML.tbd: unsupported file type  
 .globl _main
 _main:
   ret
diff --git a/lld/test/MachO/tapi-link.s b/lld/test/MachO/tapi-link.s
--- a/lld/test/MachO/tapi-link.s
+++ b/lld/test/MachO/tapi-link.s
@@ -121,7 +121,6 @@
     re-exports: [ 'libNested.dylib' ]
 ...
 
-## This tests that weak and thread-local symbols are imported as such.
 #--- libTlvWeak.tbd
 --- !tapi-tbd
 tbd-version:      4
@@ -131,8 +130,8 @@
     value:        00000000-0000-0000-0000-000000000000
 install-name:     '/usr/lib/libTlvWeak.dylib'
 current-version:  0001.001.1
-exports:
+exports:                            # Validate weak & thread-local symbols 
   - targets:      [ x86_64-macos ]
     weak-symbols: [ _weak ]
     thread-local-symbols: [ _tlv ]
----
+...
diff --git a/llvm/include/llvm/TextAPI/InterfaceFile.h b/llvm/include/llvm/TextAPI/InterfaceFile.h
--- a/llvm/include/llvm/TextAPI/InterfaceFile.h
+++ b/llvm/include/llvm/TextAPI/InterfaceFile.h
@@ -66,6 +66,9 @@
   /// Text-based stub file (.tbd) version 4.0
   TBD_V4  = 1U <<  3,
 
+  /// Text-based stub file (.tbd) version 5.0
+  TBD_V5  = 1U <<  4,
+
   All     = ~0U,
 
   LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/All),
diff --git a/llvm/lib/TextAPI/CMakeLists.txt b/llvm/lib/TextAPI/CMakeLists.txt
--- a/llvm/lib/TextAPI/CMakeLists.txt
+++ b/llvm/lib/TextAPI/CMakeLists.txt
@@ -2,6 +2,7 @@
   Architecture.cpp
   ArchitectureSet.cpp
   InterfaceFile.cpp
+  TextStubV5.cpp
   PackedVersion.cpp
   Platform.cpp
   Symbol.cpp
diff --git a/llvm/lib/TextAPI/TextStub.cpp b/llvm/lib/TextAPI/TextStub.cpp
--- a/llvm/lib/TextAPI/TextStub.cpp
+++ b/llvm/lib/TextAPI/TextStub.cpp
@@ -258,16 +258,6 @@
   UUIDv4(const Target &TargetID, const std::string &Value)
       : TargetID(TargetID), Value(Value) {}
 };
-
-// clang-format off
-enum TBDFlags : unsigned {
-  None                         = 0U,
-  FlatNamespace                = 1U << 0,
-  NotApplicationExtensionSafe  = 1U << 1,
-  InstallAPI                   = 1U << 2,
-  LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
-};
-// clang-format on
 } // end anonymous namespace.
 
 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(Architecture)
@@ -1105,10 +1095,49 @@
   File->ErrorMessage = ("malformed file\n" + Message).str();
 }
 
+namespace {
+
+Expected<FileType> canReadFileType(MemoryBufferRef InputBuffer) {
+  auto TAPIFile = InputBuffer.getBuffer().trim();
+  if (TAPIFile.startswith("{") && TAPIFile.endswith("}"))
+    return FileType::TBD_V5;
+
+  if (!TAPIFile.endswith("..."))
+    return createStringError(std::errc::not_supported, "unsupported file type");
+
+  if (TAPIFile.startswith("--- !tapi-tbd\n"))
+    return FileType::TBD_V4;
+
+  if (TAPIFile.startswith("--- !tapi-tbd-v3\n"))
+    return FileType::TBD_V3;
+
+  if (TAPIFile.startswith("--- !tapi-tbd-v2\n"))
+    return FileType::TBD_V2;
+
+  if (TAPIFile.startswith("--- !tapi-tbd-v1\n") ||
+      TAPIFile.startswith("---\narchs:"))
+    return FileType::TBD_V1;
+
+  return createStringError(std::errc::not_supported, "unsupported file type");
+}
+} // namespace
+
 Expected<std::unique_ptr<InterfaceFile>>
 TextAPIReader::get(MemoryBufferRef InputBuffer) {
   TextAPIContext Ctx;
   Ctx.Path = std::string(InputBuffer.getBufferIdentifier());
+  if (auto FTOrErr = canReadFileType(InputBuffer))
+    Ctx.FileKind = *FTOrErr;
+  else
+    return FTOrErr.takeError();
+
+  // Handle JSON Format.
+  if (Ctx.FileKind >= FileType::TBD_V5) {
+    auto FileOrErr = getInterfaceFileFromJSON(InputBuffer.getBuffer());
+    if (!FileOrErr)
+      return FileOrErr.takeError();
+    return std::move(*FileOrErr);
+  }
   yaml::Input YAMLIn(InputBuffer.getBuffer(), &Ctx, DiagHandler, &Ctx);
 
   // Fill vector with interface file objects created by parsing the YAML file.
diff --git a/llvm/lib/TextAPI/TextStubCommon.h b/llvm/lib/TextAPI/TextStubCommon.h
--- a/llvm/lib/TextAPI/TextStubCommon.h
+++ b/llvm/lib/TextAPI/TextStubCommon.h
@@ -22,6 +22,16 @@
 
 using UUID = std::pair<llvm::MachO::Target, std::string>;
 
+// clang-format off
+enum TBDFlags : unsigned {
+  None                         = 0U,
+  FlatNamespace                = 1U << 0,
+  NotApplicationExtensionSafe  = 1U << 1,
+  InstallAPI                   = 1U << 2,
+  LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/InstallAPI),
+};
+// clang-format on
+
 LLVM_YAML_STRONG_TYPEDEF(llvm::StringRef, FlowStringRef)
 LLVM_YAML_STRONG_TYPEDEF(uint8_t, SwiftVersion)
 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(UUID)
@@ -30,9 +40,13 @@
 namespace llvm {
 
 namespace MachO {
-    class ArchitectureSet;
-    class PackedVersion;
-}
+class ArchitectureSet;
+class PackedVersion;
+
+Expected<std::unique_ptr<InterfaceFile>>
+getInterfaceFileFromJSON(StringRef JSON);
+} // namespace MachO
+
 namespace yaml {
 
 template <> struct ScalarTraits<FlowStringRef> {
diff --git a/llvm/lib/TextAPI/TextStubV5.cpp b/llvm/lib/TextAPI/TextStubV5.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/lib/TextAPI/TextStubV5.cpp
@@ -0,0 +1,636 @@
+#include "TextStubCommon.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/JSON.h"
+
+using namespace llvm;
+using namespace llvm::json;
+using namespace llvm::MachO;
+
+struct JSONSymbol {
+  SymbolKind Kind;
+  std::string Name;
+  SymbolFlags Flags;
+  bool Data;
+};
+
+using AttrToTargets = std::map<std::string, TargetList>;
+using TargetsToSymbols =
+    SmallVector<std::pair<TargetList, std::vector<JSONSymbol>>>;
+
+enum TBDKey : size_t {
+  TBDVersion = 0U,
+  Document,
+  TargetInfo,
+  Targets,
+  Target,
+  Deployment,
+  Flags,
+  Attributes,
+  InstallName,
+  CurrentVersion,
+  CompatibilityVersion,
+  Version,
+  SwiftABI,
+  ABI,
+  ParentUmbrella,
+  Umbrella,
+  AllowableClients,
+  Clients,
+  ReexportLibs,
+  Names,
+  Name,
+  Exports,
+  Reexports,
+  Undefineds,
+  Data,
+  Text,
+  Weak,
+  ThreadLocal,
+  Globals,
+  ObjCClass,
+  ObjCEHType,
+  ObjCIvar,
+};
+
+std::array<StringRef, 64> Keys = {
+    "tapi_tbd_version",
+    "files",
+    "target_info",
+    "targets",
+    "target",
+    "min_deployment",
+    "flags",
+    "attributes",
+    "install_names",
+    "current_versions",
+    "compatibility_versions",
+    "version",
+    "swift_abi",
+    "abi",
+    "parent_umbrellas",
+    "umbrella",
+    "allowable_clients",
+    "clients",
+    "reexported_libraries",
+    "names",
+    "name",
+    "exported_symbols",
+    "reexported_symbols",
+    "undefined_symbols",
+    "data",
+    "text",
+    "weak",
+    "thread_local",
+    "globals",
+    "objc_classes",
+    "objc_eh_types",
+    "objc_ivars",
+};
+
+static llvm::SmallString<128> getErrorMsg(TBDKey Key) {
+  return {"invalid ", Keys[Key], " section"};
+}
+
+class JSONStubError : public llvm::ErrorInfo<llvm::json::ParseError> {
+public:
+  JSONStubError(Twine ErrMsg) : Message(ErrMsg.str()) {}
+
+  void log(llvm::raw_ostream &OS) const override { OS << Message << "\n"; }
+  std::error_code convertToErrorCode() const override {
+    return llvm::inconvertibleErrorCode();
+  }
+
+private:
+  std::string Message;
+};
+
+template <typename JsonT, typename StubT = JsonT>
+Expected<StubT> getRequiredValue(
+    TBDKey Key, const Object *Obj,
+    std::function<std::optional<JsonT>(const Object *, StringRef)> GetValue,
+    std::function<std::optional<StubT>(JsonT)> Validate = nullptr) {
+  std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
+  if (!Val)
+    return make_error<JSONStubError>(getErrorMsg(Key));
+
+  if (Validate == nullptr)
+    return static_cast<StubT>(*Val);
+
+  std::optional<StubT> Result = Validate(*Val);
+  if (!Result.has_value())
+    return make_error<JSONStubError>(getErrorMsg(Key));
+  return Result.value();
+}
+
+template <typename JsonT, typename StubT = JsonT>
+Expected<StubT> getRequiredValue(
+    TBDKey Key, const Object *Obj,
+    std::function<std::optional<JsonT>(const Object *, StringRef)> GetValue,
+    StubT DefaultValue, std::function<std::optional<StubT>(JsonT)> Validate) {
+  std::optional<JsonT> Val = GetValue(Obj, Keys[Key]);
+  if (!Val)
+    return DefaultValue;
+
+  std::optional<StubT> Result;
+  Result = Validate(*Val);
+  if (!Result.has_value())
+    return make_error<JSONStubError>(getErrorMsg(Key));
+  return Result.value();
+}
+
+Error collectFromArray(TBDKey Key, const Object *Obj,
+                       std::function<void(StringRef)> Append,
+                       bool IsRequired = false) {
+  const auto *Values = Obj->getArray(Keys[Key]);
+  if (!Values) {
+    if (IsRequired)
+      return make_error<JSONStubError>(getErrorMsg(Key));
+    return Error::success();
+  }
+
+  for (Value Val : *Values) {
+    auto ValStr = Val.getAsString();
+    if (!ValStr.has_value())
+      return make_error<JSONStubError>(getErrorMsg(Key));
+    Append(ValStr.value());
+  }
+
+  return Error::success();
+}
+
+namespace StubParser {
+
+Expected<FileType> getVersion(const Object *File) {
+  auto VersionOrErr = getRequiredValue<int64_t, FileType>(
+      TBDKey::TBDVersion, File, &Object::getInteger,
+      [](int64_t Val) -> std::optional<FileType> {
+        unsigned Result = Val;
+        if (Result != 5)
+          return std::nullopt;
+        return FileType::TBD_V5;
+      });
+
+  if (!VersionOrErr)
+    return VersionOrErr.takeError();
+  return *VersionOrErr;
+}
+
+Expected<TargetList> getTargets(const Object *Section) {
+  const auto *Targets = Section->getArray(Keys[TBDKey::Targets]);
+  if (!Targets)
+    return make_error<JSONStubError>(getErrorMsg(TBDKey::Targets));
+
+  TargetList IFTargets;
+  for (Value JSONTarget : *Targets) {
+    auto TargetStr = JSONTarget.getAsString();
+    if (!TargetStr.has_value())
+      return make_error<JSONStubError>(getErrorMsg(TBDKey::Target));
+    auto TargetOrErr = Target::create(TargetStr.value());
+    if (!TargetOrErr)
+      return make_error<JSONStubError>(getErrorMsg(TBDKey::Target));
+    IFTargets.push_back(*TargetOrErr);
+  }
+  return IFTargets;
+}
+
+Expected<TargetList> getTargetsSection(const Object *Section) {
+  const Array *Targets = Section->getArray(Keys[TBDKey::TargetInfo]);
+  if (!Targets)
+    return make_error<JSONStubError>(getErrorMsg(TBDKey::Targets));
+
+  TargetList IFTargets;
+  for (const Value &JSONTarget : *Targets) {
+    const auto *Obj = JSONTarget.getAsObject();
+    if (!Obj)
+      return make_error<JSONStubError>(getErrorMsg(TBDKey::Target));
+    auto TargetStr =
+        getRequiredValue<StringRef>(TBDKey::Target, Obj, &Object::getString);
+    if (!TargetStr)
+      return make_error<JSONStubError>(getErrorMsg(TBDKey::Target));
+    auto TargetOrErr = Target::create(*TargetStr);
+    if (!TargetOrErr)
+      return make_error<JSONStubError>(getErrorMsg(TBDKey::Target));
+    IFTargets.push_back(*TargetOrErr);
+    // TODO: Implement Deployment Version.
+  }
+  return IFTargets;
+}
+
+Error collectSymbolsFromSegment(const Object *Segment, TargetsToSymbols &Result,
+                                bool IsData, SymbolFlags SectionFlag) {
+  auto Err = collectFromArray(TBDKey::Globals, Segment,
+                              [&Result, IsData, &SectionFlag](StringRef Name) {
+                                JSONSymbol Sym = {SymbolKind::GlobalSymbol,
+                                                  Name.str(), SectionFlag,
+                                                  /*Data*/ IsData};
+                                Result.back().second.emplace_back(Sym);
+                              });
+  if (Err)
+    return Err;
+
+  Err = collectFromArray(TBDKey::ObjCClass, Segment,
+                         [&Result, IsData, &SectionFlag](StringRef Name) {
+                           JSONSymbol Sym = {SymbolKind::ObjectiveCClass,
+                                             Name.str(), SectionFlag,
+                                             /*Data*/ IsData};
+                           Result.back().second.emplace_back(Sym);
+                         });
+  if (Err)
+    return Err;
+
+  Err = collectFromArray(TBDKey::ObjCEHType, Segment,
+                         [&Result, IsData, &SectionFlag](StringRef Name) {
+                           JSONSymbol Sym = {SymbolKind::ObjectiveCClassEHType,
+                                             Name.str(), SectionFlag,
+                                             /*Data*/ IsData};
+                           Result.back().second.emplace_back(Sym);
+                         });
+  if (Err)
+    return Err;
+
+  Err = collectFromArray(TBDKey::ObjCIvar, Segment,
+                         [&Result, IsData, &SectionFlag](StringRef Name) {
+                           JSONSymbol Sym = {
+                               SymbolKind::ObjectiveCInstanceVariable,
+                               Name.str(), SectionFlag,
+                               /*Data*/ IsData};
+                           Result.back().second.emplace_back(Sym);
+                         });
+  if (Err)
+    return Err;
+
+  SymbolFlags WeakFlag = SectionFlag | (SectionFlag == SymbolFlags::Undefined
+                                            ? SymbolFlags::WeakReferenced
+                                            : SymbolFlags::WeakDefined);
+  Err = collectFromArray(
+      TBDKey::Weak, Segment, [&Result, IsData, WeakFlag](StringRef Name) {
+        JSONSymbol Sym = {SymbolKind::GlobalSymbol, Name.str(), WeakFlag,
+                          /*Data*/ IsData};
+        Result.back().second.emplace_back(Sym);
+      });
+  if (Err)
+    return Err;
+
+  Err = collectFromArray(TBDKey::ThreadLocal, Segment,
+                         [&Result, IsData, SectionFlag](StringRef Name) {
+                           JSONSymbol Sym = {
+                               SymbolKind::GlobalSymbol, Name.str(),
+                               SymbolFlags::ThreadLocalValue | SectionFlag,
+                               /*Data*/ IsData};
+                           Result.back().second.emplace_back(Sym);
+                         });
+  if (Err)
+    return Err;
+
+  return Error::success();
+}
+
+Expected<StringRef> getNameSection(const Object *File) {
+  const Array *Section = File->getArray(Keys[TBDKey::InstallName]);
+  if (!Section)
+    return make_error<JSONStubError>(getErrorMsg(TBDKey::InstallName));
+
+  assert(!Section->empty() && "unexpected missing install name");
+  // TODO: Just take first for now.
+  const auto *Obj = Section->front().getAsObject();
+  if (!Obj)
+    return make_error<JSONStubError>(getErrorMsg(TBDKey::InstallName));
+
+  return getRequiredValue<StringRef>(TBDKey::Name, Obj, &Object::getString);
+}
+
+Expected<TargetsToSymbols> getSymbolSection(const Object *File, TBDKey Key) {
+
+  const Array *Section = File->getArray(Keys[Key]);
+  if (!Section)
+    return TargetsToSymbols();
+
+  SymbolFlags SectionFlag;
+  switch (Key) {
+  case TBDKey::Reexports:
+    SectionFlag = SymbolFlags::Rexported;
+    break;
+  case TBDKey::Undefineds:
+    SectionFlag = SymbolFlags::Undefined;
+    break;
+  default:
+    SectionFlag = SymbolFlags::None;
+    break;
+  };
+
+  TargetsToSymbols Result;
+  for (auto Val : *Section) {
+    auto *Obj = Val.getAsObject();
+    if (!Obj)
+      continue;
+
+    auto TargetsOrErr = getTargets(Obj);
+    if (!TargetsOrErr)
+      return TargetsOrErr.takeError();
+    auto Targets = *TargetsOrErr;
+    Result.emplace_back(std::make_pair(Targets, std::vector<JSONSymbol>()));
+
+    auto *DataSection = Obj->getObject(Keys[TBDKey::Data]);
+    auto *TextSection = Obj->getObject(Keys[TBDKey::Text]);
+    // There should be at least one valid section.
+    if (!DataSection && !TextSection)
+      return make_error<JSONStubError>(getErrorMsg(Key));
+
+    if (DataSection) {
+      auto Err = collectSymbolsFromSegment(DataSection, Result, /*isData=*/true,
+                                           SectionFlag);
+      if (Err)
+        return Err;
+    }
+    if (TextSection) {
+      auto Err = collectSymbolsFromSegment(TextSection, Result,
+                                           /*isData=*/false, SectionFlag);
+      if (Err)
+        return Err;
+    }
+  }
+
+  return Result;
+}
+
+Expected<AttrToTargets> getLibSection(const Object *File, TBDKey Key,
+                                      TBDKey SubKey,
+                                      const TargetList &Targets) {
+  auto *Section = File->getArray(Keys[Key]);
+  if (!Section)
+    return AttrToTargets();
+
+  AttrToTargets Result;
+  TargetList MappedTargets;
+  for (auto Val : *Section) {
+    auto *Obj = Val.getAsObject();
+    if (!Obj)
+      continue;
+
+    auto TargetsOrErr = getTargets(Obj);
+    if (!TargetsOrErr) {
+      MappedTargets = Targets;
+      consumeError(TargetsOrErr.takeError());
+    } else {
+      MappedTargets = *TargetsOrErr;
+    }
+    auto Err =
+        collectFromArray(SubKey, Obj, [&Result, &MappedTargets](StringRef Key) {
+          Result[Key.str()] = MappedTargets;
+        });
+    if (Err)
+      return Err;
+  }
+
+  return Result;
+}
+
+Expected<AttrToTargets> getUmbrellaSection(const Object *File,
+                                           const TargetList &Targets) {
+  const auto *Umbrella = File->getArray(Keys[TBDKey::ParentUmbrella]);
+  if (!Umbrella)
+    return AttrToTargets();
+
+  AttrToTargets Result;
+  TargetList MappedTargets;
+  for (auto Val : *Umbrella) {
+    auto *Obj = Val.getAsObject();
+    if (!Obj)
+      return make_error<JSONStubError>(getErrorMsg(TBDKey::ParentUmbrella));
+
+    // Get Targets section.
+    auto TargetsOrErr = getTargets(Obj);
+    if (!TargetsOrErr) {
+      MappedTargets = Targets;
+      consumeError(TargetsOrErr.takeError());
+    } else {
+      MappedTargets = *TargetsOrErr;
+    }
+
+    auto UmbrellaOrErr =
+        getRequiredValue<StringRef>(TBDKey::Umbrella, Obj, &Object::getString);
+    if (!UmbrellaOrErr)
+      return UmbrellaOrErr.takeError();
+    Result[UmbrellaOrErr->str()] = Targets;
+  }
+  return Result;
+}
+
+Expected<uint8_t> getSwiftVersion(const Object *File) {
+  const Array *Versions = File->getArray(Keys[TBDKey::SwiftABI]);
+  if (!Versions)
+    return 0;
+
+  for (const auto &Val : *Versions) {
+    const auto *Obj = Val.getAsObject();
+    if (!Obj)
+      return make_error<JSONStubError>(getErrorMsg(TBDKey::SwiftABI));
+
+    // TODO: Take first for now.
+    return getRequiredValue<int64_t, uint8_t>(TBDKey::ABI, Obj,
+                                              &Object::getInteger);
+  }
+
+  return 0;
+}
+
+Expected<PackedVersion> getPackedVersion(const Object *File, TBDKey Key) {
+  const Array *Versions = File->getArray(Keys[Key]);
+  if (!Versions)
+    return PackedVersion(1, 0, 0);
+
+  for (const auto &Val : *Versions) {
+    const auto *Obj = Val.getAsObject();
+    if (!Obj)
+      return make_error<JSONStubError>(getErrorMsg(Key));
+
+    auto ValidatePV = [](StringRef Version) -> std::optional<PackedVersion> {
+      PackedVersion PV;
+      auto [success, truncated] = PV.parse64(Version);
+      if (!success || truncated)
+        return std::nullopt;
+      return PV;
+    };
+    // TODO: Take first for now.
+    return getRequiredValue<StringRef, PackedVersion>(
+        TBDKey::Version, Obj, &Object::getString, PackedVersion(1, 0, 0),
+        ValidatePV);
+  }
+
+  return PackedVersion(1, 0, 0);
+}
+
+Expected<TBDFlags> getFlags(const Object *File) {
+  TBDFlags Flags = TBDFlags::None;
+  const Array *Section = File->getArray(Keys[TBDKey::Flags]);
+  if (!Section)
+    return Flags;
+
+  for (auto &Val : *Section) {
+    // TODO: Just take first for now.
+    const auto *Obj = Val.getAsObject();
+    if (!Obj)
+      return make_error<JSONStubError>(getErrorMsg(TBDKey::Flags));
+
+    auto FlagsOrErr =
+        collectFromArray(TBDKey::Attributes, Obj, [&Flags](StringRef Flag) {
+          TBDFlags TBDFlag =
+              StringSwitch<TBDFlags>(Flag)
+                  .Case("flat_namespace", TBDFlags::FlatNamespace)
+                  .Case("not_app_extension_safe",
+                        TBDFlags::NotApplicationExtensionSafe)
+                  .Default(TBDFlags::None);
+          Flags |= TBDFlag;
+        });
+
+    if (FlagsOrErr)
+      return FlagsOrErr;
+
+    return Flags;
+  }
+
+  return Flags;
+}
+
+using IFPtr = std::unique_ptr<InterfaceFile>;
+Expected<IFPtr> parseToInterfaceFile(const Object *File) {
+  if (!File)
+    return make_error<JSONStubError>(getErrorMsg(TBDKey::Document));
+
+  auto TargetsOrErr = getTargetsSection(File);
+  if (!TargetsOrErr)
+    return TargetsOrErr.takeError();
+  TargetList Targets = *TargetsOrErr;
+
+  auto NameOrErr = getNameSection(File);
+  if (!NameOrErr)
+    return NameOrErr.takeError();
+  StringRef Name = *NameOrErr;
+
+  auto CurrVersionOrErr = getPackedVersion(File, TBDKey::CurrentVersion);
+  if (!CurrVersionOrErr)
+    return CurrVersionOrErr.takeError();
+  PackedVersion CurrVersion = *CurrVersionOrErr;
+
+  auto CompVersionOrErr = getPackedVersion(File, TBDKey::CompatibilityVersion);
+  if (!CompVersionOrErr)
+    return CompVersionOrErr.takeError();
+  PackedVersion CompVersion = *CompVersionOrErr;
+
+  auto SwiftABIOrErr = getSwiftVersion(File);
+  if (!SwiftABIOrErr)
+    return SwiftABIOrErr.takeError();
+  uint8_t SwiftABI = *SwiftABIOrErr;
+
+  auto FlagsOrErr = getFlags(File);
+  if (!FlagsOrErr)
+    return FlagsOrErr.takeError();
+  TBDFlags Flags = *FlagsOrErr;
+
+  auto UmbrellasOrErr = getUmbrellaSection(File, Targets);
+  if (!UmbrellasOrErr)
+    return UmbrellasOrErr.takeError();
+  AttrToTargets Umbrellas = *UmbrellasOrErr;
+
+  auto ClientsOrErr =
+      getLibSection(File, TBDKey::AllowableClients, TBDKey::Clients, Targets);
+  if (!ClientsOrErr)
+    return ClientsOrErr.takeError();
+  AttrToTargets Clients = *ClientsOrErr;
+
+  auto RLOrErr =
+      getLibSection(File, TBDKey::ReexportLibs, TBDKey::Names, Targets);
+  if (!RLOrErr)
+    return RLOrErr.takeError();
+  AttrToTargets ReexportLibs = std::move(*RLOrErr);
+
+  auto ExportsOrErr = getSymbolSection(File, TBDKey::Exports);
+  if (!ExportsOrErr)
+    return ExportsOrErr.takeError();
+  TargetsToSymbols Exports = std::move(*ExportsOrErr);
+
+  auto ReexportsOrErr = getSymbolSection(File, TBDKey::Reexports);
+  if (!ReexportsOrErr)
+    return ReexportsOrErr.takeError();
+  TargetsToSymbols Reexports = std::move(*ReexportsOrErr);
+
+  auto UndefinedsOrErr = getSymbolSection(File, TBDKey::Undefineds);
+  if (!UndefinedsOrErr)
+    return UndefinedsOrErr.takeError();
+  TargetsToSymbols Undefineds = std::move(*UndefinedsOrErr);
+
+  IFPtr F(new InterfaceFile);
+  F->setInstallName(Name);
+  F->setCurrentVersion(CurrVersion);
+  F->setCompatibilityVersion(CompVersion);
+  F->setSwiftABIVersion(SwiftABI);
+  F->setTwoLevelNamespace(!(Flags & TBDFlags::FlatNamespace));
+  F->setApplicationExtensionSafe(
+      !(Flags & TBDFlags::NotApplicationExtensionSafe));
+  for (auto &T : Targets)
+    F->addTarget(T);
+  for (auto &[Lib, Targets] : Clients)
+    for (auto Target : Targets)
+      F->addAllowableClient(Lib, Target);
+  for (auto &[Lib, Targets] : ReexportLibs)
+    for (auto Target : Targets)
+      F->addReexportedLibrary(Lib, Target);
+  for (auto &[Lib, Targets] : Umbrellas)
+    for (auto Target : Targets)
+      F->addParentUmbrella(Target, Lib);
+  for (auto &[Targets, Symbols] : Exports)
+    for (auto &Sym : Symbols)
+      F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
+  for (auto &[Targets, Symbols] : Reexports)
+    for (auto &Sym : Symbols)
+      F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
+  for (auto &[Targets, Symbols] : Undefineds)
+    for (auto &Sym : Symbols)
+      F->addSymbol(Sym.Kind, Sym.Name, Targets, Sym.Flags);
+
+  return F;
+}
+
+Expected<std::vector<IFPtr>> getFiles(const Object *File, FileType Type) {
+  const Array *Files = File->getArray(Keys[TBDKey::Document]);
+  if (!Files)
+    return make_error<JSONStubError>(getErrorMsg(TBDKey::Document));
+
+  std::vector<IFPtr> IFs;
+  for (auto Lib : *Files) {
+    auto IFOrErr = parseToInterfaceFile(Lib.getAsObject());
+    if (!IFOrErr)
+      return IFOrErr.takeError();
+    auto IF = std::move(*IFOrErr);
+    IF->setFileType(Type);
+    IFs.emplace_back(std::move(IF));
+  }
+  return IFs;
+}
+
+} // namespace StubParser
+
+Expected<std::unique_ptr<InterfaceFile>>
+MachO::getInterfaceFileFromJSON(StringRef JSON) {
+  auto ValOrErr = parse(JSON);
+  if (!ValOrErr)
+    return ValOrErr.takeError();
+
+  auto *Root = ValOrErr->getAsObject();
+  auto VersionOrErr = StubParser::getVersion(Root);
+  if (!VersionOrErr)
+    return VersionOrErr.takeError();
+  FileType Version = *VersionOrErr;
+
+  auto IFsOrErr = StubParser::getFiles(Root, Version);
+  if (!IFsOrErr)
+    return IFsOrErr.takeError();
+  auto IFs = std::move(*IFsOrErr);
+  assert(IFs.size() >= 1 && "expected at least one file");
+  std::unique_ptr<InterfaceFile> IF(std::move(IFs.front()));
+
+  for (auto &File : llvm::drop_begin(IFs))
+    IF->addDocument(std::shared_ptr<InterfaceFile>(std::move(File)));
+
+  return std::move(IF);
+}
diff --git a/llvm/test/Object/Inputs/tapi-v4-watchos.tbd b/llvm/test/Object/Inputs/tapi-v4-watchos.tbd
--- a/llvm/test/Object/Inputs/tapi-v4-watchos.tbd
+++ b/llvm/test/Object/Inputs/tapi-v4-watchos.tbd
@@ -11,3 +11,4 @@
 exports:
   - targets:              [ armv7k-watchos-simulator, arm64_32-watchos-simulator ]
     symbols:              [ '_sym1' ]
+...
diff --git a/llvm/test/tools/llvm-tapi-diff/Inputs/v4A.tbd b/llvm/test/tools/llvm-tapi-diff/Inputs/v4A.tbd
--- a/llvm/test/tools/llvm-tapi-diff/Inputs/v4A.tbd
+++ b/llvm/test/tools/llvm-tapi-diff/Inputs/v4A.tbd
@@ -47,3 +47,4 @@
     objc-ivars: []
     weak-symbols: []
     thread-local-symbols: []
+...
diff --git a/llvm/test/tools/llvm-tapi-diff/Inputs/v4B.tbd b/llvm/test/tools/llvm-tapi-diff/Inputs/v4B.tbd
--- a/llvm/test/tools/llvm-tapi-diff/Inputs/v4B.tbd
+++ b/llvm/test/tools/llvm-tapi-diff/Inputs/v4B.tbd
@@ -53,3 +53,4 @@
     weak-symbols:    [ _symC ]
   - targets:         [ x86_64-ios-simulator ]
     symbols:         [ _symB ]
+...
diff --git a/llvm/test/tools/llvm-tapi-diff/Inputs/v4C.tbd b/llvm/test/tools/llvm-tapi-diff/Inputs/v4C.tbd
--- a/llvm/test/tools/llvm-tapi-diff/Inputs/v4C.tbd
+++ b/llvm/test/tools/llvm-tapi-diff/Inputs/v4C.tbd
@@ -47,3 +47,4 @@
     objc-ivars: []
     weak-symbols: []
     thread-local-symbols: []
+...
diff --git a/llvm/test/tools/llvm-tapi-diff/Inputs/v4D.tbd b/llvm/test/tools/llvm-tapi-diff/Inputs/v4D.tbd
--- a/llvm/test/tools/llvm-tapi-diff/Inputs/v4D.tbd
+++ b/llvm/test/tools/llvm-tapi-diff/Inputs/v4D.tbd
@@ -102,3 +102,4 @@
     objc-ivars: []
     weak-symbols: []
     thread-local-symbols: []
+...
diff --git a/llvm/test/tools/llvm-tapi-diff/Inputs/v4E.tbd b/llvm/test/tools/llvm-tapi-diff/Inputs/v4E.tbd
--- a/llvm/test/tools/llvm-tapi-diff/Inputs/v4E.tbd
+++ b/llvm/test/tools/llvm-tapi-diff/Inputs/v4E.tbd
@@ -53,3 +53,4 @@
     weak-symbols:    [ _symC ]
   - targets:         [ x86_64-ios-simulator ]
     symbols:         [ _symB ]
+...
diff --git a/llvm/unittests/TextAPI/CMakeLists.txt b/llvm/unittests/TextAPI/CMakeLists.txt
--- a/llvm/unittests/TextAPI/CMakeLists.txt
+++ b/llvm/unittests/TextAPI/CMakeLists.txt
@@ -7,6 +7,7 @@
   TextStubV2Tests.cpp
   TextStubV3Tests.cpp
   TextStubV4Tests.cpp
+  TextStubV5Tests.cpp
 )
 
 target_link_libraries(TextAPITests PRIVATE LLVMTestingSupport)
diff --git a/llvm/unittests/TextAPI/TextStubHelpers.h b/llvm/unittests/TextAPI/TextStubHelpers.h
--- a/llvm/unittests/TextAPI/TextStubHelpers.h
+++ b/llvm/unittests/TextAPI/TextStubHelpers.h
@@ -16,10 +16,11 @@
 
 namespace llvm {
 struct ExportedSymbol {
-  llvm::MachO::SymbolKind Kind;
-  std::string Name;
-  bool WeakDefined;
-  bool ThreadLocalValue;
+  MachO::SymbolKind Kind = MachO::SymbolKind::GlobalSymbol;
+  std::string Name = {};
+  bool Weak = false;
+  bool ThreadLocalValue = false;
+  MachO::TargetList Targets = {};
 };
 
 using ExportedSymbolSeq = std::vector<ExportedSymbol>;
@@ -32,8 +33,8 @@
 }
 
 inline bool operator==(const ExportedSymbol &LHS, const ExportedSymbol &RHS) {
-  return std::tie(LHS.Kind, LHS.Name, LHS.WeakDefined, LHS.ThreadLocalValue) ==
-         std::tie(RHS.Kind, RHS.Name, RHS.WeakDefined, RHS.ThreadLocalValue);
+  return std::tie(LHS.Kind, LHS.Name, LHS.Weak, LHS.ThreadLocalValue) ==
+         std::tie(RHS.Kind, RHS.Name, RHS.Weak, RHS.ThreadLocalValue);
 }
 
 inline std::string stripWhitespace(std::string S) {
diff --git a/llvm/unittests/TextAPI/TextStubV4Tests.cpp b/llvm/unittests/TextAPI/TextStubV4Tests.cpp
--- a/llvm/unittests/TextAPI/TextStubV4Tests.cpp
+++ b/llvm/unittests/TextAPI/TextStubV4Tests.cpp
@@ -903,7 +903,8 @@
                                             "tbd-version: 4\n"
                                             "targets: [ x86_64-macos ]\n"
                                             "install-name: Test.dylib\n"
-                                            "foobar: \"unsupported key\"\n";
+                                            "foobar: \"unsupported key\"\n"
+                                            "...\n";
 
   Expected<TBDFile> Result =
       TextAPIReader::get(MemoryBufferRef(TBDv4MalformedFile2, "Test.tbd"));
diff --git a/llvm/unittests/TextAPI/TextStubV5Tests.cpp b/llvm/unittests/TextAPI/TextStubV5Tests.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/unittests/TextAPI/TextStubV5Tests.cpp
@@ -0,0 +1,352 @@
+
+//===-- TextStubV4Tests.cpp - TBD V4 File Test ----------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===-----------------------------------------------------------------------===/
+
+#include "TextStubHelpers.h"
+#include "llvm/TextAPI/InterfaceFile.h"
+#include "llvm/TextAPI/TextAPIReader.h"
+#include "llvm/TextAPI/TextAPIWriter.h"
+#include "gtest/gtest.h"
+#include <string>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::MachO;
+
+namespace TBDv5 {
+
+TEST(TBDv5, ReadFile) {
+  static const char TBDv5File[] = R"({ 
+"tapi_tbd_version": 5,
+"files": [
+    {
+        "target_info": [
+            {
+                "target": "x86_64-macos",
+                "min_deployment": "10.14" 
+            },
+            {
+                "target": "arm64-macos",
+                "min_deployment": "10.14"
+            },
+            {
+                "target": "arm64-maccatalyst",
+                "min_deployment": "12.1"
+            }
+        ],
+        "flags":[ 
+            {
+            "attributes": ["flat_namespace"]
+            }
+        ], 
+        "install_names":[
+            {
+                "name":"/S/L/F/Foo.framework/Foo"
+            }
+        ],
+        "current_versions":[ 
+            {
+                "version": "1.2"
+            }
+        ],
+        "compatibility_versions":[
+            {
+                "version": "1.1"
+            }
+         ],
+        "rpaths": [ 
+           {
+            "targets": ["x86_64-macos"],
+            "paths": ["@executable_path/.../Frameworks"]
+           }
+         ],
+        "parent_umbrellas": [
+            {
+                "umbrella": "System"
+            }
+        ],
+        "allowable_clients": [
+            {
+                "clients": [ "ClientA","ClientB" ]
+            }
+        ],
+        "reexported_libraries": [
+            {
+                "names": [
+                    "/u/l/l/libfoo.dylib",
+                    "/u/l/l/libbar.dylib"
+                ]
+            }
+        ],
+        "relinked_libraries": [ 
+            {
+                "names": [
+                    "/u/l/l/libmini.dylib",
+                    "/u/l/l/libmini1.dylib"
+                ]
+            }
+        ],
+        "exported_symbols": [
+            {
+                "targets": [ "x86_64-macos", "arm64-macos" ],
+                "data": { 
+                    "globals": [ "_global" ],
+                    "objc_classes": [ "ClassA" ],
+                    "weak": [],
+                    "thread-local": []
+                },
+                "text": { 
+                    "globals": [ "_func" ]
+                }
+            },
+            {
+                "targets": [
+                    "x86_64-macos"
+                ],
+                "data": {
+                    "globals": [ "_globalVar" ],
+                    "objc_classes": [ "ClassData" ], 
+                    "objc_eh_types": [ "ClassA", "ClassB" ], 
+                    "objc_ivars": [ "ClassA.ivar1", "ClassA.ivar2", "ClassC.ivar1" ]
+                },
+                "text": {
+                    "globals": [ "_funcFoo" ]
+                }
+            }
+        ],
+        "reexported_symbols": [
+            {
+                "targets": [ "x86_64-macos", "arm64-macos" ],
+                "data": {
+                    "globals": [ "_globalRe" ],
+                    "objc_classes": [ "ClassRexport" ]
+                },
+                "text": {
+                    "globals": [ "_funcA" ]
+                }
+            }
+        ],
+        "undefined_symbols": [
+            {
+                "targets": [ "x86_64-macos" ],
+                "data": {
+                    "globals": [ "_globalBind" ],
+                    "weak": [ "referenced_sym" ]
+                }
+            }
+        ]
+    }
+]
+})";
+
+  Expected<TBDFile> Result =
+      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
+  EXPECT_TRUE(!!Result);
+  TBDFile File = std::move(Result.get());
+  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
+  EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
+
+  TargetList AllTargets = {
+      Target(AK_x86_64, PLATFORM_MACOS),
+      Target(AK_arm64, PLATFORM_MACOS),
+      Target(AK_arm64, PLATFORM_MACCATALYST),
+  };
+  EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms());
+  EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures());
+
+  EXPECT_EQ(PackedVersion(1, 2, 0), File->getCurrentVersion());
+  EXPECT_EQ(PackedVersion(1, 1, 0), File->getCompatibilityVersion());
+  EXPECT_TRUE(File->isApplicationExtensionSafe());
+  EXPECT_FALSE(File->isTwoLevelNamespace());
+
+  InterfaceFileRef ClientA("ClientA", AllTargets);
+  InterfaceFileRef ClientB("ClientB", AllTargets);
+  EXPECT_EQ(2U, File->allowableClients().size());
+  EXPECT_EQ(ClientA, File->allowableClients().at(0));
+  EXPECT_EQ(ClientB, File->allowableClients().at(1));
+
+  InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
+  InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
+  EXPECT_EQ(2U, File->reexportedLibraries().size());
+  EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0));
+  EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1));
+
+  std::vector<std::pair<Target, std::string>> Umbrellas = {
+      {Target(AK_x86_64, PLATFORM_MACOS), "System"},
+      {Target(AK_arm64, PLATFORM_MACOS), "System"},
+      {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
+  EXPECT_EQ(Umbrellas, File->umbrellas());
+
+  ExportedSymbolSeq Exports, Reexports, Undefineds;
+  for (const auto *Sym : File->symbols()) {
+    TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
+    ExportedSymbol Temp =
+        ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
+                       Sym->isWeakDefined() || Sym->isWeakReferenced(),
+                       Sym->isThreadLocalValue(), SymTargets};
+    if (Sym->isUndefined())
+      Undefineds.emplace_back(std::move(Temp));
+    else
+      Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
+                          : Exports.emplace_back(std::move(Temp));
+  }
+  llvm::sort(Exports);
+  llvm::sort(Reexports);
+  llvm::sort(Undefineds);
+
+  TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
+                             Target(AK_arm64, PLATFORM_MACOS)};
+
+  std::vector<ExportedSymbol> ExpectedExportedSymbols = {
+      {SymbolKind::GlobalSymbol, "_func", false, false, MacOSTargets},
+      {SymbolKind::GlobalSymbol,
+       "_funcFoo",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+      {SymbolKind::GlobalSymbol, "_global", false, false, MacOSTargets},
+      {SymbolKind::GlobalSymbol,
+       "_globalVar",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+      {SymbolKind::ObjectiveCClass, "ClassA", false, false, MacOSTargets},
+      {SymbolKind::ObjectiveCClass,
+       "ClassData",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+      {SymbolKind::ObjectiveCClassEHType,
+       "ClassA",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+      {SymbolKind::ObjectiveCClassEHType,
+       "ClassB",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+      {SymbolKind::ObjectiveCInstanceVariable,
+       "ClassA.ivar1",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+      {SymbolKind::ObjectiveCInstanceVariable,
+       "ClassA.ivar2",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+      {SymbolKind::ObjectiveCInstanceVariable,
+       "ClassC.ivar1",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+  };
+  std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
+      {SymbolKind::GlobalSymbol, "_funcA", false, false, MacOSTargets},
+      {SymbolKind::GlobalSymbol, "_globalRe", false, false, MacOSTargets},
+      {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, MacOSTargets},
+  };
+
+  std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
+      {SymbolKind::GlobalSymbol,
+       "_globalBind",
+       false,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+      {SymbolKind::GlobalSymbol,
+       "referenced_sym",
+       true,
+       false,
+       {Target(AK_x86_64, PLATFORM_MACOS)}},
+  };
+
+  EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
+  EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
+  EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
+  EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
+                         std::begin(ExpectedExportedSymbols)));
+  EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
+                         std::begin(ExpectedReexportedSymbols)));
+  EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
+                         std::begin(ExpectedUndefinedSymbols)));
+}
+
+TEST(TBDv5, ReadMultipleTargets) {
+  static const char TBDv5File[] = R"({ 
+"tapi_tbd_version": 5,
+"files": [
+    {
+        "target_info": [
+            {
+                "target": "x86_64-macos",
+                "min_deployment": "10.14" 
+            },
+            {
+                "target": "arm64-macos",
+                "min_deployment": "10.14"
+            },
+            {
+                "target": "arm64-maccatalyst",
+                "min_deployment": "12.1"
+            }
+        ],
+        "install_names":[
+            { "name":"/usr/lib/libFoo.dylib" }
+        ],
+        "swift_abi":[ { "abi":8 } ],
+        "reexported_libraries": [
+            {
+                "targets": [ "x86_64-maccatalyst" ],
+                "names": [
+                    "/u/l/l/libfoo.dylib",
+                    "/u/l/l/libbar.dylib"
+                ]
+            },
+            {
+                "targets": [ "arm64-maccatalyst" ],
+                "names": [ "/u/l/l/libArmOnly.dylib" ]
+            }
+        ]
+    }
+]
+})";
+
+  Expected<TBDFile> Result =
+      TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
+  EXPECT_TRUE(!!Result);
+  TBDFile File = std::move(Result.get());
+  EXPECT_EQ(FileType::TBD_V5, File->getFileType());
+  EXPECT_EQ(std::string("/usr/lib/libFoo.dylib"), File->getInstallName());
+  EXPECT_TRUE(File->isApplicationExtensionSafe());
+  EXPECT_TRUE(File->isTwoLevelNamespace());
+  EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
+  EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
+  EXPECT_EQ(8U, File->getSwiftABIVersion());
+
+  TargetList AllTargets = {
+      Target(AK_x86_64, PLATFORM_MACOS),
+      Target(AK_arm64, PLATFORM_MACOS),
+      Target(AK_arm64, PLATFORM_MACCATALYST),
+  };
+  EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms());
+  EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures());
+
+  InterfaceFileRef ReexportA("/u/l/l/libArmOnly.dylib",
+                             {Target(AK_arm64, PLATFORM_MACCATALYST)});
+  InterfaceFileRef ReexportB("/u/l/l/libbar.dylib",
+                             {Target(AK_x86_64, PLATFORM_MACCATALYST)});
+  InterfaceFileRef ReexportC("/u/l/l/libfoo.dylib",
+                             {Target(AK_x86_64, PLATFORM_MACCATALYST)});
+  EXPECT_EQ(3U, File->reexportedLibraries().size());
+  EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0));
+  EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1));
+  EXPECT_EQ(ReexportC, File->reexportedLibraries().at(2));
+}
+
+} // end namespace TBDv5