1fe6060f1SDimitry Andric //===- InterfaceFile.cpp --------------------------------------------------===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric //
9fe6060f1SDimitry Andric // Implements the Interface File.
10fe6060f1SDimitry Andric //
11fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
12fe6060f1SDimitry Andric 
13fe6060f1SDimitry Andric #include "llvm/TextAPI/InterfaceFile.h"
14c9157d92SDimitry Andric #include "llvm/TextAPI/TextAPIError.h"
15fe6060f1SDimitry Andric #include <iomanip>
16fe6060f1SDimitry Andric #include <sstream>
17fe6060f1SDimitry Andric 
18fe6060f1SDimitry Andric using namespace llvm;
19fe6060f1SDimitry Andric using namespace llvm::MachO;
20fe6060f1SDimitry Andric 
addTarget(const Target & Target)21fe6060f1SDimitry Andric void InterfaceFileRef::addTarget(const Target &Target) {
22fe6060f1SDimitry Andric   addEntry(Targets, Target);
23fe6060f1SDimitry Andric }
24fe6060f1SDimitry Andric 
addAllowableClient(StringRef InstallName,const Target & Target)25fe6060f1SDimitry Andric void InterfaceFile::addAllowableClient(StringRef InstallName,
26fe6060f1SDimitry Andric                                        const Target &Target) {
27*6c20abcdSDimitry Andric   if (InstallName.empty())
28*6c20abcdSDimitry Andric     return;
29fe6060f1SDimitry Andric   auto Client = addEntry(AllowableClients, InstallName);
30fe6060f1SDimitry Andric   Client->addTarget(Target);
31fe6060f1SDimitry Andric }
32fe6060f1SDimitry Andric 
addReexportedLibrary(StringRef InstallName,const Target & Target)33fe6060f1SDimitry Andric void InterfaceFile::addReexportedLibrary(StringRef InstallName,
34fe6060f1SDimitry Andric                                          const Target &Target) {
35*6c20abcdSDimitry Andric   if (InstallName.empty())
36*6c20abcdSDimitry Andric     return;
37fe6060f1SDimitry Andric   auto Lib = addEntry(ReexportedLibraries, InstallName);
38fe6060f1SDimitry Andric   Lib->addTarget(Target);
39fe6060f1SDimitry Andric }
40fe6060f1SDimitry Andric 
addParentUmbrella(const Target & Target_,StringRef Parent)41fe6060f1SDimitry Andric void InterfaceFile::addParentUmbrella(const Target &Target_, StringRef Parent) {
42*6c20abcdSDimitry Andric   if (Parent.empty())
43*6c20abcdSDimitry Andric     return;
44fe6060f1SDimitry Andric   auto Iter = lower_bound(ParentUmbrellas, Target_,
45fe6060f1SDimitry Andric                           [](const std::pair<Target, std::string> &LHS,
46fe6060f1SDimitry Andric                              Target RHS) { return LHS.first < RHS; });
47fe6060f1SDimitry Andric 
48fe6060f1SDimitry Andric   if ((Iter != ParentUmbrellas.end()) && !(Target_ < Iter->first)) {
49fe6060f1SDimitry Andric     Iter->second = std::string(Parent);
50fe6060f1SDimitry Andric     return;
51fe6060f1SDimitry Andric   }
52fe6060f1SDimitry Andric 
53fe6060f1SDimitry Andric   ParentUmbrellas.emplace(Iter, Target_, std::string(Parent));
54fe6060f1SDimitry Andric }
55fe6060f1SDimitry Andric 
addRPath(const Target & InputTarget,StringRef RPath)56fe013be4SDimitry Andric void InterfaceFile::addRPath(const Target &InputTarget, StringRef RPath) {
57*6c20abcdSDimitry Andric   if (RPath.empty())
58*6c20abcdSDimitry Andric     return;
59c9157d92SDimitry Andric   using RPathEntryT = const std::pair<Target, std::string>;
60c9157d92SDimitry Andric   RPathEntryT Entry(InputTarget, RPath);
61c9157d92SDimitry Andric   auto Iter =
62c9157d92SDimitry Andric       lower_bound(RPaths, Entry,
63c9157d92SDimitry Andric                   [](RPathEntryT &LHS, RPathEntryT &RHS) { return LHS < RHS; });
64fe6060f1SDimitry Andric 
65c9157d92SDimitry Andric   if ((Iter != RPaths.end()) && (*Iter == Entry))
66fe6060f1SDimitry Andric     return;
67fe6060f1SDimitry Andric 
68c9157d92SDimitry Andric   RPaths.emplace(Iter, Entry);
69fe6060f1SDimitry Andric }
70fe6060f1SDimitry Andric 
addTarget(const Target & Target)71fe6060f1SDimitry Andric void InterfaceFile::addTarget(const Target &Target) {
72fe6060f1SDimitry Andric   addEntry(Targets, Target);
73fe6060f1SDimitry Andric }
74fe6060f1SDimitry Andric 
75fe6060f1SDimitry Andric InterfaceFile::const_filtered_target_range
targets(ArchitectureSet Archs) const76fe6060f1SDimitry Andric InterfaceFile::targets(ArchitectureSet Archs) const {
77fe6060f1SDimitry Andric   std::function<bool(const Target &)> fn = [Archs](const Target &Target_) {
78fe6060f1SDimitry Andric     return Archs.has(Target_.Arch);
79fe6060f1SDimitry Andric   };
80fe6060f1SDimitry Andric   return make_filter_range(Targets, fn);
81fe6060f1SDimitry Andric }
82fe6060f1SDimitry Andric 
addDocument(std::shared_ptr<InterfaceFile> && Document)83fe6060f1SDimitry Andric void InterfaceFile::addDocument(std::shared_ptr<InterfaceFile> &&Document) {
84fe6060f1SDimitry Andric   auto Pos = llvm::lower_bound(Documents, Document,
85fe6060f1SDimitry Andric                                [](const std::shared_ptr<InterfaceFile> &LHS,
86fe6060f1SDimitry Andric                                   const std::shared_ptr<InterfaceFile> &RHS) {
87fe6060f1SDimitry Andric                                  return LHS->InstallName < RHS->InstallName;
88fe6060f1SDimitry Andric                                });
89fe6060f1SDimitry Andric   Document->Parent = this;
90fe6060f1SDimitry Andric   Documents.insert(Pos, Document);
91fe6060f1SDimitry Andric }
92fe6060f1SDimitry Andric 
inlineLibrary(std::shared_ptr<InterfaceFile> Library,bool Overwrite)93c9157d92SDimitry Andric void InterfaceFile::inlineLibrary(std::shared_ptr<InterfaceFile> Library,
94c9157d92SDimitry Andric                                   bool Overwrite) {
95c9157d92SDimitry Andric   auto AddFwk = [&](std::shared_ptr<InterfaceFile> &&Reexport) {
96c9157d92SDimitry Andric     auto It = lower_bound(
97c9157d92SDimitry Andric         Documents, Reexport->getInstallName(),
98c9157d92SDimitry Andric         [](std::shared_ptr<InterfaceFile> &Lhs, const StringRef Rhs) {
99c9157d92SDimitry Andric           return Lhs->getInstallName() < Rhs;
100c9157d92SDimitry Andric         });
101c9157d92SDimitry Andric 
102c9157d92SDimitry Andric     if (Overwrite && It != Documents.end() &&
103c9157d92SDimitry Andric         Reexport->getInstallName() == (*It)->getInstallName()) {
104c9157d92SDimitry Andric       std::replace(Documents.begin(), Documents.end(), *It,
105c9157d92SDimitry Andric                    std::move(Reexport));
106c9157d92SDimitry Andric       return;
107c9157d92SDimitry Andric     }
108c9157d92SDimitry Andric 
109c9157d92SDimitry Andric     if ((It != Documents.end()) &&
110c9157d92SDimitry Andric         !(Reexport->getInstallName() < (*It)->getInstallName()))
111c9157d92SDimitry Andric       return;
112c9157d92SDimitry Andric 
113c9157d92SDimitry Andric     Documents.emplace(It, std::move(Reexport));
114c9157d92SDimitry Andric   };
115c9157d92SDimitry Andric   for (auto Doc : Library->documents())
116c9157d92SDimitry Andric     AddFwk(std::move(Doc));
117c9157d92SDimitry Andric 
118c9157d92SDimitry Andric   Library->Documents.clear();
119c9157d92SDimitry Andric   AddFwk(std::move(Library));
120c9157d92SDimitry Andric }
121c9157d92SDimitry Andric 
122c9157d92SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
merge(const InterfaceFile * O) const123c9157d92SDimitry Andric InterfaceFile::merge(const InterfaceFile *O) const {
124c9157d92SDimitry Andric   // Verify files can be merged.
125c9157d92SDimitry Andric   if (getInstallName() != O->getInstallName()) {
126c9157d92SDimitry Andric     return make_error<StringError>("install names do not match",
127c9157d92SDimitry Andric                                    inconvertibleErrorCode());
128c9157d92SDimitry Andric   }
129c9157d92SDimitry Andric 
130c9157d92SDimitry Andric   if (getCurrentVersion() != O->getCurrentVersion()) {
131c9157d92SDimitry Andric     return make_error<StringError>("current versions do not match",
132c9157d92SDimitry Andric                                    inconvertibleErrorCode());
133c9157d92SDimitry Andric   }
134c9157d92SDimitry Andric 
135c9157d92SDimitry Andric   if (getCompatibilityVersion() != O->getCompatibilityVersion()) {
136c9157d92SDimitry Andric     return make_error<StringError>("compatibility versions do not match",
137c9157d92SDimitry Andric                                    inconvertibleErrorCode());
138c9157d92SDimitry Andric   }
139c9157d92SDimitry Andric 
140c9157d92SDimitry Andric   if ((getSwiftABIVersion() != 0) && (O->getSwiftABIVersion() != 0) &&
141c9157d92SDimitry Andric       (getSwiftABIVersion() != O->getSwiftABIVersion())) {
142c9157d92SDimitry Andric     return make_error<StringError>("swift ABI versions do not match",
143c9157d92SDimitry Andric                                    inconvertibleErrorCode());
144c9157d92SDimitry Andric   }
145c9157d92SDimitry Andric 
146c9157d92SDimitry Andric   if (isTwoLevelNamespace() != O->isTwoLevelNamespace()) {
147c9157d92SDimitry Andric     return make_error<StringError>("two level namespace flags do not match",
148c9157d92SDimitry Andric                                    inconvertibleErrorCode());
149c9157d92SDimitry Andric   }
150c9157d92SDimitry Andric 
151c9157d92SDimitry Andric   if (isApplicationExtensionSafe() != O->isApplicationExtensionSafe()) {
152c9157d92SDimitry Andric     return make_error<StringError>(
153c9157d92SDimitry Andric         "application extension safe flags do not match",
154c9157d92SDimitry Andric         inconvertibleErrorCode());
155c9157d92SDimitry Andric   }
156c9157d92SDimitry Andric 
157c9157d92SDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
158c9157d92SDimitry Andric   IF->setFileType(std::max(getFileType(), O->getFileType()));
159c9157d92SDimitry Andric   IF->setPath(getPath());
160c9157d92SDimitry Andric   IF->setInstallName(getInstallName());
161c9157d92SDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
162c9157d92SDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
163c9157d92SDimitry Andric 
164c9157d92SDimitry Andric   if (getSwiftABIVersion() == 0)
165c9157d92SDimitry Andric     IF->setSwiftABIVersion(O->getSwiftABIVersion());
166c9157d92SDimitry Andric   else
167c9157d92SDimitry Andric     IF->setSwiftABIVersion(getSwiftABIVersion());
168c9157d92SDimitry Andric 
169c9157d92SDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
170c9157d92SDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
171c9157d92SDimitry Andric 
172c9157d92SDimitry Andric   for (const auto &It : umbrellas()) {
173c9157d92SDimitry Andric     if (!It.second.empty())
174c9157d92SDimitry Andric       IF->addParentUmbrella(It.first, It.second);
175c9157d92SDimitry Andric   }
176c9157d92SDimitry Andric   for (const auto &It : O->umbrellas()) {
177c9157d92SDimitry Andric     if (!It.second.empty())
178c9157d92SDimitry Andric       IF->addParentUmbrella(It.first, It.second);
179c9157d92SDimitry Andric   }
180c9157d92SDimitry Andric   IF->addTargets(targets());
181c9157d92SDimitry Andric   IF->addTargets(O->targets());
182c9157d92SDimitry Andric 
183c9157d92SDimitry Andric   for (const auto &Lib : allowableClients())
184c9157d92SDimitry Andric     for (const auto &Target : Lib.targets())
185c9157d92SDimitry Andric       IF->addAllowableClient(Lib.getInstallName(), Target);
186c9157d92SDimitry Andric 
187c9157d92SDimitry Andric   for (const auto &Lib : O->allowableClients())
188c9157d92SDimitry Andric     for (const auto &Target : Lib.targets())
189c9157d92SDimitry Andric       IF->addAllowableClient(Lib.getInstallName(), Target);
190c9157d92SDimitry Andric 
191c9157d92SDimitry Andric   for (const auto &Lib : reexportedLibraries())
192c9157d92SDimitry Andric     for (const auto &Target : Lib.targets())
193c9157d92SDimitry Andric       IF->addReexportedLibrary(Lib.getInstallName(), Target);
194c9157d92SDimitry Andric 
195c9157d92SDimitry Andric   for (const auto &Lib : O->reexportedLibraries())
196c9157d92SDimitry Andric     for (const auto &Target : Lib.targets())
197c9157d92SDimitry Andric       IF->addReexportedLibrary(Lib.getInstallName(), Target);
198c9157d92SDimitry Andric 
199c9157d92SDimitry Andric   for (const auto &[Target, Path] : rpaths())
200c9157d92SDimitry Andric     IF->addRPath(Target, Path);
201c9157d92SDimitry Andric   for (const auto &[Target, Path] : O->rpaths())
202c9157d92SDimitry Andric     IF->addRPath(Target, Path);
203c9157d92SDimitry Andric 
204c9157d92SDimitry Andric   for (const auto *Sym : symbols()) {
205c9157d92SDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
206c9157d92SDimitry Andric                   Sym->getFlags());
207c9157d92SDimitry Andric   }
208c9157d92SDimitry Andric 
209c9157d92SDimitry Andric   for (const auto *Sym : O->symbols()) {
210c9157d92SDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(),
211c9157d92SDimitry Andric                   Sym->getFlags());
212c9157d92SDimitry Andric   }
213c9157d92SDimitry Andric 
214c9157d92SDimitry Andric   return std::move(IF);
215c9157d92SDimitry Andric }
216c9157d92SDimitry Andric 
217c9157d92SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
remove(Architecture Arch) const218c9157d92SDimitry Andric InterfaceFile::remove(Architecture Arch) const {
219c9157d92SDimitry Andric   if (getArchitectures() == Arch)
220c9157d92SDimitry Andric     return make_error<StringError>("cannot remove last architecture slice '" +
221c9157d92SDimitry Andric                                        getArchitectureName(Arch) + "'",
222c9157d92SDimitry Andric                                    inconvertibleErrorCode());
223c9157d92SDimitry Andric 
224c9157d92SDimitry Andric   if (!getArchitectures().has(Arch)) {
225c9157d92SDimitry Andric     bool Found = false;
226c9157d92SDimitry Andric     for (auto &Doc : Documents) {
227c9157d92SDimitry Andric       if (Doc->getArchitectures().has(Arch)) {
228c9157d92SDimitry Andric         Found = true;
229c9157d92SDimitry Andric         break;
230c9157d92SDimitry Andric       }
231c9157d92SDimitry Andric     }
232c9157d92SDimitry Andric 
233c9157d92SDimitry Andric     if (!Found)
234c9157d92SDimitry Andric       return make_error<TextAPIError>(TextAPIErrorCode::NoSuchArchitecture);
235c9157d92SDimitry Andric   }
236c9157d92SDimitry Andric 
237c9157d92SDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
238c9157d92SDimitry Andric   IF->setFileType(getFileType());
239c9157d92SDimitry Andric   IF->setPath(getPath());
240c9157d92SDimitry Andric   IF->addTargets(targets(ArchitectureSet::All().clear(Arch)));
241c9157d92SDimitry Andric   IF->setInstallName(getInstallName());
242c9157d92SDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
243c9157d92SDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
244c9157d92SDimitry Andric   IF->setSwiftABIVersion(getSwiftABIVersion());
245c9157d92SDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
246c9157d92SDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
247c9157d92SDimitry Andric   for (const auto &It : umbrellas())
248c9157d92SDimitry Andric     if (It.first.Arch != Arch)
249c9157d92SDimitry Andric       IF->addParentUmbrella(It.first, It.second);
250c9157d92SDimitry Andric 
251c9157d92SDimitry Andric   for (const auto &Lib : allowableClients()) {
252c9157d92SDimitry Andric     for (const auto &Target : Lib.targets())
253c9157d92SDimitry Andric       if (Target.Arch != Arch)
254c9157d92SDimitry Andric         IF->addAllowableClient(Lib.getInstallName(), Target);
255c9157d92SDimitry Andric   }
256c9157d92SDimitry Andric 
257c9157d92SDimitry Andric   for (const auto &Lib : reexportedLibraries()) {
258c9157d92SDimitry Andric     for (const auto &Target : Lib.targets())
259c9157d92SDimitry Andric       if (Target.Arch != Arch)
260c9157d92SDimitry Andric         IF->addReexportedLibrary(Lib.getInstallName(), Target);
261c9157d92SDimitry Andric   }
262c9157d92SDimitry Andric 
263c9157d92SDimitry Andric   for (const auto *Sym : symbols()) {
264c9157d92SDimitry Andric     auto Archs = Sym->getArchitectures();
265c9157d92SDimitry Andric     Archs.clear(Arch);
266c9157d92SDimitry Andric     if (Archs.empty())
267c9157d92SDimitry Andric       continue;
268c9157d92SDimitry Andric 
269c9157d92SDimitry Andric     IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Archs),
270c9157d92SDimitry Andric                   Sym->getFlags());
271c9157d92SDimitry Andric   }
272c9157d92SDimitry Andric 
273c9157d92SDimitry Andric   for (auto &Doc : Documents) {
274c9157d92SDimitry Andric     // Skip the inlined document if the to be removed architecture is the
275c9157d92SDimitry Andric     // only one left.
276c9157d92SDimitry Andric     if (Doc->getArchitectures() == Arch)
277c9157d92SDimitry Andric       continue;
278c9157d92SDimitry Andric 
279c9157d92SDimitry Andric     // If the document doesn't contain the arch, then no work is to be done
280c9157d92SDimitry Andric     // and it can be copied over.
281c9157d92SDimitry Andric     if (!Doc->getArchitectures().has(Arch)) {
282c9157d92SDimitry Andric       auto NewDoc = Doc;
283c9157d92SDimitry Andric       IF->addDocument(std::move(NewDoc));
284c9157d92SDimitry Andric       continue;
285c9157d92SDimitry Andric     }
286c9157d92SDimitry Andric 
287c9157d92SDimitry Andric     auto Result = Doc->remove(Arch);
288c9157d92SDimitry Andric     if (!Result)
289c9157d92SDimitry Andric       return Result;
290c9157d92SDimitry Andric 
291c9157d92SDimitry Andric     IF->addDocument(std::move(Result.get()));
292c9157d92SDimitry Andric   }
293c9157d92SDimitry Andric 
294c9157d92SDimitry Andric   return std::move(IF);
295c9157d92SDimitry Andric }
296c9157d92SDimitry Andric 
297c9157d92SDimitry Andric Expected<std::unique_ptr<InterfaceFile>>
extract(Architecture Arch) const298c9157d92SDimitry Andric InterfaceFile::extract(Architecture Arch) const {
299c9157d92SDimitry Andric   if (!getArchitectures().has(Arch)) {
300c9157d92SDimitry Andric     return make_error<StringError>("file doesn't have architecture '" +
301c9157d92SDimitry Andric                                        getArchitectureName(Arch) + "'",
302c9157d92SDimitry Andric                                    inconvertibleErrorCode());
303c9157d92SDimitry Andric   }
304c9157d92SDimitry Andric 
305c9157d92SDimitry Andric   std::unique_ptr<InterfaceFile> IF(new InterfaceFile());
306c9157d92SDimitry Andric   IF->setFileType(getFileType());
307c9157d92SDimitry Andric   IF->setPath(getPath());
308c9157d92SDimitry Andric   IF->addTargets(targets(Arch));
309c9157d92SDimitry Andric   IF->setInstallName(getInstallName());
310c9157d92SDimitry Andric   IF->setCurrentVersion(getCurrentVersion());
311c9157d92SDimitry Andric   IF->setCompatibilityVersion(getCompatibilityVersion());
312c9157d92SDimitry Andric   IF->setSwiftABIVersion(getSwiftABIVersion());
313c9157d92SDimitry Andric   IF->setTwoLevelNamespace(isTwoLevelNamespace());
314c9157d92SDimitry Andric   IF->setApplicationExtensionSafe(isApplicationExtensionSafe());
315c9157d92SDimitry Andric   for (const auto &It : umbrellas())
316c9157d92SDimitry Andric     if (It.first.Arch == Arch)
317c9157d92SDimitry Andric       IF->addParentUmbrella(It.first, It.second);
318c9157d92SDimitry Andric 
319c9157d92SDimitry Andric   for (const auto &It : rpaths())
320c9157d92SDimitry Andric     if (It.first.Arch == Arch)
321c9157d92SDimitry Andric       IF->addRPath(It.first, It.second);
322c9157d92SDimitry Andric 
323c9157d92SDimitry Andric   for (const auto &Lib : allowableClients())
324c9157d92SDimitry Andric     for (const auto &Target : Lib.targets())
325c9157d92SDimitry Andric       if (Target.Arch == Arch)
326c9157d92SDimitry Andric         IF->addAllowableClient(Lib.getInstallName(), Target);
327c9157d92SDimitry Andric 
328c9157d92SDimitry Andric   for (const auto &Lib : reexportedLibraries())
329c9157d92SDimitry Andric     for (const auto &Target : Lib.targets())
330c9157d92SDimitry Andric       if (Target.Arch == Arch)
331c9157d92SDimitry Andric         IF->addReexportedLibrary(Lib.getInstallName(), Target);
332c9157d92SDimitry Andric 
333c9157d92SDimitry Andric   for (const auto *Sym : symbols()) {
334c9157d92SDimitry Andric     if (Sym->hasArchitecture(Arch))
335c9157d92SDimitry Andric       IF->addSymbol(Sym->getKind(), Sym->getName(), Sym->targets(Arch),
336c9157d92SDimitry Andric                     Sym->getFlags());
337c9157d92SDimitry Andric   }
338c9157d92SDimitry Andric 
339c9157d92SDimitry Andric   for (auto &Doc : Documents) {
340c9157d92SDimitry Andric     // Skip documents that don't have the requested architecture.
341c9157d92SDimitry Andric     if (!Doc->getArchitectures().has(Arch))
342c9157d92SDimitry Andric       continue;
343c9157d92SDimitry Andric 
344c9157d92SDimitry Andric     auto Result = Doc->extract(Arch);
345c9157d92SDimitry Andric     if (!Result)
346c9157d92SDimitry Andric       return Result;
347c9157d92SDimitry Andric 
348c9157d92SDimitry Andric     IF->addDocument(std::move(Result.get()));
349c9157d92SDimitry Andric   }
350c9157d92SDimitry Andric 
351c9157d92SDimitry Andric   return std::move(IF);
352c9157d92SDimitry Andric }
353c9157d92SDimitry Andric 
isYAMLTextStub(const FileType & Kind)354fe013be4SDimitry Andric static bool isYAMLTextStub(const FileType &Kind) {
355fe013be4SDimitry Andric   return (Kind >= FileType::TBD_V1) && (Kind < FileType::TBD_V5);
356fe013be4SDimitry Andric }
357fe013be4SDimitry Andric 
operator ==(const InterfaceFile & O) const358fe6060f1SDimitry Andric bool InterfaceFile::operator==(const InterfaceFile &O) const {
359fe6060f1SDimitry Andric   if (Targets != O.Targets)
360fe6060f1SDimitry Andric     return false;
361fe6060f1SDimitry Andric   if (InstallName != O.InstallName)
362fe6060f1SDimitry Andric     return false;
363fe6060f1SDimitry Andric   if ((CurrentVersion != O.CurrentVersion) ||
364fe6060f1SDimitry Andric       (CompatibilityVersion != O.CompatibilityVersion))
365fe6060f1SDimitry Andric     return false;
366fe6060f1SDimitry Andric   if (SwiftABIVersion != O.SwiftABIVersion)
367fe6060f1SDimitry Andric     return false;
368fe6060f1SDimitry Andric   if (IsTwoLevelNamespace != O.IsTwoLevelNamespace)
369fe6060f1SDimitry Andric     return false;
370fe6060f1SDimitry Andric   if (IsAppExtensionSafe != O.IsAppExtensionSafe)
371fe6060f1SDimitry Andric     return false;
372c9157d92SDimitry Andric   if (IsOSLibNotForSharedCache != O.IsOSLibNotForSharedCache)
373c9157d92SDimitry Andric     return false;
374c9157d92SDimitry Andric   if (HasSimSupport != O.HasSimSupport)
375c9157d92SDimitry Andric     return false;
376fe6060f1SDimitry Andric   if (ParentUmbrellas != O.ParentUmbrellas)
377fe6060f1SDimitry Andric     return false;
378fe6060f1SDimitry Andric   if (AllowableClients != O.AllowableClients)
379fe6060f1SDimitry Andric     return false;
380fe6060f1SDimitry Andric   if (ReexportedLibraries != O.ReexportedLibraries)
381fe6060f1SDimitry Andric     return false;
382fe013be4SDimitry Andric   if (*SymbolsSet != *O.SymbolsSet)
383fe6060f1SDimitry Andric     return false;
384fe013be4SDimitry Andric   // Don't compare run search paths for older filetypes that cannot express
385fe013be4SDimitry Andric   // them.
386fe013be4SDimitry Andric   if (!(isYAMLTextStub(FileKind)) && !(isYAMLTextStub(O.FileKind))) {
387fe013be4SDimitry Andric     if (RPaths != O.RPaths)
388fe013be4SDimitry Andric       return false;
389fe013be4SDimitry Andric     if (mapToPlatformVersionSet(Targets) != mapToPlatformVersionSet(O.Targets))
390fe013be4SDimitry Andric       return false;
391fe013be4SDimitry Andric   }
392fe013be4SDimitry Andric 
393fe6060f1SDimitry Andric   if (!std::equal(Documents.begin(), Documents.end(), O.Documents.begin(),
394fe6060f1SDimitry Andric                   O.Documents.end(),
395fe6060f1SDimitry Andric                   [](const std::shared_ptr<InterfaceFile> LHS,
396fe6060f1SDimitry Andric                      const std::shared_ptr<InterfaceFile> RHS) {
397fe6060f1SDimitry Andric                     return *LHS == *RHS;
398fe6060f1SDimitry Andric                   }))
399fe6060f1SDimitry Andric     return false;
400fe6060f1SDimitry Andric   return true;
401fe6060f1SDimitry Andric }
402