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/Types.h"
18 #include "clang/Basic/LLVM.h"
19 #include "clang/Basic/Specifiers.h"
20 #include "llvm/Support/VersionTuple.h"
21 #include "llvm/Support/YAMLParser.h"
22 #include "llvm/Support/YAMLTraits.h"
25 using namespace clang
;
26 using namespace api_notes
;
29 enum class APIAvailability
{
38 template <> struct ScalarEnumerationTraits
<APIAvailability
> {
39 static void enumeration(IO
&IO
, APIAvailability
&AA
) {
40 IO
.enumCase(AA
, "none", APIAvailability::None
);
41 IO
.enumCase(AA
, "nonswift", APIAvailability::NonSwift
);
42 IO
.enumCase(AA
, "available", APIAvailability::Available
);
49 enum class MethodKind
{
57 template <> struct ScalarEnumerationTraits
<MethodKind
> {
58 static void enumeration(IO
&IO
, MethodKind
&MK
) {
59 IO
.enumCase(MK
, "Class", MethodKind::Class
);
60 IO
.enumCase(MK
, "Instance", MethodKind::Instance
);
69 std::optional
<bool> NoEscape
= false;
70 std::optional
<NullabilityKind
> Nullability
;
71 std::optional
<RetainCountConventionKind
> RetainCountConvention
;
75 typedef std::vector
<Param
> ParamsSeq
;
78 LLVM_YAML_IS_SEQUENCE_VECTOR(Param
)
79 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind
)
83 template <> struct ScalarEnumerationTraits
<NullabilityKind
> {
84 static void enumeration(IO
&IO
, NullabilityKind
&NK
) {
85 IO
.enumCase(NK
, "Nonnull", NullabilityKind::NonNull
);
86 IO
.enumCase(NK
, "Optional", NullabilityKind::Nullable
);
87 IO
.enumCase(NK
, "Unspecified", NullabilityKind::Unspecified
);
88 IO
.enumCase(NK
, "NullableResult", NullabilityKind::NullableResult
);
89 // TODO: Mapping this to it's own value would allow for better cross
90 // checking. Also the default should be Unknown.
91 IO
.enumCase(NK
, "Scalar", NullabilityKind::Unspecified
);
93 // Aliases for compatibility with existing APINotes.
94 IO
.enumCase(NK
, "N", NullabilityKind::NonNull
);
95 IO
.enumCase(NK
, "O", NullabilityKind::Nullable
);
96 IO
.enumCase(NK
, "U", NullabilityKind::Unspecified
);
97 IO
.enumCase(NK
, "S", NullabilityKind::Unspecified
);
101 template <> struct ScalarEnumerationTraits
<RetainCountConventionKind
> {
102 static void enumeration(IO
&IO
, RetainCountConventionKind
&RCCK
) {
103 IO
.enumCase(RCCK
, "none", RetainCountConventionKind::None
);
104 IO
.enumCase(RCCK
, "CFReturnsRetained",
105 RetainCountConventionKind::CFReturnsRetained
);
106 IO
.enumCase(RCCK
, "CFReturnsNotRetained",
107 RetainCountConventionKind::CFReturnsNotRetained
);
108 IO
.enumCase(RCCK
, "NSReturnsRetained",
109 RetainCountConventionKind::NSReturnsRetained
);
110 IO
.enumCase(RCCK
, "NSReturnsNotRetained",
111 RetainCountConventionKind::NSReturnsNotRetained
);
115 template <> struct MappingTraits
<Param
> {
116 static void mapping(IO
&IO
, Param
&P
) {
117 IO
.mapRequired("Position", P
.Position
);
118 IO
.mapOptional("Nullability", P
.Nullability
, std::nullopt
);
119 IO
.mapOptional("RetainCountConvention", P
.RetainCountConvention
);
120 IO
.mapOptional("NoEscape", P
.NoEscape
);
121 IO
.mapOptional("Type", P
.Type
, StringRef(""));
128 typedef std::vector
<NullabilityKind
> NullabilitySeq
;
130 struct AvailabilityItem
{
131 APIAvailability Mode
= APIAvailability::Available
;
135 /// Old attribute deprecated in favor of SwiftName.
136 enum class FactoryAsInitKind
{
137 /// Infer based on name and type (the default).
139 /// Treat as a class method.
141 /// Treat as an initializer.
149 NullabilitySeq Nullability
;
150 std::optional
<NullabilityKind
> NullabilityOfRet
;
151 std::optional
<RetainCountConventionKind
> RetainCountConvention
;
152 AvailabilityItem Availability
;
153 std::optional
<bool> SwiftPrivate
;
155 FactoryAsInitKind FactoryAsInit
= FactoryAsInitKind::Infer
;
156 bool DesignatedInit
= false;
157 bool Required
= false;
158 StringRef ResultType
;
161 typedef std::vector
<Method
> MethodsSeq
;
164 LLVM_YAML_IS_SEQUENCE_VECTOR(Method
)
168 template <> struct ScalarEnumerationTraits
<FactoryAsInitKind
> {
169 static void enumeration(IO
&IO
, FactoryAsInitKind
&FIK
) {
170 IO
.enumCase(FIK
, "A", FactoryAsInitKind::Infer
);
171 IO
.enumCase(FIK
, "C", FactoryAsInitKind::AsClassMethod
);
172 IO
.enumCase(FIK
, "I", FactoryAsInitKind::AsInitializer
);
176 template <> struct MappingTraits
<Method
> {
177 static void mapping(IO
&IO
, Method
&M
) {
178 IO
.mapRequired("Selector", M
.Selector
);
179 IO
.mapRequired("MethodKind", M
.Kind
);
180 IO
.mapOptional("Parameters", M
.Params
);
181 IO
.mapOptional("Nullability", M
.Nullability
);
182 IO
.mapOptional("NullabilityOfRet", M
.NullabilityOfRet
, std::nullopt
);
183 IO
.mapOptional("RetainCountConvention", M
.RetainCountConvention
);
184 IO
.mapOptional("Availability", M
.Availability
.Mode
,
185 APIAvailability::Available
);
186 IO
.mapOptional("AvailabilityMsg", M
.Availability
.Msg
, StringRef(""));
187 IO
.mapOptional("SwiftPrivate", M
.SwiftPrivate
);
188 IO
.mapOptional("SwiftName", M
.SwiftName
, StringRef(""));
189 IO
.mapOptional("FactoryAsInit", M
.FactoryAsInit
, FactoryAsInitKind::Infer
);
190 IO
.mapOptional("DesignatedInit", M
.DesignatedInit
, false);
191 IO
.mapOptional("Required", M
.Required
, false);
192 IO
.mapOptional("ResultType", M
.ResultType
, StringRef(""));
201 std::optional
<MethodKind
> Kind
;
202 std::optional
<NullabilityKind
> Nullability
;
203 AvailabilityItem Availability
;
204 std::optional
<bool> SwiftPrivate
;
206 std::optional
<bool> SwiftImportAsAccessors
;
210 typedef std::vector
<Property
> PropertiesSeq
;
213 LLVM_YAML_IS_SEQUENCE_VECTOR(Property
)
217 template <> struct MappingTraits
<Property
> {
218 static void mapping(IO
&IO
, Property
&P
) {
219 IO
.mapRequired("Name", P
.Name
);
220 IO
.mapOptional("PropertyKind", P
.Kind
);
221 IO
.mapOptional("Nullability", P
.Nullability
, std::nullopt
);
222 IO
.mapOptional("Availability", P
.Availability
.Mode
,
223 APIAvailability::Available
);
224 IO
.mapOptional("AvailabilityMsg", P
.Availability
.Msg
, StringRef(""));
225 IO
.mapOptional("SwiftPrivate", P
.SwiftPrivate
);
226 IO
.mapOptional("SwiftName", P
.SwiftName
, StringRef(""));
227 IO
.mapOptional("SwiftImportAsAccessors", P
.SwiftImportAsAccessors
);
228 IO
.mapOptional("Type", P
.Type
, StringRef(""));
237 bool AuditedForNullability
= false;
238 AvailabilityItem Availability
;
239 std::optional
<bool> SwiftPrivate
;
241 std::optional
<StringRef
> SwiftBridge
;
242 std::optional
<StringRef
> NSErrorDomain
;
243 std::optional
<bool> SwiftImportAsNonGeneric
;
244 std::optional
<bool> SwiftObjCMembers
;
246 PropertiesSeq Properties
;
249 typedef std::vector
<Class
> ClassesSeq
;
252 LLVM_YAML_IS_SEQUENCE_VECTOR(Class
)
256 template <> struct MappingTraits
<Class
> {
257 static void mapping(IO
&IO
, Class
&C
) {
258 IO
.mapRequired("Name", C
.Name
);
259 IO
.mapOptional("AuditedForNullability", C
.AuditedForNullability
, false);
260 IO
.mapOptional("Availability", C
.Availability
.Mode
,
261 APIAvailability::Available
);
262 IO
.mapOptional("AvailabilityMsg", C
.Availability
.Msg
, StringRef(""));
263 IO
.mapOptional("SwiftPrivate", C
.SwiftPrivate
);
264 IO
.mapOptional("SwiftName", C
.SwiftName
, StringRef(""));
265 IO
.mapOptional("SwiftBridge", C
.SwiftBridge
);
266 IO
.mapOptional("NSErrorDomain", C
.NSErrorDomain
);
267 IO
.mapOptional("SwiftImportAsNonGeneric", C
.SwiftImportAsNonGeneric
);
268 IO
.mapOptional("SwiftObjCMembers", C
.SwiftObjCMembers
);
269 IO
.mapOptional("Methods", C
.Methods
);
270 IO
.mapOptional("Properties", C
.Properties
);
280 NullabilitySeq Nullability
;
281 std::optional
<NullabilityKind
> NullabilityOfRet
;
282 std::optional
<api_notes::RetainCountConventionKind
> RetainCountConvention
;
283 AvailabilityItem Availability
;
284 std::optional
<bool> SwiftPrivate
;
287 StringRef ResultType
;
290 typedef std::vector
<Function
> FunctionsSeq
;
293 LLVM_YAML_IS_SEQUENCE_VECTOR(Function
)
297 template <> struct MappingTraits
<Function
> {
298 static void mapping(IO
&IO
, Function
&F
) {
299 IO
.mapRequired("Name", F
.Name
);
300 IO
.mapOptional("Parameters", F
.Params
);
301 IO
.mapOptional("Nullability", F
.Nullability
);
302 IO
.mapOptional("NullabilityOfRet", F
.NullabilityOfRet
, std::nullopt
);
303 IO
.mapOptional("RetainCountConvention", F
.RetainCountConvention
);
304 IO
.mapOptional("Availability", F
.Availability
.Mode
,
305 APIAvailability::Available
);
306 IO
.mapOptional("AvailabilityMsg", F
.Availability
.Msg
, StringRef(""));
307 IO
.mapOptional("SwiftPrivate", F
.SwiftPrivate
);
308 IO
.mapOptional("SwiftName", F
.SwiftName
, StringRef(""));
309 IO
.mapOptional("ResultType", F
.ResultType
, StringRef(""));
316 struct GlobalVariable
{
318 std::optional
<NullabilityKind
> Nullability
;
319 AvailabilityItem Availability
;
320 std::optional
<bool> SwiftPrivate
;
325 typedef std::vector
<GlobalVariable
> GlobalVariablesSeq
;
328 LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable
)
332 template <> struct MappingTraits
<GlobalVariable
> {
333 static void mapping(IO
&IO
, GlobalVariable
&GV
) {
334 IO
.mapRequired("Name", GV
.Name
);
335 IO
.mapOptional("Nullability", GV
.Nullability
, std::nullopt
);
336 IO
.mapOptional("Availability", GV
.Availability
.Mode
,
337 APIAvailability::Available
);
338 IO
.mapOptional("AvailabilityMsg", GV
.Availability
.Msg
, StringRef(""));
339 IO
.mapOptional("SwiftPrivate", GV
.SwiftPrivate
);
340 IO
.mapOptional("SwiftName", GV
.SwiftName
, StringRef(""));
341 IO
.mapOptional("Type", GV
.Type
, StringRef(""));
348 struct EnumConstant
{
350 AvailabilityItem Availability
;
351 std::optional
<bool> SwiftPrivate
;
355 typedef std::vector
<EnumConstant
> EnumConstantsSeq
;
358 LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant
)
362 template <> struct MappingTraits
<EnumConstant
> {
363 static void mapping(IO
&IO
, EnumConstant
&EC
) {
364 IO
.mapRequired("Name", EC
.Name
);
365 IO
.mapOptional("Availability", EC
.Availability
.Mode
,
366 APIAvailability::Available
);
367 IO
.mapOptional("AvailabilityMsg", EC
.Availability
.Msg
, StringRef(""));
368 IO
.mapOptional("SwiftPrivate", EC
.SwiftPrivate
);
369 IO
.mapOptional("SwiftName", EC
.SwiftName
, StringRef(""));
376 /// Syntactic sugar for EnumExtensibility and FlagEnum
377 enum class EnumConvenienceAliasKind
{
378 /// EnumExtensibility: none, FlagEnum: false
380 /// EnumExtensibility: open, FlagEnum: false
382 /// EnumExtensibility: open, FlagEnum: true
384 /// EnumExtensibility: closed, FlagEnum: false
391 template <> struct ScalarEnumerationTraits
<EnumConvenienceAliasKind
> {
392 static void enumeration(IO
&IO
, EnumConvenienceAliasKind
&ECAK
) {
393 IO
.enumCase(ECAK
, "none", EnumConvenienceAliasKind::None
);
394 IO
.enumCase(ECAK
, "CFEnum", EnumConvenienceAliasKind::CFEnum
);
395 IO
.enumCase(ECAK
, "NSEnum", EnumConvenienceAliasKind::CFEnum
);
396 IO
.enumCase(ECAK
, "CFOptions", EnumConvenienceAliasKind::CFOptions
);
397 IO
.enumCase(ECAK
, "NSOptions", EnumConvenienceAliasKind::CFOptions
);
398 IO
.enumCase(ECAK
, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum
);
399 IO
.enumCase(ECAK
, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum
);
408 AvailabilityItem Availability
;
410 std::optional
<bool> SwiftPrivate
;
411 std::optional
<StringRef
> SwiftBridge
;
412 std::optional
<StringRef
> NSErrorDomain
;
413 std::optional
<std::string
> SwiftImportAs
;
414 std::optional
<std::string
> SwiftRetainOp
;
415 std::optional
<std::string
> SwiftReleaseOp
;
416 std::optional
<EnumExtensibilityKind
> EnumExtensibility
;
417 std::optional
<bool> FlagEnum
;
418 std::optional
<EnumConvenienceAliasKind
> EnumConvenienceKind
;
421 typedef std::vector
<Tag
> TagsSeq
;
424 LLVM_YAML_IS_SEQUENCE_VECTOR(Tag
)
428 template <> struct ScalarEnumerationTraits
<EnumExtensibilityKind
> {
429 static void enumeration(IO
&IO
, EnumExtensibilityKind
&EEK
) {
430 IO
.enumCase(EEK
, "none", EnumExtensibilityKind::None
);
431 IO
.enumCase(EEK
, "open", EnumExtensibilityKind::Open
);
432 IO
.enumCase(EEK
, "closed", EnumExtensibilityKind::Closed
);
436 template <> struct MappingTraits
<Tag
> {
437 static void mapping(IO
&IO
, Tag
&T
) {
438 IO
.mapRequired("Name", T
.Name
);
439 IO
.mapOptional("Availability", T
.Availability
.Mode
,
440 APIAvailability::Available
);
441 IO
.mapOptional("AvailabilityMsg", T
.Availability
.Msg
, StringRef(""));
442 IO
.mapOptional("SwiftPrivate", T
.SwiftPrivate
);
443 IO
.mapOptional("SwiftName", T
.SwiftName
, StringRef(""));
444 IO
.mapOptional("SwiftBridge", T
.SwiftBridge
);
445 IO
.mapOptional("NSErrorDomain", T
.NSErrorDomain
);
446 IO
.mapOptional("SwiftImportAs", T
.SwiftImportAs
);
447 IO
.mapOptional("SwiftReleaseOp", T
.SwiftReleaseOp
);
448 IO
.mapOptional("SwiftRetainOp", T
.SwiftRetainOp
);
449 IO
.mapOptional("EnumExtensibility", T
.EnumExtensibility
);
450 IO
.mapOptional("FlagEnum", T
.FlagEnum
);
451 IO
.mapOptional("EnumKind", T
.EnumConvenienceKind
);
460 AvailabilityItem Availability
;
462 std::optional
<bool> SwiftPrivate
;
463 std::optional
<StringRef
> SwiftBridge
;
464 std::optional
<StringRef
> NSErrorDomain
;
465 std::optional
<SwiftNewTypeKind
> SwiftType
;
468 typedef std::vector
<Typedef
> TypedefsSeq
;
471 LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef
)
475 template <> struct ScalarEnumerationTraits
<SwiftNewTypeKind
> {
476 static void enumeration(IO
&IO
, SwiftNewTypeKind
&SWK
) {
477 IO
.enumCase(SWK
, "none", SwiftNewTypeKind::None
);
478 IO
.enumCase(SWK
, "struct", SwiftNewTypeKind::Struct
);
479 IO
.enumCase(SWK
, "enum", SwiftNewTypeKind::Enum
);
483 template <> struct MappingTraits
<Typedef
> {
484 static void mapping(IO
&IO
, Typedef
&T
) {
485 IO
.mapRequired("Name", T
.Name
);
486 IO
.mapOptional("Availability", T
.Availability
.Mode
,
487 APIAvailability::Available
);
488 IO
.mapOptional("AvailabilityMsg", T
.Availability
.Msg
, StringRef(""));
489 IO
.mapOptional("SwiftPrivate", T
.SwiftPrivate
);
490 IO
.mapOptional("SwiftName", T
.SwiftName
, StringRef(""));
491 IO
.mapOptional("SwiftBridge", T
.SwiftBridge
);
492 IO
.mapOptional("NSErrorDomain", T
.NSErrorDomain
);
493 IO
.mapOptional("SwiftWrapper", T
.SwiftType
);
501 typedef std::vector
<Namespace
> NamespacesSeq
;
503 struct TopLevelItems
{
505 ClassesSeq Protocols
;
506 FunctionsSeq Functions
;
507 GlobalVariablesSeq Globals
;
508 EnumConstantsSeq EnumConstants
;
510 TypedefsSeq Typedefs
;
511 NamespacesSeq Namespaces
;
517 static void mapTopLevelItems(IO
&IO
, TopLevelItems
&TLI
) {
518 IO
.mapOptional("Classes", TLI
.Classes
);
519 IO
.mapOptional("Protocols", TLI
.Protocols
);
520 IO
.mapOptional("Functions", TLI
.Functions
);
521 IO
.mapOptional("Globals", TLI
.Globals
);
522 IO
.mapOptional("Enumerators", TLI
.EnumConstants
);
523 IO
.mapOptional("Tags", TLI
.Tags
);
524 IO
.mapOptional("Typedefs", TLI
.Typedefs
);
525 IO
.mapOptional("Namespaces", TLI
.Namespaces
);
533 AvailabilityItem Availability
;
535 std::optional
<bool> SwiftPrivate
;
540 LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace
)
544 template <> struct MappingTraits
<Namespace
> {
545 static void mapping(IO
&IO
, Namespace
&T
) {
546 IO
.mapRequired("Name", T
.Name
);
547 IO
.mapOptional("Availability", T
.Availability
.Mode
,
548 APIAvailability::Available
);
549 IO
.mapOptional("AvailabilityMsg", T
.Availability
.Msg
, StringRef(""));
550 IO
.mapOptional("SwiftPrivate", T
.SwiftPrivate
);
551 IO
.mapOptional("SwiftName", T
.SwiftName
, StringRef(""));
552 mapTopLevelItems(IO
, T
.Items
);
560 VersionTuple Version
;
564 typedef std::vector
<Versioned
> VersionedSeq
;
567 LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned
)
571 template <> struct MappingTraits
<Versioned
> {
572 static void mapping(IO
&IO
, Versioned
&V
) {
573 IO
.mapRequired("Version", V
.Version
);
574 mapTopLevelItems(IO
, V
.Items
);
583 AvailabilityItem Availability
;
584 TopLevelItems TopLevel
;
585 VersionedSeq SwiftVersions
;
587 std::optional
<bool> SwiftInferImportAsMember
;
589 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
590 LLVM_DUMP_METHOD
void dump() /*const*/;
597 template <> struct MappingTraits
<Module
> {
598 static void mapping(IO
&IO
, Module
&M
) {
599 IO
.mapRequired("Name", M
.Name
);
600 IO
.mapOptional("Availability", M
.Availability
.Mode
,
601 APIAvailability::Available
);
602 IO
.mapOptional("AvailabilityMsg", M
.Availability
.Msg
, StringRef(""));
603 IO
.mapOptional("SwiftInferImportAsMember", M
.SwiftInferImportAsMember
);
604 mapTopLevelItems(IO
, M
.TopLevel
);
605 IO
.mapOptional("SwiftVersions", M
.SwiftVersions
);
611 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
612 LLVM_DUMP_METHOD
void Module::dump() {
613 llvm::yaml::Output
OS(llvm::errs());
619 bool parseAPINotes(StringRef YI
, Module
&M
, llvm::SourceMgr::DiagHandlerTy Diag
,
621 llvm::yaml::Input
IS(YI
, nullptr, Diag
, DiagContext
);
623 return static_cast<bool>(IS
.error());
627 bool clang::api_notes::parseAndDumpAPINotes(StringRef YI
,
628 llvm::raw_ostream
&OS
) {
630 if (parseAPINotes(YI
, M
, nullptr, nullptr))
633 llvm::yaml::Output
YOS(OS
);