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