xref: /freebsd/contrib/llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp (revision e64bea71c21eb42e97aa615188ba91f6cce0d36d)
1 //===-- APINotesYAMLCompiler.cpp - API Notes YAML Format Reader -*- C++ -*-===//
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 // The types defined locally are designed to represent the YAML state, which
10 // adds an additional bit of state: e.g. a tri-state boolean attribute (yes, no,
11 // not applied) becomes a tri-state boolean + present.  As a result, while these
12 // enumerations appear to be redefining constants from the attributes table
13 // data, they are distinct.
14 //
15 
16 #include "clang/APINotes/APINotesYAMLCompiler.h"
17 #include "clang/APINotes/APINotesWriter.h"
18 #include "clang/APINotes/Types.h"
19 #include "clang/Basic/LLVM.h"
20 #include "clang/Basic/Specifiers.h"
21 #include "llvm/ADT/StringSet.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/VersionTuple.h"
24 #include "llvm/Support/YAMLTraits.h"
25 #include <optional>
26 #include <type_traits>
27 #include <vector>
28 
29 using namespace clang;
30 using namespace api_notes;
31 
32 namespace {
33 enum class APIAvailability {
34   Available = 0,
35   None,
36   NonSwift,
37 };
38 } // namespace
39 
40 namespace llvm {
41 namespace yaml {
42 template <> struct ScalarEnumerationTraits<APIAvailability> {
43   static void enumeration(IO &IO, APIAvailability &AA) {
44     IO.enumCase(AA, "none", APIAvailability::None);
45     IO.enumCase(AA, "nonswift", APIAvailability::NonSwift);
46     IO.enumCase(AA, "available", APIAvailability::Available);
47   }
48 };
49 } // namespace yaml
50 } // namespace llvm
51 
52 namespace {
53 enum class MethodKind {
54   Class,
55   Instance,
56 };
57 } // namespace
58 
59 namespace llvm {
60 namespace yaml {
61 template <> struct ScalarEnumerationTraits<MethodKind> {
62   static void enumeration(IO &IO, MethodKind &MK) {
63     IO.enumCase(MK, "Class", MethodKind::Class);
64     IO.enumCase(MK, "Instance", MethodKind::Instance);
65   }
66 };
67 } // namespace yaml
68 } // namespace llvm
69 
70 namespace {
71 struct Param {
72   int Position;
73   std::optional<bool> NoEscape = false;
74   std::optional<bool> Lifetimebound = false;
75   std::optional<NullabilityKind> Nullability;
76   std::optional<RetainCountConventionKind> RetainCountConvention;
77   StringRef Type;
78 };
79 
80 typedef std::vector<Param> ParamsSeq;
81 } // namespace
82 
83 LLVM_YAML_IS_SEQUENCE_VECTOR(Param)
84 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind)
85 
86 namespace llvm {
87 namespace yaml {
88 template <> struct ScalarEnumerationTraits<NullabilityKind> {
89   static void enumeration(IO &IO, NullabilityKind &NK) {
90     IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull);
91     IO.enumCase(NK, "Optional", NullabilityKind::Nullable);
92     IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified);
93     IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult);
94     // TODO: Mapping this to it's own value would allow for better cross
95     // checking. Also the default should be Unknown.
96     IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified);
97 
98     // Aliases for compatibility with existing APINotes.
99     IO.enumCase(NK, "N", NullabilityKind::NonNull);
100     IO.enumCase(NK, "O", NullabilityKind::Nullable);
101     IO.enumCase(NK, "U", NullabilityKind::Unspecified);
102     IO.enumCase(NK, "S", NullabilityKind::Unspecified);
103   }
104 };
105 
106 template <> struct ScalarEnumerationTraits<RetainCountConventionKind> {
107   static void enumeration(IO &IO, RetainCountConventionKind &RCCK) {
108     IO.enumCase(RCCK, "none", RetainCountConventionKind::None);
109     IO.enumCase(RCCK, "CFReturnsRetained",
110                 RetainCountConventionKind::CFReturnsRetained);
111     IO.enumCase(RCCK, "CFReturnsNotRetained",
112                 RetainCountConventionKind::CFReturnsNotRetained);
113     IO.enumCase(RCCK, "NSReturnsRetained",
114                 RetainCountConventionKind::NSReturnsRetained);
115     IO.enumCase(RCCK, "NSReturnsNotRetained",
116                 RetainCountConventionKind::NSReturnsNotRetained);
117   }
118 };
119 
120 template <> struct MappingTraits<Param> {
121   static void mapping(IO &IO, Param &P) {
122     IO.mapRequired("Position", P.Position);
123     IO.mapOptional("Nullability", P.Nullability, std::nullopt);
124     IO.mapOptional("RetainCountConvention", P.RetainCountConvention);
125     IO.mapOptional("NoEscape", P.NoEscape);
126     IO.mapOptional("Lifetimebound", P.Lifetimebound);
127     IO.mapOptional("Type", P.Type, StringRef(""));
128   }
129 };
130 } // namespace yaml
131 } // namespace llvm
132 
133 namespace {
134 typedef std::vector<NullabilityKind> NullabilitySeq;
135 
136 struct AvailabilityItem {
137   APIAvailability Mode = APIAvailability::Available;
138   StringRef Msg;
139 };
140 
141 /// Old attribute deprecated in favor of SwiftName.
142 enum class FactoryAsInitKind {
143   /// Infer based on name and type (the default).
144   Infer,
145   /// Treat as a class method.
146   AsClassMethod,
147   /// Treat as an initializer.
148   AsInitializer,
149 };
150 
151 struct Method {
152   StringRef Selector;
153   MethodKind Kind;
154   ParamsSeq Params;
155   NullabilitySeq Nullability;
156   std::optional<NullabilityKind> NullabilityOfRet;
157   std::optional<RetainCountConventionKind> RetainCountConvention;
158   AvailabilityItem Availability;
159   std::optional<bool> SwiftPrivate;
160   StringRef SwiftName;
161   FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer;
162   bool DesignatedInit = false;
163   bool Required = false;
164   StringRef ResultType;
165   StringRef SwiftReturnOwnership;
166 };
167 
168 typedef std::vector<Method> MethodsSeq;
169 } // namespace
170 
171 LLVM_YAML_IS_SEQUENCE_VECTOR(Method)
172 
173 namespace llvm {
174 namespace yaml {
175 template <> struct ScalarEnumerationTraits<FactoryAsInitKind> {
176   static void enumeration(IO &IO, FactoryAsInitKind &FIK) {
177     IO.enumCase(FIK, "A", FactoryAsInitKind::Infer);
178     IO.enumCase(FIK, "C", FactoryAsInitKind::AsClassMethod);
179     IO.enumCase(FIK, "I", FactoryAsInitKind::AsInitializer);
180   }
181 };
182 
183 template <> struct MappingTraits<Method> {
184   static void mapping(IO &IO, Method &M) {
185     IO.mapRequired("Selector", M.Selector);
186     IO.mapRequired("MethodKind", M.Kind);
187     IO.mapOptional("Parameters", M.Params);
188     IO.mapOptional("Nullability", M.Nullability);
189     IO.mapOptional("NullabilityOfRet", M.NullabilityOfRet, std::nullopt);
190     IO.mapOptional("RetainCountConvention", M.RetainCountConvention);
191     IO.mapOptional("Availability", M.Availability.Mode,
192                    APIAvailability::Available);
193     IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));
194     IO.mapOptional("SwiftPrivate", M.SwiftPrivate);
195     IO.mapOptional("SwiftName", M.SwiftName, StringRef(""));
196     IO.mapOptional("FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer);
197     IO.mapOptional("DesignatedInit", M.DesignatedInit, false);
198     IO.mapOptional("Required", M.Required, false);
199     IO.mapOptional("ResultType", M.ResultType, StringRef(""));
200     IO.mapOptional("SwiftReturnOwnership", M.SwiftReturnOwnership,
201                    StringRef(""));
202   }
203 };
204 } // namespace yaml
205 } // namespace llvm
206 
207 namespace {
208 struct Property {
209   StringRef Name;
210   std::optional<MethodKind> Kind;
211   std::optional<NullabilityKind> Nullability;
212   AvailabilityItem Availability;
213   std::optional<bool> SwiftPrivate;
214   StringRef SwiftName;
215   std::optional<bool> SwiftImportAsAccessors;
216   StringRef Type;
217 };
218 
219 typedef std::vector<Property> PropertiesSeq;
220 } // namespace
221 
222 LLVM_YAML_IS_SEQUENCE_VECTOR(Property)
223 
224 namespace llvm {
225 namespace yaml {
226 template <> struct MappingTraits<Property> {
227   static void mapping(IO &IO, Property &P) {
228     IO.mapRequired("Name", P.Name);
229     IO.mapOptional("PropertyKind", P.Kind);
230     IO.mapOptional("Nullability", P.Nullability, std::nullopt);
231     IO.mapOptional("Availability", P.Availability.Mode,
232                    APIAvailability::Available);
233     IO.mapOptional("AvailabilityMsg", P.Availability.Msg, StringRef(""));
234     IO.mapOptional("SwiftPrivate", P.SwiftPrivate);
235     IO.mapOptional("SwiftName", P.SwiftName, StringRef(""));
236     IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors);
237     IO.mapOptional("Type", P.Type, StringRef(""));
238   }
239 };
240 } // namespace yaml
241 } // namespace llvm
242 
243 namespace {
244 struct Class {
245   StringRef Name;
246   bool AuditedForNullability = false;
247   AvailabilityItem Availability;
248   std::optional<bool> SwiftPrivate;
249   StringRef SwiftName;
250   std::optional<StringRef> SwiftBridge;
251   std::optional<StringRef> NSErrorDomain;
252   std::optional<bool> SwiftImportAsNonGeneric;
253   std::optional<bool> SwiftObjCMembers;
254   MethodsSeq Methods;
255   PropertiesSeq Properties;
256 };
257 
258 typedef std::vector<Class> ClassesSeq;
259 } // namespace
260 
261 LLVM_YAML_IS_SEQUENCE_VECTOR(Class)
262 
263 namespace llvm {
264 namespace yaml {
265 template <> struct MappingTraits<Class> {
266   static void mapping(IO &IO, Class &C) {
267     IO.mapRequired("Name", C.Name);
268     IO.mapOptional("AuditedForNullability", C.AuditedForNullability, false);
269     IO.mapOptional("Availability", C.Availability.Mode,
270                    APIAvailability::Available);
271     IO.mapOptional("AvailabilityMsg", C.Availability.Msg, StringRef(""));
272     IO.mapOptional("SwiftPrivate", C.SwiftPrivate);
273     IO.mapOptional("SwiftName", C.SwiftName, StringRef(""));
274     IO.mapOptional("SwiftBridge", C.SwiftBridge);
275     IO.mapOptional("NSErrorDomain", C.NSErrorDomain);
276     IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric);
277     IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers);
278     IO.mapOptional("Methods", C.Methods);
279     IO.mapOptional("Properties", C.Properties);
280   }
281 };
282 } // namespace yaml
283 } // namespace llvm
284 
285 namespace {
286 struct Function {
287   StringRef Name;
288   ParamsSeq Params;
289   NullabilitySeq Nullability;
290   std::optional<NullabilityKind> NullabilityOfRet;
291   std::optional<api_notes::RetainCountConventionKind> RetainCountConvention;
292   AvailabilityItem Availability;
293   std::optional<bool> SwiftPrivate;
294   StringRef SwiftName;
295   StringRef Type;
296   StringRef ResultType;
297   StringRef SwiftReturnOwnership;
298 };
299 
300 typedef std::vector<Function> FunctionsSeq;
301 } // namespace
302 
303 LLVM_YAML_IS_SEQUENCE_VECTOR(Function)
304 
305 namespace llvm {
306 namespace yaml {
307 template <> struct MappingTraits<Function> {
308   static void mapping(IO &IO, Function &F) {
309     IO.mapRequired("Name", F.Name);
310     IO.mapOptional("Parameters", F.Params);
311     IO.mapOptional("Nullability", F.Nullability);
312     IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, std::nullopt);
313     IO.mapOptional("RetainCountConvention", F.RetainCountConvention);
314     IO.mapOptional("Availability", F.Availability.Mode,
315                    APIAvailability::Available);
316     IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef(""));
317     IO.mapOptional("SwiftPrivate", F.SwiftPrivate);
318     IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
319     IO.mapOptional("ResultType", F.ResultType, StringRef(""));
320     IO.mapOptional("SwiftReturnOwnership", F.SwiftReturnOwnership,
321                    StringRef(""));
322   }
323 };
324 } // namespace yaml
325 } // namespace llvm
326 
327 namespace {
328 struct GlobalVariable {
329   StringRef Name;
330   std::optional<NullabilityKind> Nullability;
331   AvailabilityItem Availability;
332   std::optional<bool> SwiftPrivate;
333   StringRef SwiftName;
334   StringRef Type;
335 };
336 
337 typedef std::vector<GlobalVariable> GlobalVariablesSeq;
338 } // namespace
339 
340 LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable)
341 
342 namespace llvm {
343 namespace yaml {
344 template <> struct MappingTraits<GlobalVariable> {
345   static void mapping(IO &IO, GlobalVariable &GV) {
346     IO.mapRequired("Name", GV.Name);
347     IO.mapOptional("Nullability", GV.Nullability, std::nullopt);
348     IO.mapOptional("Availability", GV.Availability.Mode,
349                    APIAvailability::Available);
350     IO.mapOptional("AvailabilityMsg", GV.Availability.Msg, StringRef(""));
351     IO.mapOptional("SwiftPrivate", GV.SwiftPrivate);
352     IO.mapOptional("SwiftName", GV.SwiftName, StringRef(""));
353     IO.mapOptional("Type", GV.Type, StringRef(""));
354   }
355 };
356 } // namespace yaml
357 } // namespace llvm
358 
359 namespace {
360 struct EnumConstant {
361   StringRef Name;
362   AvailabilityItem Availability;
363   std::optional<bool> SwiftPrivate;
364   StringRef SwiftName;
365 };
366 
367 typedef std::vector<EnumConstant> EnumConstantsSeq;
368 } // namespace
369 
370 LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant)
371 
372 namespace llvm {
373 namespace yaml {
374 template <> struct MappingTraits<EnumConstant> {
375   static void mapping(IO &IO, EnumConstant &EC) {
376     IO.mapRequired("Name", EC.Name);
377     IO.mapOptional("Availability", EC.Availability.Mode,
378                    APIAvailability::Available);
379     IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef(""));
380     IO.mapOptional("SwiftPrivate", EC.SwiftPrivate);
381     IO.mapOptional("SwiftName", EC.SwiftName, StringRef(""));
382   }
383 };
384 } // namespace yaml
385 } // namespace llvm
386 
387 namespace {
388 /// Syntactic sugar for EnumExtensibility and FlagEnum
389 enum class EnumConvenienceAliasKind {
390   /// EnumExtensibility: none, FlagEnum: false
391   None,
392   /// EnumExtensibility: open, FlagEnum: false
393   CFEnum,
394   /// EnumExtensibility: open, FlagEnum: true
395   CFOptions,
396   /// EnumExtensibility: closed, FlagEnum: false
397   CFClosedEnum
398 };
399 } // namespace
400 
401 namespace llvm {
402 namespace yaml {
403 template <> struct ScalarEnumerationTraits<EnumConvenienceAliasKind> {
404   static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK) {
405     IO.enumCase(ECAK, "none", EnumConvenienceAliasKind::None);
406     IO.enumCase(ECAK, "CFEnum", EnumConvenienceAliasKind::CFEnum);
407     IO.enumCase(ECAK, "NSEnum", EnumConvenienceAliasKind::CFEnum);
408     IO.enumCase(ECAK, "CFOptions", EnumConvenienceAliasKind::CFOptions);
409     IO.enumCase(ECAK, "NSOptions", EnumConvenienceAliasKind::CFOptions);
410     IO.enumCase(ECAK, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);
411     IO.enumCase(ECAK, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);
412   }
413 };
414 } // namespace yaml
415 } // namespace llvm
416 
417 namespace {
418 struct Field {
419   StringRef Name;
420   std::optional<NullabilityKind> Nullability;
421   AvailabilityItem Availability;
422   std::optional<bool> SwiftPrivate;
423   StringRef SwiftName;
424   StringRef Type;
425 };
426 
427 typedef std::vector<Field> FieldsSeq;
428 } // namespace
429 
430 LLVM_YAML_IS_SEQUENCE_VECTOR(Field)
431 
432 namespace llvm {
433 namespace yaml {
434 template <> struct MappingTraits<Field> {
435   static void mapping(IO &IO, Field &F) {
436     IO.mapRequired("Name", F.Name);
437     IO.mapOptional("Nullability", F.Nullability, std::nullopt);
438     IO.mapOptional("Availability", F.Availability.Mode,
439                    APIAvailability::Available);
440     IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef(""));
441     IO.mapOptional("SwiftPrivate", F.SwiftPrivate);
442     IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
443     IO.mapOptional("Type", F.Type, StringRef(""));
444   }
445 };
446 } // namespace yaml
447 } // namespace llvm
448 
449 namespace {
450 struct Tag;
451 typedef std::vector<Tag> TagsSeq;
452 
453 struct Tag {
454   StringRef Name;
455   AvailabilityItem Availability;
456   StringRef SwiftName;
457   std::optional<bool> SwiftPrivate;
458   std::optional<StringRef> SwiftBridge;
459   std::optional<StringRef> NSErrorDomain;
460   std::optional<std::string> SwiftImportAs;
461   std::optional<std::string> SwiftRetainOp;
462   std::optional<std::string> SwiftReleaseOp;
463   std::optional<std::string> SwiftDefaultOwnership;
464   std::optional<std::string> SwiftConformance;
465   std::optional<EnumExtensibilityKind> EnumExtensibility;
466   std::optional<bool> FlagEnum;
467   std::optional<EnumConvenienceAliasKind> EnumConvenienceKind;
468   std::optional<bool> SwiftCopyable;
469   std::optional<bool> SwiftEscapable;
470   FunctionsSeq Methods;
471   FieldsSeq Fields;
472 
473   /// Tags that are declared within the current tag. Only the tags that have
474   /// corresponding API Notes will be listed.
475   TagsSeq Tags;
476 };
477 } // namespace
478 
479 LLVM_YAML_IS_SEQUENCE_VECTOR(Tag)
480 
481 namespace llvm {
482 namespace yaml {
483 template <> struct ScalarEnumerationTraits<EnumExtensibilityKind> {
484   static void enumeration(IO &IO, EnumExtensibilityKind &EEK) {
485     IO.enumCase(EEK, "none", EnumExtensibilityKind::None);
486     IO.enumCase(EEK, "open", EnumExtensibilityKind::Open);
487     IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed);
488   }
489 };
490 
491 template <> struct MappingTraits<Tag> {
492   static void mapping(IO &IO, Tag &T) {
493     IO.mapRequired("Name", T.Name);
494     IO.mapOptional("Availability", T.Availability.Mode,
495                    APIAvailability::Available);
496     IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
497     IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
498     IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
499     IO.mapOptional("SwiftBridge", T.SwiftBridge);
500     IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
501     IO.mapOptional("SwiftImportAs", T.SwiftImportAs);
502     IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);
503     IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);
504     IO.mapOptional("SwiftDefaultOwnership", T.SwiftDefaultOwnership);
505     IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
506     IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
507     IO.mapOptional("FlagEnum", T.FlagEnum);
508     IO.mapOptional("EnumKind", T.EnumConvenienceKind);
509     IO.mapOptional("SwiftCopyable", T.SwiftCopyable);
510     IO.mapOptional("SwiftEscapable", T.SwiftEscapable);
511     IO.mapOptional("Methods", T.Methods);
512     IO.mapOptional("Fields", T.Fields);
513     IO.mapOptional("Tags", T.Tags);
514   }
515 };
516 } // namespace yaml
517 } // namespace llvm
518 
519 namespace {
520 struct Typedef {
521   StringRef Name;
522   AvailabilityItem Availability;
523   StringRef SwiftName;
524   std::optional<bool> SwiftPrivate;
525   std::optional<StringRef> SwiftBridge;
526   std::optional<StringRef> NSErrorDomain;
527   std::optional<SwiftNewTypeKind> SwiftType;
528 };
529 
530 typedef std::vector<Typedef> TypedefsSeq;
531 } // namespace
532 
533 LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef)
534 
535 namespace llvm {
536 namespace yaml {
537 template <> struct ScalarEnumerationTraits<SwiftNewTypeKind> {
538   static void enumeration(IO &IO, SwiftNewTypeKind &SWK) {
539     IO.enumCase(SWK, "none", SwiftNewTypeKind::None);
540     IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct);
541     IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum);
542   }
543 };
544 
545 template <> struct MappingTraits<Typedef> {
546   static void mapping(IO &IO, Typedef &T) {
547     IO.mapRequired("Name", T.Name);
548     IO.mapOptional("Availability", T.Availability.Mode,
549                    APIAvailability::Available);
550     IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
551     IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
552     IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
553     IO.mapOptional("SwiftBridge", T.SwiftBridge);
554     IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
555     IO.mapOptional("SwiftWrapper", T.SwiftType);
556   }
557 };
558 } // namespace yaml
559 } // namespace llvm
560 
561 namespace {
562 struct Namespace;
563 typedef std::vector<Namespace> NamespacesSeq;
564 
565 struct TopLevelItems {
566   ClassesSeq Classes;
567   ClassesSeq Protocols;
568   FunctionsSeq Functions;
569   GlobalVariablesSeq Globals;
570   EnumConstantsSeq EnumConstants;
571   TagsSeq Tags;
572   TypedefsSeq Typedefs;
573   NamespacesSeq Namespaces;
574 };
575 } // namespace
576 
577 namespace llvm {
578 namespace yaml {
579 static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) {
580   IO.mapOptional("Classes", TLI.Classes);
581   IO.mapOptional("Protocols", TLI.Protocols);
582   IO.mapOptional("Functions", TLI.Functions);
583   IO.mapOptional("Globals", TLI.Globals);
584   IO.mapOptional("Enumerators", TLI.EnumConstants);
585   IO.mapOptional("Tags", TLI.Tags);
586   IO.mapOptional("Typedefs", TLI.Typedefs);
587   IO.mapOptional("Namespaces", TLI.Namespaces);
588 }
589 } // namespace yaml
590 } // namespace llvm
591 
592 namespace {
593 struct Namespace {
594   StringRef Name;
595   AvailabilityItem Availability;
596   StringRef SwiftName;
597   std::optional<bool> SwiftPrivate;
598   TopLevelItems Items;
599 };
600 } // namespace
601 
602 LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace)
603 
604 namespace llvm {
605 namespace yaml {
606 template <> struct MappingTraits<Namespace> {
607   static void mapping(IO &IO, Namespace &T) {
608     IO.mapRequired("Name", T.Name);
609     IO.mapOptional("Availability", T.Availability.Mode,
610                    APIAvailability::Available);
611     IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
612     IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
613     IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
614     mapTopLevelItems(IO, T.Items);
615   }
616 };
617 } // namespace yaml
618 } // namespace llvm
619 
620 namespace {
621 struct Versioned {
622   VersionTuple Version;
623   TopLevelItems Items;
624 };
625 
626 typedef std::vector<Versioned> VersionedSeq;
627 } // namespace
628 
629 LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned)
630 
631 namespace llvm {
632 namespace yaml {
633 template <> struct MappingTraits<Versioned> {
634   static void mapping(IO &IO, Versioned &V) {
635     IO.mapRequired("Version", V.Version);
636     mapTopLevelItems(IO, V.Items);
637   }
638 };
639 } // namespace yaml
640 } // namespace llvm
641 
642 namespace {
643 struct Module {
644   StringRef Name;
645   AvailabilityItem Availability;
646   TopLevelItems TopLevel;
647   VersionedSeq SwiftVersions;
648 
649   std::optional<bool> SwiftInferImportAsMember;
650 
651 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
652   LLVM_DUMP_METHOD void dump() /*const*/;
653 #endif
654 };
655 } // namespace
656 
657 namespace llvm {
658 namespace yaml {
659 template <> struct MappingTraits<Module> {
660   static void mapping(IO &IO, Module &M) {
661     IO.mapRequired("Name", M.Name);
662     IO.mapOptional("Availability", M.Availability.Mode,
663                    APIAvailability::Available);
664     IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));
665     IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember);
666     mapTopLevelItems(IO, M.TopLevel);
667     IO.mapOptional("SwiftVersions", M.SwiftVersions);
668   }
669 };
670 } // namespace yaml
671 } // namespace llvm
672 
673 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
674 LLVM_DUMP_METHOD void Module::dump() {
675   llvm::yaml::Output OS(llvm::errs());
676   OS << *this;
677 }
678 #endif
679 
680 namespace {
681 bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag,
682                    void *DiagContext) {
683   llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext);
684   IS >> M;
685   return static_cast<bool>(IS.error());
686 }
687 } // namespace
688 
689 bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
690                                             llvm::raw_ostream &OS) {
691   Module M;
692   if (parseAPINotes(YI, M, nullptr, nullptr))
693     return true;
694 
695   llvm::yaml::Output YOS(OS);
696   YOS << M;
697 
698   return false;
699 }
700 
701 namespace {
702 using namespace api_notes;
703 
704 class YAMLConverter {
705   const Module &M;
706   APINotesWriter Writer;
707   llvm::raw_ostream &OS;
708   llvm::SourceMgr::DiagHandlerTy DiagHandler;
709   void *DiagHandlerCtxt;
710   bool ErrorOccured;
711 
712   /// Emit a diagnostic
713   bool emitError(llvm::Twine Message) {
714     DiagHandler(
715         llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
716         DiagHandlerCtxt);
717     ErrorOccured = true;
718     return true;
719   }
720 
721 public:
722   YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
723                 llvm::raw_ostream &OS,
724                 llvm::SourceMgr::DiagHandlerTy DiagHandler,
725                 void *DiagHandlerCtxt)
726       : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
727         DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
728         ErrorOccured(false) {}
729 
730   void convertAvailability(const AvailabilityItem &Availability,
731                            CommonEntityInfo &CEI, llvm::StringRef APIName) {
732     // Populate the unavailability information.
733     CEI.Unavailable = (Availability.Mode == APIAvailability::None);
734     CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift);
735     if (CEI.Unavailable || CEI.UnavailableInSwift) {
736       CEI.UnavailableMsg = std::string(Availability.Msg);
737     } else {
738       if (!Availability.Msg.empty())
739         emitError(llvm::Twine("availability message for available API '") +
740                   APIName + "' will not be used");
741     }
742   }
743 
744   void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo,
745                      std::optional<ParamInfo> &thisOrSelf) {
746     for (const auto &P : Params) {
747       ParamInfo PI;
748       if (P.Nullability)
749         PI.setNullabilityAudited(*P.Nullability);
750       PI.setNoEscape(P.NoEscape);
751       PI.setLifetimebound(P.Lifetimebound);
752       PI.setType(std::string(P.Type));
753       PI.setRetainCountConvention(P.RetainCountConvention);
754       if (static_cast<int>(OutInfo.Params.size()) <= P.Position)
755         OutInfo.Params.resize(P.Position + 1);
756       if (P.Position == -1)
757         thisOrSelf = PI;
758       else if (P.Position >= 0)
759         OutInfo.Params[P.Position] |= PI;
760       else
761         emitError("invalid parameter position " + llvm::itostr(P.Position));
762     }
763   }
764 
765   void convertNullability(const NullabilitySeq &Nullability,
766                           std::optional<NullabilityKind> ReturnNullability,
767                           FunctionInfo &OutInfo, llvm::StringRef APIName) {
768     if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
769       emitError(llvm::Twine("nullability info for '") + APIName +
770                 "' does not fit");
771       return;
772     }
773 
774     bool audited = false;
775     unsigned int idx = 1;
776     for (const auto &N : Nullability)
777       OutInfo.addTypeInfo(idx++, N);
778     audited = Nullability.size() > 0 || ReturnNullability;
779     if (audited)
780       OutInfo.addTypeInfo(0,
781                           ReturnNullability.value_or(NullabilityKind::NonNull));
782     if (!audited)
783       return;
784     OutInfo.NullabilityAudited = audited;
785     OutInfo.NumAdjustedNullable = idx;
786   }
787 
788   /// Convert the common parts of an entity from YAML.
789   template <typename T>
790   void convertCommonEntity(const T &Common, CommonEntityInfo &Info,
791                            StringRef APIName) {
792     convertAvailability(Common.Availability, Info, APIName);
793     Info.setSwiftPrivate(Common.SwiftPrivate);
794     Info.SwiftName = std::string(Common.SwiftName);
795   }
796 
797   /// Convert the common parts of a type entity from YAML.
798   template <typename T>
799   void convertCommonType(const T &Common, CommonTypeInfo &Info,
800                          StringRef APIName) {
801     convertCommonEntity(Common, Info, APIName);
802     if (Common.SwiftBridge)
803       Info.setSwiftBridge(std::string(*Common.SwiftBridge));
804     Info.setNSErrorDomain(Common.NSErrorDomain);
805   }
806 
807   // Translate from Method into ObjCMethodInfo and write it out.
808   void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName,
809                      VersionTuple SwiftVersion) {
810     ObjCMethodInfo MI;
811     convertCommonEntity(M, MI, M.Selector);
812 
813     // Check if the selector ends with ':' to determine if it takes arguments.
814     bool takesArguments = M.Selector.ends_with(":");
815 
816     // Split the selector into pieces.
817     llvm::SmallVector<StringRef, 4> Args;
818     M.Selector.split(Args, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
819     if (!takesArguments && Args.size() > 1) {
820       emitError("selector '" + M.Selector + "' is missing a ':' at the end");
821       return;
822     }
823 
824     // Construct ObjCSelectorRef.
825     api_notes::ObjCSelectorRef Selector;
826     Selector.NumArgs = !takesArguments ? 0 : Args.size();
827     Selector.Identifiers = Args;
828 
829     // Translate the initializer info.
830     MI.DesignatedInit = M.DesignatedInit;
831     MI.RequiredInit = M.Required;
832     if (M.FactoryAsInit != FactoryAsInitKind::Infer)
833       emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead");
834 
835     MI.ResultType = std::string(M.ResultType);
836     MI.SwiftReturnOwnership = std::string(M.SwiftReturnOwnership);
837 
838     // Translate parameter information.
839     convertParams(M.Params, MI, MI.Self);
840 
841     // Translate nullability info.
842     convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector);
843 
844     MI.setRetainCountConvention(M.RetainCountConvention);
845 
846     // Write it.
847     Writer.addObjCMethod(ClassID, Selector, M.Kind == MethodKind::Instance, MI,
848                          SwiftVersion);
849   }
850 
851   template <typename T>
852   void convertVariable(const T &Entity, VariableInfo &VI) {
853     convertAvailability(Entity.Availability, VI, Entity.Name);
854     VI.setSwiftPrivate(Entity.SwiftPrivate);
855     VI.SwiftName = std::string(Entity.SwiftName);
856     if (Entity.Nullability)
857       VI.setNullabilityAudited(*Entity.Nullability);
858     VI.setType(std::string(Entity.Type));
859   }
860 
861   void convertContext(std::optional<ContextID> ParentContextID, const Class &C,
862                       ContextKind Kind, VersionTuple SwiftVersion) {
863     // Write the class.
864     ContextInfo CI;
865     convertCommonType(C, CI, C.Name);
866 
867     if (C.AuditedForNullability)
868       CI.setDefaultNullability(NullabilityKind::NonNull);
869     if (C.SwiftImportAsNonGeneric)
870       CI.setSwiftImportAsNonGeneric(*C.SwiftImportAsNonGeneric);
871     if (C.SwiftObjCMembers)
872       CI.setSwiftObjCMembers(*C.SwiftObjCMembers);
873 
874     ContextID CtxID =
875         Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);
876 
877     // Write all methods.
878     llvm::StringMap<std::pair<bool, bool>> KnownMethods;
879     for (const auto &method : C.Methods) {
880       // Check for duplicate method definitions.
881       bool IsInstanceMethod = method.Kind == MethodKind::Instance;
882       bool &Known = IsInstanceMethod ? KnownMethods[method.Selector].first
883                                      : KnownMethods[method.Selector].second;
884       if (Known) {
885         emitError(llvm::Twine("duplicate definition of method '") +
886                   (IsInstanceMethod ? "-" : "+") + "[" + C.Name + " " +
887                   method.Selector + "]'");
888         continue;
889       }
890       Known = true;
891 
892       convertMethod(method, CtxID, C.Name, SwiftVersion);
893     }
894 
895     // Write all properties.
896     llvm::StringSet<> KnownInstanceProperties;
897     llvm::StringSet<> KnownClassProperties;
898     for (const auto &Property : C.Properties) {
899       // Check for duplicate property definitions.
900       if ((!Property.Kind || *Property.Kind == MethodKind::Instance) &&
901           !KnownInstanceProperties.insert(Property.Name).second) {
902         emitError(llvm::Twine("duplicate definition of instance property '") +
903                   C.Name + "." + Property.Name + "'");
904         continue;
905       }
906 
907       if ((!Property.Kind || *Property.Kind == MethodKind::Class) &&
908           !KnownClassProperties.insert(Property.Name).second) {
909         emitError(llvm::Twine("duplicate definition of class property '") +
910                   C.Name + "." + Property.Name + "'");
911         continue;
912       }
913 
914       // Translate from Property into ObjCPropertyInfo.
915       ObjCPropertyInfo PI;
916       convertVariable(Property, PI);
917       if (Property.SwiftImportAsAccessors)
918         PI.setSwiftImportAsAccessors(*Property.SwiftImportAsAccessors);
919 
920       // Add both instance and class properties with this name.
921       if (Property.Kind) {
922         Writer.addObjCProperty(CtxID, Property.Name,
923                                *Property.Kind == MethodKind::Instance, PI,
924                                SwiftVersion);
925       } else {
926         Writer.addObjCProperty(CtxID, Property.Name, true, PI, SwiftVersion);
927         Writer.addObjCProperty(CtxID, Property.Name, false, PI, SwiftVersion);
928       }
929     }
930   }
931 
932   void convertNamespaceContext(std::optional<ContextID> ParentContextID,
933                                const Namespace &TheNamespace,
934                                VersionTuple SwiftVersion) {
935     // Write the namespace.
936     ContextInfo CI;
937     convertCommonEntity(TheNamespace, CI, TheNamespace.Name);
938 
939     ContextID CtxID =
940         Writer.addContext(ParentContextID, TheNamespace.Name,
941                           ContextKind::Namespace, CI, SwiftVersion);
942 
943     convertTopLevelItems(Context(CtxID, ContextKind::Namespace),
944                          TheNamespace.Items, SwiftVersion);
945   }
946 
947   template <typename FuncOrMethodInfo>
948   void convertFunction(const Function &Function, FuncOrMethodInfo &FI) {
949     convertAvailability(Function.Availability, FI, Function.Name);
950     FI.setSwiftPrivate(Function.SwiftPrivate);
951     FI.SwiftName = std::string(Function.SwiftName);
952     std::optional<ParamInfo> This;
953     convertParams(Function.Params, FI, This);
954     if constexpr (std::is_same_v<FuncOrMethodInfo, CXXMethodInfo>)
955       FI.This = This;
956     else if (This)
957       emitError("implicit instance parameter is only permitted on C++ and "
958                 "Objective-C methods");
959     convertNullability(Function.Nullability, Function.NullabilityOfRet, FI,
960                        Function.Name);
961     FI.ResultType = std::string(Function.ResultType);
962     FI.SwiftReturnOwnership = std::string(Function.SwiftReturnOwnership);
963     FI.setRetainCountConvention(Function.RetainCountConvention);
964   }
965 
966   void convertTagContext(std::optional<Context> ParentContext, const Tag &T,
967                          VersionTuple SwiftVersion) {
968     TagInfo TI;
969     std::optional<ContextID> ParentContextID =
970         ParentContext ? std::optional<ContextID>(ParentContext->id)
971                       : std::nullopt;
972     convertCommonType(T, TI, T.Name);
973 
974     if ((T.SwiftRetainOp || T.SwiftReleaseOp) && !T.SwiftImportAs) {
975       emitError(llvm::Twine("should declare SwiftImportAs to use "
976                             "SwiftRetainOp and SwiftReleaseOp (for ") +
977                 T.Name + ")");
978       return;
979     }
980     if (T.SwiftReleaseOp.has_value() != T.SwiftRetainOp.has_value()) {
981       emitError(llvm::Twine("should declare both SwiftReleaseOp and "
982                             "SwiftRetainOp (for ") +
983                 T.Name + ")");
984       return;
985     }
986 
987     if (T.SwiftImportAs)
988       TI.SwiftImportAs = T.SwiftImportAs;
989     if (T.SwiftRetainOp)
990       TI.SwiftRetainOp = T.SwiftRetainOp;
991     if (T.SwiftReleaseOp)
992       TI.SwiftReleaseOp = T.SwiftReleaseOp;
993     if (T.SwiftConformance)
994       TI.SwiftConformance = T.SwiftConformance;
995     if (T.SwiftDefaultOwnership)
996       TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership;
997 
998     if (T.SwiftCopyable)
999       TI.setSwiftCopyable(T.SwiftCopyable);
1000     if (T.SwiftEscapable)
1001       TI.setSwiftEscapable(T.SwiftEscapable);
1002 
1003     if (T.EnumConvenienceKind) {
1004       if (T.EnumExtensibility) {
1005         emitError(
1006             llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") +
1007             T.Name + ")");
1008         return;
1009       }
1010       if (T.FlagEnum) {
1011         emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") +
1012                   T.Name + ")");
1013         return;
1014       }
1015       switch (*T.EnumConvenienceKind) {
1016       case EnumConvenienceAliasKind::None:
1017         TI.EnumExtensibility = EnumExtensibilityKind::None;
1018         TI.setFlagEnum(false);
1019         break;
1020       case EnumConvenienceAliasKind::CFEnum:
1021         TI.EnumExtensibility = EnumExtensibilityKind::Open;
1022         TI.setFlagEnum(false);
1023         break;
1024       case EnumConvenienceAliasKind::CFOptions:
1025         TI.EnumExtensibility = EnumExtensibilityKind::Open;
1026         TI.setFlagEnum(true);
1027         break;
1028       case EnumConvenienceAliasKind::CFClosedEnum:
1029         TI.EnumExtensibility = EnumExtensibilityKind::Closed;
1030         TI.setFlagEnum(false);
1031         break;
1032       }
1033     } else {
1034       TI.EnumExtensibility = T.EnumExtensibility;
1035       TI.setFlagEnum(T.FlagEnum);
1036     }
1037 
1038     Writer.addTag(ParentContext, T.Name, TI, SwiftVersion);
1039 
1040     ContextInfo CI;
1041     auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag,
1042                                       CI, SwiftVersion);
1043     Context TagCtx(TagCtxID, ContextKind::Tag);
1044 
1045     for (const auto &Field : T.Fields) {
1046       FieldInfo FI;
1047       convertVariable(Field, FI);
1048       Writer.addField(TagCtxID, Field.Name, FI, SwiftVersion);
1049     }
1050 
1051     for (const auto &CXXMethod : T.Methods) {
1052       CXXMethodInfo MI;
1053       convertFunction(CXXMethod, MI);
1054       Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);
1055     }
1056 
1057     // Convert nested tags.
1058     for (const auto &Tag : T.Tags)
1059       convertTagContext(TagCtx, Tag, SwiftVersion);
1060   }
1061 
1062   void convertTopLevelItems(std::optional<Context> Ctx,
1063                             const TopLevelItems &TLItems,
1064                             VersionTuple SwiftVersion) {
1065     std::optional<ContextID> CtxID =
1066         Ctx ? std::optional(Ctx->id) : std::nullopt;
1067 
1068     // Write all classes.
1069     llvm::StringSet<> KnownClasses;
1070     for (const auto &Class : TLItems.Classes) {
1071       // Check for duplicate class definitions.
1072       if (!KnownClasses.insert(Class.Name).second) {
1073         emitError(llvm::Twine("multiple definitions of class '") + Class.Name +
1074                   "'");
1075         continue;
1076       }
1077 
1078       convertContext(CtxID, Class, ContextKind::ObjCClass, SwiftVersion);
1079     }
1080 
1081     // Write all protocols.
1082     llvm::StringSet<> KnownProtocols;
1083     for (const auto &Protocol : TLItems.Protocols) {
1084       // Check for duplicate protocol definitions.
1085       if (!KnownProtocols.insert(Protocol.Name).second) {
1086         emitError(llvm::Twine("multiple definitions of protocol '") +
1087                   Protocol.Name + "'");
1088         continue;
1089       }
1090 
1091       convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion);
1092     }
1093 
1094     // Write all namespaces.
1095     llvm::StringSet<> KnownNamespaces;
1096     for (const auto &Namespace : TLItems.Namespaces) {
1097       // Check for duplicate namespace definitions.
1098       if (!KnownNamespaces.insert(Namespace.Name).second) {
1099         emitError(llvm::Twine("multiple definitions of namespace '") +
1100                   Namespace.Name + "'");
1101         continue;
1102       }
1103 
1104       convertNamespaceContext(CtxID, Namespace, SwiftVersion);
1105     }
1106 
1107     // Write all global variables.
1108     llvm::StringSet<> KnownGlobals;
1109     for (const auto &Global : TLItems.Globals) {
1110       // Check for duplicate global variables.
1111       if (!KnownGlobals.insert(Global.Name).second) {
1112         emitError(llvm::Twine("multiple definitions of global variable '") +
1113                   Global.Name + "'");
1114         continue;
1115       }
1116 
1117       GlobalVariableInfo GVI;
1118       convertVariable(Global, GVI);
1119       Writer.addGlobalVariable(Ctx, Global.Name, GVI, SwiftVersion);
1120     }
1121 
1122     // Write all global functions.
1123     llvm::StringSet<> KnownFunctions;
1124     for (const auto &Function : TLItems.Functions) {
1125       // Check for duplicate global functions.
1126       if (!KnownFunctions.insert(Function.Name).second) {
1127         emitError(llvm::Twine("multiple definitions of global function '") +
1128                   Function.Name + "'");
1129         continue;
1130       }
1131 
1132       GlobalFunctionInfo GFI;
1133       convertFunction(Function, GFI);
1134       Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion);
1135     }
1136 
1137     // Write all enumerators.
1138     llvm::StringSet<> KnownEnumConstants;
1139     for (const auto &EnumConstant : TLItems.EnumConstants) {
1140       // Check for duplicate enumerators
1141       if (!KnownEnumConstants.insert(EnumConstant.Name).second) {
1142         emitError(llvm::Twine("multiple definitions of enumerator '") +
1143                   EnumConstant.Name + "'");
1144         continue;
1145       }
1146 
1147       EnumConstantInfo ECI;
1148       convertAvailability(EnumConstant.Availability, ECI, EnumConstant.Name);
1149       ECI.setSwiftPrivate(EnumConstant.SwiftPrivate);
1150       ECI.SwiftName = std::string(EnumConstant.SwiftName);
1151       Writer.addEnumConstant(EnumConstant.Name, ECI, SwiftVersion);
1152     }
1153 
1154     // Write all tags.
1155     llvm::StringSet<> KnownTags;
1156     for (const auto &Tag : TLItems.Tags) {
1157       // Check for duplicate tag definitions.
1158       if (!KnownTags.insert(Tag.Name).second) {
1159         emitError(llvm::Twine("multiple definitions of tag '") + Tag.Name +
1160                   "'");
1161         continue;
1162       }
1163 
1164       convertTagContext(Ctx, Tag, SwiftVersion);
1165     }
1166 
1167     // Write all typedefs.
1168     llvm::StringSet<> KnownTypedefs;
1169     for (const auto &Typedef : TLItems.Typedefs) {
1170       // Check for duplicate typedef definitions.
1171       if (!KnownTypedefs.insert(Typedef.Name).second) {
1172         emitError(llvm::Twine("multiple definitions of typedef '") +
1173                   Typedef.Name + "'");
1174         continue;
1175       }
1176 
1177       TypedefInfo TInfo;
1178       convertCommonType(Typedef, TInfo, Typedef.Name);
1179       TInfo.SwiftWrapper = Typedef.SwiftType;
1180 
1181       Writer.addTypedef(Ctx, Typedef.Name, TInfo, SwiftVersion);
1182     }
1183   }
1184 
1185   bool convertModule() {
1186     // Write the top-level items.
1187     convertTopLevelItems(/* context */ std::nullopt, M.TopLevel,
1188                          VersionTuple());
1189 
1190     // Convert the versioned information.
1191     for (const auto &Versioned : M.SwiftVersions)
1192       convertTopLevelItems(/* context */ std::nullopt, Versioned.Items,
1193                            Versioned.Version);
1194 
1195     if (!ErrorOccured)
1196       Writer.writeToStream(OS);
1197 
1198     return ErrorOccured;
1199   }
1200 };
1201 } // namespace
1202 
1203 static bool compile(const Module &M, const FileEntry *SourceFile,
1204                     llvm::raw_ostream &OS,
1205                     llvm::SourceMgr::DiagHandlerTy DiagHandler,
1206                     void *DiagHandlerCtxt) {
1207   YAMLConverter C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1208   return C.convertModule();
1209 }
1210 
1211 /// Simple diagnostic handler that prints diagnostics to standard error.
1212 static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context) {
1213   Diag.print(nullptr, llvm::errs());
1214 }
1215 
1216 bool api_notes::compileAPINotes(StringRef YAMLInput,
1217                                 const FileEntry *SourceFile,
1218                                 llvm::raw_ostream &OS,
1219                                 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1220                                 void *DiagHandlerCtxt) {
1221   Module TheModule;
1222 
1223   if (!DiagHandler)
1224     DiagHandler = &printDiagnostic;
1225 
1226   if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt))
1227     return true;
1228 
1229   return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1230 }
1231