clang: lib/APINotes/APINotesYAMLCompiler.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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
26#include <type_traits>
27#include
28
29using namespace clang;
30using namespace api_notes;
31
32namespace {
33enum class APIAvailability {
34 Available = 0,
36 NonSwift,
37};
38}
39
40namespace llvm {
41namespace yaml {
42template <> struct ScalarEnumerationTraits {
43 static void enumeration(IO &IO, APIAvailability &AA) {
44 IO.enumCase(AA, "none", APIAvailability::None);
45 IO.enumCase(AA, "nonswift", APIAvailability::NonSwift);
46 IO.enumCase(AA, "available", APIAvailability::Available);
47 }
48};
49}
50}
51
52namespace {
53enum class MethodKind {
55 Instance,
56};
57}
58
59namespace llvm {
60namespace yaml {
61template <> struct ScalarEnumerationTraits {
63 IO.enumCase(MK, "Class", MethodKind::Class);
64 IO.enumCase(MK, "Instance", MethodKind::Instance);
65 }
66};
67}
68}
69
70namespace {
71struct Param {
72 int Position;
73 std::optional NoEscape = false;
74 std::optional Lifetimebound = false;
75 std::optional Nullability;
76 std::optional RetainCountConvention;
77 StringRef Type;
78};
79
80typedef std::vector ParamsSeq;
81}
82
83LLVM_YAML_IS_SEQUENCE_VECTOR(Param)
85
86namespace llvm {
87namespace yaml {
90 IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull);
91 IO.enumCase(NK, "Optional", NullabilityKind::Nullable);
92 IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified);
93 IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult);
94
95
96 IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified);
97
98
99 IO.enumCase(NK, "N", NullabilityKind::NonNull);
100 IO.enumCase(NK, "O", NullabilityKind::Nullable);
101 IO.enumCase(NK, "U", NullabilityKind::Unspecified);
102 IO.enumCase(NK, "S", NullabilityKind::Unspecified);
103 }
104};
105
108 IO.enumCase(RCCK, "none", RetainCountConventionKind::None);
109 IO.enumCase(RCCK, "CFReturnsRetained",
110 RetainCountConventionKind::CFReturnsRetained);
111 IO.enumCase(RCCK, "CFReturnsNotRetained",
112 RetainCountConventionKind::CFReturnsNotRetained);
113 IO.enumCase(RCCK, "NSReturnsRetained",
114 RetainCountConventionKind::NSReturnsRetained);
115 IO.enumCase(RCCK, "NSReturnsNotRetained",
116 RetainCountConventionKind::NSReturnsNotRetained);
117 }
118};
119
120template <> struct MappingTraits {
122 IO.mapRequired("Position", P.Position);
123 IO.mapOptional("Nullability", P.Nullability, std::nullopt);
124 IO.mapOptional("RetainCountConvention", P.RetainCountConvention);
125 IO.mapOptional("NoEscape", P.NoEscape);
126 IO.mapOptional("Lifetimebound", P.Lifetimebound);
127 IO.mapOptional("Type", P.Type, StringRef(""));
128 }
129};
130}
131}
132
133namespace {
134typedef std::vector NullabilitySeq;
135
136struct AvailabilityItem {
137 APIAvailability Mode = APIAvailability::Available;
138 StringRef Msg;
139};
140
141
142enum class FactoryAsInitKind {
143
144 Infer,
145
146 AsClassMethod,
147
148 AsInitializer,
149};
150
151struct Method {
153 MethodKind Kind;
154 ParamsSeq Params;
156 std::optional NullabilityOfRet;
157 std::optional RetainCountConvention;
158 AvailabilityItem Availability;
159 std::optional SwiftPrivate;
160 StringRef SwiftName;
161 FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer;
162 bool DesignatedInit = false;
164 StringRef ResultType;
165 StringRef SwiftReturnOwnership;
166};
167
168typedef std::vector MethodsSeq;
169}
170
171LLVM_YAML_IS_SEQUENCE_VECTOR(Method)
172
173namespace llvm {
174namespace yaml {
175template <> struct ScalarEnumerationTraits {
176 static void enumeration(IO &IO, FactoryAsInitKind &FIK) {
177 IO.enumCase(FIK, "A", FactoryAsInitKind::Infer);
178 IO.enumCase(FIK, "C", FactoryAsInitKind::AsClassMethod);
179 IO.enumCase(FIK, "I", FactoryAsInitKind::AsInitializer);
180 }
181};
182
183template <> struct MappingTraits {
184 static void mapping(IO &IO, Method &M) {
185 IO.mapRequired("Selector", M.Selector);
186 IO.mapRequired("MethodKind", M.Kind);
187 IO.mapOptional("Parameters", M.Params);
188 IO.mapOptional("Nullability", M.Nullability);
189 IO.mapOptional("NullabilityOfRet", M.NullabilityOfRet, std::nullopt);
190 IO.mapOptional("RetainCountConvention", M.RetainCountConvention);
191 IO.mapOptional("Availability", M.Availability.Mode,
192 APIAvailability::Available);
193 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));
194 IO.mapOptional("SwiftPrivate", M.SwiftPrivate);
195 IO.mapOptional("SwiftName", M.SwiftName, StringRef(""));
196 IO.mapOptional("FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer);
197 IO.mapOptional("DesignatedInit", M.DesignatedInit, false);
198 IO.mapOptional("Required", M.Required, false);
199 IO.mapOptional("ResultType", M.ResultType, StringRef(""));
200 IO.mapOptional("SwiftReturnOwnership", M.SwiftReturnOwnership,
201 StringRef(""));
202 }
203};
204}
205}
206
207namespace {
209 StringRef Name;
210 std::optional Kind;
211 std::optional Nullability;
212 AvailabilityItem Availability;
213 std::optional SwiftPrivate;
214 StringRef SwiftName;
215 std::optional SwiftImportAsAccessors;
216 StringRef Type;
217};
218
219typedef std::vector PropertiesSeq;
220}
221
222LLVM_YAML_IS_SEQUENCE_VECTOR(Property)
223
224namespace llvm {
225namespace yaml {
226template <> struct MappingTraits<Property> {
227 static void mapping(IO &IO, Property &P) {
228 IO.mapRequired("Name", P.Name);
229 IO.mapOptional("PropertyKind", P.Kind);
230 IO.mapOptional("Nullability", P.Nullability, std::nullopt);
231 IO.mapOptional("Availability", P.Availability.Mode,
232 APIAvailability::Available);
233 IO.mapOptional("AvailabilityMsg", P.Availability.Msg, StringRef(""));
234 IO.mapOptional("SwiftPrivate", P.SwiftPrivate);
235 IO.mapOptional("SwiftName", P.SwiftName, StringRef(""));
236 IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors);
237 IO.mapOptional("Type", P.Type, StringRef(""));
238 }
239};
240}
241}
242
243namespace {
245 StringRef Name;
246 bool AuditedForNullability = false;
247 AvailabilityItem Availability;
248 std::optional SwiftPrivate;
249 StringRef SwiftName;
250 std::optional SwiftBridge;
251 std::optional NSErrorDomain;
252 std::optional SwiftImportAsNonGeneric;
253 std::optional SwiftObjCMembers;
254 MethodsSeq Methods;
255 PropertiesSeq Properties;
256};
257
258typedef std::vector ClassesSeq;
259}
260
261LLVM_YAML_IS_SEQUENCE_VECTOR(Class)
262
263namespace llvm {
264namespace yaml {
265template <> struct MappingTraits<Class> {
267 IO.mapRequired("Name", C.Name);
268 IO.mapOptional("AuditedForNullability", C.AuditedForNullability, false);
269 IO.mapOptional("Availability", C.Availability.Mode,
270 APIAvailability::Available);
271 IO.mapOptional("AvailabilityMsg", C.Availability.Msg, StringRef(""));
272 IO.mapOptional("SwiftPrivate", C.SwiftPrivate);
273 IO.mapOptional("SwiftName", C.SwiftName, StringRef(""));
274 IO.mapOptional("SwiftBridge", C.SwiftBridge);
275 IO.mapOptional("NSErrorDomain", C.NSErrorDomain);
276 IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric);
277 IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers);
278 IO.mapOptional("Methods", C.Methods);
279 IO.mapOptional("Properties", C.Properties);
280 }
281};
282}
283}
284
285namespace {
287 StringRef Name;
288 ParamsSeq Params;
290 std::optional NullabilityOfRet;
291 std::optional<api_notes::RetainCountConventionKind> RetainCountConvention;
292 AvailabilityItem Availability;
293 std::optional SwiftPrivate;
294 StringRef SwiftName;
295 StringRef Type;
296 StringRef ResultType;
297 StringRef SwiftReturnOwnership;
298};
299
300typedef std::vector FunctionsSeq;
301}
302
303LLVM_YAML_IS_SEQUENCE_VECTOR(Function)
304
305namespace llvm {
306namespace yaml {
307template <> struct MappingTraits<Function> {
308 static void mapping(IO &IO, Function &F) {
309 IO.mapRequired("Name", F.Name);
310 IO.mapOptional("Parameters", F.Params);
311 IO.mapOptional("Nullability", F.Nullability);
312 IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, std::nullopt);
313 IO.mapOptional("RetainCountConvention", F.RetainCountConvention);
314 IO.mapOptional("Availability", F.Availability.Mode,
315 APIAvailability::Available);
316 IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef(""));
317 IO.mapOptional("SwiftPrivate", F.SwiftPrivate);
318 IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
319 IO.mapOptional("ResultType", F.ResultType, StringRef(""));
320 IO.mapOptional("SwiftReturnOwnership", F.SwiftReturnOwnership,
321 StringRef(""));
322 }
323};
324}
325}
326
327namespace {
328struct GlobalVariable {
329 StringRef Name;
330 std::optional Nullability;
331 AvailabilityItem Availability;
332 std::optional SwiftPrivate;
333 StringRef SwiftName;
334 StringRef Type;
335};
336
337typedef std::vector GlobalVariablesSeq;
338}
339
340LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable)
341
342namespace llvm {
343namespace yaml {
344template <> struct MappingTraits {
345 static void mapping(IO &IO, GlobalVariable &GV) {
346 IO.mapRequired("Name", GV.Name);
347 IO.mapOptional("Nullability", GV.Nullability, std::nullopt);
348 IO.mapOptional("Availability", GV.Availability.Mode,
349 APIAvailability::Available);
350 IO.mapOptional("AvailabilityMsg", GV.Availability.Msg, StringRef(""));
351 IO.mapOptional("SwiftPrivate", GV.SwiftPrivate);
352 IO.mapOptional("SwiftName", GV.SwiftName, StringRef(""));
353 IO.mapOptional("Type", GV.Type, StringRef(""));
354 }
355};
356}
357}
358
359namespace {
361 StringRef Name;
362 AvailabilityItem Availability;
363 std::optional SwiftPrivate;
364 StringRef SwiftName;
365};
366
367typedef std::vector EnumConstantsSeq;
368}
369
370LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant)
371
372namespace llvm {
373namespace yaml {
374template <> struct MappingTraits {
375 static void mapping(IO &IO, EnumConstant &EC) {
376 IO.mapRequired("Name", EC.Name);
377 IO.mapOptional("Availability", EC.Availability.Mode,
378 APIAvailability::Available);
379 IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef(""));
380 IO.mapOptional("SwiftPrivate", EC.SwiftPrivate);
381 IO.mapOptional("SwiftName", EC.SwiftName, StringRef(""));
382 }
383};
384}
385}
386
387namespace {
388
389enum class EnumConvenienceAliasKind {
390
392
393 CFEnum,
394
395 CFOptions,
396
397 CFClosedEnum
398};
399}
400
401namespace llvm {
402namespace yaml {
403template <> struct ScalarEnumerationTraits {
404 static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK) {
405 IO.enumCase(ECAK, "none", EnumConvenienceAliasKind::None);
406 IO.enumCase(ECAK, "CFEnum", EnumConvenienceAliasKind::CFEnum);
407 IO.enumCase(ECAK, "NSEnum", EnumConvenienceAliasKind::CFEnum);
408 IO.enumCase(ECAK, "CFOptions", EnumConvenienceAliasKind::CFOptions);
409 IO.enumCase(ECAK, "NSOptions", EnumConvenienceAliasKind::CFOptions);
410 IO.enumCase(ECAK, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);
411 IO.enumCase(ECAK, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);
412 }
413};
414}
415}
416
417namespace {
419 StringRef Name;
420 std::optional Nullability;
421 AvailabilityItem Availability;
422 std::optional SwiftPrivate;
423 StringRef SwiftName;
424 StringRef Type;
425};
426
427typedef std::vector FieldsSeq;
428}
429
430LLVM_YAML_IS_SEQUENCE_VECTOR(Field)
431
432namespace llvm {
433namespace yaml {
434template <> struct MappingTraits {
435 static void mapping(IO &IO, Field &F) {
436 IO.mapRequired("Name", F.Name);
437 IO.mapOptional("Nullability", F.Nullability, std::nullopt);
438 IO.mapOptional("Availability", F.Availability.Mode,
439 APIAvailability::Available);
440 IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef(""));
441 IO.mapOptional("SwiftPrivate", F.SwiftPrivate);
442 IO.mapOptional("SwiftName", F.SwiftName, StringRef(""));
443 IO.mapOptional("Type", F.Type, StringRef(""));
444 }
445};
446}
447}
448
449namespace {
450struct Tag;
451typedef std::vector TagsSeq;
452
453struct Tag {
454 StringRef Name;
455 AvailabilityItem Availability;
456 StringRef SwiftName;
457 std::optional SwiftPrivate;
458 std::optional SwiftBridge;
459 std::optional NSErrorDomain;
460 std::optionalstd::string SwiftImportAs;
461 std::optionalstd::string SwiftRetainOp;
462 std::optionalstd::string SwiftReleaseOp;
463 std::optionalstd::string SwiftConformance;
464 std::optional EnumExtensibility;
465 std::optional FlagEnum;
466 std::optional EnumConvenienceKind;
467 std::optional SwiftCopyable;
468 std::optional SwiftEscapable;
469 FunctionsSeq Methods;
470 FieldsSeq Fields;
471
472
473
474 TagsSeq Tags;
475};
476}
477
478LLVM_YAML_IS_SEQUENCE_VECTOR(Tag)
479
480namespace llvm {
481namespace yaml {
484 IO.enumCase(EEK, "none", EnumExtensibilityKind::None);
485 IO.enumCase(EEK, "open", EnumExtensibilityKind::Open);
486 IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed);
487 }
488};
489
490template <> struct MappingTraits<Tag> {
492 IO.mapRequired("Name", T.Name);
493 IO.mapOptional("Availability", T.Availability.Mode,
494 APIAvailability::Available);
495 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
496 IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
497 IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
498 IO.mapOptional("SwiftBridge", T.SwiftBridge);
499 IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
500 IO.mapOptional("SwiftImportAs", T.SwiftImportAs);
501 IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp);
502 IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp);
503 IO.mapOptional("SwiftConformsTo", T.SwiftConformance);
504 IO.mapOptional("EnumExtensibility", T.EnumExtensibility);
505 IO.mapOptional("FlagEnum", T.FlagEnum);
506 IO.mapOptional("EnumKind", T.EnumConvenienceKind);
507 IO.mapOptional("SwiftCopyable", T.SwiftCopyable);
508 IO.mapOptional("SwiftEscapable", T.SwiftEscapable);
509 IO.mapOptional("Methods", T.Methods);
510 IO.mapOptional("Fields", T.Fields);
511 IO.mapOptional("Tags", T.Tags);
512 }
513};
514}
515}
516
517namespace {
518struct Typedef {
519 StringRef Name;
520 AvailabilityItem Availability;
521 StringRef SwiftName;
522 std::optional SwiftPrivate;
523 std::optional SwiftBridge;
524 std::optional NSErrorDomain;
525 std::optional SwiftType;
526};
527
528typedef std::vector TypedefsSeq;
529}
530
531LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef)
532
533namespace llvm {
534namespace yaml {
537 IO.enumCase(SWK, "none", SwiftNewTypeKind::None);
538 IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct);
539 IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum);
540 }
541};
542
543template <> struct MappingTraits {
544 static void mapping(IO &IO, Typedef &T) {
545 IO.mapRequired("Name", T.Name);
546 IO.mapOptional("Availability", T.Availability.Mode,
547 APIAvailability::Available);
548 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
549 IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
550 IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
551 IO.mapOptional("SwiftBridge", T.SwiftBridge);
552 IO.mapOptional("NSErrorDomain", T.NSErrorDomain);
553 IO.mapOptional("SwiftWrapper", T.SwiftType);
554 }
555};
556}
557}
558
559namespace {
561typedef std::vector NamespacesSeq;
562
563struct TopLevelItems {
564 ClassesSeq Classes;
565 ClassesSeq Protocols;
566 FunctionsSeq Functions;
567 GlobalVariablesSeq Globals;
568 EnumConstantsSeq EnumConstants;
569 TagsSeq Tags;
570 TypedefsSeq Typedefs;
571 NamespacesSeq Namespaces;
572};
573}
574
575namespace llvm {
576namespace yaml {
578 IO.mapOptional("Classes", TLI.Classes);
579 IO.mapOptional("Protocols", TLI.Protocols);
580 IO.mapOptional("Functions", TLI.Functions);
581 IO.mapOptional("Globals", TLI.Globals);
582 IO.mapOptional("Enumerators", TLI.EnumConstants);
583 IO.mapOptional("Tags", TLI.Tags);
584 IO.mapOptional("Typedefs", TLI.Typedefs);
585 IO.mapOptional("Namespaces", TLI.Namespaces);
586}
587}
588}
589
590namespace {
592 StringRef Name;
593 AvailabilityItem Availability;
594 StringRef SwiftName;
595 std::optional SwiftPrivate;
596 TopLevelItems Items;
597};
598}
599
600LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace)
601
602namespace llvm {
603namespace yaml {
605 static void mapping(IO &IO, Namespace &T) {
606 IO.mapRequired("Name", T.Name);
607 IO.mapOptional("Availability", T.Availability.Mode,
608 APIAvailability::Available);
609 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef(""));
610 IO.mapOptional("SwiftPrivate", T.SwiftPrivate);
611 IO.mapOptional("SwiftName", T.SwiftName, StringRef(""));
613 }
614};
615}
616}
617
618namespace {
619struct Versioned {
620 VersionTuple Version;
621 TopLevelItems Items;
622};
623
624typedef std::vector VersionedSeq;
625}
626
627LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned)
628
629namespace llvm {
630namespace yaml {
631template <> struct MappingTraits {
632 static void mapping(IO &IO, Versioned &V) {
633 IO.mapRequired("Version", V.Version);
635 }
636};
637}
638}
639
640namespace {
642 StringRef Name;
643 AvailabilityItem Availability;
644 TopLevelItems TopLevel;
645 VersionedSeq SwiftVersions;
646
647 std::optional SwiftInferImportAsMember;
648
649#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
650 LLVM_DUMP_METHOD void dump() ;
651#endif
652};
653}
654
655namespace llvm {
656namespace yaml {
657template <> struct MappingTraits<Module> {
659 IO.mapRequired("Name", M.Name);
660 IO.mapOptional("Availability", M.Availability.Mode,
661 APIAvailability::Available);
662 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef(""));
663 IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember);
665 IO.mapOptional("SwiftVersions", M.SwiftVersions);
666 }
667};
668}
669}
670
671#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
672LLVM_DUMP_METHOD void Module::dump() {
673 llvm::yaml::Output OS(llvm::errs());
674 OS << *this;
675}
676#endif
677
678namespace {
679bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag,
680 void *DiagContext) {
681 llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext);
682 IS >> M;
683 return static_cast<bool>(IS.error());
684}
685}
686
688 llvm::raw_ostream &OS) {
690 if (parseAPINotes(YI, M, nullptr, nullptr))
691 return true;
692
693 llvm::yaml::Output YOS(OS);
694 YOS << M;
695
696 return false;
697}
698
699namespace {
700using namespace api_notes;
701
702class YAMLConverter {
705 llvm::raw_ostream &OS;
706 llvm::SourceMgr::DiagHandlerTy DiagHandler;
707 void *DiagHandlerCtxt;
708 bool ErrorOccured;
709
710
711 bool emitError(llvm::Twine Message) {
712 DiagHandler(
713 llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()),
714 DiagHandlerCtxt);
715 ErrorOccured = true;
716 return true;
717 }
718
719public:
720 YAMLConverter(const Module &TheModule, const FileEntry *SourceFile,
721 llvm::raw_ostream &OS,
722 llvm::SourceMgr::DiagHandlerTy DiagHandler,
723 void *DiagHandlerCtxt)
724 : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS),
725 DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
726 ErrorOccured(false) {}
727
728 void convertAvailability(const AvailabilityItem &Availability,
730
731 CEI.Unavailable = (Availability.Mode == APIAvailability::None);
732 CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift);
735 } else {
736 if (!Availability.Msg.empty())
737 emitError(llvm::Twine("availability message for available API '") +
738 APIName + "' will not be used");
739 }
740 }
741
742 void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo,
743 std::optional &thisOrSelf) {
744 for (const auto &P : Params) {
746 if (P.Nullability)
750 PI.setType(std::string(P.Type));
752 if (static_cast<int>(OutInfo.Params.size()) <= P.Position)
753 OutInfo.Params.resize(P.Position + 1);
754 if (P.Position == -1)
755 thisOrSelf = PI;
756 else if (P.Position >= 0)
757 OutInfo.Params[P.Position] |= PI;
758 else
759 emitError("invalid parameter position " + llvm::itostr(P.Position));
760 }
761 }
762
763 void convertNullability(const NullabilitySeq &Nullability,
764 std::optional ReturnNullability,
765 FunctionInfo &OutInfo, llvm::StringRef APIName) {
767 emitError(llvm::Twine("nullability info for '") + APIName +
768 "' does not fit");
769 return;
770 }
771
772 bool audited = false;
773 unsigned int idx = 1;
774 for (const auto &N : Nullability)
776 audited = Nullability.size() > 0 || ReturnNullability;
777 if (audited)
779 ReturnNullability.value_or(NullabilityKind::NonNull));
780 if (!audited)
781 return;
784 }
785
786
787 template
788 void convertCommonEntity(const T &Common, CommonEntityInfo &Info,
789 StringRef APIName) {
790 convertAvailability(Common.Availability, Info, APIName);
792 Info.SwiftName = std::string(Common.SwiftName);
793 }
794
795
796 template
797 void convertCommonType(const T &Common, CommonTypeInfo &Info,
798 StringRef APIName) {
799 convertCommonEntity(Common, Info, APIName);
800 if (Common.SwiftBridge)
801 Info.setSwiftBridge(std::string(*Common.SwiftBridge));
803 }
804
805
806 void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName,
807 VersionTuple SwiftVersion) {
809 convertCommonEntity(M, MI, M.Selector);
810
811
812 bool takesArguments = M.Selector.ends_with(":");
813
814
816 M.Selector.split(Args, ":", -1, false);
817 if (!takesArguments && Args.size() > 1) {
818 emitError("selector '" + M.Selector + "' is missing a ':' at the end");
819 return;
820 }
821
822
824 Selector.NumArgs = !takesArguments ? 0 : Args.size();
826
827
830 if (M.FactoryAsInit != FactoryAsInitKind::Infer)
831 emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead");
832
833 MI.ResultType = std::string(M.ResultType);
835
836
837 convertParams(M.Params, MI, MI.Self);
838
839
840 convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector);
841
843
844
846 SwiftVersion);
847 }
848
849 template
850 void convertVariable(const T &Entity, VariableInfo &VI) {
851 convertAvailability(Entity.Availability, VI, Entity.Name);
853 VI.SwiftName = std::string(Entity.SwiftName);
854 if (Entity.Nullability)
856 VI.setType(std::string(Entity.Type));
857 }
858
859 void convertContext(std::optional ParentContextID, const Class &C,
861
863 convertCommonType(C, CI, C.Name);
864
865 if (C.AuditedForNullability)
867 if (C.SwiftImportAsNonGeneric)
869 if (C.SwiftObjCMembers)
871
873 Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion);
874
875
876 llvm::StringMap<std::pair<bool, bool>> KnownMethods;
877 for (const auto &method : C.Methods) {
878
880 bool &Known = IsInstanceMethod ? KnownMethods[method.Selector].first
881 : KnownMethods[method.Selector].second;
882 if (Known) {
883 emitError(llvm::Twine("duplicate definition of method '") +
884 (IsInstanceMethod ? "-" : "+") + "[" + C.Name + " " +
885 method.Selector + "]'");
886 continue;
887 }
888 Known = true;
889
890 convertMethod(method, CtxID, C.Name, SwiftVersion);
891 }
892
893
894 llvm::StringSet<> KnownInstanceProperties;
895 llvm::StringSet<> KnownClassProperties;
896 for (const auto &Property : C.Properties) {
897
898 if ((.Kind || *Property.Kind == MethodKind::Instance) &&
899 !KnownInstanceProperties.insert(Property.Name).second) {
900 emitError(llvm::Twine("duplicate definition of instance property '") +
901 C.Name + "." + Property.Name + "'");
902 continue;
903 }
904
905 if ((.Kind || *Property.Kind == MethodKind::Class) &&
906 !KnownClassProperties.insert(Property.Name).second) {
907 emitError(llvm::Twine("duplicate definition of class property '") +
908 C.Name + "." + Property.Name + "'");
909 continue;
910 }
911
912
914 convertVariable(Property, PI);
915 if (Property.SwiftImportAsAccessors)
917
918
921 *Property.Kind == MethodKind::Instance, PI,
922 SwiftVersion);
923 } else {
926 }
927 }
928 }
929
930 void convertNamespaceContext(std::optional ParentContextID,
931 const Namespace &TheNamespace,
932 VersionTuple SwiftVersion) {
933
935 convertCommonEntity(TheNamespace, CI, TheNamespace.Name);
936
938 Writer.addContext(ParentContextID, TheNamespace.Name,
939 ContextKind::Namespace, CI, SwiftVersion);
940
941 convertTopLevelItems(Context(CtxID, ContextKind::Namespace),
942 TheNamespace.Items, SwiftVersion);
943 }
944
945 template
946 void convertFunction(const Function &Function, FuncOrMethodInfo &FI) {
947 convertAvailability(Function.Availability, FI, Function.Name);
948 FI.setSwiftPrivate(Function.SwiftPrivate);
949 FI.SwiftName = std::string(Function.SwiftName);
950 std::optional This;
951 convertParams(Function.Params, FI, This);
952 if constexpr (std::is_same_v<FuncOrMethodInfo, CXXMethodInfo>)
953 FI.This = This;
954 else if (This)
955 emitError("implicit instance parameter is only permitted on C++ and "
956 "Objective-C methods");
957 convertNullability(Function.Nullability, Function.NullabilityOfRet, FI,
959 FI.ResultType = std::string(Function.ResultType);
960 FI.SwiftReturnOwnership = std::string(Function.SwiftReturnOwnership);
961 FI.setRetainCountConvention(Function.RetainCountConvention);
962 }
963
964 void convertTagContext(std::optional ParentContext, const Tag &T,
965 VersionTuple SwiftVersion) {
967 std::optional ParentContextID =
968 ParentContext ? std::optional(ParentContext->id)
969 : std::nullopt;
970 convertCommonType(T, TI, T.Name);
971
972 if ((T.SwiftRetainOp || T.SwiftReleaseOp) && .SwiftImportAs) {
973 emitError(llvm::Twine("should declare SwiftImportAs to use "
974 "SwiftRetainOp and SwiftReleaseOp (for ") +
975 T.Name + ")");
976 return;
977 }
978 if (T.SwiftReleaseOp.has_value() != T.SwiftRetainOp.has_value()) {
979 emitError(llvm::Twine("should declare both SwiftReleaseOp and "
980 "SwiftRetainOp (for ") +
981 T.Name + ")");
982 return;
983 }
984
985 if (T.SwiftImportAs)
987 if (T.SwiftRetainOp)
989 if (T.SwiftReleaseOp)
991 if (T.SwiftConformance)
993
994 if (T.SwiftCopyable)
996 if (T.SwiftEscapable)
998
999 if (T.EnumConvenienceKind) {
1000 if (T.EnumExtensibility) {
1001 emitError(
1002 llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") +
1003 T.Name + ")");
1004 return;
1005 }
1006 if (T.FlagEnum) {
1007 emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") +
1008 T.Name + ")");
1009 return;
1010 }
1011 switch (*T.EnumConvenienceKind) {
1012 case EnumConvenienceAliasKind::None:
1015 break;
1016 case EnumConvenienceAliasKind::CFEnum:
1019 break;
1020 case EnumConvenienceAliasKind::CFOptions:
1023 break;
1024 case EnumConvenienceAliasKind::CFClosedEnum:
1027 break;
1028 }
1029 } else {
1032 }
1033
1034 Writer.addTag(ParentContext, T.Name, TI, SwiftVersion);
1035
1037 auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag,
1038 CI, SwiftVersion);
1039 Context TagCtx(TagCtxID, ContextKind::Tag);
1040
1041 for (const auto &Field : T.Fields) {
1043 convertVariable(Field, FI);
1044 Writer.addField(TagCtxID, Field.Name, FI, SwiftVersion);
1045 }
1046
1047 for (const auto &CXXMethod : T.Methods) {
1049 convertFunction(CXXMethod, MI);
1050 Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);
1051 }
1052
1053
1054 for (const auto &Tag : T.Tags)
1055 convertTagContext(TagCtx, Tag, SwiftVersion);
1056 }
1057
1058 void convertTopLevelItems(std::optional Ctx,
1059 const TopLevelItems &TLItems,
1060 VersionTuple SwiftVersion) {
1061 std::optional CtxID =
1062 Ctx ? std::optional(Ctx->id) : std::nullopt;
1063
1064
1065 llvm::StringSet<> KnownClasses;
1066 for (const auto &Class : TLItems.Classes) {
1067
1068 if (!KnownClasses.insert(Class.Name).second) {
1069 emitError(llvm::Twine("multiple definitions of class '") + Class.Name +
1070 "'");
1071 continue;
1072 }
1073
1074 convertContext(CtxID, Class, ContextKind::ObjCClass, SwiftVersion);
1075 }
1076
1077
1078 llvm::StringSet<> KnownProtocols;
1079 for (const auto &Protocol : TLItems.Protocols) {
1080
1081 if (!KnownProtocols.insert(Protocol.Name).second) {
1082 emitError(llvm::Twine("multiple definitions of protocol '") +
1084 continue;
1085 }
1086
1087 convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion);
1088 }
1089
1090
1091 llvm::StringSet<> KnownNamespaces;
1092 for (const auto &Namespace : TLItems.Namespaces) {
1093
1094 if (!KnownNamespaces.insert(Namespace.Name).second) {
1095 emitError(llvm::Twine("multiple definitions of namespace '") +
1097 continue;
1098 }
1099
1100 convertNamespaceContext(CtxID, Namespace, SwiftVersion);
1101 }
1102
1103
1104 llvm::StringSet<> KnownGlobals;
1105 for (const auto &Global : TLItems.Globals) {
1106
1107 if (!KnownGlobals.insert(Global.Name).second) {
1108 emitError(llvm::Twine("multiple definitions of global variable '") +
1110 continue;
1111 }
1112
1114 convertVariable(Global, GVI);
1116 }
1117
1118
1119 llvm::StringSet<> KnownFunctions;
1120 for (const auto &Function : TLItems.Functions) {
1121
1122 if (!KnownFunctions.insert(Function.Name).second) {
1123 emitError(llvm::Twine("multiple definitions of global function '") +
1125 continue;
1126 }
1127
1129 convertFunction(Function, GFI);
1131 }
1132
1133
1134 llvm::StringSet<> KnownEnumConstants;
1135 for (const auto &EnumConstant : TLItems.EnumConstants) {
1136
1137 if (!KnownEnumConstants.insert(EnumConstant.Name).second) {
1138 emitError(llvm::Twine("multiple definitions of enumerator '") +
1140 continue;
1141 }
1142
1148 }
1149
1150
1151 llvm::StringSet<> KnownTags;
1152 for (const auto &Tag : TLItems.Tags) {
1153
1154 if (!KnownTags.insert(Tag.Name).second) {
1155 emitError(llvm::Twine("multiple definitions of tag '") + Tag.Name +
1156 "'");
1157 continue;
1158 }
1159
1160 convertTagContext(Ctx, Tag, SwiftVersion);
1161 }
1162
1163
1164 llvm::StringSet<> KnownTypedefs;
1165 for (const auto &Typedef : TLItems.Typedefs) {
1166
1167 if (!KnownTypedefs.insert(Typedef.Name).second) {
1168 emitError(llvm::Twine("multiple definitions of typedef '") +
1169 Typedef.Name + "'");
1170 continue;
1171 }
1172
1174 convertCommonType(Typedef, TInfo, Typedef.Name);
1176
1177 Writer.addTypedef(Ctx, Typedef.Name, TInfo, SwiftVersion);
1178 }
1179 }
1180
1181 bool convertModule() {
1182
1183 convertTopLevelItems( std::nullopt, M.TopLevel,
1184 VersionTuple());
1185
1186
1187 for (const auto &Versioned : M.SwiftVersions)
1188 convertTopLevelItems( std::nullopt, Versioned.Items,
1189 Versioned.Version);
1190
1191 if (!ErrorOccured)
1193
1194 return ErrorOccured;
1195 }
1196};
1197}
1198
1200 llvm::raw_ostream &OS,
1201 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1202 void *DiagHandlerCtxt) {
1203 YAMLConverter C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1204 return C.convertModule();
1205}
1206
1207
1209 Diag.print(nullptr, llvm::errs());
1210}
1211
1214 llvm::raw_ostream &OS,
1215 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1216 void *DiagHandlerCtxt) {
1218
1219 if (!DiagHandler)
1221
1222 if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt))
1223 return true;
1224
1225 return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1226}
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)
enum clang::sema::@1727::IndirectLocalPathEntry::EntryKind Kind
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).
Describes a module or submodule.
std::string Name
The name of this module.
void dump() const
Dump the contents of this module to the given output stream.
Smart pointer class that efficiently represents Objective-C method names.
The base class of the type hierarchy.
A class that writes API notes data to a binary representation that can be read by the APINotesReader.
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).
Describes API notes data for a C++ method.
Describes API notes data for any entity.
unsigned UnavailableInSwift
Whether this entity is marked unavailable in Swift.
unsigned Unavailable
Whether this entity is marked unavailable.
std::string SwiftName
Swift name of this entity.
void setSwiftPrivate(std::optional< bool > Private)
std::string UnavailableMsg
Message to use when this entity is unavailable.
Describes API notes for types.
void setNSErrorDomain(const std::optional< std::string > &Domain)
void setSwiftBridge(std::optional< std::string > SwiftType)
Opaque context ID used to refer to an Objective-C class or protocol or a C++ namespace.
Describes API notes data for an Objective-C class or protocol or a C++ namespace.
void setDefaultNullability(NullabilityKind Kind)
Set the default nullability for properties and methods of this class.
void setSwiftObjCMembers(std::optional< bool > Value)
void setSwiftImportAsNonGeneric(std::optional< bool > Value)
Describes API notes data for an enumerator.
Describes API notes data for a C/C++ record field.
API notes for a function or method.
std::string SwiftReturnOwnership
Ownership convention for return value.
void addTypeInfo(unsigned index, NullabilityKind kind)
void setRetainCountConvention(std::optional< RetainCountConventionKind > Value)
std::vector< ParamInfo > Params
The function parameters.
unsigned NumAdjustedNullable
Number of types whose nullability is encoded with the NullabilityPayload.
std::string ResultType
The result type of this function, as a C type.
static unsigned getMaxNullabilityIndex()
unsigned NullabilityAudited
Whether the signature has been audited with respect to nullability.
Describes API notes data for a global function.
Describes API notes data for a global variable.
Describes API notes data for an Objective-C method.
unsigned DesignatedInit
Whether this is a designated initializer of its class.
std::optional< ParamInfo > Self
unsigned RequiredInit
Whether this is a required initializer.
Describes API notes data for an Objective-C property.
void setSwiftImportAsAccessors(std::optional< bool > Value)
Describes a function or method parameter.
void setNoEscape(std::optional< bool > Value)
void setLifetimebound(std::optional< bool > Value)
void setRetainCountConvention(std::optional< RetainCountConventionKind > Value)
Describes API notes data for a tag.
std::optional< std::string > SwiftReleaseOp
std::optional< std::string > SwiftRetainOp
std::optional< std::string > SwiftImportAs
std::optional< EnumExtensibilityKind > EnumExtensibility
void setSwiftCopyable(std::optional< bool > Value)
void setSwiftEscapable(std::optional< bool > Value)
void setFlagEnum(std::optional< bool > Value)
std::optional< std::string > SwiftConformance
The Swift protocol that this type should be automatically conformed to.
Describes API notes data for a typedef.
std::optional< SwiftNewTypeKind > SwiftWrapper
API notes for a variable/property.
void setNullabilityAudited(NullabilityKind kind)
void setType(const std::string &type)
RetainCountConventionKind
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.
EnumExtensibilityKind
The payload for an enum_extensibility attribute.
bool parseAndDumpAPINotes(llvm::StringRef YI, llvm::raw_ostream &OS)
Parses the APINotes YAML content and writes the representation back to the specified stream.
bool This(InterpState &S, CodePtr OpPC)
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
NullabilityKind
Describes the nullability of a particular type.
@ Property
The type of a property.
const FunctionProtoType * T
@ Class
The "class" keyword introduces the elaborated-type-specifier.
static void mapTopLevelItems(IO &IO, TopLevelItems &TLI)
Diagnostic wrappers for TextAPI types for error reporting.
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
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, MethodKind &MK)
static void enumeration(IO &IO, NullabilityKind &NK)
static void enumeration(IO &IO, RetainCountConventionKind &RCCK)
static void enumeration(IO &IO, SwiftNewTypeKind &SWK)