xref: /llvm-project/llvm/unittests/TextAPI/TextStubV5Tests.cpp (revision 913f21ae5c460d6fdd73ac7663534e73f8e19044)
1 //===-- TextStubV5Tests.cpp - TBD V5 File Test ----------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===-----------------------------------------------------------------------===/
8 
9 #include "TextStubHelpers.h"
10 #include "llvm/TextAPI/InterfaceFile.h"
11 #include "llvm/TextAPI/TextAPIReader.h"
12 #include "llvm/TextAPI/TextAPIWriter.h"
13 #include "gtest/gtest.h"
14 #include <string>
15 #include <vector>
16 
17 using namespace llvm;
18 using namespace llvm::MachO;
19 
20 namespace TBDv5 {
21 
22 TEST(TBDv5, ReadFile) {
23   static const char TBDv5File[] = R"({
24 "tapi_tbd_version": 5,
25 "main_library": {
26   "target_info": [
27     {
28       "target": "x86_64-macos",
29       "min_deployment": "10.14"
30     },
31     {
32       "target": "arm64-macos",
33       "min_deployment": "10.14"
34     },
35     {
36       "target": "arm64-maccatalyst",
37       "min_deployment": "12.1"
38     }
39   ],
40   "flags": [
41     {
42       "targets": [
43             "x86_64-macos"
44         ],
45       "attributes": [
46             "flat_namespace"
47         ]
48     }
49   ],
50   "install_names": [
51     {
52         "name": "/S/L/F/Foo.framework/Foo"
53     }
54   ],
55   "current_versions": [
56     {
57         "version": "1.2"
58     }
59   ],
60   "compatibility_versions": [
61     { "version": "1.1" }
62   ],
63   "rpaths": [
64     {
65       "targets": [
66           "x86_64-macos"
67       ],
68       "paths": [
69           "@executable_path/.../Frameworks"
70       ]
71     }
72   ],
73   "parent_umbrellas": [
74     {
75       "umbrella": "System"
76     }
77   ],
78   "allowable_clients": [
79     {
80         "clients": [
81             "ClientA",
82             "ClientB"
83         ]
84     }
85   ],
86   "reexported_libraries": [
87     {
88         "names": [
89             "/u/l/l/libfoo.dylib",
90             "/u/l/l/libbar.dylib"
91         ]
92     }
93   ],
94   "exported_symbols": [
95     {
96         "targets": [
97             "x86_64-macos",
98             "arm64-macos"
99         ],
100         "data": {
101             "global": [
102                 "_global"
103             ],
104             "objc_class": [
105                 "ClassA"
106             ],
107             "weak": [],
108             "thread_local": []
109         },
110         "text": {
111             "global": [
112                 "_func"
113             ],
114             "weak": [],
115             "thread_local": []
116         }
117     },
118     {
119       "targets": [
120           "x86_64-macos"
121       ],
122       "data": {
123           "global": [
124               "_globalVar"
125           ],
126           "objc_class": [
127               "ClassA",
128               "ClassB",
129               "ClassData"
130           ],
131           "objc_eh_type": [
132               "ClassA",
133               "ClassB"
134           ],
135           "objc_ivar": [
136               "ClassA.ivar1",
137               "ClassA.ivar2",
138               "ClassC.ivar1"
139           ]
140       },
141       "text": {
142           "global": [
143               "_funcFoo"
144           ]
145       }
146     }
147   ],
148   "reexported_symbols": [
149     {
150         "targets": [
151             "x86_64-macos",
152             "arm64-macos"
153         ],
154         "data": {
155             "global": [
156                 "_globalRe"
157             ],
158             "objc_class": [
159                 "ClassRexport"
160             ]
161         },
162         "text": {
163             "global": [
164                 "_funcA"
165             ]
166         }
167     }
168   ],
169   "undefined_symbols": [
170     {
171         "targets": [
172             "x86_64-macos"
173         ],
174         "data": {
175             "global": [
176                 "_globalBind"
177             ],
178             "weak": [
179                 "referenced_sym"
180             ]
181         }
182     }
183   ]
184 },
185 "libraries": []
186 })";
187 
188   Expected<TBDFile> Result =
189       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
190   EXPECT_TRUE(!!Result);
191   TBDFile File = std::move(Result.get());
192   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
193   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
194 
195   TargetList AllTargets = {
196       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
197       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
198       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
199   };
200   EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms());
201   EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures());
202 
203   EXPECT_EQ(PackedVersion(1, 2, 0), File->getCurrentVersion());
204   EXPECT_EQ(PackedVersion(1, 1, 0), File->getCompatibilityVersion());
205   EXPECT_TRUE(File->isApplicationExtensionSafe());
206   EXPECT_FALSE(File->isTwoLevelNamespace());
207   EXPECT_EQ(0U, File->documents().size());
208 
209   InterfaceFileRef ClientA("ClientA", AllTargets);
210   InterfaceFileRef ClientB("ClientB", AllTargets);
211   EXPECT_EQ(2U, File->allowableClients().size());
212   EXPECT_EQ(ClientA, File->allowableClients().at(0));
213   EXPECT_EQ(ClientB, File->allowableClients().at(1));
214 
215   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
216   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
217   EXPECT_EQ(2U, File->reexportedLibraries().size());
218   EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0));
219   EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1));
220 
221   TargetToAttr RPaths = {
222       {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"},
223   };
224   EXPECT_EQ(RPaths, File->rpaths());
225 
226   TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"},
227                             {Target(AK_arm64, PLATFORM_MACOS), "System"},
228                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
229   EXPECT_EQ(Umbrellas, File->umbrellas());
230 
231   ExportedSymbolSeq Exports, Reexports, Undefineds;
232   for (const auto *Sym : File->symbols()) {
233     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
234     ExportedSymbol Temp =
235         ExportedSymbol{Sym->getKind(),
236                        std::string(Sym->getName()),
237                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
238                        Sym->isThreadLocalValue(),
239                        Sym->isData(),
240                        SymTargets};
241     if (Sym->isUndefined())
242       Undefineds.emplace_back(std::move(Temp));
243     else
244       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
245                           : Exports.emplace_back(std::move(Temp));
246   }
247   llvm::sort(Exports);
248   llvm::sort(Reexports);
249   llvm::sort(Undefineds);
250 
251   TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
252                              Target(AK_arm64, PLATFORM_MACOS)};
253 
254   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
255       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
256       {SymbolKind::GlobalSymbol,
257        "_funcFoo",
258        false,
259        false,
260        false,
261        {Target(AK_x86_64, PLATFORM_MACOS)}},
262       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
263       {SymbolKind::GlobalSymbol,
264        "_globalVar",
265        false,
266        false,
267        true,
268        {Target(AK_x86_64, PLATFORM_MACOS)}},
269       {SymbolKind::ObjectiveCClass,
270        "ClassA",
271        false,
272        false,
273        true,
274        {Target(AK_x86_64, PLATFORM_MACOS)}},
275       {SymbolKind::ObjectiveCClass,
276        "ClassB",
277        false,
278        false,
279        true,
280        {Target(AK_x86_64, PLATFORM_MACOS)}},
281       {SymbolKind::ObjectiveCClass,
282        "ClassData",
283        false,
284        false,
285        true,
286        {Target(AK_x86_64, PLATFORM_MACOS)}},
287       {SymbolKind::ObjectiveCClassEHType,
288        "ClassA",
289        false,
290        false,
291        true,
292        {Target(AK_x86_64, PLATFORM_MACOS)}},
293       {SymbolKind::ObjectiveCClassEHType,
294        "ClassB",
295        false,
296        false,
297        true,
298        {Target(AK_x86_64, PLATFORM_MACOS)}},
299       {SymbolKind::ObjectiveCInstanceVariable,
300        "ClassA.ivar1",
301        false,
302        false,
303        true,
304        {Target(AK_x86_64, PLATFORM_MACOS)}},
305       {SymbolKind::ObjectiveCInstanceVariable,
306        "ClassA.ivar2",
307        false,
308        false,
309        true,
310        {Target(AK_x86_64, PLATFORM_MACOS)}},
311       {SymbolKind::ObjectiveCInstanceVariable,
312        "ClassC.ivar1",
313        false,
314        false,
315        true,
316        {Target(AK_x86_64, PLATFORM_MACOS)}},
317   };
318   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
319       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
320       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
321       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
322        MacOSTargets},
323   };
324 
325   std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
326       {SymbolKind::GlobalSymbol,
327        "_globalBind",
328        false,
329        false,
330        true,
331        {Target(AK_x86_64, PLATFORM_MACOS)}},
332       {SymbolKind::GlobalSymbol,
333        "referenced_sym",
334        true,
335        false,
336        true,
337        {Target(AK_x86_64, PLATFORM_MACOS)}},
338   };
339 
340   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
341   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
342   EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
343   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
344                          std::begin(ExpectedExportedSymbols)));
345   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
346                          std::begin(ExpectedReexportedSymbols)));
347   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
348                          std::begin(ExpectedUndefinedSymbols)));
349 
350   EXPECT_TRUE(
351       File->getSymbol(SymbolKind::GlobalSymbol, "_globalBind").has_value());
352 }
353 
354 TEST(TBDv5, ReadMultipleTargets) {
355   static const char TBDv5File[] = R"({
356 "tapi_tbd_version": 5,
357 "main_library":  {
358   "target_info": [
359       {
360           "target": "x86_64-macos",
361           "min_deployment": "10.14"
362       },
363       {
364           "target": "arm64-macos",
365           "min_deployment": "10.14"
366       },
367       {
368           "target": "arm64-maccatalyst",
369           "min_deployment": "12.1"
370       }
371   ],
372   "install_names":[
373       { "name":"/usr/lib/libFoo.dylib" }
374   ],
375   "swift_abi":[ { "abi":8 } ],
376   "reexported_libraries": [
377       {
378           "targets": [ "x86_64-maccatalyst" ],
379           "names": [
380               "/u/l/l/libfoo.dylib",
381               "/u/l/l/libbar.dylib"
382           ]
383       },
384       {
385           "targets": [ "arm64-maccatalyst" ],
386           "names": [ "/u/l/l/libArmOnly.dylib" ]
387       }
388   ]
389 }
390 })";
391 
392   Expected<TBDFile> Result =
393       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
394   EXPECT_TRUE(!!Result);
395   TBDFile File = std::move(Result.get());
396   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
397   EXPECT_EQ(std::string("/usr/lib/libFoo.dylib"), File->getInstallName());
398   EXPECT_TRUE(File->isApplicationExtensionSafe());
399   EXPECT_TRUE(File->isTwoLevelNamespace());
400   EXPECT_EQ(PackedVersion(1, 0, 0), File->getCurrentVersion());
401   EXPECT_EQ(PackedVersion(1, 0, 0), File->getCompatibilityVersion());
402   EXPECT_EQ(8U, File->getSwiftABIVersion());
403 
404   TargetList AllTargets = {
405       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
406       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)),
407       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)),
408   };
409   EXPECT_EQ(mapToPlatformSet(AllTargets), File->getPlatforms());
410   EXPECT_EQ(mapToArchitectureSet(AllTargets), File->getArchitectures());
411 
412   InterfaceFileRef ReexportA("/u/l/l/libArmOnly.dylib",
413                              {Target(AK_arm64, PLATFORM_MACCATALYST)});
414   InterfaceFileRef ReexportB("/u/l/l/libbar.dylib",
415                              {Target(AK_x86_64, PLATFORM_MACCATALYST)});
416   InterfaceFileRef ReexportC("/u/l/l/libfoo.dylib",
417                              {Target(AK_x86_64, PLATFORM_MACCATALYST)});
418   EXPECT_EQ(3U, File->reexportedLibraries().size());
419   EXPECT_EQ(ReexportA, File->reexportedLibraries().at(0));
420   EXPECT_EQ(ReexportB, File->reexportedLibraries().at(1));
421   EXPECT_EQ(ReexportC, File->reexportedLibraries().at(2));
422 }
423 
424 TEST(TBDv5, ReadMultipleDocuments) {
425   static const char TBDv5File[] = R"({
426 "tapi_tbd_version": 5,
427 "main_library": {
428   "target_info": [
429     {
430       "target": "armv7-ios",
431       "min_deployment": "11.0"
432     }
433   ],
434   "install_names":[
435     { "name":"/S/L/F/Foo.framework/Foo" }
436   ],
437   "reexported_libraries": [
438     { "names": ["/u/l/l/libfoo.dylib"] }
439   ]
440 },
441 "libraries": [
442   {
443     "target_info": [
444       {
445         "target": "armv7-ios",
446         "min_deployment": "11.0"
447       }
448     ],
449     "install_names":[
450       { "name":"/u/l/l/libfoo.dylib" }
451     ],
452     "flags":[
453       { "attributes": ["not_app_extension_safe"] }
454     ],
455     "exported_symbols": [
456       {
457         "data": {
458           "thread_local": [ "_globalVar" ],
459           "objc_class": [ "ClassData", "ClassA", "ClassB"],
460           "objc_eh_type": [ "ClassA", "ClassB" ]
461         },
462         "text": {
463           "global": [ "_funcFoo" ]
464         }
465       }
466     ]
467   }
468 ]})";
469 
470   Expected<TBDFile> Result =
471       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
472   EXPECT_TRUE(!!Result);
473   TBDFile File = std::move(Result.get());
474   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
475   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
476   EXPECT_TRUE(File->isTwoLevelNamespace());
477   EXPECT_TRUE(File->isApplicationExtensionSafe());
478 
479   TargetList Targets(File->targets().begin(), File->targets().end());
480   Target iOSTarget(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0));
481   EXPECT_EQ(TargetList{iOSTarget}, Targets);
482   std::vector<const Symbol *> Symbols(File->symbols().begin(),
483                                       File->symbols().end());
484   EXPECT_EQ(0U, Symbols.size());
485 
486   InterfaceFileRef Reexport("/u/l/l/libfoo.dylib", {iOSTarget});
487   EXPECT_EQ(1U, File->reexportedLibraries().size());
488   EXPECT_EQ(Reexport, File->reexportedLibraries().at(0));
489 
490   // Check inlined library.
491   EXPECT_EQ(1U, File->documents().size());
492   TBDReexportFile Document = File->documents().front();
493   Targets = {Document->targets().begin(), Document->targets().end()};
494   EXPECT_EQ(TargetList{iOSTarget}, Targets);
495   EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName());
496   EXPECT_EQ(0U, Document->getSwiftABIVersion());
497   EXPECT_TRUE(Document->isTwoLevelNamespace());
498   EXPECT_FALSE(Document->isApplicationExtensionSafe());
499 
500   ExportedSymbolSeq Exports;
501   for (const auto *Sym : Document->symbols())
502     Exports.emplace_back(
503         ExportedSymbol{Sym->getKind(),
504                        std::string(Sym->getName()),
505                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
506                        Sym->isThreadLocalValue(),
507                        Sym->isData(),
508                        {iOSTarget}});
509 
510   llvm::sort(Exports);
511   ExportedSymbolSeq ExpectedExports = {
512       {SymbolKind::GlobalSymbol, "_funcFoo", false, false, false, {iOSTarget}},
513       {SymbolKind::GlobalSymbol, "_globalVar", false, true, true, {iOSTarget}},
514       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, {iOSTarget}},
515       {SymbolKind::ObjectiveCClass, "ClassB", false, false, true, {iOSTarget}},
516       {SymbolKind::ObjectiveCClass,
517        "ClassData",
518        false,
519        false,
520        true,
521        {iOSTarget}},
522       {SymbolKind::ObjectiveCClassEHType,
523        "ClassA",
524        false,
525        false,
526        true,
527        {iOSTarget}},
528       {SymbolKind::ObjectiveCClassEHType,
529        "ClassB",
530        false,
531        false,
532        true,
533        {iOSTarget}},
534   };
535 
536   EXPECT_EQ(ExpectedExports.size(), Exports.size());
537   EXPECT_TRUE(
538       std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
539 }
540 
541 TEST(TBDv5, WriteFile) {
542   static const char TBDv5File[] = R"({
543 "tapi_tbd_version": 5,
544 "main_library": {
545   "target_info": [
546     {
547       "target": "x86_64-macos",
548       "min_deployment": "10.14"
549     },
550     {
551       "target": "arm64-macos",
552       "min_deployment": "10.14"
553     },
554     {
555       "target": "arm64-maccatalyst",
556       "min_deployment": "12.1"
557     }
558   ],
559   "install_names": [
560     {
561         "name": "@rpath/S/L/F/Foo.framework/Foo"
562     }
563   ],
564   "current_versions": [
565     {
566         "version": "1.2"
567     }
568   ],
569   "compatibility_versions": [
570     { "version": "1.1" }
571   ],
572   "flags": [
573     {
574       "attributes": [
575             "flat_namespace"
576         ]
577     }
578   ],
579   "rpaths": [
580     {
581       "targets": [
582           "x86_64-macos"
583       ],
584       "paths": [
585           "@executable_path/.../Frameworks"
586       ]
587     }
588   ],
589   "parent_umbrellas": [
590     {
591       "umbrella": "System"
592     }
593   ],
594   "allowable_clients": [
595     {
596         "clients": [
597             "ClientA",
598             "ClientB"
599         ]
600     }
601   ],
602   "reexported_libraries": [
603     {
604         "names": [
605             "/u/l/l/libfoo.dylib",
606             "/u/l/l/libbar.dylib"
607         ]
608     }
609   ],
610   "exported_symbols": [
611     {
612         "targets": [
613             "x86_64-macos",
614             "arm64-macos"
615         ],
616         "data": {
617             "global": [
618                 "_global"
619             ],
620             "objc_class": [
621                 "ClassA"
622             ],
623             "weak": [],
624             "thread_local": []
625         },
626         "text": {
627             "global": [
628                 "_func"
629             ],
630             "weak": [],
631             "thread_local": []
632         }
633     },
634     {
635       "targets": [
636           "x86_64-macos"
637       ],
638       "data": {
639           "global": [
640               "_globalVar"
641           ],
642           "objc_class": [
643               "ClassA",
644               "ClassB",
645               "ClassData"
646           ],
647           "objc_eh_type": [
648               "ClassA",
649               "ClassB"
650           ],
651           "objc_ivar": [
652               "ClassA.ivar1",
653               "ClassA.ivar2",
654               "ClassC.ivar1"
655           ]
656       },
657       "text": {
658           "global": [
659               "_funcFoo"
660           ]
661       }
662     }
663   ],
664   "reexported_symbols": [
665     {
666         "data": {
667             "global": [
668                 "_globalRe"
669             ],
670             "objc_class": [
671                 "ClassRexport"
672             ]
673         },
674         "text": {
675             "global": [
676                 "_funcA"
677             ]
678         }
679     }
680   ],
681   "undefined_symbols": [
682     {
683         "targets": [
684             "x86_64-macos"
685         ],
686         "data": {
687             "global": [
688                 "_globalBind"
689             ],
690             "weak": [
691                 "referenced_sym"
692             ]
693         }
694     }
695   ]
696 }})";
697 
698   InterfaceFile File;
699   File.setFileType(FileType::TBD_V5);
700 
701   TargetList AllTargets = {
702       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
703       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(10, 14)),
704       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(12, 1)),
705   };
706   File.addTargets(AllTargets);
707   File.setInstallName("@rpath/S/L/F/Foo.framework/Foo");
708   File.setCurrentVersion(PackedVersion(1, 2, 0));
709   File.setCompatibilityVersion(PackedVersion(1, 1, 0));
710   File.addRPath(AllTargets[0], "@executable_path/.../Frameworks");
711 
712   for (const auto &Targ : AllTargets) {
713     File.addParentUmbrella(Targ, "System");
714     File.addAllowableClient("ClientA", Targ);
715     File.addAllowableClient("ClientB", Targ);
716     File.addReexportedLibrary("/u/l/l/libfoo.dylib", Targ);
717     File.addReexportedLibrary("/u/l/l/libbar.dylib", Targ);
718   }
719 
720   SymbolFlags Flags = SymbolFlags::None;
721   // Exports.
722   File.addSymbol(SymbolKind::GlobalSymbol, "_global",
723                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data);
724   File.addSymbol(SymbolKind::GlobalSymbol, "_func",
725                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Text);
726   File.addSymbol(SymbolKind::ObjectiveCClass, "ClassA",
727                  {AllTargets[0], AllTargets[1]}, Flags | SymbolFlags::Data);
728   File.addSymbol(SymbolKind::GlobalSymbol, "_funcFoo", {AllTargets[0]},
729                  Flags | SymbolFlags::Text);
730   File.addSymbol(SymbolKind::GlobalSymbol, "_globalVar", {AllTargets[0]},
731                  Flags | SymbolFlags::Data);
732   File.addSymbol(SymbolKind::ObjectiveCClass, "ClassData", {AllTargets[0]},
733                  Flags | SymbolFlags::Data);
734   File.addSymbol(SymbolKind::ObjectiveCClassEHType, "ClassA", {AllTargets[0]},
735                  Flags | SymbolFlags::Data);
736   File.addSymbol(SymbolKind::ObjectiveCClassEHType, "ClassB", {AllTargets[0]},
737                  Flags | SymbolFlags::Data);
738   File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassA.ivar1",
739                  {AllTargets[0]}, Flags | SymbolFlags::Data);
740   File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassA.ivar2",
741                  {AllTargets[0]}, Flags | SymbolFlags::Data);
742   File.addSymbol(SymbolKind::ObjectiveCInstanceVariable, "ClassC.ivar1",
743                  {AllTargets[0]}, Flags | SymbolFlags::Data);
744 
745   // Reexports.
746   Flags = SymbolFlags::Rexported;
747   File.addSymbol(SymbolKind::GlobalSymbol, "_globalRe", AllTargets,
748                  Flags | SymbolFlags::Data);
749   File.addSymbol(SymbolKind::GlobalSymbol, "_funcA", AllTargets,
750                  Flags | SymbolFlags::Text);
751   File.addSymbol(SymbolKind::ObjectiveCClass, "ClassRexport", AllTargets,
752                  Flags | SymbolFlags::Data);
753 
754   // Undefineds.
755   Flags = SymbolFlags::Undefined;
756   File.addSymbol(SymbolKind::GlobalSymbol, "_globalBind", {AllTargets[0]},
757                  Flags | SymbolFlags::Data);
758   File.addSymbol(SymbolKind::GlobalSymbol, "referenced_sym", {AllTargets[0]},
759                  Flags | SymbolFlags::Data | SymbolFlags::WeakReferenced);
760 
761   File.setTwoLevelNamespace(false);
762   File.setApplicationExtensionSafe(true);
763 
764   // Write out file then process it back into IF and compare equality
765   // against TBDv5File.
766   SmallString<4096> Buffer;
767   raw_svector_ostream OS(Buffer);
768   Error Result = TextAPIWriter::writeToStream(OS, File);
769   EXPECT_FALSE(Result);
770 
771   Expected<TBDFile> Input =
772       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd"));
773   EXPECT_TRUE(!!Input);
774   TBDFile InputFile = std::move(Input.get());
775 
776   Expected<TBDFile> Output =
777       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
778   EXPECT_TRUE(!!Output);
779   TBDFile OutputFile = std::move(Output.get());
780   EXPECT_EQ(*InputFile, *OutputFile);
781 }
782 
783 TEST(TBDv5, WriteMultipleDocuments) {
784   static const char TBDv5File[] = R"({
785 "tapi_tbd_version": 5,
786 "main_library": {
787   "target_info": [
788     {
789       "target": "armv7-ios",
790       "min_deployment": "11.0"
791     }
792   ],
793   "install_names":[
794     { "name":"/S/L/F/Foo.framework/Foo" }
795   ],
796   "reexported_libraries": [
797     { "names": ["/u/l/l/libfoo.dylib"]
798     }
799   ]
800 },
801 "libraries": [
802   {
803     "target_info": [
804       {
805         "target": "armv7-ios",
806         "min_deployment": "11.0"
807       },
808       {
809         "target": "armv7s-ios",
810         "min_deployment": "11.0"
811       }
812     ],
813     "install_names":[
814       { "name":"/u/l/l/libfoo.dylib" }
815     ],
816     "current_versions": [
817       {
818           "version": "2.1.1"
819       }
820     ],
821     "rpaths": [
822       {
823         "targets": [
824             "armv7-ios"
825         ],
826         "paths": [
827             "@executable_path/.../Frameworks"
828         ]
829       }],
830     "reexported_libraries": [ { "names": ["@rpath/libfoo.dylib"] } ],
831     "flags":[
832       { "attributes": ["not_app_extension_safe"] }
833     ],
834     "exported_symbols": [
835       {
836         "text": {
837           "global": [ "_funcFoo" ]
838         }
839       }
840     ]
841   },
842   {
843     "target_info": [
844       {
845         "target": "armv7-ios",
846         "min_deployment": "11.0"
847       }
848     ],
849     "install_names":[
850       { "name":"@rpath/libfoo.dylib" }
851     ],
852     "exported_symbols": [
853       {
854         "data": {
855           "global": [ "_varFooBaz" ]
856         }
857       }
858     ]
859   }
860 ]})";
861 
862   InterfaceFile File;
863   File.setFileType(FileType::TBD_V5);
864 
865   TargetList AllTargets = {
866       Target(AK_armv7, PLATFORM_IOS, VersionTuple(11, 0)),
867       Target(AK_armv7s, PLATFORM_IOS, VersionTuple(11, 0)),
868   };
869   File.setInstallName("/S/L/F/Foo.framework/Foo");
870   File.addTarget(AllTargets[0]);
871   File.setCurrentVersion(PackedVersion(1, 0, 0));
872   File.setCompatibilityVersion(PackedVersion(1, 0, 0));
873   File.addReexportedLibrary("/u/l/l/libfoo.dylib", AllTargets[0]);
874   File.setTwoLevelNamespace();
875   File.setApplicationExtensionSafe(true);
876 
877   InterfaceFile NestedFile;
878   NestedFile.setFileType(FileType::TBD_V5);
879   NestedFile.setInstallName("/u/l/l/libfoo.dylib");
880   NestedFile.addTargets(AllTargets);
881   NestedFile.setCompatibilityVersion(PackedVersion(1, 0, 0));
882   NestedFile.setTwoLevelNamespace();
883   NestedFile.setApplicationExtensionSafe(false);
884   NestedFile.setCurrentVersion(PackedVersion(2, 1, 1));
885   NestedFile.addRPath(AllTargets[0], "@executable_path/.../Frameworks");
886   for (const auto &Targ : AllTargets)
887     NestedFile.addReexportedLibrary("@rpath/libfoo.dylib", Targ);
888   NestedFile.addSymbol(SymbolKind::GlobalSymbol, "_funcFoo", AllTargets,
889                        SymbolFlags::Text);
890   File.addDocument(std::make_shared<InterfaceFile>(std::move(NestedFile)));
891 
892   InterfaceFile NestedFileB;
893   NestedFileB.setFileType(FileType::TBD_V5);
894   NestedFileB.setInstallName("@rpath/libfoo.dylib");
895   NestedFileB.addTarget(AllTargets[0]);
896   NestedFileB.setCompatibilityVersion(PackedVersion(1, 0, 0));
897   NestedFileB.setCurrentVersion(PackedVersion(1, 0, 0));
898   NestedFileB.setTwoLevelNamespace();
899   NestedFileB.setApplicationExtensionSafe(true);
900   NestedFileB.addSymbol(SymbolKind::GlobalSymbol, "_varFooBaz", {AllTargets[0]},
901                         SymbolFlags::Data);
902   File.addDocument(std::make_shared<InterfaceFile>(std::move(NestedFileB)));
903 
904   // Write out file then process it back into IF and compare equality
905   // against TBDv5File.
906   SmallString<4096> Buffer;
907   raw_svector_ostream OS(Buffer);
908   Error Result = TextAPIWriter::writeToStream(OS, File, /*Compact=*/true);
909   EXPECT_FALSE(Result);
910 
911   Expected<TBDFile> Input =
912       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Input.tbd"));
913   EXPECT_TRUE(!!Input);
914   TBDFile InputFile = std::move(Input.get());
915 
916   Expected<TBDFile> Output =
917       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
918   EXPECT_TRUE(!!Output);
919   TBDFile OutputFile = std::move(Output.get());
920   EXPECT_EQ(*InputFile, *OutputFile);
921 }
922 
923 TEST(TBDv5, Target_Simulator) {
924   static const char TBDv5File[] = R"({
925 "tapi_tbd_version": 5,
926 "main_library": {
927   "target_info": [
928     {
929       "target": "arm64-ios-simulator",
930       "min_deployment": "11.0"
931     },
932     {
933       "target": "x86_64-ios-simulator",
934       "min_deployment": "11.3"
935     }
936   ],
937   "install_names":[
938     { "name":"/S/L/F/Foo.framework/Foo" }
939   ]
940 }})";
941 
942   Expected<TBDFile> Result =
943       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
944   EXPECT_TRUE(!!Result);
945   TBDFile File = std::move(Result.get());
946   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
947   TargetList ExpectedTargets = {
948       Target(AK_x86_64, PLATFORM_IOSSIMULATOR, VersionTuple(11, 3)),
949       Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(14, 0)),
950   };
951   TargetList Targets{File->targets().begin(), File->targets().end()};
952   llvm::sort(Targets);
953   EXPECT_EQ(Targets, ExpectedTargets);
954 
955   SmallString<4096> Buffer;
956   raw_svector_ostream OS(Buffer);
957   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
958   EXPECT_TRUE(!WriteResult);
959 
960   Expected<TBDFile> Output =
961       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
962   EXPECT_TRUE(!!Output);
963   TBDFile WriteResultFile = std::move(Output.get());
964   EXPECT_EQ(*File, *WriteResultFile);
965 }
966 
967 TEST(TBDv5, Target_UnsupportedMinOS) {
968   static const char TBDv5File[] = R"({
969 "tapi_tbd_version": 5,
970 "main_library": {
971   "target_info": [
972     {
973       "target": "arm64-macos",
974       "min_deployment": "10.14"
975     },
976     {
977       "target": "x86_64-macos",
978       "min_deployment": "10.14"
979     }
980   ],
981   "install_names":[
982     { "name":"/S/L/F/Foo.framework/Foo" }
983   ]
984 }})";
985 
986   Expected<TBDFile> Result =
987       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
988   EXPECT_TRUE(!!Result);
989   TBDFile File = std::move(Result.get());
990   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
991   TargetList ExpectedTargets = {
992       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
993       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0)),
994   };
995   TargetList Targets{File->targets().begin(), File->targets().end()};
996   llvm::sort(Targets);
997   EXPECT_EQ(Targets, ExpectedTargets);
998 
999   SmallString<4096> Buffer;
1000   raw_svector_ostream OS(Buffer);
1001   Error WriteResult = TextAPIWriter::writeToStream(OS, *File);
1002   EXPECT_TRUE(!WriteResult);
1003 
1004   Expected<TBDFile> Output =
1005       TextAPIReader::get(MemoryBufferRef(Buffer, "Output.tbd"));
1006   EXPECT_TRUE(!!Output);
1007   TBDFile WriteResultFile = std::move(Output.get());
1008   EXPECT_EQ(*File, *WriteResultFile);
1009 }
1010 
1011 TEST(TBDv5, MisspelledKey) {
1012   static const char TBDv5File[] = R"({
1013 "tapi_tbd_version": 5,
1014 "main_library": {
1015   "target_info": [
1016     {
1017       "target": "arm64-ios-simulator",
1018       "min_deployment": "11.0"
1019     }
1020   ],
1021   "intall_names":[
1022     { "name":"/S/L/F/Foo.framework/Foo" }
1023   ]
1024 }})";
1025 
1026   Expected<TBDFile> Result =
1027       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1028   EXPECT_FALSE(!!Result);
1029   std::string ErrorMessage = toString(Result.takeError());
1030   EXPECT_EQ("invalid install_names section\n", ErrorMessage);
1031 }
1032 
1033 TEST(TBDv5, InvalidVersion) {
1034   static const char TBDv5File[] = R"({
1035 "tapi_tbd_version": 11,
1036 "main_library": {
1037   "target_info": [
1038     {
1039       "target": "arm64-ios-simulator",
1040       "min_deployment": "11.0"
1041     }
1042   ],
1043   "install_names":[
1044     { "name":"/S/L/F/Foo.framework/Foo" }
1045   ]
1046 }})";
1047 
1048   Expected<TBDFile> Result =
1049       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1050   EXPECT_FALSE(!!Result);
1051   std::string ErrorMessage = toString(Result.takeError());
1052   EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage);
1053 }
1054 
1055 TEST(TBDv5, MissingRequiredKey) {
1056   static const char TBDv5File[] = R"({
1057 "main_library": {
1058   "target_info": [
1059     {
1060       "target": "arm64-ios-simulator",
1061       "min_deployment": "11.0"
1062     }
1063   ],
1064   "install_names":[
1065     { "name":"/S/L/F/Foo.framework/Foo" }
1066   ]
1067 }})";
1068 
1069   Expected<TBDFile> Result =
1070       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1071   EXPECT_FALSE(!!Result);
1072   std::string ErrorMessage = toString(Result.takeError());
1073   EXPECT_EQ("invalid tapi_tbd_version section\n", ErrorMessage);
1074 }
1075 
1076 TEST(TBDv5, InvalidSymbols) {
1077   static const char TBDv5File[] = R"({
1078 "tapi_tbd_version": 5,
1079 "main_library": {
1080   "target_info": [
1081     {
1082       "target": "arm64-driverkit",
1083       "min_deployment": "11.0"
1084     }
1085   ],
1086   "install_names":[
1087     { "name":"/S/L/F/Foo.framework/Foo" }
1088   ],
1089   "exported_symbols": [
1090     {
1091       "daa": {
1092         "global": {
1093             "weak": []
1094           }
1095       }
1096     }
1097   ]
1098 }})";
1099 
1100   Expected<TBDFile> Result =
1101       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1102   EXPECT_FALSE(!!Result);
1103   std::string ErrorMessage = toString(Result.takeError());
1104   EXPECT_EQ("invalid exported_symbols section\n", ErrorMessage);
1105 }
1106 
1107 TEST(TBDv5, DefaultMinOS) {
1108   static const char TBDv5File[] = R"({
1109 "tapi_tbd_version": 5,
1110 "main_library": {
1111   "target_info": [
1112     {
1113       "target": "arm64-ios-simulator"
1114     }
1115   ],
1116   "install_names":[
1117     { "name":"/S/L/F/Foo.framework/Foo" }
1118   ]
1119 }})";
1120 
1121   Expected<TBDFile> Result =
1122       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1123   EXPECT_TRUE(!!Result);
1124   TBDFile File = std::move(Result.get());
1125   EXPECT_EQ(FileType::TBD_V5, File->getFileType());
1126   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"), File->getInstallName());
1127   EXPECT_TRUE(File->targets().begin() != File->targets().end());
1128   EXPECT_EQ(*File->targets().begin(),
1129             Target(AK_arm64, PLATFORM_IOSSIMULATOR, VersionTuple(0, 0)));
1130 }
1131 
1132 TEST(TBDv5, InvalidMinOS) {
1133   static const char TBDv5File[] = R"({
1134 "tapi_tbd_version": 5,
1135 "main_library": {
1136   "target_info": [
1137     {
1138       "target": "arm64-ios-simulator",
1139       "min_deployment": "swift-abi"
1140     }
1141   ],
1142   "install_names":[
1143     { "name":"/S/L/F/Foo.framework/Foo" }
1144   ]
1145 }})";
1146 
1147   Expected<TBDFile> Result =
1148       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1149   EXPECT_FALSE(!!Result);
1150   std::string ErrorMessage = toString(Result.takeError());
1151   EXPECT_EQ("invalid min_deployment section\n", ErrorMessage);
1152 }
1153 
1154 TEST(TBDv5, SimSupport) {
1155   static const char TBDv5File[] = R"({
1156 "tapi_tbd_version": 5,
1157 "main_library": {
1158   "target_info": [
1159     {
1160       "target": "arm64-macos",
1161       "min_deployment": "11.1"
1162     }
1163   ],
1164   "install_names":[
1165     { "name":"/S/L/F/Foo.framework/Foo" }
1166   ],
1167   "flags":[
1168     { "attributes": ["sim_support"] }
1169   ]
1170 }})";
1171 
1172   Expected<TBDFile> Result =
1173       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1174   EXPECT_TRUE(!!Result);
1175   Target ExpectedTarget = Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 1));
1176   TBDFile ReadFile = std::move(Result.get());
1177   EXPECT_EQ(FileType::TBD_V5, ReadFile->getFileType());
1178   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1179             ReadFile->getInstallName());
1180   EXPECT_TRUE(ReadFile->targets().begin() != ReadFile->targets().end());
1181   EXPECT_EQ(*ReadFile->targets().begin(), ExpectedTarget);
1182   EXPECT_TRUE(ReadFile->hasSimulatorSupport());
1183 }
1184 
1185 TEST(TBDv5, MergeIF) {
1186   static const char TBDv5FileA[] = R"({
1187 "tapi_tbd_version": 5,
1188 "main_library": {
1189   "target_info": [
1190     {
1191       "target": "x86_64-macos",
1192       "min_deployment": "10.14"
1193     },
1194     {
1195       "target": "arm64-macos",
1196       "min_deployment": "10.14"
1197     },
1198     {
1199       "target": "arm64-maccatalyst",
1200       "min_deployment": "12.1"
1201     }
1202   ],
1203   "flags": [
1204     {
1205       "targets": [
1206             "x86_64-macos"
1207         ],
1208       "attributes": [
1209             "flat_namespace"
1210         ]
1211     }
1212   ],
1213   "install_names": [
1214     {
1215         "name": "/S/L/F/Foo.framework/Foo"
1216     }
1217   ],
1218   "current_versions": [
1219     {
1220         "version": "1.2"
1221     }
1222   ],
1223   "compatibility_versions": [
1224     { "version": "1.1" }
1225   ],
1226   "rpaths": [
1227     {
1228       "targets": [
1229           "x86_64-macos"
1230       ],
1231       "paths": [
1232           "@executable_path/.../Frameworks"
1233       ]
1234     }
1235   ],
1236   "parent_umbrellas": [
1237     {
1238       "umbrella": "System"
1239     }
1240   ],
1241   "allowable_clients": [
1242     {
1243         "clients": [
1244             "ClientA",
1245             "ClientB"
1246         ]
1247     }
1248   ],
1249   "reexported_libraries": [
1250     {
1251         "names": [
1252             "/u/l/l/libfoo.dylib",
1253             "/u/l/l/libbar.dylib"
1254         ]
1255     }
1256   ],
1257   "exported_symbols": [
1258     {
1259         "targets": [
1260             "x86_64-macos",
1261             "arm64-macos"
1262         ],
1263         "data": {
1264             "global": [
1265                 "_global"
1266             ],
1267             "objc_class": [
1268                 "ClassA"
1269             ],
1270             "weak": [],
1271             "thread_local": []
1272         },
1273         "text": {
1274             "global": [
1275                 "_func"
1276             ],
1277             "weak": [],
1278             "thread_local": []
1279         }
1280     },
1281     {
1282       "targets": [
1283           "x86_64-macos"
1284       ],
1285       "data": {
1286           "global": [
1287               "_globalVar"
1288           ],
1289           "objc_class": [
1290               "ClassA",
1291               "ClassB",
1292               "ClassData"
1293           ],
1294           "objc_eh_type": [
1295               "ClassA",
1296               "ClassB"
1297           ],
1298           "objc_ivar": [
1299               "ClassA.ivar1",
1300               "ClassA.ivar2",
1301               "ClassC.ivar1"
1302           ]
1303       },
1304       "text": {
1305           "global": [
1306               "_funcFoo"
1307           ]
1308       }
1309     }
1310   ],
1311   "reexported_symbols": [
1312     {
1313         "targets": [
1314             "x86_64-macos",
1315             "arm64-macos"
1316         ],
1317         "data": {
1318             "global": [
1319                 "_globalRe"
1320             ],
1321             "objc_class": [
1322                 "ClassRexport"
1323             ]
1324         },
1325         "text": {
1326             "global": [
1327                 "_funcA"
1328             ]
1329         }
1330     }
1331   ],
1332   "undefined_symbols": [
1333     {
1334         "targets": [
1335             "x86_64-macos"
1336         ],
1337         "data": {
1338             "global": [
1339                 "_globalBind"
1340             ],
1341             "weak": [
1342                 "referenced_sym"
1343             ]
1344         }
1345     }
1346   ]
1347 },
1348 "libraries": []
1349 })";
1350 
1351   static const char TBDv5FileB[] = R"({
1352 "tapi_tbd_version": 5,
1353 "main_library": {
1354   "target_info": [
1355     {
1356       "target": "x86_64-macos",
1357       "min_deployment": "10.14"
1358     },
1359     {
1360       "target": "arm64-macos",
1361       "min_deployment": "10.14"
1362     },
1363     {
1364       "target": "arm64-maccatalyst",
1365       "min_deployment": "12.1"
1366     }
1367   ],
1368   "flags": [
1369     {
1370       "targets": [
1371             "x86_64-macos"
1372         ],
1373       "attributes": [
1374             "flat_namespace"
1375         ]
1376     }
1377   ],
1378   "install_names": [
1379     {
1380         "name": "/S/L/F/Foo.framework/Foo"
1381     }
1382   ],
1383   "current_versions": [
1384     {
1385         "version": "1.2"
1386     }
1387   ],
1388   "compatibility_versions": [
1389     { "version": "1.1" }
1390   ],
1391   "exported_symbols": [
1392     {
1393         "targets": [
1394             "x86_64-macos",
1395             "arm64-macos"
1396         ],
1397         "data": {
1398             "global": [
1399                 "_globalZ"
1400             ],
1401             "objc_class": [
1402                 "ClassZ"
1403             ],
1404             "weak": [],
1405             "thread_local": []
1406         },
1407         "text": {
1408             "global": [
1409                 "_funcZ"
1410             ],
1411             "weak": [],
1412             "thread_local": []
1413         }
1414     },
1415     {
1416       "targets": [
1417           "x86_64-macos"
1418       ],
1419       "data": {
1420           "global": [
1421               "_globalVarZ"
1422           ],
1423           "objc_class": [
1424               "ClassZ",
1425               "ClassF"
1426           ],
1427           "objc_eh_type": [
1428               "ClassZ",
1429               "ClassF"
1430           ],
1431           "objc_ivar": [
1432               "ClassZ.ivar1",
1433               "ClassZ.ivar2",
1434               "ClassF.ivar1"
1435           ]
1436       },
1437       "text": {
1438           "global": [
1439               "_funcFooZ"
1440           ]
1441       }
1442     }
1443   ]
1444 },
1445 "libraries": []
1446 })";
1447 
1448   Expected<TBDFile> ResultA =
1449       TextAPIReader::get(MemoryBufferRef(TBDv5FileA, "Test.tbd"));
1450   EXPECT_TRUE(!!ResultA);
1451   TBDFile FileA = std::move(ResultA.get());
1452 
1453   Expected<TBDFile> ResultB =
1454       TextAPIReader::get(MemoryBufferRef(TBDv5FileB, "Test.tbd"));
1455   EXPECT_TRUE(!!ResultB);
1456   TBDFile FileB = std::move(ResultB.get());
1457 
1458   Expected<TBDFile> MergedResult = FileA->merge(FileB.get());
1459   EXPECT_TRUE(!!MergedResult);
1460   TBDFile MergedFile = std::move(MergedResult.get());
1461 
1462   EXPECT_EQ(FileType::TBD_V5, MergedFile->getFileType());
1463   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1464             MergedFile->getInstallName());
1465   TargetList AllTargets = {
1466       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
1467       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1468       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1469   };
1470   EXPECT_EQ(mapToPlatformSet(AllTargets), MergedFile->getPlatforms());
1471   EXPECT_EQ(mapToArchitectureSet(AllTargets), MergedFile->getArchitectures());
1472   EXPECT_EQ(PackedVersion(1, 2, 0), MergedFile->getCurrentVersion());
1473   EXPECT_EQ(PackedVersion(1, 1, 0), MergedFile->getCompatibilityVersion());
1474   EXPECT_TRUE(MergedFile->isApplicationExtensionSafe());
1475   EXPECT_FALSE(MergedFile->isTwoLevelNamespace());
1476   EXPECT_EQ(0U, MergedFile->documents().size());
1477   InterfaceFileRef ClientA("ClientA", AllTargets);
1478   InterfaceFileRef ClientB("ClientB", AllTargets);
1479   EXPECT_EQ(2U, MergedFile->allowableClients().size());
1480   EXPECT_EQ(ClientA, MergedFile->allowableClients().at(0));
1481   EXPECT_EQ(ClientB, MergedFile->allowableClients().at(1));
1482 
1483   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
1484   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
1485   EXPECT_EQ(2U, MergedFile->reexportedLibraries().size());
1486   EXPECT_EQ(ReexportA, MergedFile->reexportedLibraries().at(0));
1487   EXPECT_EQ(ReexportB, MergedFile->reexportedLibraries().at(1));
1488 
1489   TargetToAttr RPaths = {
1490       {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"},
1491   };
1492   EXPECT_EQ(RPaths, MergedFile->rpaths());
1493 
1494   TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"},
1495                             {Target(AK_arm64, PLATFORM_MACOS), "System"},
1496                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
1497   EXPECT_EQ(Umbrellas, MergedFile->umbrellas());
1498 
1499   ExportedSymbolSeq Exports, Reexports, Undefineds;
1500   for (const auto *Sym : MergedFile->symbols()) {
1501     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
1502     ExportedSymbol Temp =
1503         ExportedSymbol{Sym->getKind(),
1504                        std::string(Sym->getName()),
1505                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
1506                        Sym->isThreadLocalValue(),
1507                        Sym->isData(),
1508                        SymTargets};
1509     if (Sym->isUndefined())
1510       Undefineds.emplace_back(std::move(Temp));
1511     else
1512       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
1513                           : Exports.emplace_back(std::move(Temp));
1514   }
1515   llvm::sort(Exports);
1516   llvm::sort(Reexports);
1517   llvm::sort(Undefineds);
1518 
1519   TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
1520                              Target(AK_arm64, PLATFORM_MACOS)};
1521 
1522   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
1523       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
1524       {SymbolKind::GlobalSymbol,
1525        "_funcFoo",
1526        false,
1527        false,
1528        false,
1529        {Target(AK_x86_64, PLATFORM_MACOS)}},
1530       {SymbolKind::GlobalSymbol,
1531        "_funcFooZ",
1532        false,
1533        false,
1534        false,
1535        {Target(AK_x86_64, PLATFORM_MACOS)}},
1536       {SymbolKind::GlobalSymbol, "_funcZ", false, false, false, MacOSTargets},
1537       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
1538       {SymbolKind::GlobalSymbol,
1539        "_globalVar",
1540        false,
1541        false,
1542        true,
1543        {Target(AK_x86_64, PLATFORM_MACOS)}},
1544       {SymbolKind::GlobalSymbol,
1545        "_globalVarZ",
1546        false,
1547        false,
1548        true,
1549        {Target(AK_x86_64, PLATFORM_MACOS)}},
1550       {SymbolKind::GlobalSymbol, "_globalZ", false, false, true, MacOSTargets},
1551       {SymbolKind::ObjectiveCClass,
1552        "ClassA",
1553        false,
1554        false,
1555        true,
1556        {Target(AK_x86_64, PLATFORM_MACOS)}},
1557       {SymbolKind::ObjectiveCClass,
1558        "ClassB",
1559        false,
1560        false,
1561        true,
1562        {Target(AK_x86_64, PLATFORM_MACOS)}},
1563       {SymbolKind::ObjectiveCClass,
1564        "ClassData",
1565        false,
1566        false,
1567        true,
1568        {Target(AK_x86_64, PLATFORM_MACOS)}},
1569       {SymbolKind::ObjectiveCClass,
1570        "ClassF",
1571        false,
1572        false,
1573        true,
1574        {Target(AK_x86_64, PLATFORM_MACOS)}},
1575       {SymbolKind::ObjectiveCClass,
1576        "ClassZ",
1577        false,
1578        false,
1579        true,
1580        {Target(AK_x86_64, PLATFORM_MACOS)}},
1581       {SymbolKind::ObjectiveCClassEHType,
1582        "ClassA",
1583        false,
1584        false,
1585        true,
1586        {Target(AK_x86_64, PLATFORM_MACOS)}},
1587       {SymbolKind::ObjectiveCClassEHType,
1588        "ClassB",
1589        false,
1590        false,
1591        true,
1592        {Target(AK_x86_64, PLATFORM_MACOS)}},
1593       {SymbolKind::ObjectiveCClassEHType,
1594        "ClassF",
1595        false,
1596        false,
1597        true,
1598        {Target(AK_x86_64, PLATFORM_MACOS)}},
1599       {SymbolKind::ObjectiveCClassEHType,
1600        "ClassZ",
1601        false,
1602        false,
1603        true,
1604        {Target(AK_x86_64, PLATFORM_MACOS)}},
1605       {SymbolKind::ObjectiveCInstanceVariable,
1606        "ClassA.ivar1",
1607        false,
1608        false,
1609        true,
1610        {Target(AK_x86_64, PLATFORM_MACOS)}},
1611       {SymbolKind::ObjectiveCInstanceVariable,
1612        "ClassA.ivar2",
1613        false,
1614        false,
1615        true,
1616        {Target(AK_x86_64, PLATFORM_MACOS)}},
1617       {SymbolKind::ObjectiveCInstanceVariable,
1618        "ClassC.ivar1",
1619        false,
1620        false,
1621        true,
1622        {Target(AK_x86_64, PLATFORM_MACOS)}},
1623       {SymbolKind::ObjectiveCInstanceVariable,
1624        "ClassF.ivar1",
1625        false,
1626        false,
1627        true,
1628        {Target(AK_x86_64, PLATFORM_MACOS)}},
1629       {SymbolKind::ObjectiveCInstanceVariable,
1630        "ClassZ.ivar1",
1631        false,
1632        false,
1633        true,
1634        {Target(AK_x86_64, PLATFORM_MACOS)}},
1635       {SymbolKind::ObjectiveCInstanceVariable,
1636        "ClassZ.ivar2",
1637        false,
1638        false,
1639        true,
1640        {Target(AK_x86_64, PLATFORM_MACOS)}},
1641   };
1642 
1643   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
1644       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
1645       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
1646       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
1647        MacOSTargets},
1648   };
1649 
1650   std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
1651       {SymbolKind::GlobalSymbol,
1652        "_globalBind",
1653        false,
1654        false,
1655        true,
1656        {Target(AK_x86_64, PLATFORM_MACOS)}},
1657       {SymbolKind::GlobalSymbol,
1658        "referenced_sym",
1659        true,
1660        false,
1661        true,
1662        {Target(AK_x86_64, PLATFORM_MACOS)}},
1663   };
1664 
1665   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
1666   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
1667   EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
1668   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
1669                          std::begin(ExpectedExportedSymbols)));
1670   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
1671                          std::begin(ExpectedReexportedSymbols)));
1672   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
1673                          std::begin(ExpectedUndefinedSymbols)));
1674 }
1675 
1676 TEST(TBDv5, ExtractIF) {
1677   static const char TBDv5File[] = R"({
1678 "tapi_tbd_version": 5,
1679 "main_library": {
1680   "target_info": [
1681     {
1682       "target": "x86_64-macos",
1683       "min_deployment": "10.14"
1684     },
1685     {
1686       "target": "arm64-macos",
1687       "min_deployment": "10.14"
1688     },
1689     {
1690       "target": "arm64-maccatalyst",
1691       "min_deployment": "12.1"
1692     }
1693   ],
1694   "flags": [
1695     {
1696       "targets": [
1697             "x86_64-macos"
1698         ],
1699       "attributes": [
1700             "flat_namespace"
1701         ]
1702     }
1703   ],
1704   "install_names": [
1705     {
1706         "name": "/S/L/F/Foo.framework/Foo"
1707     }
1708   ],
1709   "current_versions": [
1710     {
1711         "version": "1.2"
1712     }
1713   ],
1714   "compatibility_versions": [
1715     { "version": "1.1" }
1716   ],
1717   "rpaths": [
1718     {
1719       "targets": [
1720           "x86_64-macos"
1721       ],
1722       "paths": [
1723           "@executable_path/.../Frameworks"
1724       ]
1725     }
1726   ],
1727   "parent_umbrellas": [
1728     {
1729       "umbrella": "System"
1730     }
1731   ],
1732   "allowable_clients": [
1733     {
1734         "clients": [
1735             "ClientA",
1736             "ClientB"
1737         ]
1738     }
1739   ],
1740   "reexported_libraries": [
1741     {
1742         "names": [
1743             "/u/l/l/libfoo.dylib",
1744             "/u/l/l/libbar.dylib"
1745         ]
1746     }
1747   ],
1748   "exported_symbols": [
1749     {
1750         "targets": [
1751             "x86_64-macos",
1752             "arm64-macos"
1753         ],
1754         "data": {
1755             "global": [
1756                 "_global"
1757             ],
1758             "objc_class": [
1759                 "ClassA"
1760             ],
1761             "weak": [],
1762             "thread_local": []
1763         },
1764         "text": {
1765             "global": [
1766                 "_func"
1767             ],
1768             "weak": [],
1769             "thread_local": []
1770         }
1771     },
1772     {
1773       "targets": [
1774           "x86_64-macos"
1775       ],
1776       "data": {
1777           "global": [
1778               "_globalVar"
1779           ],
1780           "objc_class": [
1781               "ClassA",
1782               "ClassB",
1783               "ClassData"
1784           ],
1785           "objc_eh_type": [
1786               "ClassA",
1787               "ClassB"
1788           ],
1789           "objc_ivar": [
1790               "ClassA.ivar1",
1791               "ClassA.ivar2",
1792               "ClassC.ivar1"
1793           ]
1794       },
1795       "text": {
1796           "global": [
1797               "_funcFoo"
1798           ]
1799       }
1800     }
1801   ],
1802   "reexported_symbols": [
1803     {
1804         "targets": [
1805             "x86_64-macos",
1806             "arm64-macos"
1807         ],
1808         "data": {
1809             "global": [
1810                 "_globalRe"
1811             ],
1812             "objc_class": [
1813                 "ClassRexport"
1814             ]
1815         },
1816         "text": {
1817             "global": [
1818                 "_funcA"
1819             ]
1820         }
1821     }
1822   ],
1823   "undefined_symbols": [
1824     {
1825         "targets": [
1826             "x86_64-macos"
1827         ],
1828         "data": {
1829             "global": [
1830                 "_globalBind"
1831             ],
1832             "weak": [
1833                 "referenced_sym"
1834             ]
1835         }
1836     }
1837   ]
1838 },
1839 "libraries": []
1840 })";
1841 
1842   Expected<TBDFile> Result =
1843       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1844   EXPECT_TRUE(!!Result);
1845   TBDFile File = std::move(Result.get());
1846 
1847   Expected<TBDFile> ExtractedResult = File->extract(AK_arm64);
1848   EXPECT_TRUE(!!ExtractedResult);
1849   TBDFile ExtractedFile = std::move(ExtractedResult.get());
1850 
1851   EXPECT_EQ(FileType::TBD_V5, ExtractedFile->getFileType());
1852   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1853             ExtractedFile->getInstallName());
1854 
1855   TargetList AllTargets = {
1856       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1857       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1858   };
1859   EXPECT_EQ(mapToPlatformSet(AllTargets), ExtractedFile->getPlatforms());
1860   EXPECT_EQ(mapToArchitectureSet(AllTargets),
1861             ExtractedFile->getArchitectures());
1862 
1863   EXPECT_EQ(PackedVersion(1, 2, 0), ExtractedFile->getCurrentVersion());
1864   EXPECT_EQ(PackedVersion(1, 1, 0), ExtractedFile->getCompatibilityVersion());
1865   EXPECT_TRUE(ExtractedFile->isApplicationExtensionSafe());
1866   EXPECT_FALSE(ExtractedFile->isTwoLevelNamespace());
1867   EXPECT_EQ(0U, ExtractedFile->documents().size());
1868 
1869   InterfaceFileRef ClientA("ClientA", AllTargets);
1870   InterfaceFileRef ClientB("ClientB", AllTargets);
1871   EXPECT_EQ(2U, ExtractedFile->allowableClients().size());
1872   EXPECT_EQ(ClientA, ExtractedFile->allowableClients().at(0));
1873   EXPECT_EQ(ClientB, ExtractedFile->allowableClients().at(1));
1874 
1875   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
1876   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
1877   EXPECT_EQ(2U, ExtractedFile->reexportedLibraries().size());
1878   EXPECT_EQ(ReexportA, ExtractedFile->reexportedLibraries().at(0));
1879   EXPECT_EQ(ReexportB, ExtractedFile->reexportedLibraries().at(1));
1880 
1881   EXPECT_EQ(0u, ExtractedFile->rpaths().size());
1882 
1883   TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
1884                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
1885   EXPECT_EQ(Umbrellas, ExtractedFile->umbrellas());
1886 
1887   ExportedSymbolSeq Exports, Reexports, Undefineds;
1888   for (const auto *Sym : ExtractedFile->symbols()) {
1889     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
1890     ExportedSymbol Temp =
1891         ExportedSymbol{Sym->getKind(),
1892                        std::string(Sym->getName()),
1893                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
1894                        Sym->isThreadLocalValue(),
1895                        Sym->isData(),
1896                        SymTargets};
1897     if (Sym->isUndefined())
1898       Undefineds.emplace_back(std::move(Temp));
1899     else
1900       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
1901                           : Exports.emplace_back(std::move(Temp));
1902   }
1903   llvm::sort(Exports);
1904   llvm::sort(Reexports);
1905   llvm::sort(Undefineds);
1906 
1907   TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
1908 
1909   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
1910       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
1911       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
1912       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
1913   };
1914   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
1915       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
1916       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
1917       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
1918        MacOSTargets},
1919   };
1920 
1921   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
1922   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
1923   EXPECT_EQ(0U, Undefineds.size());
1924   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
1925                          std::begin(ExpectedExportedSymbols)));
1926   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
1927                          std::begin(ExpectedReexportedSymbols)));
1928 }
1929 
1930 TEST(TBDv5, RemoveIF) {
1931   static const char TBDv5File[] = R"({
1932 "tapi_tbd_version": 5,
1933 "main_library": {
1934   "target_info": [
1935     {
1936       "target": "x86_64-macos",
1937       "min_deployment": "10.14"
1938     },
1939     {
1940       "target": "arm64-macos",
1941       "min_deployment": "10.14"
1942     },
1943     {
1944       "target": "arm64-maccatalyst",
1945       "min_deployment": "12.1"
1946     }
1947   ],
1948   "flags": [
1949     {
1950       "targets": [
1951             "x86_64-macos"
1952         ],
1953       "attributes": [
1954             "flat_namespace"
1955         ]
1956     }
1957   ],
1958   "install_names": [
1959     {
1960         "name": "/S/L/F/Foo.framework/Foo"
1961     }
1962   ],
1963   "current_versions": [
1964     {
1965         "version": "1.2"
1966     }
1967   ],
1968   "compatibility_versions": [
1969     { "version": "1.1" }
1970   ],
1971   "rpaths": [
1972     {
1973       "targets": [
1974           "x86_64-macos"
1975       ],
1976       "paths": [
1977           "@executable_path/.../Frameworks"
1978       ]
1979     }
1980   ],
1981   "parent_umbrellas": [
1982     {
1983       "umbrella": "System"
1984     }
1985   ],
1986   "allowable_clients": [
1987     {
1988         "clients": [
1989             "ClientA",
1990             "ClientB"
1991         ]
1992     }
1993   ],
1994   "reexported_libraries": [
1995     {
1996         "names": [
1997             "/u/l/l/libfoo.dylib",
1998             "/u/l/l/libbar.dylib"
1999         ]
2000     }
2001   ],
2002   "exported_symbols": [
2003     {
2004         "targets": [
2005             "x86_64-macos",
2006             "arm64-macos"
2007         ],
2008         "data": {
2009             "global": [
2010                 "_global"
2011             ],
2012             "objc_class": [
2013                 "ClassA"
2014             ],
2015             "weak": [],
2016             "thread_local": []
2017         },
2018         "text": {
2019             "global": [
2020                 "_func"
2021             ],
2022             "weak": [],
2023             "thread_local": []
2024         }
2025     },
2026     {
2027       "targets": [
2028           "x86_64-macos"
2029       ],
2030       "data": {
2031           "global": [
2032               "_globalVar"
2033           ],
2034           "objc_class": [
2035               "ClassA",
2036               "ClassB",
2037               "ClassData"
2038           ],
2039           "objc_eh_type": [
2040               "ClassA",
2041               "ClassB"
2042           ],
2043           "objc_ivar": [
2044               "ClassA.ivar1",
2045               "ClassA.ivar2",
2046               "ClassC.ivar1"
2047           ]
2048       },
2049       "text": {
2050           "global": [
2051               "_funcFoo"
2052           ]
2053       }
2054     }
2055   ],
2056   "reexported_symbols": [
2057     {
2058         "targets": [
2059             "x86_64-macos",
2060             "arm64-macos"
2061         ],
2062         "data": {
2063             "global": [
2064                 "_globalRe"
2065             ],
2066             "objc_class": [
2067                 "ClassRexport"
2068             ]
2069         },
2070         "text": {
2071             "global": [
2072                 "_funcA"
2073             ]
2074         }
2075     }
2076   ],
2077   "undefined_symbols": [
2078     {
2079         "targets": [
2080             "x86_64-macos"
2081         ],
2082         "data": {
2083             "global": [
2084                 "_globalBind"
2085             ],
2086             "weak": [
2087                 "referenced_sym"
2088             ]
2089         }
2090     }
2091   ]
2092 },
2093 "libraries": []
2094 })";
2095 
2096   Expected<TBDFile> Result =
2097       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
2098   EXPECT_TRUE(!!Result);
2099   TBDFile File = std::move(Result.get());
2100 
2101   Expected<TBDFile> RemovedResult = File->remove(AK_x86_64);
2102   EXPECT_TRUE(!!RemovedResult);
2103   TBDFile RemovedFile = std::move(RemovedResult.get());
2104 
2105   EXPECT_EQ(FileType::TBD_V5, RemovedFile->getFileType());
2106   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2107             RemovedFile->getInstallName());
2108 
2109   TargetList AllTargets = {
2110       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
2111       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
2112   };
2113   EXPECT_EQ(mapToPlatformSet(AllTargets), RemovedFile->getPlatforms());
2114   EXPECT_EQ(mapToArchitectureSet(AllTargets), RemovedFile->getArchitectures());
2115 
2116   EXPECT_EQ(PackedVersion(1, 2, 0), RemovedFile->getCurrentVersion());
2117   EXPECT_EQ(PackedVersion(1, 1, 0), RemovedFile->getCompatibilityVersion());
2118   EXPECT_TRUE(RemovedFile->isApplicationExtensionSafe());
2119   EXPECT_FALSE(RemovedFile->isTwoLevelNamespace());
2120   EXPECT_EQ(0U, RemovedFile->documents().size());
2121 
2122   InterfaceFileRef ClientA("ClientA", AllTargets);
2123   InterfaceFileRef ClientB("ClientB", AllTargets);
2124   EXPECT_EQ(2U, RemovedFile->allowableClients().size());
2125   EXPECT_EQ(ClientA, RemovedFile->allowableClients().at(0));
2126   EXPECT_EQ(ClientB, RemovedFile->allowableClients().at(1));
2127 
2128   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2129   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2130   EXPECT_EQ(2U, RemovedFile->reexportedLibraries().size());
2131   EXPECT_EQ(ReexportA, RemovedFile->reexportedLibraries().at(0));
2132   EXPECT_EQ(ReexportB, RemovedFile->reexportedLibraries().at(1));
2133 
2134   EXPECT_EQ(0u, RemovedFile->rpaths().size());
2135 
2136   TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
2137                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
2138   EXPECT_EQ(Umbrellas, RemovedFile->umbrellas());
2139 
2140   ExportedSymbolSeq Exports, Reexports, Undefineds;
2141   for (const auto *Sym : RemovedFile->symbols()) {
2142     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2143     ExportedSymbol Temp =
2144         ExportedSymbol{Sym->getKind(),
2145                        std::string(Sym->getName()),
2146                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2147                        Sym->isThreadLocalValue(),
2148                        Sym->isData(),
2149                        SymTargets};
2150     if (Sym->isUndefined())
2151       Undefineds.emplace_back(std::move(Temp));
2152     else
2153       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
2154                           : Exports.emplace_back(std::move(Temp));
2155   }
2156   llvm::sort(Exports);
2157   llvm::sort(Reexports);
2158   llvm::sort(Undefineds);
2159 
2160   TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
2161 
2162   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
2163       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
2164       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
2165       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
2166   };
2167   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
2168       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
2169       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
2170       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
2171        MacOSTargets},
2172   };
2173 
2174   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
2175   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
2176   EXPECT_EQ(0U, Undefineds.size());
2177   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
2178                          std::begin(ExpectedExportedSymbols)));
2179   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
2180                          std::begin(ExpectedReexportedSymbols)));
2181 }
2182 
2183 TEST(TBDv5, InlineIF) {
2184   static const char UmbrellaFile[] = R"({
2185 "tapi_tbd_version": 5,
2186 "main_library": {
2187   "target_info": [
2188     {
2189       "target": "x86_64-macos",
2190       "min_deployment": "10.14"
2191     },
2192     {
2193       "target": "arm64-macos",
2194       "min_deployment": "10.14"
2195     }
2196   ],
2197   "install_names": [
2198     {
2199         "name": "/S/L/F/Foo.framework/Foo"
2200     }
2201   ],
2202   "current_versions": [
2203     {
2204         "version": "1.2"
2205     }
2206   ],
2207   "reexported_libraries": [
2208     {
2209         "names": [
2210             "/u/l/l/libfoo.dylib",
2211             "/u/l/l/libbar.dylib"
2212         ]
2213     }
2214   ]
2215 }})";
2216 
2217   static const char ReexportFile[] = R"({
2218 "tapi_tbd_version": 5,
2219 "main_library": {
2220   "target_info": [
2221     {
2222       "target": "x86_64-macos",
2223       "min_deployment": "10.14"
2224     },
2225     {
2226       "target": "arm64-macos",
2227       "min_deployment": "10.14"
2228     }
2229   ],
2230   "install_names": [
2231     {
2232         "name" : "/u/l/l/libfoo.dylib"
2233     }
2234   ],
2235   "current_versions": [
2236     {
2237         "version": "1"
2238     }
2239   ],
2240   "rpaths": [
2241     {
2242       "targets": [
2243           "x86_64-macos"
2244       ],
2245       "paths": [
2246           "@executable_path/.../Frameworks"
2247       ]
2248     }
2249   ],
2250   "exported_symbols": [
2251     {
2252         "targets": [
2253             "x86_64-macos",
2254             "arm64-macos"
2255         ],
2256         "data": {
2257             "global": [
2258                 "_global"
2259             ],
2260             "objc_class": [
2261                 "ClassA"
2262             ],
2263             "weak": [],
2264             "thread_local": []
2265         }
2266     }
2267   ]}})";
2268 
2269   Expected<TBDFile> UmbrellaResult =
2270       TextAPIReader::get(MemoryBufferRef(UmbrellaFile, "Test.tbd"));
2271   EXPECT_TRUE(!!UmbrellaResult);
2272   TBDFile Umbrella = std::move(UmbrellaResult.get());
2273 
2274   Expected<TBDFile> ReexportResult =
2275       TextAPIReader::get(MemoryBufferRef(ReexportFile, "Test.tbd"));
2276   EXPECT_TRUE(!!ReexportResult);
2277   TBDReexportFile Reexport = std::move(ReexportResult.get());
2278   Umbrella->inlineLibrary(Reexport);
2279 
2280   EXPECT_EQ(FileType::TBD_V5, Umbrella->getFileType());
2281   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2282             Umbrella->getInstallName());
2283 
2284   TargetList AllTargets = {
2285       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
2286       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
2287   };
2288   EXPECT_EQ(mapToPlatformSet(AllTargets), Umbrella->getPlatforms());
2289   EXPECT_EQ(mapToArchitectureSet(AllTargets), Umbrella->getArchitectures());
2290 
2291   EXPECT_EQ(PackedVersion(1, 2, 0), Umbrella->getCurrentVersion());
2292   EXPECT_EQ(PackedVersion(1, 0, 0), Umbrella->getCompatibilityVersion());
2293   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2294   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2295   EXPECT_EQ(2U, Umbrella->reexportedLibraries().size());
2296   EXPECT_EQ(ReexportA, Umbrella->reexportedLibraries().at(0));
2297   EXPECT_EQ(ReexportB, Umbrella->reexportedLibraries().at(1));
2298   EXPECT_EQ(1U, Umbrella->documents().size());
2299 
2300   TBDReexportFile Document = Umbrella->documents().front();
2301   EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName());
2302   EXPECT_EQ(0U, Document->getSwiftABIVersion());
2303   EXPECT_TRUE(Document->isTwoLevelNamespace());
2304   EXPECT_TRUE(Document->isApplicationExtensionSafe());
2305   EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion());
2306   EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion());
2307 
2308   ExportedSymbolSeq Exports;
2309   for (const auto *Sym : Document->symbols()) {
2310     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2311     Exports.emplace_back(
2312         ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
2313                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2314                        Sym->isThreadLocalValue(), Sym->isData(), SymTargets});
2315   }
2316   llvm::sort(Exports);
2317 
2318   ExportedSymbolSeq ExpectedExports = {
2319       {SymbolKind::GlobalSymbol, "_global", false, false, true, AllTargets},
2320       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, AllTargets},
2321   };
2322   EXPECT_EQ(ExpectedExports.size(), Exports.size());
2323   EXPECT_TRUE(
2324       std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
2325 }
2326 } // end namespace TBDv5
2327