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