1 //===-- APINotesYAMLCompiler.cpp - API Notes YAML Format Reader -*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // The types defined locally are designed to represent the YAML state, which 10 // adds an additional bit of state: e.g. a tri-state boolean attribute (yes, no, 11 // not applied) becomes a tri-state boolean + present. As a result, while these 12 // enumerations appear to be redefining constants from the attributes table 13 // data, they are distinct. 14 // 15 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/ADT/Optional.h" 21 #include "llvm/Support/VersionTuple.h" 22 #include "llvm/Support/YAMLParser.h" 23 #include "llvm/Support/YAMLTraits.h" 24 #include <vector> 25 using namespace clang; 26 using namespace api_notes; 27 28 namespace { 29 enum class APIAvailability { 30 Available = 0, 31 OSX, 32 IOS, 33 None, 34 NonSwift, 35 }; 36 } // namespace 37 38 namespace llvm { 39 namespace yaml { 40 template <> struct ScalarEnumerationTraits<APIAvailability> { 41 static void enumeration(IO &IO, APIAvailability &AA) { 42 IO.enumCase(AA, "OSX", APIAvailability::OSX); 43 IO.enumCase(AA, "iOS", APIAvailability::IOS); 44 IO.enumCase(AA, "none", APIAvailability::None); 45 IO.enumCase(AA, "nonswift", APIAvailability::NonSwift); 46 IO.enumCase(AA, "available", APIAvailability::Available); 47 } 48 }; 49 } // namespace yaml 50 } // namespace llvm 51 52 namespace { 53 enum class MethodKind { 54 Class, 55 Instance, 56 }; 57 } // namespace 58 59 namespace llvm { 60 namespace yaml { 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); 65 } 66 }; 67 } // namespace yaml 68 } // namespace llvm 69 70 namespace { 71 struct Param { 72 unsigned Position; 73 Optional<bool> NoEscape = false; 74 Optional<NullabilityKind> Nullability; 75 Optional<RetainCountConventionKind> RetainCountConvention; 76 StringRef Type; 77 }; 78 79 typedef std::vector<Param> ParamsSeq; 80 } // namespace 81 82 LLVM_YAML_IS_SEQUENCE_VECTOR(Param) 83 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind) 84 85 namespace llvm { 86 namespace yaml { 87 template <> struct ScalarEnumerationTraits<NullabilityKind> { 88 static void enumeration(IO &IO, NullabilityKind &NK) { 89 IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull); 90 IO.enumCase(NK, "Optional", NullabilityKind::Nullable); 91 IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified); 92 // TODO: Mapping this to it's own value would allow for better cross 93 // checking. Also the default should be Unknown. 94 IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified); 95 96 // Aliases for compatibility with existing APINotes. 97 IO.enumCase(NK, "N", NullabilityKind::NonNull); 98 IO.enumCase(NK, "O", NullabilityKind::Nullable); 99 IO.enumCase(NK, "U", NullabilityKind::Unspecified); 100 IO.enumCase(NK, "S", NullabilityKind::Unspecified); 101 } 102 }; 103 104 template <> struct ScalarEnumerationTraits<RetainCountConventionKind> { 105 static void enumeration(IO &IO, RetainCountConventionKind &RCCK) { 106 IO.enumCase(RCCK, "none", RetainCountConventionKind::None); 107 IO.enumCase(RCCK, "CFReturnsRetained", 108 RetainCountConventionKind::CFReturnsRetained); 109 IO.enumCase(RCCK, "CFReturnsNotRetained", 110 RetainCountConventionKind::CFReturnsNotRetained); 111 IO.enumCase(RCCK, "NSReturnsRetained", 112 RetainCountConventionKind::NSReturnsRetained); 113 IO.enumCase(RCCK, "NSReturnsNotRetained", 114 RetainCountConventionKind::NSReturnsNotRetained); 115 } 116 }; 117 118 template <> struct MappingTraits<Param> { 119 static void mapping(IO &IO, Param &P) { 120 IO.mapRequired("Position", P.Position); 121 IO.mapOptional("Nullability", P.Nullability, llvm::None); 122 IO.mapOptional("RetainCountConvention", P.RetainCountConvention); 123 IO.mapOptional("NoEscape", P.NoEscape); 124 IO.mapOptional("Type", P.Type, StringRef("")); 125 } 126 }; 127 } // namespace yaml 128 } // namespace llvm 129 130 namespace { 131 typedef std::vector<NullabilityKind> NullabilitySeq; 132 133 struct AvailabilityItem { 134 APIAvailability Mode = APIAvailability::Available; 135 StringRef Msg; 136 }; 137 138 /// Old attribute deprecated in favor of SwiftName. 139 enum class FactoryAsInitKind { 140 /// Infer based on name and type (the default). 141 Infer, 142 /// Treat as a class method. 143 AsClassMethod, 144 /// Treat as an initializer. 145 AsInitializer, 146 }; 147 148 struct Method { 149 StringRef Selector; 150 MethodKind Kind; 151 ParamsSeq Params; 152 NullabilitySeq Nullability; 153 Optional<NullabilityKind> NullabilityOfRet; 154 Optional<RetainCountConventionKind> RetainCountConvention; 155 AvailabilityItem Availability; 156 Optional<bool> SwiftPrivate; 157 StringRef SwiftName; 158 FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer; 159 bool DesignatedInit = false; 160 bool Required = false; 161 StringRef ResultType; 162 }; 163 164 typedef std::vector<Method> MethodsSeq; 165 } // namespace 166 167 LLVM_YAML_IS_SEQUENCE_VECTOR(Method) 168 169 namespace llvm { 170 namespace yaml { 171 template <> struct ScalarEnumerationTraits<FactoryAsInitKind> { 172 static void enumeration(IO &IO, FactoryAsInitKind &FIK) { 173 IO.enumCase(FIK, "A", FactoryAsInitKind::Infer); 174 IO.enumCase(FIK, "C", FactoryAsInitKind::AsClassMethod); 175 IO.enumCase(FIK, "I", FactoryAsInitKind::AsInitializer); 176 } 177 }; 178 179 template <> struct MappingTraits<Method> { 180 static void mapping(IO &IO, Method &M) { 181 IO.mapRequired("Selector", M.Selector); 182 IO.mapRequired("MethodKind", M.Kind); 183 IO.mapOptional("Parameters", M.Params); 184 IO.mapOptional("Nullability", M.Nullability); 185 IO.mapOptional("NullabilityOfRet", M.NullabilityOfRet, llvm::None); 186 IO.mapOptional("RetainCountConvention", M.RetainCountConvention); 187 IO.mapOptional("Availability", M.Availability.Mode, 188 APIAvailability::Available); 189 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); 190 IO.mapOptional("SwiftPrivate", M.SwiftPrivate); 191 IO.mapOptional("SwiftName", M.SwiftName, StringRef("")); 192 IO.mapOptional("FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer); 193 IO.mapOptional("DesignatedInit", M.DesignatedInit, false); 194 IO.mapOptional("Required", M.Required, false); 195 IO.mapOptional("ResultType", M.ResultType, StringRef("")); 196 } 197 }; 198 } // namespace yaml 199 } // namespace llvm 200 201 namespace { 202 struct Property { 203 StringRef Name; 204 llvm::Optional<MethodKind> Kind; 205 llvm::Optional<NullabilityKind> Nullability; 206 AvailabilityItem Availability; 207 Optional<bool> SwiftPrivate; 208 StringRef SwiftName; 209 Optional<bool> SwiftImportAsAccessors; 210 StringRef Type; 211 }; 212 213 typedef std::vector<Property> PropertiesSeq; 214 } // namespace 215 216 LLVM_YAML_IS_SEQUENCE_VECTOR(Property) 217 218 namespace llvm { 219 namespace yaml { 220 template <> struct MappingTraits<Property> { 221 static void mapping(IO &IO, Property &P) { 222 IO.mapRequired("Name", P.Name); 223 IO.mapOptional("PropertyKind", P.Kind); 224 IO.mapOptional("Nullability", P.Nullability, llvm::None); 225 IO.mapOptional("Availability", P.Availability.Mode, 226 APIAvailability::Available); 227 IO.mapOptional("AvailabilityMsg", P.Availability.Msg, StringRef("")); 228 IO.mapOptional("SwiftPrivate", P.SwiftPrivate); 229 IO.mapOptional("SwiftName", P.SwiftName, StringRef("")); 230 IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors); 231 IO.mapOptional("Type", P.Type, StringRef("")); 232 } 233 }; 234 } // namespace yaml 235 } // namespace llvm 236 237 namespace { 238 struct Class { 239 StringRef Name; 240 bool AuditedForNullability = false; 241 AvailabilityItem Availability; 242 Optional<bool> SwiftPrivate; 243 StringRef SwiftName; 244 Optional<StringRef> SwiftBridge; 245 Optional<StringRef> NSErrorDomain; 246 Optional<bool> SwiftImportAsNonGeneric; 247 Optional<bool> SwiftObjCMembers; 248 MethodsSeq Methods; 249 PropertiesSeq Properties; 250 }; 251 252 typedef std::vector<Class> ClassesSeq; 253 } // namespace 254 255 LLVM_YAML_IS_SEQUENCE_VECTOR(Class) 256 257 namespace llvm { 258 namespace yaml { 259 template <> struct MappingTraits<Class> { 260 static void mapping(IO &IO, Class &C) { 261 IO.mapRequired("Name", C.Name); 262 IO.mapOptional("AuditedForNullability", C.AuditedForNullability, false); 263 IO.mapOptional("Availability", C.Availability.Mode, 264 APIAvailability::Available); 265 IO.mapOptional("AvailabilityMsg", C.Availability.Msg, StringRef("")); 266 IO.mapOptional("SwiftPrivate", C.SwiftPrivate); 267 IO.mapOptional("SwiftName", C.SwiftName, StringRef("")); 268 IO.mapOptional("SwiftBridge", C.SwiftBridge); 269 IO.mapOptional("NSErrorDomain", C.NSErrorDomain); 270 IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric); 271 IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers); 272 IO.mapOptional("Methods", C.Methods); 273 IO.mapOptional("Properties", C.Properties); 274 } 275 }; 276 } // namespace yaml 277 } // namespace llvm 278 279 namespace { 280 struct Function { 281 StringRef Name; 282 ParamsSeq Params; 283 NullabilitySeq Nullability; 284 Optional<NullabilityKind> NullabilityOfRet; 285 Optional<api_notes::RetainCountConventionKind> RetainCountConvention; 286 AvailabilityItem Availability; 287 Optional<bool> SwiftPrivate; 288 StringRef SwiftName; 289 StringRef Type; 290 StringRef ResultType; 291 }; 292 293 typedef std::vector<Function> FunctionsSeq; 294 } // namespace 295 296 LLVM_YAML_IS_SEQUENCE_VECTOR(Function) 297 298 namespace llvm { 299 namespace yaml { 300 template <> struct MappingTraits<Function> { 301 static void mapping(IO &IO, Function &F) { 302 IO.mapRequired("Name", F.Name); 303 IO.mapOptional("Parameters", F.Params); 304 IO.mapOptional("Nullability", F.Nullability); 305 IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, llvm::None); 306 IO.mapOptional("RetainCountConvention", F.RetainCountConvention); 307 IO.mapOptional("Availability", F.Availability.Mode, 308 APIAvailability::Available); 309 IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef("")); 310 IO.mapOptional("SwiftPrivate", F.SwiftPrivate); 311 IO.mapOptional("SwiftName", F.SwiftName, StringRef("")); 312 IO.mapOptional("ResultType", F.ResultType, StringRef("")); 313 } 314 }; 315 } // namespace yaml 316 } // namespace llvm 317 318 namespace { 319 struct GlobalVariable { 320 StringRef Name; 321 llvm::Optional<NullabilityKind> Nullability; 322 AvailabilityItem Availability; 323 Optional<bool> SwiftPrivate; 324 StringRef SwiftName; 325 StringRef Type; 326 }; 327 328 typedef std::vector<GlobalVariable> GlobalVariablesSeq; 329 } // namespace 330 331 LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable) 332 333 namespace llvm { 334 namespace yaml { 335 template <> struct MappingTraits<GlobalVariable> { 336 static void mapping(IO &IO, GlobalVariable &GV) { 337 IO.mapRequired("Name", GV.Name); 338 IO.mapOptional("Nullability", GV.Nullability, llvm::None); 339 IO.mapOptional("Availability", GV.Availability.Mode, 340 APIAvailability::Available); 341 IO.mapOptional("AvailabilityMsg", GV.Availability.Msg, StringRef("")); 342 IO.mapOptional("SwiftPrivate", GV.SwiftPrivate); 343 IO.mapOptional("SwiftName", GV.SwiftName, StringRef("")); 344 IO.mapOptional("Type", GV.Type, StringRef("")); 345 } 346 }; 347 } // namespace yaml 348 } // namespace llvm 349 350 namespace { 351 struct EnumConstant { 352 StringRef Name; 353 AvailabilityItem Availability; 354 Optional<bool> SwiftPrivate; 355 StringRef SwiftName; 356 }; 357 358 typedef std::vector<EnumConstant> EnumConstantsSeq; 359 } // namespace 360 361 LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant) 362 363 namespace llvm { 364 namespace yaml { 365 template <> struct MappingTraits<EnumConstant> { 366 static void mapping(IO &IO, EnumConstant &EC) { 367 IO.mapRequired("Name", EC.Name); 368 IO.mapOptional("Availability", EC.Availability.Mode, 369 APIAvailability::Available); 370 IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef("")); 371 IO.mapOptional("SwiftPrivate", EC.SwiftPrivate); 372 IO.mapOptional("SwiftName", EC.SwiftName, StringRef("")); 373 } 374 }; 375 } // namespace yaml 376 } // namespace llvm 377 378 namespace { 379 /// Syntactic sugar for EnumExtensibility and FlagEnum 380 enum class EnumConvenienceAliasKind { 381 /// EnumExtensibility: none, FlagEnum: false 382 None, 383 /// EnumExtensibility: open, FlagEnum: false 384 CFEnum, 385 /// EnumExtensibility: open, FlagEnum: true 386 CFOptions, 387 /// EnumExtensibility: closed, FlagEnum: false 388 CFClosedEnum 389 }; 390 } // namespace 391 392 namespace llvm { 393 namespace yaml { 394 template <> struct ScalarEnumerationTraits<EnumConvenienceAliasKind> { 395 static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK) { 396 IO.enumCase(ECAK, "none", EnumConvenienceAliasKind::None); 397 IO.enumCase(ECAK, "CFEnum", EnumConvenienceAliasKind::CFEnum); 398 IO.enumCase(ECAK, "NSEnum", EnumConvenienceAliasKind::CFEnum); 399 IO.enumCase(ECAK, "CFOptions", EnumConvenienceAliasKind::CFOptions); 400 IO.enumCase(ECAK, "NSOptions", EnumConvenienceAliasKind::CFOptions); 401 IO.enumCase(ECAK, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum); 402 IO.enumCase(ECAK, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum); 403 } 404 }; 405 } // namespace yaml 406 } // namespace llvm 407 408 namespace { 409 struct Tag { 410 StringRef Name; 411 AvailabilityItem Availability; 412 StringRef SwiftName; 413 Optional<bool> SwiftPrivate; 414 Optional<StringRef> SwiftBridge; 415 Optional<StringRef> NSErrorDomain; 416 Optional<EnumExtensibilityKind> EnumExtensibility; 417 Optional<bool> FlagEnum; 418 Optional<EnumConvenienceAliasKind> EnumConvenienceKind; 419 }; 420 421 typedef std::vector<Tag> TagsSeq; 422 } // namespace 423 424 LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) 425 426 namespace llvm { 427 namespace yaml { 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); 433 } 434 }; 435 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("EnumExtensibility", T.EnumExtensibility); 447 IO.mapOptional("FlagEnum", T.FlagEnum); 448 IO.mapOptional("EnumKind", T.EnumConvenienceKind); 449 } 450 }; 451 } // namespace yaml 452 } // namespace llvm 453 454 namespace { 455 struct Typedef { 456 StringRef Name; 457 AvailabilityItem Availability; 458 StringRef SwiftName; 459 Optional<bool> SwiftPrivate; 460 Optional<StringRef> SwiftBridge; 461 Optional<StringRef> NSErrorDomain; 462 Optional<SwiftNewTypeKind> SwiftType; 463 }; 464 465 typedef std::vector<Typedef> TypedefsSeq; 466 } // namespace 467 468 LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef) 469 470 namespace llvm { 471 namespace yaml { 472 template <> struct ScalarEnumerationTraits<SwiftNewTypeKind> { 473 static void enumeration(IO &IO, SwiftNewTypeKind &SWK) { 474 IO.enumCase(SWK, "none", SwiftNewTypeKind::None); 475 IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct); 476 IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum); 477 } 478 }; 479 480 template <> struct MappingTraits<Typedef> { 481 static void mapping(IO &IO, Typedef &T) { 482 IO.mapRequired("Name", T.Name); 483 IO.mapOptional("Availability", T.Availability.Mode, 484 APIAvailability::Available); 485 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 486 IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 487 IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 488 IO.mapOptional("SwiftBridge", T.SwiftBridge); 489 IO.mapOptional("NSErrorDomain", T.NSErrorDomain); 490 IO.mapOptional("SwiftWrapper", T.SwiftType); 491 } 492 }; 493 } // namespace yaml 494 } // namespace llvm 495 496 namespace { 497 struct TopLevelItems { 498 ClassesSeq Classes; 499 ClassesSeq Protocols; 500 FunctionsSeq Functions; 501 GlobalVariablesSeq Globals; 502 EnumConstantsSeq EnumConstants; 503 TagsSeq Tags; 504 TypedefsSeq Typedefs; 505 }; 506 } // namespace 507 508 namespace llvm { 509 namespace yaml { 510 static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) { 511 IO.mapOptional("Classes", TLI.Classes); 512 IO.mapOptional("Protocols", TLI.Protocols); 513 IO.mapOptional("Functions", TLI.Functions); 514 IO.mapOptional("Globals", TLI.Globals); 515 IO.mapOptional("Enumerators", TLI.EnumConstants); 516 IO.mapOptional("Tags", TLI.Tags); 517 IO.mapOptional("Typedefs", TLI.Typedefs); 518 } 519 } // namespace yaml 520 } // namespace llvm 521 522 namespace { 523 struct Versioned { 524 VersionTuple Version; 525 TopLevelItems Items; 526 }; 527 528 typedef std::vector<Versioned> VersionedSeq; 529 } // namespace 530 531 LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned) 532 533 namespace llvm { 534 namespace yaml { 535 template <> struct MappingTraits<Versioned> { 536 static void mapping(IO &IO, Versioned &V) { 537 IO.mapRequired("Version", V.Version); 538 mapTopLevelItems(IO, V.Items); 539 } 540 }; 541 } // namespace yaml 542 } // namespace llvm 543 544 namespace { 545 struct Module { 546 StringRef Name; 547 AvailabilityItem Availability; 548 TopLevelItems TopLevel; 549 VersionedSeq SwiftVersions; 550 551 llvm::Optional<bool> SwiftInferImportAsMember = {llvm::None}; 552 553 LLVM_DUMP_METHOD void dump() /*const*/; 554 }; 555 } // namespace 556 557 namespace llvm { 558 namespace yaml { 559 template <> struct MappingTraits<Module> { 560 static void mapping(IO &IO, Module &M) { 561 IO.mapRequired("Name", M.Name); 562 IO.mapOptional("Availability", M.Availability.Mode, 563 APIAvailability::Available); 564 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); 565 IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember); 566 mapTopLevelItems(IO, M.TopLevel); 567 IO.mapOptional("SwiftVersions", M.SwiftVersions); 568 } 569 }; 570 } // namespace yaml 571 } // namespace llvm 572 573 void Module::dump() { 574 llvm::yaml::Output OS(llvm::errs()); 575 OS << *this; 576 } 577 578 namespace { 579 bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag, 580 void *DiagContext) { 581 llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext); 582 IS >> M; 583 return static_cast<bool>(IS.error()); 584 } 585 } // namespace 586 587 bool clang::api_notes::parseAndDumpAPINotes(StringRef YI, 588 llvm::raw_ostream &OS) { 589 Module M; 590 if (parseAPINotes(YI, M, nullptr, nullptr)) 591 return true; 592 593 llvm::yaml::Output YOS(OS); 594 YOS << M; 595 596 return false; 597 } 598