21#include "llvm/ADT/STLExtras.h"
22#include "llvm/ADT/SmallString.h"
23#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/StringSet.h"
25#include "llvm/Support/SourceMgr.h"
26#include "llvm/Support/VersionTuple.h"
27#include "llvm/Support/YAMLTraits.h"
28#include "llvm/Support/raw_ostream.h"
50enum class APIAvailability {
58struct BoundsSafetyNotes {
60 std::optional<unsigned> Level;
61 StringRef BoundsExpr =
"";
69 IO.enumCase(AA,
"counted_by",
71 IO.enumCase(AA,
"counted_by_or_null",
74 IO.enumCase(AA,
"sized_by_or_null",
84template <>
struct ScalarEnumerationTraits<APIAvailability> {
86 IO.enumCase(AA,
"none", APIAvailability::None);
87 IO.enumCase(AA,
"nonswift", APIAvailability::NonSwift);
88 IO.enumCase(AA,
"available", APIAvailability::Available);
95enum class MethodKind {
103template <>
struct ScalarEnumerationTraits<MethodKind> {
105 IO.enumCase(MK,
"Class", MethodKind::Class);
106 IO.enumCase(MK,
"Instance", MethodKind::Instance);
115 std::optional<bool> NoEscape =
false;
116 std::optional<bool> Lifetimebound =
false;
117 std::optional<NullabilityKind> Nullability;
118 std::optional<RetainCountConventionKind> RetainCountConvention;
119 std::optional<BoundsSafetyNotes> BoundsSafety;
123typedef std::vector<Param> ParamsSeq;
126LLVM_YAML_IS_SEQUENCE_VECTOR(Param)
152 IO.enumCase(RCCK,
"CFReturnsRetained",
154 IO.enumCase(RCCK,
"CFReturnsNotRetained",
156 IO.enumCase(RCCK,
"NSReturnsRetained",
158 IO.enumCase(RCCK,
"NSReturnsNotRetained",
163template <>
struct MappingTraits<Param> {
165 IO.mapRequired(
"Position", P.Position);
166 IO.mapOptional(
"Nullability", P.Nullability, std::nullopt);
167 IO.mapOptional(
"RetainCountConvention", P.RetainCountConvention);
168 IO.mapOptional(
"NoEscape", P.NoEscape);
169 IO.mapOptional(
"Lifetimebound", P.Lifetimebound);
170 IO.mapOptional(
"Type", P.Type, StringRef(
""));
171 IO.mapOptional(
"BoundsSafety", P.BoundsSafety);
175template <>
struct MappingTraits<BoundsSafetyNotes> {
176 static void mapping(IO &IO, BoundsSafetyNotes &BS) {
177 IO.mapRequired(
"Kind", BS.Kind);
178 IO.mapRequired(
"BoundedBy", BS.BoundsExpr);
179 IO.mapOptional(
"Level", BS.Level);
186typedef std::vector<NullabilityKind> NullabilitySeq;
188struct AvailabilityItem {
189 APIAvailability Mode = APIAvailability::Available;
194enum class FactoryAsInitKind {
207 NullabilitySeq Nullability;
208 std::optional<NullabilityKind> NullabilityOfRet;
209 std::optional<RetainCountConventionKind> RetainCountConvention;
210 AvailabilityItem Availability;
211 std::optional<bool> SwiftPrivate;
213 FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer;
214 bool DesignatedInit =
false;
215 bool Required =
false;
216 StringRef ResultType;
217 StringRef SwiftReturnOwnership;
221typedef std::vector<Method> MethodsSeq;
224LLVM_YAML_IS_SEQUENCE_VECTOR(Method)
228template <>
struct ScalarEnumerationTraits<FactoryAsInitKind> {
230 IO.enumCase(FIK,
"A", FactoryAsInitKind::Infer);
231 IO.enumCase(FIK,
"C", FactoryAsInitKind::AsClassMethod);
232 IO.enumCase(FIK,
"I", FactoryAsInitKind::AsInitializer);
236template <>
struct MappingTraits<Method> {
238 IO.mapRequired(
"Selector", M.Selector);
239 IO.mapRequired(
"MethodKind", M.Kind);
240 IO.mapOptional(
"Parameters", M.Params);
241 IO.mapOptional(
"Nullability", M.Nullability);
242 IO.mapOptional(
"NullabilityOfRet", M.NullabilityOfRet, std::nullopt);
243 IO.mapOptional(
"RetainCountConvention", M.RetainCountConvention);
244 IO.mapOptional(
"Availability", M.Availability.Mode,
245 APIAvailability::Available);
246 IO.mapOptional(
"AvailabilityMsg", M.Availability.Msg, StringRef(
""));
247 IO.mapOptional(
"SwiftPrivate", M.SwiftPrivate);
248 IO.mapOptional(
"SwiftName", M.SwiftName, StringRef(
""));
249 IO.mapOptional(
"FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer);
250 IO.mapOptional(
"DesignatedInit", M.DesignatedInit,
false);
251 IO.mapOptional(
"Required", M.Required,
false);
252 IO.mapOptional(
"ResultType", M.ResultType, StringRef(
""));
253 IO.mapOptional(
"SwiftReturnOwnership", M.SwiftReturnOwnership,
264 std::optional<MethodKind> Kind;
265 std::optional<NullabilityKind> Nullability;
266 AvailabilityItem Availability;
267 std::optional<bool> SwiftPrivate;
269 std::optional<bool> SwiftImportAsAccessors;
274typedef std::vector<Property> PropertiesSeq;
277LLVM_YAML_IS_SEQUENCE_VECTOR(Property)
281template <>
struct MappingTraits<Property> {
283 IO.mapRequired(
"Name", P.Name);
284 IO.mapOptional(
"PropertyKind", P.Kind);
285 IO.mapOptional(
"Nullability", P.Nullability, std::nullopt);
286 IO.mapOptional(
"Availability", P.Availability.Mode,
287 APIAvailability::Available);
288 IO.mapOptional(
"AvailabilityMsg", P.Availability.Msg, StringRef(
""));
289 IO.mapOptional(
"SwiftPrivate", P.SwiftPrivate);
290 IO.mapOptional(
"SwiftName", P.SwiftName, StringRef(
""));
291 IO.mapOptional(
"SwiftImportAsAccessors", P.SwiftImportAsAccessors);
292 IO.mapOptional(
"Type", P.Type, StringRef(
""));
302 bool AuditedForNullability =
false;
303 AvailabilityItem Availability;
304 std::optional<bool> SwiftPrivate;
306 std::optional<StringRef> SwiftBridge;
307 std::optional<StringRef> NSErrorDomain;
308 std::optional<bool> SwiftImportAsNonGeneric;
309 std::optional<bool> SwiftObjCMembers;
310 std::optional<std::string> SwiftConformance;
312 PropertiesSeq Properties;
316typedef std::vector<Class> ClassesSeq;
319LLVM_YAML_IS_SEQUENCE_VECTOR(Class)
323template <>
struct MappingTraits<Class> {
325 IO.mapRequired(
"Name",
C.Name);
326 IO.mapOptional(
"AuditedForNullability",
C.AuditedForNullability,
false);
327 IO.mapOptional(
"Availability",
C.Availability.Mode,
328 APIAvailability::Available);
329 IO.mapOptional(
"AvailabilityMsg",
C.Availability.Msg, StringRef(
""));
330 IO.mapOptional(
"SwiftPrivate",
C.SwiftPrivate);
331 IO.mapOptional(
"SwiftName",
C.SwiftName, StringRef(
""));
332 IO.mapOptional(
"SwiftBridge",
C.SwiftBridge);
333 IO.mapOptional(
"NSErrorDomain",
C.NSErrorDomain);
334 IO.mapOptional(
"SwiftImportAsNonGeneric",
C.SwiftImportAsNonGeneric);
335 IO.mapOptional(
"SwiftObjCMembers",
C.SwiftObjCMembers);
336 IO.mapOptional(
"SwiftConformsTo",
C.SwiftConformance);
337 IO.mapOptional(
"Methods",
C.Methods);
338 IO.mapOptional(
"Properties",
C.Properties);
346typedef std::vector<StringRef> WhereParamsSeq;
348struct FunctionWhere {
349 std::optional<WhereParamsSeq> Parameters;
354 std::optional<FunctionWhere> Where;
356 NullabilitySeq Nullability;
357 std::optional<NullabilityKind> NullabilityOfRet;
358 std::optional<api_notes::RetainCountConventionKind> RetainCountConvention;
359 AvailabilityItem Availability;
360 std::optional<bool> SwiftPrivate;
363 StringRef ResultType;
364 StringRef SwiftReturnOwnership;
366 bool UnsafeBufferUsage =
false;
369typedef std::vector<Function> FunctionsSeq;
372LLVM_YAML_IS_SEQUENCE_VECTOR(Function)
376template <>
struct MappingTraits<FunctionWhere> {
377 static void mapping(IO &IO, FunctionWhere &W) {
378 IO.mapOptional(
"Parameters", W.Parameters);
382template <>
struct MappingTraits<Function> {
384 IO.mapRequired(
"Name", F.Name);
385 IO.mapOptional(
"Where", F.Where);
386 IO.mapOptional(
"Parameters", F.Params);
387 IO.mapOptional(
"Nullability", F.Nullability);
388 IO.mapOptional(
"NullabilityOfRet", F.NullabilityOfRet, std::nullopt);
389 IO.mapOptional(
"RetainCountConvention", F.RetainCountConvention);
390 IO.mapOptional(
"Availability", F.Availability.Mode,
391 APIAvailability::Available);
392 IO.mapOptional(
"AvailabilityMsg", F.Availability.Msg, StringRef(
""));
393 IO.mapOptional(
"SwiftPrivate", F.SwiftPrivate);
394 IO.mapOptional(
"SwiftName", F.SwiftName, StringRef(
""));
395 IO.mapOptional(
"ResultType", F.ResultType, StringRef(
""));
396 IO.mapOptional(
"SwiftReturnOwnership", F.SwiftReturnOwnership,
399 IO.mapOptional(
"UnsafeBufferUsage", F.UnsafeBufferUsage,
false);
406struct GlobalVariable {
408 std::optional<NullabilityKind> Nullability;
409 AvailabilityItem Availability;
410 std::optional<bool> SwiftPrivate;
416typedef std::vector<GlobalVariable> GlobalVariablesSeq;
419LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable)
423template <>
struct MappingTraits<GlobalVariable> {
424 static void mapping(IO &IO, GlobalVariable &GV) {
425 IO.mapRequired(
"Name", GV.Name);
426 IO.mapOptional(
"Nullability", GV.Nullability, std::nullopt);
427 IO.mapOptional(
"Availability", GV.Availability.Mode,
428 APIAvailability::Available);
429 IO.mapOptional(
"AvailabilityMsg", GV.Availability.Msg, StringRef(
""));
430 IO.mapOptional(
"SwiftPrivate", GV.SwiftPrivate);
431 IO.mapOptional(
"SwiftName", GV.SwiftName, StringRef(
""));
432 IO.mapOptional(
"Type", GV.Type, StringRef(
""));
442 AvailabilityItem Availability;
443 std::optional<bool> SwiftPrivate;
448typedef std::vector<EnumConstant> EnumConstantsSeq;
451LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant)
455template <>
struct MappingTraits<EnumConstant> {
456 static void mapping(IO &IO, EnumConstant &EC) {
457 IO.mapRequired(
"Name", EC.Name);
458 IO.mapOptional(
"Availability", EC.Availability.Mode,
459 APIAvailability::Available);
460 IO.mapOptional(
"AvailabilityMsg", EC.Availability.Msg, StringRef(
""));
461 IO.mapOptional(
"SwiftPrivate", EC.SwiftPrivate);
462 IO.mapOptional(
"SwiftName", EC.SwiftName, StringRef(
""));
471enum class EnumConvenienceAliasKind {
485template <>
struct ScalarEnumerationTraits<EnumConvenienceAliasKind> {
487 IO.enumCase(ECAK,
"none", EnumConvenienceAliasKind::None);
488 IO.enumCase(ECAK,
"CFEnum", EnumConvenienceAliasKind::CFEnum);
489 IO.enumCase(ECAK,
"NSEnum", EnumConvenienceAliasKind::CFEnum);
490 IO.enumCase(ECAK,
"CFOptions", EnumConvenienceAliasKind::CFOptions);
491 IO.enumCase(ECAK,
"NSOptions", EnumConvenienceAliasKind::CFOptions);
492 IO.enumCase(ECAK,
"CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);
493 IO.enumCase(ECAK,
"NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum);
502 std::optional<NullabilityKind> Nullability;
503 AvailabilityItem Availability;
504 std::optional<bool> SwiftPrivate;
510typedef std::vector<Field> FieldsSeq;
513LLVM_YAML_IS_SEQUENCE_VECTOR(Field)
517template <>
struct MappingTraits<Field> {
519 IO.mapRequired(
"Name", F.Name);
520 IO.mapOptional(
"Nullability", F.Nullability, std::nullopt);
521 IO.mapOptional(
"Availability", F.Availability.Mode,
522 APIAvailability::Available);
523 IO.mapOptional(
"AvailabilityMsg", F.Availability.Msg, StringRef(
""));
524 IO.mapOptional(
"SwiftPrivate", F.SwiftPrivate);
525 IO.mapOptional(
"SwiftName", F.SwiftName, StringRef(
""));
526 IO.mapOptional(
"Type", F.Type, StringRef(
""));
535typedef std::vector<Tag> TagsSeq;
539 AvailabilityItem Availability;
541 std::optional<bool> SwiftPrivate;
542 std::optional<StringRef> SwiftBridge;
543 std::optional<StringRef> NSErrorDomain;
544 std::optional<std::string> SwiftImportAs;
545 std::optional<std::string> SwiftRetainOp;
546 std::optional<std::string> SwiftReleaseOp;
547 std::optional<std::string> SwiftDestroyOp;
548 std::optional<std::string> SwiftDefaultOwnership;
549 std::optional<std::string> SwiftConformance;
550 std::optional<EnumExtensibilityKind> EnumExtensibility;
551 std::optional<bool> FlagEnum;
552 std::optional<EnumConvenienceAliasKind> EnumConvenienceKind;
553 std::optional<bool> SwiftCopyable;
554 std::optional<bool> SwiftEscapable;
556 FunctionsSeq Methods;
565LLVM_YAML_IS_SEQUENCE_VECTOR(Tag)
577template <>
struct MappingTraits<Tag> {
579 IO.mapRequired(
"Name",
T.Name);
580 IO.mapOptional(
"Availability",
T.Availability.Mode,
581 APIAvailability::Available);
582 IO.mapOptional(
"AvailabilityMsg",
T.Availability.Msg, StringRef(
""));
583 IO.mapOptional(
"SwiftPrivate",
T.SwiftPrivate);
584 IO.mapOptional(
"SwiftName",
T.SwiftName, StringRef(
""));
585 IO.mapOptional(
"SwiftBridge",
T.SwiftBridge);
586 IO.mapOptional(
"NSErrorDomain",
T.NSErrorDomain);
587 IO.mapOptional(
"SwiftImportAs",
T.SwiftImportAs);
588 IO.mapOptional(
"SwiftReleaseOp",
T.SwiftReleaseOp);
589 IO.mapOptional(
"SwiftRetainOp",
T.SwiftRetainOp);
590 IO.mapOptional(
"SwiftDestroyOp",
T.SwiftDestroyOp);
591 IO.mapOptional(
"SwiftDefaultOwnership",
T.SwiftDefaultOwnership);
592 IO.mapOptional(
"SwiftConformsTo",
T.SwiftConformance);
593 IO.mapOptional(
"EnumExtensibility",
T.EnumExtensibility);
594 IO.mapOptional(
"FlagEnum",
T.FlagEnum);
595 IO.mapOptional(
"EnumKind",
T.EnumConvenienceKind);
596 IO.mapOptional(
"SwiftCopyable",
T.SwiftCopyable);
597 IO.mapOptional(
"SwiftEscapable",
T.SwiftEscapable);
598 IO.mapOptional(
"Methods",
T.Methods);
599 IO.mapOptional(
"Fields",
T.Fields);
600 IO.mapOptional(
"Tags",
T.Tags);
610 AvailabilityItem Availability;
612 std::optional<bool> SwiftPrivate;
613 std::optional<StringRef> SwiftBridge;
614 std::optional<StringRef> NSErrorDomain;
615 std::optional<SwiftNewTypeKind> SwiftType;
616 std::optional<std::string> SwiftConformance;
620typedef std::vector<Typedef> TypedefsSeq;
623LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef)
635template <>
struct MappingTraits<Typedef> {
637 IO.mapRequired(
"Name",
T.Name);
638 IO.mapOptional(
"Availability",
T.Availability.Mode,
639 APIAvailability::Available);
640 IO.mapOptional(
"AvailabilityMsg",
T.Availability.Msg, StringRef(
""));
641 IO.mapOptional(
"SwiftPrivate",
T.SwiftPrivate);
642 IO.mapOptional(
"SwiftName",
T.SwiftName, StringRef(
""));
643 IO.mapOptional(
"SwiftBridge",
T.SwiftBridge);
644 IO.mapOptional(
"NSErrorDomain",
T.NSErrorDomain);
645 IO.mapOptional(
"SwiftWrapper",
T.SwiftType);
646 IO.mapOptional(
"SwiftConformsTo",
T.SwiftConformance);
654typedef std::vector<Namespace> NamespacesSeq;
656struct TopLevelItems {
658 ClassesSeq Protocols;
659 FunctionsSeq Functions;
660 GlobalVariablesSeq Globals;
661 EnumConstantsSeq EnumConstants;
663 TypedefsSeq Typedefs;
664 NamespacesSeq Namespaces;
671 IO.mapOptional(
"Classes", TLI.Classes);
672 IO.mapOptional(
"Protocols", TLI.Protocols);
673 IO.mapOptional(
"Functions", TLI.Functions);
674 IO.mapOptional(
"Globals", TLI.Globals);
675 IO.mapOptional(
"Enumerators", TLI.EnumConstants);
676 IO.mapOptional(
"Tags", TLI.Tags);
677 IO.mapOptional(
"Typedefs", TLI.Typedefs);
678 IO.mapOptional(
"Namespaces", TLI.Namespaces);
686 AvailabilityItem Availability;
688 std::optional<bool> SwiftPrivate;
694LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace)
698template <>
struct MappingTraits<Namespace> {
700 IO.mapRequired(
"Name",
T.Name);
701 IO.mapOptional(
"Availability",
T.Availability.Mode,
702 APIAvailability::Available);
703 IO.mapOptional(
"AvailabilityMsg",
T.Availability.Msg, StringRef(
""));
704 IO.mapOptional(
"SwiftPrivate",
T.SwiftPrivate);
705 IO.mapOptional(
"SwiftName",
T.SwiftName, StringRef(
""));
714 VersionTuple Version;
718typedef std::vector<Versioned> VersionedSeq;
721LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned)
725template <>
struct MappingTraits<Versioned> {
727 IO.mapRequired(
"Version",
V.Version);
737 AvailabilityItem Availability;
738 TopLevelItems TopLevel;
739 VersionedSeq SwiftVersions;
741 std::optional<bool> SwiftInferImportAsMember;
743#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
744 LLVM_DUMP_METHOD
void dump() ;
751template <>
struct MappingTraits<
Module> {
753 IO.mapRequired(
"Name", M.
Name);
754 IO.mapOptional(
"Availability", M.Availability.Mode,
755 APIAvailability::Available);
756 IO.mapOptional(
"AvailabilityMsg", M.Availability.Msg, StringRef(
""));
757 IO.mapOptional(
"SwiftInferImportAsMember", M.SwiftInferImportAsMember);
759 IO.mapOptional(
"SwiftVersions", M.SwiftVersions);
765#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
767 llvm::yaml::Output OS(llvm::errs());
773bool parseAPINotes(StringRef YI,
Module &M, llvm::SourceMgr::DiagHandlerTy
Diag,
775 llvm::yaml::Input IS(YI,
nullptr,
Diag, DiagContext);
777 return static_cast<bool>(IS.error());
782 llvm::raw_ostream &OS) {
784 if (parseAPINotes(YI, M,
nullptr,
nullptr))
787 llvm::yaml::Output YOS(OS);
797getFunctionSelectorKey(llvm::StringRef Name,
800 llvm::raw_svector_ostream
OS(Key);
801 auto AppendKeyPart = [&
OS](llvm::StringRef Part) {
802 OS << Part.size() <<
':' << Part;
807 for (llvm::StringRef
Parameter : Parameters)
809 return Key.str().str();
814 APINotesWriter Writer;
815 llvm::raw_ostream &
OS;
816 llvm::SourceMgr::DiagHandlerTy DiagHandler;
817 void *DiagHandlerCtxt;
821 bool emitError(llvm::Twine Message) {
823 llvm::SMDiagnostic(
"", llvm::SourceMgr::DK_Error,
Message.str()),
825 ErrorOccurred =
true;
830 YAMLConverter(
const Module &TheModule,
const FileEntry *SourceFile,
831 llvm::raw_ostream &OS,
832 llvm::SourceMgr::DiagHandlerTy DiagHandler,
833 void *DiagHandlerCtxt)
834 : M(TheModule), Writer(TheModule.Name, SourceFile),
OS(
OS),
835 DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt),
836 ErrorOccurred(
false) {}
838 void convertAvailability(
const AvailabilityItem &Availability,
839 CommonEntityInfo &CEI, llvm::StringRef APIName) {
841 CEI.
Unavailable = (Availability.Mode == APIAvailability::None);
846 if (!Availability.Msg.empty())
847 emitError(llvm::Twine(
"availability message for available API '") +
848 APIName +
"' will not be used");
852 void convertParams(
const ParamsSeq &Params, FunctionInfo &OutInfo,
853 std::optional<ParamInfo> &thisOrSelf) {
854 for (
const auto &P : Params) {
860 PI.
setType(std::string(P.Type));
862 if (P.BoundsSafety) {
863 BoundsSafetyInfo BSI;
865 if (P.BoundsSafety->Level)
870 if (
static_cast<int>(OutInfo.
Params.size()) <= P.Position)
871 OutInfo.
Params.resize(P.Position + 1);
872 if (P.Position == -1)
874 else if (P.Position >= 0)
875 OutInfo.
Params[P.Position] |= PI;
877 emitError(
"invalid parameter position " + llvm::itostr(P.Position));
881 void convertNullability(
const NullabilitySeq &Nullability,
882 std::optional<NullabilityKind> ReturnNullability,
883 FunctionInfo &OutInfo, llvm::StringRef APIName) {
885 emitError(llvm::Twine(
"nullability info for '") + APIName +
890 bool audited =
false;
891 unsigned int idx = 1;
892 for (
const auto &N : Nullability)
894 audited =
Nullability.size() > 0 || ReturnNullability;
897 ReturnNullability.value_or(NullabilityKind::NonNull));
905 template <
typename T>
906 void convertCommonEntity(
const T &Common, CommonEntityInfo &Info,
908 convertAvailability(Common.Availability, Info, APIName);
910 if (Common.SafetyKind != SwiftSafetyKind::None)
912 Info.
SwiftName = std::string(Common.SwiftName);
916 template <
typename T>
917 void convertCommonType(
const T &Common, CommonTypeInfo &Info,
919 convertCommonEntity(Common, Info, APIName);
920 if (Common.SwiftBridge)
923 if (
auto conformance = Common.SwiftConformance)
928 void convertMethod(
const Method &M, ContextID ClassID, StringRef ClassName,
929 VersionTuple SwiftVersion) {
931 convertCommonEntity(M, MI, M.Selector);
934 bool takesArguments = M.Selector.ends_with(
":");
937 llvm::SmallVector<StringRef, 4> Args;
938 M.Selector.split(Args,
":", -1,
false);
939 if (!takesArguments && Args.size() > 1) {
940 emitError(
"selector '" + M.Selector +
"' is missing a ':' at the end");
945 api_notes::ObjCSelectorRef Selector;
946 Selector.
NumArgs = !takesArguments ? 0 : Args.size();
952 if (M.FactoryAsInit != FactoryAsInitKind::Infer)
953 emitError(
"'FactoryAsInit' is no longer valid; use 'SwiftName' instead");
959 convertParams(M.Params, MI, MI.
Self);
962 convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector);
967 Writer.
addObjCMethod(ClassID, Selector, M.Kind == MethodKind::Instance, MI,
971 template <
typename T>
972 void convertVariable(
const T &Entity, VariableInfo &VI) {
973 convertAvailability(Entity.Availability, VI, Entity.Name);
975 VI.
SwiftName = std::string(Entity.SwiftName);
976 if (Entity.Nullability)
978 VI.
setType(std::string(Entity.Type));
981 void convertContext(std::optional<ContextID> ParentContextID,
const Class &
C,
985 convertCommonType(
C, CI,
C.Name);
987 if (
C.AuditedForNullability)
989 if (
C.SwiftImportAsNonGeneric)
991 if (
C.SwiftObjCMembers)
995 Writer.
addContext(ParentContextID,
C.Name, Kind, CI, SwiftVersion);
998 llvm::StringMap<std::pair<bool, bool>> KnownMethods;
999 for (
const auto &method :
C.Methods) {
1003 : KnownMethods[method.Selector].second;
1005 emitError(llvm::Twine(
"duplicate definition of method '") +
1006 (IsInstanceMethod ?
"-" :
"+") +
"[" +
C.Name +
" " +
1007 method.Selector +
"]'");
1012 convertMethod(method, CtxID,
C.Name, SwiftVersion);
1016 llvm::StringSet<> KnownInstanceProperties;
1017 llvm::StringSet<> KnownClassProperties;
1018 for (
const auto &
Property :
C.Properties) {
1021 !KnownInstanceProperties.insert(
Property.Name).second) {
1022 emitError(llvm::Twine(
"duplicate definition of instance property '") +
1028 !KnownClassProperties.insert(
Property.Name).second) {
1029 emitError(llvm::Twine(
"duplicate definition of class property '") +
1035 ObjCPropertyInfo PI;
1037 if (
Property.SwiftImportAsAccessors)
1043 *
Property.Kind == MethodKind::Instance, PI,
1052 void convertNamespaceContext(std::optional<ContextID> ParentContextID,
1054 VersionTuple SwiftVersion) {
1057 convertCommonEntity(TheNamespace, CI, TheNamespace.Name);
1060 Writer.
addContext(ParentContextID, TheNamespace.Name,
1061 ContextKind::Namespace, CI, SwiftVersion);
1063 convertTopLevelItems(Context(CtxID, ContextKind::Namespace),
1064 TheNamespace.Items, SwiftVersion);
1067 std::pair<bool, std::optional<llvm::ArrayRef<llvm::StringRef>>>
1070 return {
true, std::nullopt};
1073 emitError(
"'Where' requires 'Parameters'");
1074 return {
false, std::nullopt};
1076 return {
true, llvm::ArrayRef<llvm::StringRef>(*
Function.Where->Parameters)};
1079 template <
typename FuncOrMethodInfo>
1082 FI.setSwiftPrivate(
Function.SwiftPrivate);
1083 if (
Function.SafetyKind != SwiftSafetyKind::None)
1084 FI.setSwiftSafety(
Function.SafetyKind);
1085 FI.SwiftName = std::string(
Function.SwiftName);
1086 std::optional<ParamInfo>
This;
1087 convertParams(
Function.Params, FI, This);
1088 if constexpr (std::is_same_v<FuncOrMethodInfo, CXXMethodInfo>)
1091 emitError(
"implicit instance parameter is only permitted on C++ and "
1092 "Objective-C methods");
1095 FI.ResultType = std::string(
Function.ResultType);
1096 FI.SwiftReturnOwnership = std::string(
Function.SwiftReturnOwnership);
1097 FI.setRetainCountConvention(
Function.RetainCountConvention);
1098 FI.UnsafeBufferUsage =
Function.UnsafeBufferUsage;
1101 void convertTagContext(std::optional<Context> ParentContext,
const Tag &
T,
1102 VersionTuple SwiftVersion) {
1104 std::optional<ContextID> ParentContextID =
1105 ParentContext ? std::optional<ContextID>(ParentContext->id)
1107 convertCommonType(
T, TI,
T.Name);
1109 if ((
T.SwiftRetainOp ||
T.SwiftReleaseOp) && !
T.SwiftImportAs) {
1110 emitError(llvm::Twine(
"should declare SwiftImportAs to use "
1111 "SwiftRetainOp and SwiftReleaseOp (for ") +
1115 if (
T.SwiftReleaseOp.has_value() !=
T.SwiftRetainOp.has_value()) {
1116 emitError(llvm::Twine(
"should declare both SwiftReleaseOp and "
1117 "SwiftRetainOp (for ") +
1122 if (
T.SwiftImportAs)
1124 if (
T.SwiftRetainOp)
1126 if (
T.SwiftReleaseOp)
1128 if (
T.SwiftDestroyOp)
1130 if (
T.SwiftDefaultOwnership)
1133 if (
T.SwiftCopyable)
1135 if (
T.SwiftEscapable)
1138 if (
T.EnumConvenienceKind) {
1139 if (
T.EnumExtensibility) {
1141 llvm::Twine(
"cannot mix EnumKind and EnumExtensibility (for ") +
1146 emitError(llvm::Twine(
"cannot mix EnumKind and FlagEnum (for ") +
1150 switch (*
T.EnumConvenienceKind) {
1151 case EnumConvenienceAliasKind::None:
1155 case EnumConvenienceAliasKind::CFEnum:
1159 case EnumConvenienceAliasKind::CFOptions:
1163 case EnumConvenienceAliasKind::CFClosedEnum:
1173 Writer.
addTag(ParentContext,
T.Name, TI, SwiftVersion);
1176 auto TagCtxID = Writer.
addContext(ParentContextID,
T.Name, ContextKind::Tag,
1178 Context TagCtx(TagCtxID, ContextKind::Tag);
1180 for (
const auto &Field :
T.Fields) {
1182 convertVariable(Field, FI);
1186 llvm::StringSet<> KnownMethodSelectors;
1187 for (
const auto &CXXMethod :
T.Methods) {
1188 auto WhereParameters = getWhereParameters(CXXMethod);
1189 if (!WhereParameters.first)
1192 if (WhereParameters.second) {
1193 if (!KnownMethodSelectors
1194 .insert(getFunctionSelectorKey(CXXMethod.Name,
1195 *WhereParameters.second))
1197 emitError(llvm::Twine(
"multiple API notes entries for C++ method '") +
1198 CXXMethod.Name +
"' with Where.Parameters " +
1205 convertFunction(CXXMethod, MI);
1206 if (WhereParameters.second)
1207 Writer.
addCXXMethod(TagCtxID, CXXMethod.Name, *WhereParameters.second,
1210 Writer.
addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion);
1214 for (
const auto &
Tag :
T.Tags)
1215 convertTagContext(TagCtx,
Tag, SwiftVersion);
1218 void convertTopLevelItems(std::optional<Context> Ctx,
1219 const TopLevelItems &TLItems,
1220 VersionTuple SwiftVersion) {
1221 std::optional<ContextID> CtxID =
1222 Ctx ? std::optional(Ctx->id) : std::nullopt;
1225 llvm::StringSet<> KnownClasses;
1226 for (
const auto &
Class : TLItems.Classes) {
1228 if (!KnownClasses.insert(
Class.Name).second) {
1229 emitError(llvm::Twine(
"multiple definitions of class '") +
Class.Name +
1234 convertContext(CtxID,
Class, ContextKind::ObjCClass, SwiftVersion);
1238 llvm::StringSet<> KnownProtocols;
1239 for (
const auto &Protocol : TLItems.Protocols) {
1241 if (!KnownProtocols.insert(
Protocol.Name).second) {
1242 emitError(llvm::Twine(
"multiple definitions of protocol '") +
1247 convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion);
1251 llvm::StringSet<> KnownNamespaces;
1252 for (
const auto &
Namespace : TLItems.Namespaces) {
1254 if (!KnownNamespaces.insert(
Namespace.Name).second) {
1255 emitError(llvm::Twine(
"multiple definitions of namespace '") +
1260 convertNamespaceContext(CtxID,
Namespace, SwiftVersion);
1264 llvm::StringSet<> KnownGlobals;
1265 for (
const auto &
Global : TLItems.Globals) {
1267 if (!KnownGlobals.insert(
Global.Name).second) {
1268 emitError(llvm::Twine(
"multiple definitions of global variable '") +
1273 GlobalVariableInfo GVI;
1274 convertVariable(
Global, GVI);
1279 llvm::StringSet<> KnownNameOnlyFunctions;
1280 llvm::StringSet<> KnownFunctionSelectors;
1281 for (
const auto &
Function : TLItems.Functions) {
1282 auto WhereParameters = getWhereParameters(
Function);
1283 if (!WhereParameters.first)
1286 if (WhereParameters.second) {
1287 if (!KnownFunctionSelectors
1288 .insert(getFunctionSelectorKey(
Function.Name,
1289 *WhereParameters.second))
1292 llvm::Twine(
"multiple API notes entries for global function '") +
1293 Function.Name +
"' with Where.Parameters " +
1300 if (!WhereParameters.second &&
1301 !KnownNameOnlyFunctions.insert(
Function.Name).second) {
1302 emitError(llvm::Twine(
"multiple definitions of global function '") +
1307 GlobalFunctionInfo GFI;
1309 if (WhereParameters.second)
1317 llvm::StringSet<> KnownEnumConstants;
1318 for (
const auto &EnumConstant : TLItems.EnumConstants) {
1320 if (!KnownEnumConstants.insert(
EnumConstant.Name).second) {
1321 emitError(llvm::Twine(
"multiple definitions of enumerator '") +
1326 EnumConstantInfo ECI;
1334 llvm::StringSet<> KnownTags;
1335 for (
const auto &
Tag : TLItems.Tags) {
1337 if (!KnownTags.insert(
Tag.Name).second) {
1338 emitError(llvm::Twine(
"multiple definitions of tag '") +
Tag.Name +
1343 convertTagContext(Ctx,
Tag, SwiftVersion);
1347 llvm::StringSet<> KnownTypedefs;
1348 for (
const auto &
Typedef : TLItems.Typedefs) {
1350 if (!KnownTypedefs.insert(
Typedef.Name).second) {
1351 emitError(llvm::Twine(
"multiple definitions of typedef '") +
1364 bool convertModule() {
1366 convertTopLevelItems( std::nullopt, M.TopLevel,
1370 for (
const auto &Versioned : M.SwiftVersions)
1371 convertTopLevelItems( std::nullopt, Versioned.Items,
1377 return ErrorOccurred;
1383 llvm::raw_ostream &OS,
1384 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1385 void *DiagHandlerCtxt) {
1386 YAMLConverter
C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
1387 return C.convertModule();
1392 Diag.print(
nullptr, llvm::errs());
1397 llvm::raw_ostream &OS,
1398 llvm::SourceMgr::DiagHandlerTy DiagHandler,
1399 void *DiagHandlerCtxt) {
1405 if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt))
1408 return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt);
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)
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.
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).
std::string ExternalBounds
void setKindAudited(BoundsSafetyKind kind)
void setLevelAudited(unsigned level)
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 setSwiftSafety(SwiftSafetyKind Safety)
void setSwiftPrivate(std::optional< bool > Private)
std::string UnavailableMsg
Message to use when this entity is unavailable.
void setSwiftConformance(std::optional< std::string > conformance)
void setNSErrorDomain(const std::optional< std::string > &Domain)
void setSwiftBridge(std::optional< std::string > SwiftType)
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)
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.
unsigned DesignatedInit
Whether this is a designated initializer of its class.
std::optional< ParamInfo > Self
unsigned RequiredInit
Whether this is a required initializer.
void setSwiftImportAsAccessors(std::optional< bool > Value)
std::optional< BoundsSafetyInfo > BoundsSafety
void setNoEscape(std::optional< bool > Value)
void setLifetimebound(std::optional< bool > Value)
void setRetainCountConvention(std::optional< RetainCountConventionKind > Value)
std::optional< std::string > SwiftReleaseOp
std::optional< std::string > SwiftRetainOp
std::optional< std::string > SwiftImportAs
std::optional< std::string > SwiftDefaultOwnership
std::optional< EnumExtensibilityKind > EnumExtensibility
void setSwiftCopyable(std::optional< bool > Value)
std::optional< std::string > SwiftDestroyOp
void setSwiftEscapable(std::optional< bool > Value)
void setFlagEnum(std::optional< bool > Value)
std::optional< SwiftNewTypeKind > SwiftWrapper
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.
std::string formatAPINotesParameterSelector(RangeT &&Parameters)
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)
The JSON file list parser is used to communicate input to InstallAPI.
NullabilityKind
Describes the nullability of a particular type.
@ Nullable
Values of this type can be null.
@ Unspecified
Whether values of this type can be null is (explicitly) unspecified.
@ NonNull
Values of this type can never be null.
@ Module
Module linkage, which indicates that the entity can be referred to from other translation units withi...
@ Property
The type of a property.
@ Parameter
The parameter type of a method or function.
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.
llvm::ArrayRef< llvm::StringRef > Identifiers
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, FunctionWhere &W)
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, MethodKind &MK)
static void enumeration(IO &IO, NullabilityKind &NK)
static void enumeration(IO &IO, RetainCountConventionKind &RCCK)
static void enumeration(IO &IO, SwiftNewTypeKind &SWK)
static void enumeration(IO &IO, SwiftSafetyKind &SK)