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