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