xref: /llvm-project/clang/lib/APINotes/APINotesYAMLCompiler.cpp (revision 48f7f63ac723a5001b74627493d360ff3d8d1186)
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> SwiftConformance;
464   std::optional<EnumExtensibilityKind> EnumExtensibility;
465   std::optional<bool> FlagEnum;
466   std::optional<EnumConvenienceAliasKind> EnumConvenienceKind;
467   std::optional<bool> SwiftCopyable;
468   std::optional<bool> SwiftEscapable;
469   FunctionsSeq Methods;
470   FieldsSeq Fields;
471 
472   /// Tags that are declared within the current tag. Only the tags that have
473   /// corresponding API Notes will be listed.
474   TagsSeq Tags;
475 };
476 } // namespace
477 
478 LLVM_YAML_IS_SEQUENCE_VECTOR(Tag)
479 
480 namespace llvm {
481 namespace yaml {
482 template <> struct ScalarEnumerationTraits<EnumExtensibilityKind> {
483   static void enumeration(IO &IO, EnumExtensibilityKind &EEK) {
484     IO.enumCase(EEK, "none", EnumExtensibilityKind::None);
485     IO.enumCase(EEK, "open", EnumExtensibilityKind::Open);
486     IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed);
487   }
488 };
489 
490 template <> struct MappingTraits<Tag> {
491   static void mapping(IO &IO, Tag &T) {
492     IO.mapRequired("Name", T.Name);
493     IO.mapOptional("Availability", T.Availability.Mode,
494                    APIAvailability::Available);
495     IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
496     IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
497     IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
498     IO.mapOptional("SwiftBridge", T.SwiftBridge);
499     IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
500     IO.mapOptional("SwiftImportAs", T.SwiftImportAs);
501     IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);
502     IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);
503     IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
504     IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
505     IO.mapOptional("FlagEnum", T.FlagEnum);
506     IO.mapOptional("EnumKind", T.EnumConvenienceKind);
507     IO.mapOptional("SwiftCopyable", T.SwiftCopyable);
508     IO.mapOptional("SwiftEscapable", T.SwiftEscapable);
509     IO.mapOptional("Methods", T.Methods);
510     IO.mapOptional("Fields", T.Fields);
511     IO.mapOptional("Tags", T.Tags);
512   }
513 };
514 } // namespace yaml
515 } // namespace llvm
516 
517 namespace {
518 struct Typedef {
519   StringRef Name;
520   AvailabilityItem Availability;
521   StringRef SwiftName;
522   std::optional<bool> SwiftPrivate;
523   std::optional<StringRef> SwiftBridge;
524   std::optional<StringRef> NSErrorDomain;
525   std::optional<SwiftNewTypeKind> SwiftType;
526 };
527 
528 typedef std::vector<Typedef> TypedefsSeq;
529 } // namespace
530 
531 LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef)
532 
533 namespace llvm {
534 namespace yaml {
535 template <> struct ScalarEnumerationTraits<SwiftNewTypeKind> {
536   static void enumeration(IO &IO, SwiftNewTypeKind &SWK) {
537     IO.enumCase(SWK, "none", SwiftNewTypeKind::None);
538     IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct);
539     IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum);
540   }
541 };
542 
543 template <> struct MappingTraits<Typedef> {
544   static void mapping(IO &IO, Typedef &T) {
545     IO.mapRequired("Name", T.Name);
546     IO.mapOptional("Availability", T.Availability.Mode,
547                    APIAvailability::Available);
548     IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
549     IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
550     IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
551     IO.mapOptional("SwiftBridge", T.SwiftBridge);
552     IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
553     IO.mapOptional("SwiftWrapper", T.SwiftType);
554   }
555 };
556 } // namespace yaml
557 } // namespace llvm
558 
559 namespace {
560 struct Namespace;
561 typedef std::vector<Namespace> NamespacesSeq;
562 
563 struct TopLevelItems {
564   ClassesSeq Classes;
565   ClassesSeq Protocols;
566   FunctionsSeq Functions;
567   GlobalVariablesSeq Globals;
568   EnumConstantsSeq EnumConstants;
569   TagsSeq Tags;
570   TypedefsSeq Typedefs;
571   NamespacesSeq Namespaces;
572 };
573 } // namespace
574 
575 namespace llvm {
576 namespace yaml {
577 static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) {
578   IO.mapOptional("Classes", TLI.Classes);
579   IO.mapOptional("Protocols", TLI.Protocols);
580   IO.mapOptional("Functions", TLI.Functions);
581   IO.mapOptional("Globals", TLI.Globals);
582   IO.mapOptional("Enumerators", TLI.EnumConstants);
583   IO.mapOptional("Tags", TLI.Tags);
584   IO.mapOptional("Typedefs", TLI.Typedefs);
585   IO.mapOptional("Namespaces", TLI.Namespaces);
586 }
587 } // namespace yaml
588 } // namespace llvm
589 
590 namespace {
591 struct Namespace {
592   StringRef Name;
593   AvailabilityItem Availability;
594   StringRef SwiftName;
595   std::optional<bool> SwiftPrivate;
596   TopLevelItems Items;
597 };
598 } // namespace
599 
600 LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace)
601 
602 namespace llvm {
603 namespace yaml {
604 template <> struct MappingTraits<Namespace> {
605   static void mapping(IO &IO, Namespace &T) {
606     IO.mapRequired("Name", T.Name);
607     IO.mapOptional("Availability", T.Availability.Mode,
608                    APIAvailability::Available);
609     IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
610     IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
611     IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
612     mapTopLevelItems(IO, T.Items);
613   }
614 };
615 } // namespace yaml
616 } // namespace llvm
617 
618 namespace {
619 struct Versioned {
620   VersionTuple Version;
621   TopLevelItems Items;
622 };
623 
624 typedef std::vector<Versioned> VersionedSeq;
625 } // namespace
626 
627 LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned)
628 
629 namespace llvm {
630 namespace yaml {
631 template <> struct MappingTraits<Versioned> {
632   static void mapping(IO &IO, Versioned &V) {
633     IO.mapRequired("Version", V.Version);
634     mapTopLevelItems(IO, V.Items);
635   }
636 };
637 } // namespace yaml
638 } // namespace llvm
639 
640 namespace {
641 struct Module {
642   StringRef Name;
643   AvailabilityItem Availability;
644   TopLevelItems TopLevel;
645   VersionedSeq SwiftVersions;
646 
647   std::optional<bool> SwiftInferImportAsMember;
648 
649 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
650   LLVM_DUMP_METHOD void dump() /*const*/;
651 #endif
652 };
653 } // namespace
654 
655 namespace llvm {
656 namespace yaml {
657 template <> struct MappingTraits<Module> {
658   static void mapping(IO &IO, Module &M) {
659     IO.mapRequired("Name", M.Name);
660     IO.mapOptional("Availability", M.Availability.Mode,
661                    APIAvailability::Available);
662     IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));
663     IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember);
664     mapTopLevelItems(IO, M.TopLevel);
665     IO.mapOptional("SwiftVersions", M.SwiftVersions);
666   }
667 };
668 } // namespace yaml
669 } // namespace llvm
670 
671 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
672 LLVM_DUMP_METHOD void Module::dump() {
673   llvm::yaml::Output OS(llvm::errs());
674   OS << *this;
675 }
676 #endif
677 
678 namespace {
679 bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag,
680                    void *DiagContext) {
681   llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext);
682   IS >> M;
683   return static_cast<bool>(IS.error());
684 }
685 } // namespace
686 
687 bool clang::api_notes::parseAndDumpAPINotes(StringRef YI,
688                                             llvm::raw_ostream &OS) {
689   Module M;
690   if (parseAPINotes(YI, M, nullptr, nullptr))
691     return true;
692 
693   llvm::yaml::Output YOS(OS);
694   YOS << M;
695 
696   return false;
697 }
698 
699 namespace {
700 using namespace api_notes;
701 
702 class YAMLConverter {
703   const Module &M;
704   APINotesWriter Writer;
705   llvm::raw_ostream &OS;
706   llvm::SourceMgr::DiagHandlerTy DiagHandler;
707   void *DiagHandlerCtxt;
708   bool ErrorOccured;
709 
710   /// Emit a diagnostic
711   bool emitError(llvm::Twine Message) {
712     DiagHandler(
713         llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
714         DiagHandlerCtxt);
715     ErrorOccured = true;
716     return true;
717   }
718 
719 public:
720   YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
721                 llvm::raw_ostream &OS,
722                 llvm::SourceMgr::DiagHandlerTy DiagHandler,
723                 void *DiagHandlerCtxt)
724       : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
725         DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
726         ErrorOccured(false) {}
727 
728   void convertAvailability(const AvailabilityItem &Availability,
729                            CommonEntityInfo &CEI, llvm::StringRef APIName) {
730     // Populate the unavailability information.
731     CEI.Unavailable = (Availability.Mode == APIAvailability::None);
732     CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift);
733     if (CEI.Unavailable || CEI.UnavailableInSwift) {
734       CEI.UnavailableMsg = std::string(Availability.Msg);
735     } else {
736       if (!Availability.Msg.empty())
737         emitError(llvm::Twine("availability message for available API '") +
738                   APIName + "' will not be used");
739     }
740   }
741 
742   void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo,
743                      std::optional<ParamInfo> &thisOrSelf) {
744     for (const auto &P : Params) {
745       ParamInfo PI;
746       if (P.Nullability)
747         PI.setNullabilityAudited(*P.Nullability);
748       PI.setNoEscape(P.NoEscape);
749       PI.setLifetimebound(P.Lifetimebound);
750       PI.setType(std::string(P.Type));
751       PI.setRetainCountConvention(P.RetainCountConvention);
752       if (static_cast<int>(OutInfo.Params.size()) <= P.Position)
753         OutInfo.Params.resize(P.Position + 1);
754       if (P.Position == -1)
755         thisOrSelf = PI;
756       else if (P.Position >= 0)
757         OutInfo.Params[P.Position] |= PI;
758       else
759         emitError("invalid parameter position " + llvm::itostr(P.Position));
760     }
761   }
762 
763   void convertNullability(const NullabilitySeq &Nullability,
764                           std::optional<NullabilityKind> ReturnNullability,
765                           FunctionInfo &OutInfo, llvm::StringRef APIName) {
766     if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) {
767       emitError(llvm::Twine("nullability info for '") + APIName +
768                 "' does not fit");
769       return;
770     }
771 
772     bool audited = false;
773     unsigned int idx = 1;
774     for (const auto &N : Nullability)
775       OutInfo.addTypeInfo(idx++, N);
776     audited = Nullability.size() > 0 || ReturnNullability;
777     if (audited)
778       OutInfo.addTypeInfo(0,
779                           ReturnNullability.value_or(NullabilityKind::NonNull));
780     if (!audited)
781       return;
782     OutInfo.NullabilityAudited = audited;
783     OutInfo.NumAdjustedNullable = idx;
784   }
785 
786   /// Convert the common parts of an entity from YAML.
787   template <typename T>
788   void convertCommonEntity(const T &Common, CommonEntityInfo &Info,
789                            StringRef APIName) {
790     convertAvailability(Common.Availability, Info, APIName);
791     Info.setSwiftPrivate(Common.SwiftPrivate);
792     Info.SwiftName = std::string(Common.SwiftName);
793   }
794 
795   /// Convert the common parts of a type entity from YAML.
796   template <typename T>
797   void convertCommonType(const T &Common, CommonTypeInfo &Info,
798                          StringRef APIName) {
799     convertCommonEntity(Common, Info, APIName);
800     if (Common.SwiftBridge)
801       Info.setSwiftBridge(std::string(*Common.SwiftBridge));
802     Info.setNSErrorDomain(Common.NSErrorDomain);
803   }
804 
805   // Translate from Method into ObjCMethodInfo and write it out.
806   void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName,
807                      VersionTuple SwiftVersion) {
808     ObjCMethodInfo MI;
809     convertCommonEntity(M, MI, M.Selector);
810 
811     // Check if the selector ends with ':' to determine if it takes arguments.
812     bool takesArguments = M.Selector.ends_with(":");
813 
814     // Split the selector into pieces.
815     llvm::SmallVector<StringRef, 4> Args;
816     M.Selector.split(Args, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
817     if (!takesArguments && Args.size() > 1) {
818       emitError("selector '" + M.Selector + "' is missing a ':' at the end");
819       return;
820     }
821 
822     // Construct ObjCSelectorRef.
823     api_notes::ObjCSelectorRef Selector;
824     Selector.NumArgs = !takesArguments ? 0 : Args.size();
825     Selector.Identifiers = Args;
826 
827     // Translate the initializer info.
828     MI.DesignatedInit = M.DesignatedInit;
829     MI.RequiredInit = M.Required;
830     if (M.FactoryAsInit != FactoryAsInitKind::Infer)
831       emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead");
832 
833     MI.ResultType = std::string(M.ResultType);
834     MI.SwiftReturnOwnership = std::string(M.SwiftReturnOwnership);
835 
836     // Translate parameter information.
837     convertParams(M.Params, MI, MI.Self);
838 
839     // Translate nullability info.
840     convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector);
841 
842     MI.setRetainCountConvention(M.RetainCountConvention);
843 
844     // Write it.
845     Writer.addObjCMethod(ClassID, Selector, M.Kind == MethodKind::Instance, MI,
846                          SwiftVersion);
847   }
848 
849   template <typename T>
850   void convertVariable(const T &Entity, VariableInfo &VI) {
851     convertAvailability(Entity.Availability, VI, Entity.Name);
852     VI.setSwiftPrivate(Entity.SwiftPrivate);
853     VI.SwiftName = std::string(Entity.SwiftName);
854     if (Entity.Nullability)
855       VI.setNullabilityAudited(*Entity.Nullability);
856     VI.setType(std::string(Entity.Type));
857   }
858 
859   void convertContext(std::optional<ContextID> ParentContextID, const Class &C,
860                       ContextKind Kind, VersionTuple SwiftVersion) {
861     // Write the class.
862     ContextInfo CI;
863     convertCommonType(C, CI, C.Name);
864 
865     if (C.AuditedForNullability)
866       CI.setDefaultNullability(NullabilityKind::NonNull);
867     if (C.SwiftImportAsNonGeneric)
868       CI.setSwiftImportAsNonGeneric(*C.SwiftImportAsNonGeneric);
869     if (C.SwiftObjCMembers)
870       CI.setSwiftObjCMembers(*C.SwiftObjCMembers);
871 
872     ContextID CtxID =
873         Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);
874 
875     // Write all methods.
876     llvm::StringMap<std::pair<bool, bool>> KnownMethods;
877     for (const auto &method : C.Methods) {
878       // Check for duplicate method definitions.
879       bool IsInstanceMethod = method.Kind == MethodKind::Instance;
880       bool &Known = IsInstanceMethod ? KnownMethods[method.Selector].first
881                                      : KnownMethods[method.Selector].second;
882       if (Known) {
883         emitError(llvm::Twine("duplicate definition of method '") +
884                   (IsInstanceMethod ? "-" : "+") + "[" + C.Name + " " +
885                   method.Selector + "]'");
886         continue;
887       }
888       Known = true;
889 
890       convertMethod(method, CtxID, C.Name, SwiftVersion);
891     }
892 
893     // Write all properties.
894     llvm::StringSet<> KnownInstanceProperties;
895     llvm::StringSet<> KnownClassProperties;
896     for (const auto &Property : C.Properties) {
897       // Check for duplicate property definitions.
898       if ((!Property.Kind || *Property.Kind == MethodKind::Instance) &&
899           !KnownInstanceProperties.insert(Property.Name).second) {
900         emitError(llvm::Twine("duplicate definition of instance property '") +
901                   C.Name + "." + Property.Name + "'");
902         continue;
903       }
904 
905       if ((!Property.Kind || *Property.Kind == MethodKind::Class) &&
906           !KnownClassProperties.insert(Property.Name).second) {
907         emitError(llvm::Twine("duplicate definition of class property '") +
908                   C.Name + "." + Property.Name + "'");
909         continue;
910       }
911 
912       // Translate from Property into ObjCPropertyInfo.
913       ObjCPropertyInfo PI;
914       convertVariable(Property, PI);
915       if (Property.SwiftImportAsAccessors)
916         PI.setSwiftImportAsAccessors(*Property.SwiftImportAsAccessors);
917 
918       // Add both instance and class properties with this name.
919       if (Property.Kind) {
920         Writer.addObjCProperty(CtxID, Property.Name,
921                                *Property.Kind == MethodKind::Instance, PI,
922                                SwiftVersion);
923       } else {
924         Writer.addObjCProperty(CtxID, Property.Name, true, PI, SwiftVersion);
925         Writer.addObjCProperty(CtxID, Property.Name, false, PI, SwiftVersion);
926       }
927     }
928   }
929 
930   void convertNamespaceContext(std::optional<ContextID> ParentContextID,
931                                const Namespace &TheNamespace,
932                                VersionTuple SwiftVersion) {
933     // Write the namespace.
934     ContextInfo CI;
935     convertCommonEntity(TheNamespace, CI, TheNamespace.Name);
936 
937     ContextID CtxID =
938         Writer.addContext(ParentContextID, TheNamespace.Name,
939                           ContextKind::Namespace, CI, SwiftVersion);
940 
941     convertTopLevelItems(Context(CtxID, ContextKind::Namespace),
942                          TheNamespace.Items, SwiftVersion);
943   }
944 
945   template <typename FuncOrMethodInfo>
946   void convertFunction(const Function &Function, FuncOrMethodInfo &FI) {
947     convertAvailability(Function.Availability, FI, Function.Name);
948     FI.setSwiftPrivate(Function.SwiftPrivate);
949     FI.SwiftName = std::string(Function.SwiftName);
950     std::optional<ParamInfo> This;
951     convertParams(Function.Params, FI, This);
952     if constexpr (std::is_same_v<FuncOrMethodInfo, CXXMethodInfo>)
953       FI.This = This;
954     else if (This)
955       emitError("implicit instance parameter is only permitted on C++ and "
956                 "Objective-C methods");
957     convertNullability(Function.Nullability, Function.NullabilityOfRet, FI,
958                        Function.Name);
959     FI.ResultType = std::string(Function.ResultType);
960     FI.SwiftReturnOwnership = std::string(Function.SwiftReturnOwnership);
961     FI.setRetainCountConvention(Function.RetainCountConvention);
962   }
963 
964   void convertTagContext(std::optional<Context> ParentContext, const Tag &T,
965                          VersionTuple SwiftVersion) {
966     TagInfo TI;
967     std::optional<ContextID> ParentContextID =
968         ParentContext ? std::optional<ContextID>(ParentContext->id)
969                       : std::nullopt;
970     convertCommonType(T, TI, T.Name);
971 
972     if ((T.SwiftRetainOp || T.SwiftReleaseOp) && !T.SwiftImportAs) {
973       emitError(llvm::Twine("should declare SwiftImportAs to use "
974                             "SwiftRetainOp and SwiftReleaseOp (for ") +
975                 T.Name + ")");
976       return;
977     }
978     if (T.SwiftReleaseOp.has_value() != T.SwiftRetainOp.has_value()) {
979       emitError(llvm::Twine("should declare both SwiftReleaseOp and "
980                             "SwiftRetainOp (for ") +
981                 T.Name + ")");
982       return;
983     }
984 
985     if (T.SwiftImportAs)
986       TI.SwiftImportAs = T.SwiftImportAs;
987     if (T.SwiftRetainOp)
988       TI.SwiftRetainOp = T.SwiftRetainOp;
989     if (T.SwiftReleaseOp)
990       TI.SwiftReleaseOp = T.SwiftReleaseOp;
991     if (T.SwiftConformance)
992       TI.SwiftConformance = T.SwiftConformance;
993 
994     if (T.SwiftCopyable)
995       TI.setSwiftCopyable(T.SwiftCopyable);
996     if (T.SwiftEscapable)
997       TI.setSwiftEscapable(T.SwiftEscapable);
998 
999     if (T.EnumConvenienceKind) {
1000       if (T.EnumExtensibility) {
1001         emitError(
1002             llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") +
1003             T.Name + ")");
1004         return;
1005       }
1006       if (T.FlagEnum) {
1007         emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") +
1008                   T.Name + ")");
1009         return;
1010       }
1011       switch (*T.EnumConvenienceKind) {
1012       case EnumConvenienceAliasKind::None:
1013         TI.EnumExtensibility = EnumExtensibilityKind::None;
1014         TI.setFlagEnum(false);
1015         break;
1016       case EnumConvenienceAliasKind::CFEnum:
1017         TI.EnumExtensibility = EnumExtensibilityKind::Open;
1018         TI.setFlagEnum(false);
1019         break;
1020       case EnumConvenienceAliasKind::CFOptions:
1021         TI.EnumExtensibility = EnumExtensibilityKind::Open;
1022         TI.setFlagEnum(true);
1023         break;
1024       case EnumConvenienceAliasKind::CFClosedEnum:
1025         TI.EnumExtensibility = EnumExtensibilityKind::Closed;
1026         TI.setFlagEnum(false);
1027         break;
1028       }
1029     } else {
1030       TI.EnumExtensibility = T.EnumExtensibility;
1031       TI.setFlagEnum(T.FlagEnum);
1032     }
1033 
1034     Writer.addTag(ParentContext, T.Name, TI, SwiftVersion);
1035 
1036     ContextInfo CI;
1037     auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag,
1038                                       CI, SwiftVersion);
1039     Context TagCtx(TagCtxID, ContextKind::Tag);
1040 
1041     for (const auto &Field : T.Fields) {
1042       FieldInfo FI;
1043       convertVariable(Field, FI);
1044       Writer.addField(TagCtxID, Field.Name, FI, SwiftVersion);
1045     }
1046 
1047     for (const auto &CXXMethod : T.Methods) {
1048       CXXMethodInfo MI;
1049       convertFunction(CXXMethod, MI);
1050       Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);
1051     }
1052 
1053     // Convert nested tags.
1054     for (const auto &Tag : T.Tags)
1055       convertTagContext(TagCtx, Tag, SwiftVersion);
1056   }
1057 
1058   void convertTopLevelItems(std::optional<Context> Ctx,
1059                             const TopLevelItems &TLItems,
1060                             VersionTuple SwiftVersion) {
1061     std::optional<ContextID> CtxID =
1062         Ctx ? std::optional(Ctx->id) : std::nullopt;
1063 
1064     // Write all classes.
1065     llvm::StringSet<> KnownClasses;
1066     for (const auto &Class : TLItems.Classes) {
1067       // Check for duplicate class definitions.
1068       if (!KnownClasses.insert(Class.Name).second) {
1069         emitError(llvm::Twine("multiple definitions of class '") + Class.Name +
1070                   "'");
1071         continue;
1072       }
1073 
1074       convertContext(CtxID, Class, ContextKind::ObjCClass, SwiftVersion);
1075     }
1076 
1077     // Write all protocols.
1078     llvm::StringSet<> KnownProtocols;
1079     for (const auto &Protocol : TLItems.Protocols) {
1080       // Check for duplicate protocol definitions.
1081       if (!KnownProtocols.insert(Protocol.Name).second) {
1082         emitError(llvm::Twine("multiple definitions of protocol '") +
1083                   Protocol.Name + "'");
1084         continue;
1085       }
1086 
1087       convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion);
1088     }
1089 
1090     // Write all namespaces.
1091     llvm::StringSet<> KnownNamespaces;
1092     for (const auto &Namespace : TLItems.Namespaces) {
1093       // Check for duplicate namespace definitions.
1094       if (!KnownNamespaces.insert(Namespace.Name).second) {
1095         emitError(llvm::Twine("multiple definitions of namespace '") +
1096                   Namespace.Name + "'");
1097         continue;
1098       }
1099 
1100       convertNamespaceContext(CtxID, Namespace, SwiftVersion);
1101     }
1102 
1103     // Write all global variables.
1104     llvm::StringSet<> KnownGlobals;
1105     for (const auto &Global : TLItems.Globals) {
1106       // Check for duplicate global variables.
1107       if (!KnownGlobals.insert(Global.Name).second) {
1108         emitError(llvm::Twine("multiple definitions of global variable '") +
1109                   Global.Name + "'");
1110         continue;
1111       }
1112 
1113       GlobalVariableInfo GVI;
1114       convertVariable(Global, GVI);
1115       Writer.addGlobalVariable(Ctx, Global.Name, GVI, SwiftVersion);
1116     }
1117 
1118     // Write all global functions.
1119     llvm::StringSet<> KnownFunctions;
1120     for (const auto &Function : TLItems.Functions) {
1121       // Check for duplicate global functions.
1122       if (!KnownFunctions.insert(Function.Name).second) {
1123         emitError(llvm::Twine("multiple definitions of global function '") +
1124                   Function.Name + "'");
1125         continue;
1126       }
1127 
1128       GlobalFunctionInfo GFI;
1129       convertFunction(Function, GFI);
1130       Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion);
1131     }
1132 
1133     // Write all enumerators.
1134     llvm::StringSet<> KnownEnumConstants;
1135     for (const auto &EnumConstant : TLItems.EnumConstants) {
1136       // Check for duplicate enumerators
1137       if (!KnownEnumConstants.insert(EnumConstant.Name).second) {
1138         emitError(llvm::Twine("multiple definitions of enumerator '") +
1139                   EnumConstant.Name + "'");
1140         continue;
1141       }
1142 
1143       EnumConstantInfo ECI;
1144       convertAvailability(EnumConstant.Availability, ECI, EnumConstant.Name);
1145       ECI.setSwiftPrivate(EnumConstant.SwiftPrivate);
1146       ECI.SwiftName = std::string(EnumConstant.SwiftName);
1147       Writer.addEnumConstant(EnumConstant.Name, ECI, SwiftVersion);
1148     }
1149 
1150     // Write all tags.
1151     llvm::StringSet<> KnownTags;
1152     for (const auto &Tag : TLItems.Tags) {
1153       // Check for duplicate tag definitions.
1154       if (!KnownTags.insert(Tag.Name).second) {
1155         emitError(llvm::Twine("multiple definitions of tag '") + Tag.Name +
1156                   "'");
1157         continue;
1158       }
1159 
1160       convertTagContext(Ctx, Tag, SwiftVersion);
1161     }
1162 
1163     // Write all typedefs.
1164     llvm::StringSet<> KnownTypedefs;
1165     for (const auto &Typedef : TLItems.Typedefs) {
1166       // Check for duplicate typedef definitions.
1167       if (!KnownTypedefs.insert(Typedef.Name).second) {
1168         emitError(llvm::Twine("multiple definitions of typedef '") +
1169                   Typedef.Name + "'");
1170         continue;
1171       }
1172 
1173       TypedefInfo TInfo;
1174       convertCommonType(Typedef, TInfo, Typedef.Name);
1175       TInfo.SwiftWrapper = Typedef.SwiftType;
1176 
1177       Writer.addTypedef(Ctx, Typedef.Name, TInfo, SwiftVersion);
1178     }
1179   }
1180 
1181   bool convertModule() {
1182     // Write the top-level items.
1183     convertTopLevelItems(/* context */ std::nullopt, M.TopLevel,
1184                          VersionTuple());
1185 
1186     // Convert the versioned information.
1187     for (const auto &Versioned : M.SwiftVersions)
1188       convertTopLevelItems(/* context */ std::nullopt, Versioned.Items,
1189                            Versioned.Version);
1190 
1191     if (!ErrorOccured)
1192       Writer.writeToStream(OS);
1193 
1194     return ErrorOccured;
1195   }
1196 };
1197 } // namespace
1198 
1199 static bool compile(const Module &M, const FileEntry *SourceFile,
1200                     llvm::raw_ostream &OS,
1201                     llvm::SourceMgr::DiagHandlerTy DiagHandler,
1202                     void *DiagHandlerCtxt) {
1203   YAMLConverter C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1204   return C.convertModule();
1205 }
1206 
1207 /// Simple diagnostic handler that prints diagnostics to standard error.
1208 static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context) {
1209   Diag.print(nullptr, llvm::errs());
1210 }
1211 
1212 bool api_notes::compileAPINotes(StringRef YAMLInput,
1213                                 const FileEntry *SourceFile,
1214                                 llvm::raw_ostream &OS,
1215                                 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1216                                 void *DiagHandlerCtxt) {
1217   Module TheModule;
1218 
1219   if (!DiagHandler)
1220     DiagHandler = &printDiagnostic;
1221 
1222   if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt))
1223     return true;
1224 
1225   return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1226 }
1227