xref: /llvm-project/llvm/unittests/TextAPI/TextStubV5Tests.cpp (revision 3b73139150be1f62e1f79c54a7d4bb46940ad50f)
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, MergeIF) {
1155   static const char TBDv5FileA[] = R"({
1156 "tapi_tbd_version": 5,
1157 "main_library": {
1158   "target_info": [
1159     {
1160       "target": "x86_64-macos",
1161       "min_deployment": "10.14"
1162     },
1163     {
1164       "target": "arm64-macos",
1165       "min_deployment": "10.14"
1166     },
1167     {
1168       "target": "arm64-maccatalyst",
1169       "min_deployment": "12.1"
1170     }
1171   ],
1172   "flags": [
1173     {
1174       "targets": [
1175             "x86_64-macos"
1176         ],
1177       "attributes": [
1178             "flat_namespace"
1179         ]
1180     }
1181   ],
1182   "install_names": [
1183     {
1184         "name": "/S/L/F/Foo.framework/Foo"
1185     }
1186   ],
1187   "current_versions": [
1188     {
1189         "version": "1.2"
1190     }
1191   ],
1192   "compatibility_versions": [
1193     { "version": "1.1" }
1194   ],
1195   "rpaths": [
1196     {
1197       "targets": [
1198           "x86_64-macos"
1199       ],
1200       "paths": [
1201           "@executable_path/.../Frameworks"
1202       ]
1203     }
1204   ],
1205   "parent_umbrellas": [
1206     {
1207       "umbrella": "System"
1208     }
1209   ],
1210   "allowable_clients": [
1211     {
1212         "clients": [
1213             "ClientA",
1214             "ClientB"
1215         ]
1216     }
1217   ],
1218   "reexported_libraries": [
1219     {
1220         "names": [
1221             "/u/l/l/libfoo.dylib",
1222             "/u/l/l/libbar.dylib"
1223         ]
1224     }
1225   ],
1226   "exported_symbols": [
1227     {
1228         "targets": [
1229             "x86_64-macos",
1230             "arm64-macos"
1231         ],
1232         "data": {
1233             "global": [
1234                 "_global"
1235             ],
1236             "objc_class": [
1237                 "ClassA"
1238             ],
1239             "weak": [],
1240             "thread_local": []
1241         },
1242         "text": {
1243             "global": [
1244                 "_func"
1245             ],
1246             "weak": [],
1247             "thread_local": []
1248         }
1249     },
1250     {
1251       "targets": [
1252           "x86_64-macos"
1253       ],
1254       "data": {
1255           "global": [
1256               "_globalVar"
1257           ],
1258           "objc_class": [
1259               "ClassA",
1260               "ClassB",
1261               "ClassData"
1262           ],
1263           "objc_eh_type": [
1264               "ClassA",
1265               "ClassB"
1266           ],
1267           "objc_ivar": [
1268               "ClassA.ivar1",
1269               "ClassA.ivar2",
1270               "ClassC.ivar1"
1271           ]
1272       },
1273       "text": {
1274           "global": [
1275               "_funcFoo"
1276           ]
1277       }
1278     }
1279   ],
1280   "reexported_symbols": [
1281     {
1282         "targets": [
1283             "x86_64-macos",
1284             "arm64-macos"
1285         ],
1286         "data": {
1287             "global": [
1288                 "_globalRe"
1289             ],
1290             "objc_class": [
1291                 "ClassRexport"
1292             ]
1293         },
1294         "text": {
1295             "global": [
1296                 "_funcA"
1297             ]
1298         }
1299     }
1300   ],
1301   "undefined_symbols": [
1302     {
1303         "targets": [
1304             "x86_64-macos"
1305         ],
1306         "data": {
1307             "global": [
1308                 "_globalBind"
1309             ],
1310             "weak": [
1311                 "referenced_sym"
1312             ]
1313         }
1314     }
1315   ]
1316 },
1317 "libraries": []
1318 })";
1319 
1320   static const char TBDv5FileB[] = R"({
1321 "tapi_tbd_version": 5,
1322 "main_library": {
1323   "target_info": [
1324     {
1325       "target": "x86_64-macos",
1326       "min_deployment": "10.14"
1327     },
1328     {
1329       "target": "arm64-macos",
1330       "min_deployment": "10.14"
1331     },
1332     {
1333       "target": "arm64-maccatalyst",
1334       "min_deployment": "12.1"
1335     }
1336   ],
1337   "flags": [
1338     {
1339       "targets": [
1340             "x86_64-macos"
1341         ],
1342       "attributes": [
1343             "flat_namespace"
1344         ]
1345     }
1346   ],
1347   "install_names": [
1348     {
1349         "name": "/S/L/F/Foo.framework/Foo"
1350     }
1351   ],
1352   "current_versions": [
1353     {
1354         "version": "1.2"
1355     }
1356   ],
1357   "compatibility_versions": [
1358     { "version": "1.1" }
1359   ],
1360   "exported_symbols": [
1361     {
1362         "targets": [
1363             "x86_64-macos",
1364             "arm64-macos"
1365         ],
1366         "data": {
1367             "global": [
1368                 "_globalZ"
1369             ],
1370             "objc_class": [
1371                 "ClassZ"
1372             ],
1373             "weak": [],
1374             "thread_local": []
1375         },
1376         "text": {
1377             "global": [
1378                 "_funcZ"
1379             ],
1380             "weak": [],
1381             "thread_local": []
1382         }
1383     },
1384     {
1385       "targets": [
1386           "x86_64-macos"
1387       ],
1388       "data": {
1389           "global": [
1390               "_globalVarZ"
1391           ],
1392           "objc_class": [
1393               "ClassZ",
1394               "ClassF"
1395           ],
1396           "objc_eh_type": [
1397               "ClassZ",
1398               "ClassF"
1399           ],
1400           "objc_ivar": [
1401               "ClassZ.ivar1",
1402               "ClassZ.ivar2",
1403               "ClassF.ivar1"
1404           ]
1405       },
1406       "text": {
1407           "global": [
1408               "_funcFooZ"
1409           ]
1410       }
1411     }
1412   ]
1413 },
1414 "libraries": []
1415 })";
1416 
1417   Expected<TBDFile> ResultA =
1418       TextAPIReader::get(MemoryBufferRef(TBDv5FileA, "Test.tbd"));
1419   EXPECT_TRUE(!!ResultA);
1420   TBDFile FileA = std::move(ResultA.get());
1421 
1422   Expected<TBDFile> ResultB =
1423       TextAPIReader::get(MemoryBufferRef(TBDv5FileB, "Test.tbd"));
1424   EXPECT_TRUE(!!ResultB);
1425   TBDFile FileB = std::move(ResultB.get());
1426 
1427   Expected<TBDFile> MergedResult = FileA->merge(FileB.get());
1428   EXPECT_TRUE(!!MergedResult);
1429   TBDFile MergedFile = std::move(MergedResult.get());
1430 
1431   EXPECT_EQ(FileType::TBD_V5, MergedFile->getFileType());
1432   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1433             MergedFile->getInstallName());
1434   TargetList AllTargets = {
1435       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
1436       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1437       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1438   };
1439   EXPECT_EQ(mapToPlatformSet(AllTargets), MergedFile->getPlatforms());
1440   EXPECT_EQ(mapToArchitectureSet(AllTargets), MergedFile->getArchitectures());
1441   EXPECT_EQ(PackedVersion(1, 2, 0), MergedFile->getCurrentVersion());
1442   EXPECT_EQ(PackedVersion(1, 1, 0), MergedFile->getCompatibilityVersion());
1443   EXPECT_TRUE(MergedFile->isApplicationExtensionSafe());
1444   EXPECT_FALSE(MergedFile->isTwoLevelNamespace());
1445   EXPECT_EQ(0U, MergedFile->documents().size());
1446   InterfaceFileRef ClientA("ClientA", AllTargets);
1447   InterfaceFileRef ClientB("ClientB", AllTargets);
1448   EXPECT_EQ(2U, MergedFile->allowableClients().size());
1449   EXPECT_EQ(ClientA, MergedFile->allowableClients().at(0));
1450   EXPECT_EQ(ClientB, MergedFile->allowableClients().at(1));
1451 
1452   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
1453   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
1454   EXPECT_EQ(2U, MergedFile->reexportedLibraries().size());
1455   EXPECT_EQ(ReexportA, MergedFile->reexportedLibraries().at(0));
1456   EXPECT_EQ(ReexportB, MergedFile->reexportedLibraries().at(1));
1457 
1458   TargetToAttr RPaths = {
1459       {Target(AK_x86_64, PLATFORM_MACOS), "@executable_path/.../Frameworks"},
1460   };
1461   EXPECT_EQ(RPaths, MergedFile->rpaths());
1462 
1463   TargetToAttr Umbrellas = {{Target(AK_x86_64, PLATFORM_MACOS), "System"},
1464                             {Target(AK_arm64, PLATFORM_MACOS), "System"},
1465                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
1466   EXPECT_EQ(Umbrellas, MergedFile->umbrellas());
1467 
1468   ExportedSymbolSeq Exports, Reexports, Undefineds;
1469   for (const auto *Sym : MergedFile->symbols()) {
1470     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
1471     ExportedSymbol Temp =
1472         ExportedSymbol{Sym->getKind(),
1473                        std::string(Sym->getName()),
1474                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
1475                        Sym->isThreadLocalValue(),
1476                        Sym->isData(),
1477                        SymTargets};
1478     if (Sym->isUndefined())
1479       Undefineds.emplace_back(std::move(Temp));
1480     else
1481       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
1482                           : Exports.emplace_back(std::move(Temp));
1483   }
1484   llvm::sort(Exports);
1485   llvm::sort(Reexports);
1486   llvm::sort(Undefineds);
1487 
1488   TargetList MacOSTargets = {Target(AK_x86_64, PLATFORM_MACOS),
1489                              Target(AK_arm64, PLATFORM_MACOS)};
1490 
1491   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
1492       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
1493       {SymbolKind::GlobalSymbol,
1494        "_funcFoo",
1495        false,
1496        false,
1497        false,
1498        {Target(AK_x86_64, PLATFORM_MACOS)}},
1499       {SymbolKind::GlobalSymbol,
1500        "_funcFooZ",
1501        false,
1502        false,
1503        false,
1504        {Target(AK_x86_64, PLATFORM_MACOS)}},
1505       {SymbolKind::GlobalSymbol, "_funcZ", false, false, false, MacOSTargets},
1506       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
1507       {SymbolKind::GlobalSymbol,
1508        "_globalVar",
1509        false,
1510        false,
1511        true,
1512        {Target(AK_x86_64, PLATFORM_MACOS)}},
1513       {SymbolKind::GlobalSymbol,
1514        "_globalVarZ",
1515        false,
1516        false,
1517        true,
1518        {Target(AK_x86_64, PLATFORM_MACOS)}},
1519       {SymbolKind::GlobalSymbol, "_globalZ", false, false, true, MacOSTargets},
1520       {SymbolKind::ObjectiveCClass,
1521        "ClassA",
1522        false,
1523        false,
1524        true,
1525        {Target(AK_x86_64, PLATFORM_MACOS)}},
1526       {SymbolKind::ObjectiveCClass,
1527        "ClassB",
1528        false,
1529        false,
1530        true,
1531        {Target(AK_x86_64, PLATFORM_MACOS)}},
1532       {SymbolKind::ObjectiveCClass,
1533        "ClassData",
1534        false,
1535        false,
1536        true,
1537        {Target(AK_x86_64, PLATFORM_MACOS)}},
1538       {SymbolKind::ObjectiveCClass,
1539        "ClassF",
1540        false,
1541        false,
1542        true,
1543        {Target(AK_x86_64, PLATFORM_MACOS)}},
1544       {SymbolKind::ObjectiveCClass,
1545        "ClassZ",
1546        false,
1547        false,
1548        true,
1549        {Target(AK_x86_64, PLATFORM_MACOS)}},
1550       {SymbolKind::ObjectiveCClassEHType,
1551        "ClassA",
1552        false,
1553        false,
1554        true,
1555        {Target(AK_x86_64, PLATFORM_MACOS)}},
1556       {SymbolKind::ObjectiveCClassEHType,
1557        "ClassB",
1558        false,
1559        false,
1560        true,
1561        {Target(AK_x86_64, PLATFORM_MACOS)}},
1562       {SymbolKind::ObjectiveCClassEHType,
1563        "ClassF",
1564        false,
1565        false,
1566        true,
1567        {Target(AK_x86_64, PLATFORM_MACOS)}},
1568       {SymbolKind::ObjectiveCClassEHType,
1569        "ClassZ",
1570        false,
1571        false,
1572        true,
1573        {Target(AK_x86_64, PLATFORM_MACOS)}},
1574       {SymbolKind::ObjectiveCInstanceVariable,
1575        "ClassA.ivar1",
1576        false,
1577        false,
1578        true,
1579        {Target(AK_x86_64, PLATFORM_MACOS)}},
1580       {SymbolKind::ObjectiveCInstanceVariable,
1581        "ClassA.ivar2",
1582        false,
1583        false,
1584        true,
1585        {Target(AK_x86_64, PLATFORM_MACOS)}},
1586       {SymbolKind::ObjectiveCInstanceVariable,
1587        "ClassC.ivar1",
1588        false,
1589        false,
1590        true,
1591        {Target(AK_x86_64, PLATFORM_MACOS)}},
1592       {SymbolKind::ObjectiveCInstanceVariable,
1593        "ClassF.ivar1",
1594        false,
1595        false,
1596        true,
1597        {Target(AK_x86_64, PLATFORM_MACOS)}},
1598       {SymbolKind::ObjectiveCInstanceVariable,
1599        "ClassZ.ivar1",
1600        false,
1601        false,
1602        true,
1603        {Target(AK_x86_64, PLATFORM_MACOS)}},
1604       {SymbolKind::ObjectiveCInstanceVariable,
1605        "ClassZ.ivar2",
1606        false,
1607        false,
1608        true,
1609        {Target(AK_x86_64, PLATFORM_MACOS)}},
1610   };
1611 
1612   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
1613       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
1614       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
1615       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
1616        MacOSTargets},
1617   };
1618 
1619   std::vector<ExportedSymbol> ExpectedUndefinedSymbols = {
1620       {SymbolKind::GlobalSymbol,
1621        "_globalBind",
1622        false,
1623        false,
1624        true,
1625        {Target(AK_x86_64, PLATFORM_MACOS)}},
1626       {SymbolKind::GlobalSymbol,
1627        "referenced_sym",
1628        true,
1629        false,
1630        true,
1631        {Target(AK_x86_64, PLATFORM_MACOS)}},
1632   };
1633 
1634   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
1635   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
1636   EXPECT_EQ(ExpectedUndefinedSymbols.size(), Undefineds.size());
1637   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
1638                          std::begin(ExpectedExportedSymbols)));
1639   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
1640                          std::begin(ExpectedReexportedSymbols)));
1641   EXPECT_TRUE(std::equal(Undefineds.begin(), Undefineds.end(),
1642                          std::begin(ExpectedUndefinedSymbols)));
1643 }
1644 
1645 TEST(TBDv5, ExtractIF) {
1646   static const char TBDv5File[] = R"({
1647 "tapi_tbd_version": 5,
1648 "main_library": {
1649   "target_info": [
1650     {
1651       "target": "x86_64-macos",
1652       "min_deployment": "10.14"
1653     },
1654     {
1655       "target": "arm64-macos",
1656       "min_deployment": "10.14"
1657     },
1658     {
1659       "target": "arm64-maccatalyst",
1660       "min_deployment": "12.1"
1661     }
1662   ],
1663   "flags": [
1664     {
1665       "targets": [
1666             "x86_64-macos"
1667         ],
1668       "attributes": [
1669             "flat_namespace"
1670         ]
1671     }
1672   ],
1673   "install_names": [
1674     {
1675         "name": "/S/L/F/Foo.framework/Foo"
1676     }
1677   ],
1678   "current_versions": [
1679     {
1680         "version": "1.2"
1681     }
1682   ],
1683   "compatibility_versions": [
1684     { "version": "1.1" }
1685   ],
1686   "rpaths": [
1687     {
1688       "targets": [
1689           "x86_64-macos"
1690       ],
1691       "paths": [
1692           "@executable_path/.../Frameworks"
1693       ]
1694     }
1695   ],
1696   "parent_umbrellas": [
1697     {
1698       "umbrella": "System"
1699     }
1700   ],
1701   "allowable_clients": [
1702     {
1703         "clients": [
1704             "ClientA",
1705             "ClientB"
1706         ]
1707     }
1708   ],
1709   "reexported_libraries": [
1710     {
1711         "names": [
1712             "/u/l/l/libfoo.dylib",
1713             "/u/l/l/libbar.dylib"
1714         ]
1715     }
1716   ],
1717   "exported_symbols": [
1718     {
1719         "targets": [
1720             "x86_64-macos",
1721             "arm64-macos"
1722         ],
1723         "data": {
1724             "global": [
1725                 "_global"
1726             ],
1727             "objc_class": [
1728                 "ClassA"
1729             ],
1730             "weak": [],
1731             "thread_local": []
1732         },
1733         "text": {
1734             "global": [
1735                 "_func"
1736             ],
1737             "weak": [],
1738             "thread_local": []
1739         }
1740     },
1741     {
1742       "targets": [
1743           "x86_64-macos"
1744       ],
1745       "data": {
1746           "global": [
1747               "_globalVar"
1748           ],
1749           "objc_class": [
1750               "ClassA",
1751               "ClassB",
1752               "ClassData"
1753           ],
1754           "objc_eh_type": [
1755               "ClassA",
1756               "ClassB"
1757           ],
1758           "objc_ivar": [
1759               "ClassA.ivar1",
1760               "ClassA.ivar2",
1761               "ClassC.ivar1"
1762           ]
1763       },
1764       "text": {
1765           "global": [
1766               "_funcFoo"
1767           ]
1768       }
1769     }
1770   ],
1771   "reexported_symbols": [
1772     {
1773         "targets": [
1774             "x86_64-macos",
1775             "arm64-macos"
1776         ],
1777         "data": {
1778             "global": [
1779                 "_globalRe"
1780             ],
1781             "objc_class": [
1782                 "ClassRexport"
1783             ]
1784         },
1785         "text": {
1786             "global": [
1787                 "_funcA"
1788             ]
1789         }
1790     }
1791   ],
1792   "undefined_symbols": [
1793     {
1794         "targets": [
1795             "x86_64-macos"
1796         ],
1797         "data": {
1798             "global": [
1799                 "_globalBind"
1800             ],
1801             "weak": [
1802                 "referenced_sym"
1803             ]
1804         }
1805     }
1806   ]
1807 },
1808 "libraries": []
1809 })";
1810 
1811   Expected<TBDFile> Result =
1812       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
1813   EXPECT_TRUE(!!Result);
1814   TBDFile File = std::move(Result.get());
1815 
1816   Expected<TBDFile> ExtractedResult = File->extract(AK_arm64);
1817   EXPECT_TRUE(!!ExtractedResult);
1818   TBDFile ExtractedFile = std::move(ExtractedResult.get());
1819 
1820   EXPECT_EQ(FileType::TBD_V5, ExtractedFile->getFileType());
1821   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
1822             ExtractedFile->getInstallName());
1823 
1824   TargetList AllTargets = {
1825       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
1826       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
1827   };
1828   EXPECT_EQ(mapToPlatformSet(AllTargets), ExtractedFile->getPlatforms());
1829   EXPECT_EQ(mapToArchitectureSet(AllTargets),
1830             ExtractedFile->getArchitectures());
1831 
1832   EXPECT_EQ(PackedVersion(1, 2, 0), ExtractedFile->getCurrentVersion());
1833   EXPECT_EQ(PackedVersion(1, 1, 0), ExtractedFile->getCompatibilityVersion());
1834   EXPECT_TRUE(ExtractedFile->isApplicationExtensionSafe());
1835   EXPECT_FALSE(ExtractedFile->isTwoLevelNamespace());
1836   EXPECT_EQ(0U, ExtractedFile->documents().size());
1837 
1838   InterfaceFileRef ClientA("ClientA", AllTargets);
1839   InterfaceFileRef ClientB("ClientB", AllTargets);
1840   EXPECT_EQ(2U, ExtractedFile->allowableClients().size());
1841   EXPECT_EQ(ClientA, ExtractedFile->allowableClients().at(0));
1842   EXPECT_EQ(ClientB, ExtractedFile->allowableClients().at(1));
1843 
1844   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
1845   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
1846   EXPECT_EQ(2U, ExtractedFile->reexportedLibraries().size());
1847   EXPECT_EQ(ReexportA, ExtractedFile->reexportedLibraries().at(0));
1848   EXPECT_EQ(ReexportB, ExtractedFile->reexportedLibraries().at(1));
1849 
1850   EXPECT_EQ(0u, ExtractedFile->rpaths().size());
1851 
1852   TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
1853                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
1854   EXPECT_EQ(Umbrellas, ExtractedFile->umbrellas());
1855 
1856   ExportedSymbolSeq Exports, Reexports, Undefineds;
1857   for (const auto *Sym : ExtractedFile->symbols()) {
1858     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
1859     ExportedSymbol Temp =
1860         ExportedSymbol{Sym->getKind(),
1861                        std::string(Sym->getName()),
1862                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
1863                        Sym->isThreadLocalValue(),
1864                        Sym->isData(),
1865                        SymTargets};
1866     if (Sym->isUndefined())
1867       Undefineds.emplace_back(std::move(Temp));
1868     else
1869       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
1870                           : Exports.emplace_back(std::move(Temp));
1871   }
1872   llvm::sort(Exports);
1873   llvm::sort(Reexports);
1874   llvm::sort(Undefineds);
1875 
1876   TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
1877 
1878   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
1879       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
1880       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
1881       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
1882   };
1883   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
1884       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
1885       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
1886       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
1887        MacOSTargets},
1888   };
1889 
1890   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
1891   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
1892   EXPECT_EQ(0U, Undefineds.size());
1893   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
1894                          std::begin(ExpectedExportedSymbols)));
1895   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
1896                          std::begin(ExpectedReexportedSymbols)));
1897 }
1898 
1899 TEST(TBDv5, RemoveIF) {
1900   static const char TBDv5File[] = R"({
1901 "tapi_tbd_version": 5,
1902 "main_library": {
1903   "target_info": [
1904     {
1905       "target": "x86_64-macos",
1906       "min_deployment": "10.14"
1907     },
1908     {
1909       "target": "arm64-macos",
1910       "min_deployment": "10.14"
1911     },
1912     {
1913       "target": "arm64-maccatalyst",
1914       "min_deployment": "12.1"
1915     }
1916   ],
1917   "flags": [
1918     {
1919       "targets": [
1920             "x86_64-macos"
1921         ],
1922       "attributes": [
1923             "flat_namespace"
1924         ]
1925     }
1926   ],
1927   "install_names": [
1928     {
1929         "name": "/S/L/F/Foo.framework/Foo"
1930     }
1931   ],
1932   "current_versions": [
1933     {
1934         "version": "1.2"
1935     }
1936   ],
1937   "compatibility_versions": [
1938     { "version": "1.1" }
1939   ],
1940   "rpaths": [
1941     {
1942       "targets": [
1943           "x86_64-macos"
1944       ],
1945       "paths": [
1946           "@executable_path/.../Frameworks"
1947       ]
1948     }
1949   ],
1950   "parent_umbrellas": [
1951     {
1952       "umbrella": "System"
1953     }
1954   ],
1955   "allowable_clients": [
1956     {
1957         "clients": [
1958             "ClientA",
1959             "ClientB"
1960         ]
1961     }
1962   ],
1963   "reexported_libraries": [
1964     {
1965         "names": [
1966             "/u/l/l/libfoo.dylib",
1967             "/u/l/l/libbar.dylib"
1968         ]
1969     }
1970   ],
1971   "exported_symbols": [
1972     {
1973         "targets": [
1974             "x86_64-macos",
1975             "arm64-macos"
1976         ],
1977         "data": {
1978             "global": [
1979                 "_global"
1980             ],
1981             "objc_class": [
1982                 "ClassA"
1983             ],
1984             "weak": [],
1985             "thread_local": []
1986         },
1987         "text": {
1988             "global": [
1989                 "_func"
1990             ],
1991             "weak": [],
1992             "thread_local": []
1993         }
1994     },
1995     {
1996       "targets": [
1997           "x86_64-macos"
1998       ],
1999       "data": {
2000           "global": [
2001               "_globalVar"
2002           ],
2003           "objc_class": [
2004               "ClassA",
2005               "ClassB",
2006               "ClassData"
2007           ],
2008           "objc_eh_type": [
2009               "ClassA",
2010               "ClassB"
2011           ],
2012           "objc_ivar": [
2013               "ClassA.ivar1",
2014               "ClassA.ivar2",
2015               "ClassC.ivar1"
2016           ]
2017       },
2018       "text": {
2019           "global": [
2020               "_funcFoo"
2021           ]
2022       }
2023     }
2024   ],
2025   "reexported_symbols": [
2026     {
2027         "targets": [
2028             "x86_64-macos",
2029             "arm64-macos"
2030         ],
2031         "data": {
2032             "global": [
2033                 "_globalRe"
2034             ],
2035             "objc_class": [
2036                 "ClassRexport"
2037             ]
2038         },
2039         "text": {
2040             "global": [
2041                 "_funcA"
2042             ]
2043         }
2044     }
2045   ],
2046   "undefined_symbols": [
2047     {
2048         "targets": [
2049             "x86_64-macos"
2050         ],
2051         "data": {
2052             "global": [
2053                 "_globalBind"
2054             ],
2055             "weak": [
2056                 "referenced_sym"
2057             ]
2058         }
2059     }
2060   ]
2061 },
2062 "libraries": []
2063 })";
2064 
2065   Expected<TBDFile> Result =
2066       TextAPIReader::get(MemoryBufferRef(TBDv5File, "Test.tbd"));
2067   EXPECT_TRUE(!!Result);
2068   TBDFile File = std::move(Result.get());
2069 
2070   Expected<TBDFile> RemovedResult = File->remove(AK_x86_64);
2071   EXPECT_TRUE(!!RemovedResult);
2072   TBDFile RemovedFile = std::move(RemovedResult.get());
2073 
2074   EXPECT_EQ(FileType::TBD_V5, RemovedFile->getFileType());
2075   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2076             RemovedFile->getInstallName());
2077 
2078   TargetList AllTargets = {
2079       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
2080       Target(AK_arm64, PLATFORM_MACCATALYST, VersionTuple(14, 0)),
2081   };
2082   EXPECT_EQ(mapToPlatformSet(AllTargets), RemovedFile->getPlatforms());
2083   EXPECT_EQ(mapToArchitectureSet(AllTargets), RemovedFile->getArchitectures());
2084 
2085   EXPECT_EQ(PackedVersion(1, 2, 0), RemovedFile->getCurrentVersion());
2086   EXPECT_EQ(PackedVersion(1, 1, 0), RemovedFile->getCompatibilityVersion());
2087   EXPECT_TRUE(RemovedFile->isApplicationExtensionSafe());
2088   EXPECT_FALSE(RemovedFile->isTwoLevelNamespace());
2089   EXPECT_EQ(0U, RemovedFile->documents().size());
2090 
2091   InterfaceFileRef ClientA("ClientA", AllTargets);
2092   InterfaceFileRef ClientB("ClientB", AllTargets);
2093   EXPECT_EQ(2U, RemovedFile->allowableClients().size());
2094   EXPECT_EQ(ClientA, RemovedFile->allowableClients().at(0));
2095   EXPECT_EQ(ClientB, RemovedFile->allowableClients().at(1));
2096 
2097   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2098   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2099   EXPECT_EQ(2U, RemovedFile->reexportedLibraries().size());
2100   EXPECT_EQ(ReexportA, RemovedFile->reexportedLibraries().at(0));
2101   EXPECT_EQ(ReexportB, RemovedFile->reexportedLibraries().at(1));
2102 
2103   EXPECT_EQ(0u, RemovedFile->rpaths().size());
2104 
2105   TargetToAttr Umbrellas = {{Target(AK_arm64, PLATFORM_MACOS), "System"},
2106                             {Target(AK_arm64, PLATFORM_MACCATALYST), "System"}};
2107   EXPECT_EQ(Umbrellas, RemovedFile->umbrellas());
2108 
2109   ExportedSymbolSeq Exports, Reexports, Undefineds;
2110   for (const auto *Sym : RemovedFile->symbols()) {
2111     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2112     ExportedSymbol Temp =
2113         ExportedSymbol{Sym->getKind(),
2114                        std::string(Sym->getName()),
2115                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2116                        Sym->isThreadLocalValue(),
2117                        Sym->isData(),
2118                        SymTargets};
2119     if (Sym->isUndefined())
2120       Undefineds.emplace_back(std::move(Temp));
2121     else
2122       Sym->isReexported() ? Reexports.emplace_back(std::move(Temp))
2123                           : Exports.emplace_back(std::move(Temp));
2124   }
2125   llvm::sort(Exports);
2126   llvm::sort(Reexports);
2127   llvm::sort(Undefineds);
2128 
2129   TargetList MacOSTargets = {Target(AK_arm64, PLATFORM_MACOS)};
2130 
2131   std::vector<ExportedSymbol> ExpectedExportedSymbols = {
2132       {SymbolKind::GlobalSymbol, "_func", false, false, false, MacOSTargets},
2133       {SymbolKind::GlobalSymbol, "_global", false, false, true, MacOSTargets},
2134       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, MacOSTargets},
2135   };
2136   std::vector<ExportedSymbol> ExpectedReexportedSymbols = {
2137       {SymbolKind::GlobalSymbol, "_funcA", false, false, false, MacOSTargets},
2138       {SymbolKind::GlobalSymbol, "_globalRe", false, false, true, MacOSTargets},
2139       {SymbolKind::ObjectiveCClass, "ClassRexport", false, false, true,
2140        MacOSTargets},
2141   };
2142 
2143   EXPECT_EQ(ExpectedExportedSymbols.size(), Exports.size());
2144   EXPECT_EQ(ExpectedReexportedSymbols.size(), Reexports.size());
2145   EXPECT_EQ(0U, Undefineds.size());
2146   EXPECT_TRUE(std::equal(Exports.begin(), Exports.end(),
2147                          std::begin(ExpectedExportedSymbols)));
2148   EXPECT_TRUE(std::equal(Reexports.begin(), Reexports.end(),
2149                          std::begin(ExpectedReexportedSymbols)));
2150 }
2151 
2152 TEST(TBDv5, InlineIF) {
2153   static const char UmbrellaFile[] = R"({
2154 "tapi_tbd_version": 5,
2155 "main_library": {
2156   "target_info": [
2157     {
2158       "target": "x86_64-macos",
2159       "min_deployment": "10.14"
2160     },
2161     {
2162       "target": "arm64-macos",
2163       "min_deployment": "10.14"
2164     }
2165   ],
2166   "install_names": [
2167     {
2168         "name": "/S/L/F/Foo.framework/Foo"
2169     }
2170   ],
2171   "current_versions": [
2172     {
2173         "version": "1.2"
2174     }
2175   ],
2176   "reexported_libraries": [
2177     {
2178         "names": [
2179             "/u/l/l/libfoo.dylib",
2180             "/u/l/l/libbar.dylib"
2181         ]
2182     }
2183   ]
2184 }})";
2185 
2186   static const char ReexportFile[] = R"({
2187 "tapi_tbd_version": 5,
2188 "main_library": {
2189   "target_info": [
2190     {
2191       "target": "x86_64-macos",
2192       "min_deployment": "10.14"
2193     },
2194     {
2195       "target": "arm64-macos",
2196       "min_deployment": "10.14"
2197     }
2198   ],
2199   "install_names": [
2200     {
2201         "name" : "/u/l/l/libfoo.dylib"
2202     }
2203   ],
2204   "current_versions": [
2205     {
2206         "version": "1"
2207     }
2208   ],
2209   "rpaths": [
2210     {
2211       "targets": [
2212           "x86_64-macos"
2213       ],
2214       "paths": [
2215           "@executable_path/.../Frameworks"
2216       ]
2217     }
2218   ],
2219   "exported_symbols": [
2220     {
2221         "targets": [
2222             "x86_64-macos",
2223             "arm64-macos"
2224         ],
2225         "data": {
2226             "global": [
2227                 "_global"
2228             ],
2229             "objc_class": [
2230                 "ClassA"
2231             ],
2232             "weak": [],
2233             "thread_local": []
2234         }
2235     }
2236   ]}})";
2237 
2238   Expected<TBDFile> UmbrellaResult =
2239       TextAPIReader::get(MemoryBufferRef(UmbrellaFile, "Test.tbd"));
2240   EXPECT_TRUE(!!UmbrellaResult);
2241   TBDFile Umbrella = std::move(UmbrellaResult.get());
2242 
2243   Expected<TBDFile> ReexportResult =
2244       TextAPIReader::get(MemoryBufferRef(ReexportFile, "Test.tbd"));
2245   EXPECT_TRUE(!!ReexportResult);
2246   TBDReexportFile Reexport = std::move(ReexportResult.get());
2247   Umbrella->inlineLibrary(Reexport);
2248 
2249   EXPECT_EQ(FileType::TBD_V5, Umbrella->getFileType());
2250   EXPECT_EQ(std::string("/S/L/F/Foo.framework/Foo"),
2251             Umbrella->getInstallName());
2252 
2253   TargetList AllTargets = {
2254       Target(AK_x86_64, PLATFORM_MACOS, VersionTuple(10, 14)),
2255       Target(AK_arm64, PLATFORM_MACOS, VersionTuple(11, 0, 0)),
2256   };
2257   EXPECT_EQ(mapToPlatformSet(AllTargets), Umbrella->getPlatforms());
2258   EXPECT_EQ(mapToArchitectureSet(AllTargets), Umbrella->getArchitectures());
2259 
2260   EXPECT_EQ(PackedVersion(1, 2, 0), Umbrella->getCurrentVersion());
2261   EXPECT_EQ(PackedVersion(1, 0, 0), Umbrella->getCompatibilityVersion());
2262   InterfaceFileRef ReexportA("/u/l/l/libbar.dylib", AllTargets);
2263   InterfaceFileRef ReexportB("/u/l/l/libfoo.dylib", AllTargets);
2264   EXPECT_EQ(2U, Umbrella->reexportedLibraries().size());
2265   EXPECT_EQ(ReexportA, Umbrella->reexportedLibraries().at(0));
2266   EXPECT_EQ(ReexportB, Umbrella->reexportedLibraries().at(1));
2267   EXPECT_EQ(1U, Umbrella->documents().size());
2268 
2269   TBDReexportFile Document = Umbrella->documents().front();
2270   EXPECT_EQ(std::string("/u/l/l/libfoo.dylib"), Document->getInstallName());
2271   EXPECT_EQ(0U, Document->getSwiftABIVersion());
2272   EXPECT_TRUE(Document->isTwoLevelNamespace());
2273   EXPECT_TRUE(Document->isApplicationExtensionSafe());
2274   EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCurrentVersion());
2275   EXPECT_EQ(PackedVersion(1, 0, 0), Document->getCompatibilityVersion());
2276 
2277   ExportedSymbolSeq Exports;
2278   for (const auto *Sym : Document->symbols()) {
2279     TargetList SymTargets{Sym->targets().begin(), Sym->targets().end()};
2280     Exports.emplace_back(
2281         ExportedSymbol{Sym->getKind(), std::string(Sym->getName()),
2282                        Sym->isWeakDefined() || Sym->isWeakReferenced(),
2283                        Sym->isThreadLocalValue(), Sym->isData(), SymTargets});
2284   }
2285   llvm::sort(Exports);
2286 
2287   ExportedSymbolSeq ExpectedExports = {
2288       {SymbolKind::GlobalSymbol, "_global", false, false, true, AllTargets},
2289       {SymbolKind::ObjectiveCClass, "ClassA", false, false, true, AllTargets},
2290   };
2291   EXPECT_EQ(ExpectedExports.size(), Exports.size());
2292   EXPECT_TRUE(
2293       std::equal(Exports.begin(), Exports.end(), std::begin(ExpectedExports)));
2294 }
2295 } // end namespace TBDv5
2296