1 //===-- APINotesYAMLCompiler.cpp - API Notes YAML Format Reader -*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
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.
16 #include "clang/APINotes/APINotesYAMLCompiler.h"
17 #include "clang/APINotes/APINotesWriter.h"
18 #include "clang/APINotes/Types.h"
19 #include "clang/Basic/LLVM.h"
20 #include "clang/Basic/Specifiers.h"
21 #include "llvm/ADT/StringSet.h"
22 #include "llvm/Support/SourceMgr.h"
23 #include "llvm/Support/VersionTuple.h"
24 #include "llvm/Support/YAMLTraits.h"
26 #include <type_traits>
29 using namespace clang
;
30 using namespace api_notes
;
33 enum class APIAvailability
{
42 template <> struct ScalarEnumerationTraits
<APIAvailability
> {
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
);
53 enum class MethodKind
{
61 template <> struct ScalarEnumerationTraits
<MethodKind
> {
62 static void enumeration(IO
&IO
, MethodKind
&MK
) {
63 IO
.enumCase(MK
, "Class", MethodKind::Class
);
64 IO
.enumCase(MK
, "Instance", MethodKind::Instance
);
73 std::optional
<bool> NoEscape
= false;
74 std::optional
<bool> Lifetimebound
= false;
75 std::optional
<NullabilityKind
> Nullability
;
76 std::optional
<RetainCountConventionKind
> RetainCountConvention
;
80 typedef std::vector
<Param
> ParamsSeq
;
83 LLVM_YAML_IS_SEQUENCE_VECTOR(Param
)
84 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind
)
88 template <> struct ScalarEnumerationTraits
<NullabilityKind
> {
89 static void enumeration(IO
&IO
, NullabilityKind
&NK
) {
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 // TODO: Mapping this to it's own value would allow for better cross
95 // checking. Also the default should be Unknown.
96 IO
.enumCase(NK
, "Scalar", NullabilityKind::Unspecified
);
98 // Aliases for compatibility with existing APINotes.
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
);
106 template <> struct ScalarEnumerationTraits
<RetainCountConventionKind
> {
107 static void enumeration(IO
&IO
, RetainCountConventionKind
&RCCK
) {
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
);
120 template <> struct MappingTraits
<Param
> {
121 static void mapping(IO
&IO
, Param
&P
) {
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(""));
134 typedef std::vector
<NullabilityKind
> NullabilitySeq
;
136 struct AvailabilityItem
{
137 APIAvailability Mode
= APIAvailability::Available
;
141 /// Old attribute deprecated in favor of SwiftName.
142 enum class FactoryAsInitKind
{
143 /// Infer based on name and type (the default).
145 /// Treat as a class method.
147 /// Treat as an initializer.
155 NullabilitySeq Nullability
;
156 std::optional
<NullabilityKind
> NullabilityOfRet
;
157 std::optional
<RetainCountConventionKind
> RetainCountConvention
;
158 AvailabilityItem Availability
;
159 std::optional
<bool> SwiftPrivate
;
161 FactoryAsInitKind FactoryAsInit
= FactoryAsInitKind::Infer
;
162 bool DesignatedInit
= false;
163 bool Required
= false;
164 StringRef ResultType
;
165 StringRef SwiftReturnOwnership
;
168 typedef std::vector
<Method
> MethodsSeq
;
171 LLVM_YAML_IS_SEQUENCE_VECTOR(Method
)
175 template <> struct ScalarEnumerationTraits
<FactoryAsInitKind
> {
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
);
183 template <> struct MappingTraits
<Method
> {
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
,
210 std::optional
<MethodKind
> Kind
;
211 std::optional
<NullabilityKind
> Nullability
;
212 AvailabilityItem Availability
;
213 std::optional
<bool> SwiftPrivate
;
215 std::optional
<bool> SwiftImportAsAccessors
;
219 typedef std::vector
<Property
> PropertiesSeq
;
222 LLVM_YAML_IS_SEQUENCE_VECTOR(Property
)
226 template <> 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(""));
246 bool AuditedForNullability
= false;
247 AvailabilityItem Availability
;
248 std::optional
<bool> SwiftPrivate
;
250 std::optional
<StringRef
> SwiftBridge
;
251 std::optional
<StringRef
> NSErrorDomain
;
252 std::optional
<bool> SwiftImportAsNonGeneric
;
253 std::optional
<bool> SwiftObjCMembers
;
255 PropertiesSeq Properties
;
258 typedef std::vector
<Class
> ClassesSeq
;
261 LLVM_YAML_IS_SEQUENCE_VECTOR(Class
)
265 template <> struct MappingTraits
<Class
> {
266 static void mapping(IO
&IO
, Class
&C
) {
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
);
289 NullabilitySeq Nullability
;
290 std::optional
<NullabilityKind
> NullabilityOfRet
;
291 std::optional
<api_notes::RetainCountConventionKind
> RetainCountConvention
;
292 AvailabilityItem Availability
;
293 std::optional
<bool> SwiftPrivate
;
296 StringRef ResultType
;
297 StringRef SwiftReturnOwnership
;
300 typedef std::vector
<Function
> FunctionsSeq
;
303 LLVM_YAML_IS_SEQUENCE_VECTOR(Function
)
307 template <> 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
,
328 struct GlobalVariable
{
330 std::optional
<NullabilityKind
> Nullability
;
331 AvailabilityItem Availability
;
332 std::optional
<bool> SwiftPrivate
;
337 typedef std::vector
<GlobalVariable
> GlobalVariablesSeq
;
340 LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable
)
344 template <> struct MappingTraits
<GlobalVariable
> {
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(""));
360 struct EnumConstant
{
362 AvailabilityItem Availability
;
363 std::optional
<bool> SwiftPrivate
;
367 typedef std::vector
<EnumConstant
> EnumConstantsSeq
;
370 LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant
)
374 template <> struct MappingTraits
<EnumConstant
> {
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(""));
388 /// Syntactic sugar for EnumExtensibility and FlagEnum
389 enum class EnumConvenienceAliasKind
{
390 /// EnumExtensibility: none, FlagEnum: false
392 /// EnumExtensibility: open, FlagEnum: false
394 /// EnumExtensibility: open, FlagEnum: true
396 /// EnumExtensibility: closed, FlagEnum: false
403 template <> struct ScalarEnumerationTraits
<EnumConvenienceAliasKind
> {
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
);
420 std::optional
<NullabilityKind
> Nullability
;
421 AvailabilityItem Availability
;
422 std::optional
<bool> SwiftPrivate
;
427 typedef std::vector
<Field
> FieldsSeq
;
430 LLVM_YAML_IS_SEQUENCE_VECTOR(Field
)
434 template <> struct MappingTraits
<Field
> {
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(""));
451 typedef std::vector
<Tag
> TagsSeq
;
455 AvailabilityItem Availability
;
457 std::optional
<bool> SwiftPrivate
;
458 std::optional
<StringRef
> SwiftBridge
;
459 std::optional
<StringRef
> NSErrorDomain
;
460 std::optional
<std::string
> SwiftImportAs
;
461 std::optional
<std::string
> SwiftRetainOp
;
462 std::optional
<std::string
> SwiftReleaseOp
;
463 std::optional
<std::string
> SwiftConformance
;
464 std::optional
<EnumExtensibilityKind
> EnumExtensibility
;
465 std::optional
<bool> FlagEnum
;
466 std::optional
<EnumConvenienceAliasKind
> EnumConvenienceKind
;
467 std::optional
<bool> SwiftCopyable
;
468 std::optional
<bool> SwiftEscapable
;
469 FunctionsSeq Methods
;
472 /// Tags that are declared within the current tag. Only the tags that have
473 /// corresponding API Notes will be listed.
478 LLVM_YAML_IS_SEQUENCE_VECTOR(Tag
)
482 template <> struct ScalarEnumerationTraits
<EnumExtensibilityKind
> {
483 static void enumeration(IO
&IO
, EnumExtensibilityKind
&EEK
) {
484 IO
.enumCase(EEK
, "none", EnumExtensibilityKind::None
);
485 IO
.enumCase(EEK
, "open", EnumExtensibilityKind::Open
);
486 IO
.enumCase(EEK
, "closed", EnumExtensibilityKind::Closed
);
490 template <> struct MappingTraits
<Tag
> {
491 static void mapping(IO
&IO
, Tag
&T
) {
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
);
520 AvailabilityItem Availability
;
522 std::optional
<bool> SwiftPrivate
;
523 std::optional
<StringRef
> SwiftBridge
;
524 std::optional
<StringRef
> NSErrorDomain
;
525 std::optional
<SwiftNewTypeKind
> SwiftType
;
528 typedef std::vector
<Typedef
> TypedefsSeq
;
531 LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef
)
535 template <> struct ScalarEnumerationTraits
<SwiftNewTypeKind
> {
536 static void enumeration(IO
&IO
, SwiftNewTypeKind
&SWK
) {
537 IO
.enumCase(SWK
, "none", SwiftNewTypeKind::None
);
538 IO
.enumCase(SWK
, "struct", SwiftNewTypeKind::Struct
);
539 IO
.enumCase(SWK
, "enum", SwiftNewTypeKind::Enum
);
543 template <> struct MappingTraits
<Typedef
> {
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
);
561 typedef std::vector
<Namespace
> NamespacesSeq
;
563 struct TopLevelItems
{
565 ClassesSeq Protocols
;
566 FunctionsSeq Functions
;
567 GlobalVariablesSeq Globals
;
568 EnumConstantsSeq EnumConstants
;
570 TypedefsSeq Typedefs
;
571 NamespacesSeq Namespaces
;
577 static void mapTopLevelItems(IO
&IO
, TopLevelItems
&TLI
) {
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
);
593 AvailabilityItem Availability
;
595 std::optional
<bool> SwiftPrivate
;
600 LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace
)
604 template <> struct MappingTraits
<Namespace
> {
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(""));
612 mapTopLevelItems(IO
, T
.Items
);
620 VersionTuple Version
;
624 typedef std::vector
<Versioned
> VersionedSeq
;
627 LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned
)
631 template <> struct MappingTraits
<Versioned
> {
632 static void mapping(IO
&IO
, Versioned
&V
) {
633 IO
.mapRequired("Version", V
.Version
);
634 mapTopLevelItems(IO
, V
.Items
);
643 AvailabilityItem Availability
;
644 TopLevelItems TopLevel
;
645 VersionedSeq SwiftVersions
;
647 std::optional
<bool> SwiftInferImportAsMember
;
649 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
650 LLVM_DUMP_METHOD
void dump() /*const*/;
657 template <> struct MappingTraits
<Module
> {
658 static void mapping(IO
&IO
, Module
&M
) {
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
);
664 mapTopLevelItems(IO
, M
.TopLevel
);
665 IO
.mapOptional("SwiftVersions", M
.SwiftVersions
);
671 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
672 LLVM_DUMP_METHOD
void Module::dump() {
673 llvm::yaml::Output
OS(llvm::errs());
679 bool parseAPINotes(StringRef YI
, Module
&M
, llvm::SourceMgr::DiagHandlerTy Diag
,
681 llvm::yaml::Input
IS(YI
, nullptr, Diag
, DiagContext
);
683 return static_cast<bool>(IS
.error());
687 bool clang::api_notes::parseAndDumpAPINotes(StringRef YI
,
688 llvm::raw_ostream
&OS
) {
690 if (parseAPINotes(YI
, M
, nullptr, nullptr))
693 llvm::yaml::Output
YOS(OS
);
700 using namespace api_notes
;
702 class YAMLConverter
{
704 APINotesWriter Writer
;
705 llvm::raw_ostream
&OS
;
706 llvm::SourceMgr::DiagHandlerTy DiagHandler
;
707 void *DiagHandlerCtxt
;
710 /// Emit a diagnostic
711 bool emitError(llvm::Twine Message
) {
713 llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error
, Message
.str()),
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) {}
728 void convertAvailability(const AvailabilityItem
&Availability
,
729 CommonEntityInfo
&CEI
, llvm::StringRef APIName
) {
730 // Populate the unavailability information.
731 CEI
.Unavailable
= (Availability
.Mode
== APIAvailability::None
);
732 CEI
.UnavailableInSwift
= (Availability
.Mode
== APIAvailability::NonSwift
);
733 if (CEI
.Unavailable
|| CEI
.UnavailableInSwift
) {
734 CEI
.UnavailableMsg
= std::string(Availability
.Msg
);
736 if (!Availability
.Msg
.empty())
737 emitError(llvm::Twine("availability message for available API '") +
738 APIName
+ "' will not be used");
742 void convertParams(const ParamsSeq
&Params
, FunctionInfo
&OutInfo
,
743 std::optional
<ParamInfo
> &thisOrSelf
) {
744 for (const auto &P
: Params
) {
747 PI
.setNullabilityAudited(*P
.Nullability
);
748 PI
.setNoEscape(P
.NoEscape
);
749 PI
.setLifetimebound(P
.Lifetimebound
);
750 PI
.setType(std::string(P
.Type
));
751 PI
.setRetainCountConvention(P
.RetainCountConvention
);
752 if (static_cast<int>(OutInfo
.Params
.size()) <= P
.Position
)
753 OutInfo
.Params
.resize(P
.Position
+ 1);
754 if (P
.Position
== -1)
756 else if (P
.Position
>= 0)
757 OutInfo
.Params
[P
.Position
] |= PI
;
759 emitError("invalid parameter position " + llvm::itostr(P
.Position
));
763 void convertNullability(const NullabilitySeq
&Nullability
,
764 std::optional
<NullabilityKind
> ReturnNullability
,
765 FunctionInfo
&OutInfo
, llvm::StringRef APIName
) {
766 if (Nullability
.size() > FunctionInfo::getMaxNullabilityIndex()) {
767 emitError(llvm::Twine("nullability info for '") + APIName
+
772 bool audited
= false;
773 unsigned int idx
= 1;
774 for (const auto &N
: Nullability
)
775 OutInfo
.addTypeInfo(idx
++, N
);
776 audited
= Nullability
.size() > 0 || ReturnNullability
;
778 OutInfo
.addTypeInfo(0,
779 ReturnNullability
.value_or(NullabilityKind::NonNull
));
782 OutInfo
.NullabilityAudited
= audited
;
783 OutInfo
.NumAdjustedNullable
= idx
;
786 /// Convert the common parts of an entity from YAML.
787 template <typename T
>
788 void convertCommonEntity(const T
&Common
, CommonEntityInfo
&Info
,
790 convertAvailability(Common
.Availability
, Info
, APIName
);
791 Info
.setSwiftPrivate(Common
.SwiftPrivate
);
792 Info
.SwiftName
= std::string(Common
.SwiftName
);
795 /// Convert the common parts of a type entity from YAML.
796 template <typename T
>
797 void convertCommonType(const T
&Common
, CommonTypeInfo
&Info
,
799 convertCommonEntity(Common
, Info
, APIName
);
800 if (Common
.SwiftBridge
)
801 Info
.setSwiftBridge(std::string(*Common
.SwiftBridge
));
802 Info
.setNSErrorDomain(Common
.NSErrorDomain
);
805 // Translate from Method into ObjCMethodInfo and write it out.
806 void convertMethod(const Method
&M
, ContextID ClassID
, StringRef ClassName
,
807 VersionTuple SwiftVersion
) {
809 convertCommonEntity(M
, MI
, M
.Selector
);
811 // Check if the selector ends with ':' to determine if it takes arguments.
812 bool takesArguments
= M
.Selector
.ends_with(":");
814 // Split the selector into pieces.
815 llvm::SmallVector
<StringRef
, 4> Args
;
816 M
.Selector
.split(Args
, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false);
817 if (!takesArguments
&& Args
.size() > 1) {
818 emitError("selector '" + M
.Selector
+ "' is missing a ':' at the end");
822 // Construct ObjCSelectorRef.
823 api_notes::ObjCSelectorRef Selector
;
824 Selector
.NumArgs
= !takesArguments
? 0 : Args
.size();
825 Selector
.Identifiers
= Args
;
827 // Translate the initializer info.
828 MI
.DesignatedInit
= M
.DesignatedInit
;
829 MI
.RequiredInit
= M
.Required
;
830 if (M
.FactoryAsInit
!= FactoryAsInitKind::Infer
)
831 emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead");
833 MI
.ResultType
= std::string(M
.ResultType
);
834 MI
.SwiftReturnOwnership
= std::string(M
.SwiftReturnOwnership
);
836 // Translate parameter information.
837 convertParams(M
.Params
, MI
, MI
.Self
);
839 // Translate nullability info.
840 convertNullability(M
.Nullability
, M
.NullabilityOfRet
, MI
, M
.Selector
);
842 MI
.setRetainCountConvention(M
.RetainCountConvention
);
845 Writer
.addObjCMethod(ClassID
, Selector
, M
.Kind
== MethodKind::Instance
, MI
,
849 template <typename T
>
850 void convertVariable(const T
&Entity
, VariableInfo
&VI
) {
851 convertAvailability(Entity
.Availability
, VI
, Entity
.Name
);
852 VI
.setSwiftPrivate(Entity
.SwiftPrivate
);
853 VI
.SwiftName
= std::string(Entity
.SwiftName
);
854 if (Entity
.Nullability
)
855 VI
.setNullabilityAudited(*Entity
.Nullability
);
856 VI
.setType(std::string(Entity
.Type
));
859 void convertContext(std::optional
<ContextID
> ParentContextID
, const Class
&C
,
860 ContextKind Kind
, VersionTuple SwiftVersion
) {
863 convertCommonType(C
, CI
, C
.Name
);
865 if (C
.AuditedForNullability
)
866 CI
.setDefaultNullability(NullabilityKind::NonNull
);
867 if (C
.SwiftImportAsNonGeneric
)
868 CI
.setSwiftImportAsNonGeneric(*C
.SwiftImportAsNonGeneric
);
869 if (C
.SwiftObjCMembers
)
870 CI
.setSwiftObjCMembers(*C
.SwiftObjCMembers
);
873 Writer
.addContext(ParentContextID
, C
.Name
, Kind
, CI
, SwiftVersion
);
875 // Write all methods.
876 llvm::StringMap
<std::pair
<bool, bool>> KnownMethods
;
877 for (const auto &method
: C
.Methods
) {
878 // Check for duplicate method definitions.
879 bool IsInstanceMethod
= method
.Kind
== MethodKind::Instance
;
880 bool &Known
= IsInstanceMethod
? KnownMethods
[method
.Selector
].first
881 : KnownMethods
[method
.Selector
].second
;
883 emitError(llvm::Twine("duplicate definition of method '") +
884 (IsInstanceMethod
? "-" : "+") + "[" + C
.Name
+ " " +
885 method
.Selector
+ "]'");
890 convertMethod(method
, CtxID
, C
.Name
, SwiftVersion
);
893 // Write all properties.
894 llvm::StringSet
<> KnownInstanceProperties
;
895 llvm::StringSet
<> KnownClassProperties
;
896 for (const auto &Property
: C
.Properties
) {
897 // Check for duplicate property definitions.
898 if ((!Property
.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
+ "'");
905 if ((!Property
.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
+ "'");
912 // Translate from Property into ObjCPropertyInfo.
914 convertVariable(Property
, PI
);
915 if (Property
.SwiftImportAsAccessors
)
916 PI
.setSwiftImportAsAccessors(*Property
.SwiftImportAsAccessors
);
918 // Add both instance and class properties with this name.
920 Writer
.addObjCProperty(CtxID
, Property
.Name
,
921 *Property
.Kind
== MethodKind::Instance
, PI
,
924 Writer
.addObjCProperty(CtxID
, Property
.Name
, true, PI
, SwiftVersion
);
925 Writer
.addObjCProperty(CtxID
, Property
.Name
, false, PI
, SwiftVersion
);
930 void convertNamespaceContext(std::optional
<ContextID
> ParentContextID
,
931 const Namespace
&TheNamespace
,
932 VersionTuple SwiftVersion
) {
933 // Write the namespace.
935 convertCommonEntity(TheNamespace
, CI
, TheNamespace
.Name
);
938 Writer
.addContext(ParentContextID
, TheNamespace
.Name
,
939 ContextKind::Namespace
, CI
, SwiftVersion
);
941 convertTopLevelItems(Context(CtxID
, ContextKind::Namespace
),
942 TheNamespace
.Items
, SwiftVersion
);
945 template <typename FuncOrMethodInfo
>
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
<ParamInfo
> This
;
951 convertParams(Function
.Params
, FI
, This
);
952 if constexpr (std::is_same_v
<FuncOrMethodInfo
, CXXMethodInfo
>)
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
);
964 void convertTagContext(std::optional
<Context
> ParentContext
, const Tag
&T
,
965 VersionTuple SwiftVersion
) {
967 std::optional
<ContextID
> ParentContextID
=
968 ParentContext
? std::optional
<ContextID
>(ParentContext
->id
)
970 convertCommonType(T
, TI
, T
.Name
);
972 if ((T
.SwiftRetainOp
|| T
.SwiftReleaseOp
) && !T
.SwiftImportAs
) {
973 emitError(llvm::Twine("should declare SwiftImportAs to use "
974 "SwiftRetainOp and SwiftReleaseOp (for ") +
978 if (T
.SwiftReleaseOp
.has_value() != T
.SwiftRetainOp
.has_value()) {
979 emitError(llvm::Twine("should declare both SwiftReleaseOp and "
980 "SwiftRetainOp (for ") +
986 TI
.SwiftImportAs
= T
.SwiftImportAs
;
988 TI
.SwiftRetainOp
= T
.SwiftRetainOp
;
989 if (T
.SwiftReleaseOp
)
990 TI
.SwiftReleaseOp
= T
.SwiftReleaseOp
;
991 if (T
.SwiftConformance
)
992 TI
.SwiftConformance
= T
.SwiftConformance
;
995 TI
.setSwiftCopyable(T
.SwiftCopyable
);
996 if (T
.SwiftEscapable
)
997 TI
.setSwiftEscapable(T
.SwiftEscapable
);
999 if (T
.EnumConvenienceKind
) {
1000 if (T
.EnumExtensibility
) {
1002 llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") +
1007 emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") +
1011 switch (*T
.EnumConvenienceKind
) {
1012 case EnumConvenienceAliasKind::None
:
1013 TI
.EnumExtensibility
= EnumExtensibilityKind::None
;
1014 TI
.setFlagEnum(false);
1016 case EnumConvenienceAliasKind::CFEnum
:
1017 TI
.EnumExtensibility
= EnumExtensibilityKind::Open
;
1018 TI
.setFlagEnum(false);
1020 case EnumConvenienceAliasKind::CFOptions
:
1021 TI
.EnumExtensibility
= EnumExtensibilityKind::Open
;
1022 TI
.setFlagEnum(true);
1024 case EnumConvenienceAliasKind::CFClosedEnum
:
1025 TI
.EnumExtensibility
= EnumExtensibilityKind::Closed
;
1026 TI
.setFlagEnum(false);
1030 TI
.EnumExtensibility
= T
.EnumExtensibility
;
1031 TI
.setFlagEnum(T
.FlagEnum
);
1034 Writer
.addTag(ParentContext
, T
.Name
, TI
, SwiftVersion
);
1037 auto TagCtxID
= Writer
.addContext(ParentContextID
, T
.Name
, ContextKind::Tag
,
1039 Context
TagCtx(TagCtxID
, ContextKind::Tag
);
1041 for (const auto &Field
: T
.Fields
) {
1043 convertVariable(Field
, FI
);
1044 Writer
.addField(TagCtxID
, Field
.Name
, FI
, SwiftVersion
);
1047 for (const auto &CXXMethod
: T
.Methods
) {
1049 convertFunction(CXXMethod
, MI
);
1050 Writer
.addCXXMethod(TagCtxID
, CXXMethod
.Name
, MI
, SwiftVersion
);
1053 // Convert nested tags.
1054 for (const auto &Tag
: T
.Tags
)
1055 convertTagContext(TagCtx
, Tag
, SwiftVersion
);
1058 void convertTopLevelItems(std::optional
<Context
> Ctx
,
1059 const TopLevelItems
&TLItems
,
1060 VersionTuple SwiftVersion
) {
1061 std::optional
<ContextID
> CtxID
=
1062 Ctx
? std::optional(Ctx
->id
) : std::nullopt
;
1064 // Write all classes.
1065 llvm::StringSet
<> KnownClasses
;
1066 for (const auto &Class
: TLItems
.Classes
) {
1067 // Check for duplicate class definitions.
1068 if (!KnownClasses
.insert(Class
.Name
).second
) {
1069 emitError(llvm::Twine("multiple definitions of class '") + Class
.Name
+
1074 convertContext(CtxID
, Class
, ContextKind::ObjCClass
, SwiftVersion
);
1077 // Write all protocols.
1078 llvm::StringSet
<> KnownProtocols
;
1079 for (const auto &Protocol
: TLItems
.Protocols
) {
1080 // Check for duplicate protocol definitions.
1081 if (!KnownProtocols
.insert(Protocol
.Name
).second
) {
1082 emitError(llvm::Twine("multiple definitions of protocol '") +
1083 Protocol
.Name
+ "'");
1087 convertContext(CtxID
, Protocol
, ContextKind::ObjCProtocol
, SwiftVersion
);
1090 // Write all namespaces.
1091 llvm::StringSet
<> KnownNamespaces
;
1092 for (const auto &Namespace
: TLItems
.Namespaces
) {
1093 // Check for duplicate namespace definitions.
1094 if (!KnownNamespaces
.insert(Namespace
.Name
).second
) {
1095 emitError(llvm::Twine("multiple definitions of namespace '") +
1096 Namespace
.Name
+ "'");
1100 convertNamespaceContext(CtxID
, Namespace
, SwiftVersion
);
1103 // Write all global variables.
1104 llvm::StringSet
<> KnownGlobals
;
1105 for (const auto &Global
: TLItems
.Globals
) {
1106 // Check for duplicate global variables.
1107 if (!KnownGlobals
.insert(Global
.Name
).second
) {
1108 emitError(llvm::Twine("multiple definitions of global variable '") +
1113 GlobalVariableInfo GVI
;
1114 convertVariable(Global
, GVI
);
1115 Writer
.addGlobalVariable(Ctx
, Global
.Name
, GVI
, SwiftVersion
);
1118 // Write all global functions.
1119 llvm::StringSet
<> KnownFunctions
;
1120 for (const auto &Function
: TLItems
.Functions
) {
1121 // Check for duplicate global functions.
1122 if (!KnownFunctions
.insert(Function
.Name
).second
) {
1123 emitError(llvm::Twine("multiple definitions of global function '") +
1124 Function
.Name
+ "'");
1128 GlobalFunctionInfo GFI
;
1129 convertFunction(Function
, GFI
);
1130 Writer
.addGlobalFunction(Ctx
, Function
.Name
, GFI
, SwiftVersion
);
1133 // Write all enumerators.
1134 llvm::StringSet
<> KnownEnumConstants
;
1135 for (const auto &EnumConstant
: TLItems
.EnumConstants
) {
1136 // Check for duplicate enumerators
1137 if (!KnownEnumConstants
.insert(EnumConstant
.Name
).second
) {
1138 emitError(llvm::Twine("multiple definitions of enumerator '") +
1139 EnumConstant
.Name
+ "'");
1143 EnumConstantInfo ECI
;
1144 convertAvailability(EnumConstant
.Availability
, ECI
, EnumConstant
.Name
);
1145 ECI
.setSwiftPrivate(EnumConstant
.SwiftPrivate
);
1146 ECI
.SwiftName
= std::string(EnumConstant
.SwiftName
);
1147 Writer
.addEnumConstant(EnumConstant
.Name
, ECI
, SwiftVersion
);
1151 llvm::StringSet
<> KnownTags
;
1152 for (const auto &Tag
: TLItems
.Tags
) {
1153 // Check for duplicate tag definitions.
1154 if (!KnownTags
.insert(Tag
.Name
).second
) {
1155 emitError(llvm::Twine("multiple definitions of tag '") + Tag
.Name
+
1160 convertTagContext(Ctx
, Tag
, SwiftVersion
);
1163 // Write all typedefs.
1164 llvm::StringSet
<> KnownTypedefs
;
1165 for (const auto &Typedef
: TLItems
.Typedefs
) {
1166 // Check for duplicate typedef definitions.
1167 if (!KnownTypedefs
.insert(Typedef
.Name
).second
) {
1168 emitError(llvm::Twine("multiple definitions of typedef '") +
1169 Typedef
.Name
+ "'");
1174 convertCommonType(Typedef
, TInfo
, Typedef
.Name
);
1175 TInfo
.SwiftWrapper
= Typedef
.SwiftType
;
1177 Writer
.addTypedef(Ctx
, Typedef
.Name
, TInfo
, SwiftVersion
);
1181 bool convertModule() {
1182 // Write the top-level items.
1183 convertTopLevelItems(/* context */ std::nullopt
, M
.TopLevel
,
1186 // Convert the versioned information.
1187 for (const auto &Versioned
: M
.SwiftVersions
)
1188 convertTopLevelItems(/* context */ std::nullopt
, Versioned
.Items
,
1192 Writer
.writeToStream(OS
);
1194 return ErrorOccured
;
1199 static bool compile(const Module
&M
, const FileEntry
*SourceFile
,
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();
1207 /// Simple diagnostic handler that prints diagnostics to standard error.
1208 static void printDiagnostic(const llvm::SMDiagnostic
&Diag
, void *Context
) {
1209 Diag
.print(nullptr, llvm::errs());
1212 bool api_notes::compileAPINotes(StringRef YAMLInput
,
1213 const FileEntry
*SourceFile
,
1214 llvm::raw_ostream
&OS
,
1215 llvm::SourceMgr::DiagHandlerTy DiagHandler
,
1216 void *DiagHandlerCtxt
) {
1220 DiagHandler
= &printDiagnostic
;
1222 if (parseAPINotes(YAMLInput
, TheModule
, DiagHandler
, DiagHandlerCtxt
))
1225 return compile(TheModule
, SourceFile
, OS
, DiagHandler
, DiagHandlerCtxt
);