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/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" 25 #include <optional> 26 #include <vector> 27 28 using namespace clang; 29 using namespace api_notes; 30 31 namespace { 32 enum class APIAvailability { 33 Available = 0, 34 None, 35 NonSwift, 36 }; 37 } // namespace 38 39 namespace llvm { 40 namespace yaml { 41 template <> struct ScalarEnumerationTraits<APIAvailability> { 42 static void enumeration(IO &IO, APIAvailability &AA) { 43 IO.enumCase(AA, "none", APIAvailability::None); 44 IO.enumCase(AA, "nonswift", APIAvailability::NonSwift); 45 IO.enumCase(AA, "available", APIAvailability::Available); 46 } 47 }; 48 } // namespace yaml 49 } // namespace llvm 50 51 namespace { 52 enum class MethodKind { 53 Class, 54 Instance, 55 }; 56 } // namespace 57 58 namespace llvm { 59 namespace yaml { 60 template <> struct ScalarEnumerationTraits<MethodKind> { 61 static void enumeration(IO &IO, MethodKind &MK) { 62 IO.enumCase(MK, "Class", MethodKind::Class); 63 IO.enumCase(MK, "Instance", MethodKind::Instance); 64 } 65 }; 66 } // namespace yaml 67 } // namespace llvm 68 69 namespace { 70 struct Param { 71 unsigned Position; 72 std::optional<bool> NoEscape = false; 73 std::optional<NullabilityKind> Nullability; 74 std::optional<RetainCountConventionKind> RetainCountConvention; 75 StringRef Type; 76 }; 77 78 typedef std::vector<Param> ParamsSeq; 79 } // namespace 80 81 LLVM_YAML_IS_SEQUENCE_VECTOR(Param) 82 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind) 83 84 namespace llvm { 85 namespace yaml { 86 template <> struct ScalarEnumerationTraits<NullabilityKind> { 87 static void enumeration(IO &IO, NullabilityKind &NK) { 88 IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull); 89 IO.enumCase(NK, "Optional", NullabilityKind::Nullable); 90 IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified); 91 IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult); 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, std::nullopt); 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 std::optional<NullabilityKind> NullabilityOfRet; 154 std::optional<RetainCountConventionKind> RetainCountConvention; 155 AvailabilityItem Availability; 156 std::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, std::nullopt); 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 std::optional<MethodKind> Kind; 205 std::optional<NullabilityKind> Nullability; 206 AvailabilityItem Availability; 207 std::optional<bool> SwiftPrivate; 208 StringRef SwiftName; 209 std::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, std::nullopt); 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 std::optional<bool> SwiftPrivate; 243 StringRef SwiftName; 244 std::optional<StringRef> SwiftBridge; 245 std::optional<StringRef> NSErrorDomain; 246 std::optional<bool> SwiftImportAsNonGeneric; 247 std::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 std::optional<NullabilityKind> NullabilityOfRet; 285 std::optional<api_notes::RetainCountConventionKind> RetainCountConvention; 286 AvailabilityItem Availability; 287 std::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, std::nullopt); 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 std::optional<NullabilityKind> Nullability; 322 AvailabilityItem Availability; 323 std::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, std::nullopt); 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 std::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 std::optional<bool> SwiftPrivate; 414 std::optional<StringRef> SwiftBridge; 415 std::optional<StringRef> NSErrorDomain; 416 std::optional<std::string> SwiftImportAs; 417 std::optional<std::string> SwiftRetainOp; 418 std::optional<std::string> SwiftReleaseOp; 419 std::optional<EnumExtensibilityKind> EnumExtensibility; 420 std::optional<bool> FlagEnum; 421 std::optional<EnumConvenienceAliasKind> EnumConvenienceKind; 422 }; 423 424 typedef std::vector<Tag> TagsSeq; 425 } // namespace 426 427 LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) 428 429 namespace llvm { 430 namespace yaml { 431 template <> struct ScalarEnumerationTraits<EnumExtensibilityKind> { 432 static void enumeration(IO &IO, EnumExtensibilityKind &EEK) { 433 IO.enumCase(EEK, "none", EnumExtensibilityKind::None); 434 IO.enumCase(EEK, "open", EnumExtensibilityKind::Open); 435 IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed); 436 } 437 }; 438 439 template <> struct MappingTraits<Tag> { 440 static void mapping(IO &IO, Tag &T) { 441 IO.mapRequired("Name", T.Name); 442 IO.mapOptional("Availability", T.Availability.Mode, 443 APIAvailability::Available); 444 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 445 IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 446 IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 447 IO.mapOptional("SwiftBridge", T.SwiftBridge); 448 IO.mapOptional("NSErrorDomain", T.NSErrorDomain); 449 IO.mapOptional("SwiftImportAs", T.SwiftImportAs); 450 IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp); 451 IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp); 452 IO.mapOptional("EnumExtensibility", T.EnumExtensibility); 453 IO.mapOptional("FlagEnum", T.FlagEnum); 454 IO.mapOptional("EnumKind", T.EnumConvenienceKind); 455 } 456 }; 457 } // namespace yaml 458 } // namespace llvm 459 460 namespace { 461 struct Typedef { 462 StringRef Name; 463 AvailabilityItem Availability; 464 StringRef SwiftName; 465 std::optional<bool> SwiftPrivate; 466 std::optional<StringRef> SwiftBridge; 467 std::optional<StringRef> NSErrorDomain; 468 std::optional<SwiftNewTypeKind> SwiftType; 469 }; 470 471 typedef std::vector<Typedef> TypedefsSeq; 472 } // namespace 473 474 LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef) 475 476 namespace llvm { 477 namespace yaml { 478 template <> struct ScalarEnumerationTraits<SwiftNewTypeKind> { 479 static void enumeration(IO &IO, SwiftNewTypeKind &SWK) { 480 IO.enumCase(SWK, "none", SwiftNewTypeKind::None); 481 IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct); 482 IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum); 483 } 484 }; 485 486 template <> struct MappingTraits<Typedef> { 487 static void mapping(IO &IO, Typedef &T) { 488 IO.mapRequired("Name", T.Name); 489 IO.mapOptional("Availability", T.Availability.Mode, 490 APIAvailability::Available); 491 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 492 IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 493 IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 494 IO.mapOptional("SwiftBridge", T.SwiftBridge); 495 IO.mapOptional("NSErrorDomain", T.NSErrorDomain); 496 IO.mapOptional("SwiftWrapper", T.SwiftType); 497 } 498 }; 499 } // namespace yaml 500 } // namespace llvm 501 502 namespace { 503 struct Namespace; 504 typedef std::vector<Namespace> NamespacesSeq; 505 506 struct TopLevelItems { 507 ClassesSeq Classes; 508 ClassesSeq Protocols; 509 FunctionsSeq Functions; 510 GlobalVariablesSeq Globals; 511 EnumConstantsSeq EnumConstants; 512 TagsSeq Tags; 513 TypedefsSeq Typedefs; 514 NamespacesSeq Namespaces; 515 }; 516 } // namespace 517 518 namespace llvm { 519 namespace yaml { 520 static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) { 521 IO.mapOptional("Classes", TLI.Classes); 522 IO.mapOptional("Protocols", TLI.Protocols); 523 IO.mapOptional("Functions", TLI.Functions); 524 IO.mapOptional("Globals", TLI.Globals); 525 IO.mapOptional("Enumerators", TLI.EnumConstants); 526 IO.mapOptional("Tags", TLI.Tags); 527 IO.mapOptional("Typedefs", TLI.Typedefs); 528 IO.mapOptional("Namespaces", TLI.Namespaces); 529 } 530 } // namespace yaml 531 } // namespace llvm 532 533 namespace { 534 struct Namespace { 535 StringRef Name; 536 AvailabilityItem Availability; 537 StringRef SwiftName; 538 std::optional<bool> SwiftPrivate; 539 TopLevelItems Items; 540 }; 541 } // namespace 542 543 LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace) 544 545 namespace llvm { 546 namespace yaml { 547 template <> struct MappingTraits<Namespace> { 548 static void mapping(IO &IO, Namespace &T) { 549 IO.mapRequired("Name", T.Name); 550 IO.mapOptional("Availability", T.Availability.Mode, 551 APIAvailability::Available); 552 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 553 IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 554 IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 555 mapTopLevelItems(IO, T.Items); 556 } 557 }; 558 } // namespace yaml 559 } // namespace llvm 560 561 namespace { 562 struct Versioned { 563 VersionTuple Version; 564 TopLevelItems Items; 565 }; 566 567 typedef std::vector<Versioned> VersionedSeq; 568 } // namespace 569 570 LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned) 571 572 namespace llvm { 573 namespace yaml { 574 template <> struct MappingTraits<Versioned> { 575 static void mapping(IO &IO, Versioned &V) { 576 IO.mapRequired("Version", V.Version); 577 mapTopLevelItems(IO, V.Items); 578 } 579 }; 580 } // namespace yaml 581 } // namespace llvm 582 583 namespace { 584 struct Module { 585 StringRef Name; 586 AvailabilityItem Availability; 587 TopLevelItems TopLevel; 588 VersionedSeq SwiftVersions; 589 590 std::optional<bool> SwiftInferImportAsMember; 591 592 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 593 LLVM_DUMP_METHOD void dump() /*const*/; 594 #endif 595 }; 596 } // namespace 597 598 namespace llvm { 599 namespace yaml { 600 template <> struct MappingTraits<Module> { 601 static void mapping(IO &IO, Module &M) { 602 IO.mapRequired("Name", M.Name); 603 IO.mapOptional("Availability", M.Availability.Mode, 604 APIAvailability::Available); 605 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); 606 IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember); 607 mapTopLevelItems(IO, M.TopLevel); 608 IO.mapOptional("SwiftVersions", M.SwiftVersions); 609 } 610 }; 611 } // namespace yaml 612 } // namespace llvm 613 614 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 615 LLVM_DUMP_METHOD void Module::dump() { 616 llvm::yaml::Output OS(llvm::errs()); 617 OS << *this; 618 } 619 #endif 620 621 namespace { 622 bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag, 623 void *DiagContext) { 624 llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext); 625 IS >> M; 626 return static_cast<bool>(IS.error()); 627 } 628 } // namespace 629 630 bool clang::api_notes::parseAndDumpAPINotes(StringRef YI, 631 llvm::raw_ostream &OS) { 632 Module M; 633 if (parseAPINotes(YI, M, nullptr, nullptr)) 634 return true; 635 636 llvm::yaml::Output YOS(OS); 637 YOS << M; 638 639 return false; 640 } 641 642 namespace { 643 using namespace api_notes; 644 645 class YAMLConverter { 646 const Module &M; 647 APINotesWriter Writer; 648 llvm::raw_ostream &OS; 649 llvm::SourceMgr::DiagHandlerTy DiagHandler; 650 void *DiagHandlerCtxt; 651 bool ErrorOccured; 652 653 /// Emit a diagnostic 654 bool emitError(llvm::Twine Message) { 655 DiagHandler( 656 llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()), 657 DiagHandlerCtxt); 658 ErrorOccured = true; 659 return true; 660 } 661 662 public: 663 YAMLConverter(const Module &TheModule, const FileEntry *SourceFile, 664 llvm::raw_ostream &OS, 665 llvm::SourceMgr::DiagHandlerTy DiagHandler, 666 void *DiagHandlerCtxt) 667 : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS), 668 DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt), 669 ErrorOccured(false) {} 670 671 void convertAvailability(const AvailabilityItem &Availability, 672 CommonEntityInfo &CEI, llvm::StringRef APIName) { 673 // Populate the unavailability information. 674 CEI.Unavailable = (Availability.Mode == APIAvailability::None); 675 CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift); 676 if (CEI.Unavailable || CEI.UnavailableInSwift) { 677 CEI.UnavailableMsg = std::string(Availability.Msg); 678 } else { 679 if (!Availability.Msg.empty()) 680 emitError(llvm::Twine("availability message for available API '") + 681 APIName + "' will not be used"); 682 } 683 } 684 685 void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo) { 686 for (const auto &P : Params) { 687 ParamInfo PI; 688 if (P.Nullability) 689 PI.setNullabilityAudited(*P.Nullability); 690 PI.setNoEscape(P.NoEscape); 691 PI.setType(std::string(P.Type)); 692 PI.setRetainCountConvention(P.RetainCountConvention); 693 if (OutInfo.Params.size() <= P.Position) 694 OutInfo.Params.resize(P.Position + 1); 695 OutInfo.Params[P.Position] |= PI; 696 } 697 } 698 699 void convertNullability(const NullabilitySeq &Nullability, 700 std::optional<NullabilityKind> ReturnNullability, 701 FunctionInfo &OutInfo, llvm::StringRef APIName) { 702 if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) { 703 emitError(llvm::Twine("nullability info for '") + APIName + 704 "' does not fit"); 705 return; 706 } 707 708 bool audited = false; 709 unsigned int idx = 1; 710 for (const auto &N : Nullability) 711 OutInfo.addTypeInfo(idx++, N); 712 audited = Nullability.size() > 0 || ReturnNullability; 713 if (audited) 714 OutInfo.addTypeInfo(0, ReturnNullability ? *ReturnNullability 715 : NullabilityKind::NonNull); 716 if (!audited) 717 return; 718 OutInfo.NullabilityAudited = audited; 719 OutInfo.NumAdjustedNullable = idx; 720 } 721 722 /// Convert the common parts of an entity from YAML. 723 template <typename T> 724 void convertCommonEntity(const T &Common, CommonEntityInfo &Info, 725 StringRef APIName) { 726 convertAvailability(Common.Availability, Info, APIName); 727 Info.setSwiftPrivate(Common.SwiftPrivate); 728 Info.SwiftName = std::string(Common.SwiftName); 729 } 730 731 /// Convert the common parts of a type entity from YAML. 732 template <typename T> 733 void convertCommonType(const T &Common, CommonTypeInfo &Info, 734 StringRef APIName) { 735 convertCommonEntity(Common, Info, APIName); 736 if (Common.SwiftBridge) 737 Info.setSwiftBridge(std::string(*Common.SwiftBridge)); 738 Info.setNSErrorDomain(Common.NSErrorDomain); 739 } 740 741 // Translate from Method into ObjCMethodInfo and write it out. 742 void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName, 743 VersionTuple SwiftVersion) { 744 ObjCMethodInfo MI; 745 convertCommonEntity(M, MI, M.Selector); 746 747 // Check if the selector ends with ':' to determine if it takes arguments. 748 bool takesArguments = M.Selector.ends_with(":"); 749 750 // Split the selector into pieces. 751 llvm::SmallVector<StringRef, 4> Args; 752 M.Selector.split(Args, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false); 753 if (!takesArguments && Args.size() > 1) { 754 emitError("selector '" + M.Selector + "' is missing a ':' at the end"); 755 return; 756 } 757 758 // Construct ObjCSelectorRef. 759 api_notes::ObjCSelectorRef Selector; 760 Selector.NumArgs = !takesArguments ? 0 : Args.size(); 761 Selector.Identifiers = Args; 762 763 // Translate the initializer info. 764 MI.DesignatedInit = M.DesignatedInit; 765 MI.RequiredInit = M.Required; 766 if (M.FactoryAsInit != FactoryAsInitKind::Infer) 767 emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead"); 768 769 MI.ResultType = std::string(M.ResultType); 770 771 // Translate parameter information. 772 convertParams(M.Params, MI); 773 774 // Translate nullability info. 775 convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector); 776 777 MI.setRetainCountConvention(M.RetainCountConvention); 778 779 // Write it. 780 Writer.addObjCMethod(ClassID, Selector, M.Kind == MethodKind::Instance, MI, 781 SwiftVersion); 782 } 783 784 void convertContext(std::optional<ContextID> ParentContextID, const Class &C, 785 ContextKind Kind, VersionTuple SwiftVersion) { 786 // Write the class. 787 ObjCContextInfo CI; 788 convertCommonType(C, CI, C.Name); 789 790 if (C.AuditedForNullability) 791 CI.setDefaultNullability(NullabilityKind::NonNull); 792 if (C.SwiftImportAsNonGeneric) 793 CI.setSwiftImportAsNonGeneric(*C.SwiftImportAsNonGeneric); 794 if (C.SwiftObjCMembers) 795 CI.setSwiftObjCMembers(*C.SwiftObjCMembers); 796 797 ContextID CtxID = 798 Writer.addObjCContext(ParentContextID, C.Name, Kind, CI, SwiftVersion); 799 800 // Write all methods. 801 llvm::StringMap<std::pair<bool, bool>> KnownMethods; 802 for (const auto &method : C.Methods) { 803 // Check for duplicate method definitions. 804 bool IsInstanceMethod = method.Kind == MethodKind::Instance; 805 bool &Known = IsInstanceMethod ? KnownMethods[method.Selector].first 806 : KnownMethods[method.Selector].second; 807 if (Known) { 808 emitError(llvm::Twine("duplicate definition of method '") + 809 (IsInstanceMethod ? "-" : "+") + "[" + C.Name + " " + 810 method.Selector + "]'"); 811 continue; 812 } 813 Known = true; 814 815 convertMethod(method, CtxID, C.Name, SwiftVersion); 816 } 817 818 // Write all properties. 819 llvm::StringSet<> KnownInstanceProperties; 820 llvm::StringSet<> KnownClassProperties; 821 for (const auto &Property : C.Properties) { 822 // Check for duplicate property definitions. 823 if ((!Property.Kind || *Property.Kind == MethodKind::Instance) && 824 !KnownInstanceProperties.insert(Property.Name).second) { 825 emitError(llvm::Twine("duplicate definition of instance property '") + 826 C.Name + "." + Property.Name + "'"); 827 continue; 828 } 829 830 if ((!Property.Kind || *Property.Kind == MethodKind::Class) && 831 !KnownClassProperties.insert(Property.Name).second) { 832 emitError(llvm::Twine("duplicate definition of class property '") + 833 C.Name + "." + Property.Name + "'"); 834 continue; 835 } 836 837 // Translate from Property into ObjCPropertyInfo. 838 ObjCPropertyInfo PI; 839 convertAvailability(Property.Availability, PI, Property.Name); 840 PI.setSwiftPrivate(Property.SwiftPrivate); 841 PI.SwiftName = std::string(Property.SwiftName); 842 if (Property.Nullability) 843 PI.setNullabilityAudited(*Property.Nullability); 844 if (Property.SwiftImportAsAccessors) 845 PI.setSwiftImportAsAccessors(*Property.SwiftImportAsAccessors); 846 PI.setType(std::string(Property.Type)); 847 848 // Add both instance and class properties with this name. 849 if (Property.Kind) { 850 Writer.addObjCProperty(CtxID, Property.Name, 851 *Property.Kind == MethodKind::Instance, PI, 852 SwiftVersion); 853 } else { 854 Writer.addObjCProperty(CtxID, Property.Name, true, PI, SwiftVersion); 855 Writer.addObjCProperty(CtxID, Property.Name, false, PI, SwiftVersion); 856 } 857 } 858 } 859 860 void convertNamespaceContext(std::optional<ContextID> ParentContextID, 861 const Namespace &TheNamespace, 862 VersionTuple SwiftVersion) { 863 // Write the namespace. 864 ObjCContextInfo CI; 865 convertCommonEntity(TheNamespace, CI, TheNamespace.Name); 866 867 ContextID CtxID = 868 Writer.addObjCContext(ParentContextID, TheNamespace.Name, 869 ContextKind::Namespace, CI, SwiftVersion); 870 871 convertTopLevelItems(Context(CtxID, ContextKind::Namespace), 872 TheNamespace.Items, SwiftVersion); 873 } 874 875 void convertTopLevelItems(std::optional<Context> Ctx, 876 const TopLevelItems &TLItems, 877 VersionTuple SwiftVersion) { 878 std::optional<ContextID> CtxID = 879 Ctx ? std::optional(Ctx->id) : std::nullopt; 880 881 // Write all classes. 882 llvm::StringSet<> KnownClasses; 883 for (const auto &Class : TLItems.Classes) { 884 // Check for duplicate class definitions. 885 if (!KnownClasses.insert(Class.Name).second) { 886 emitError(llvm::Twine("multiple definitions of class '") + Class.Name + 887 "'"); 888 continue; 889 } 890 891 convertContext(CtxID, Class, ContextKind::ObjCClass, SwiftVersion); 892 } 893 894 // Write all protocols. 895 llvm::StringSet<> KnownProtocols; 896 for (const auto &Protocol : TLItems.Protocols) { 897 // Check for duplicate protocol definitions. 898 if (!KnownProtocols.insert(Protocol.Name).second) { 899 emitError(llvm::Twine("multiple definitions of protocol '") + 900 Protocol.Name + "'"); 901 continue; 902 } 903 904 convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion); 905 } 906 907 // Write all namespaces. 908 llvm::StringSet<> KnownNamespaces; 909 for (const auto &Namespace : TLItems.Namespaces) { 910 // Check for duplicate namespace definitions. 911 if (!KnownNamespaces.insert(Namespace.Name).second) { 912 emitError(llvm::Twine("multiple definitions of namespace '") + 913 Namespace.Name + "'"); 914 continue; 915 } 916 917 convertNamespaceContext(CtxID, Namespace, SwiftVersion); 918 } 919 920 // Write all global variables. 921 llvm::StringSet<> KnownGlobals; 922 for (const auto &Global : TLItems.Globals) { 923 // Check for duplicate global variables. 924 if (!KnownGlobals.insert(Global.Name).second) { 925 emitError(llvm::Twine("multiple definitions of global variable '") + 926 Global.Name + "'"); 927 continue; 928 } 929 930 GlobalVariableInfo GVI; 931 convertAvailability(Global.Availability, GVI, Global.Name); 932 GVI.setSwiftPrivate(Global.SwiftPrivate); 933 GVI.SwiftName = std::string(Global.SwiftName); 934 if (Global.Nullability) 935 GVI.setNullabilityAudited(*Global.Nullability); 936 GVI.setType(std::string(Global.Type)); 937 Writer.addGlobalVariable(Ctx, Global.Name, GVI, SwiftVersion); 938 } 939 940 // Write all global functions. 941 llvm::StringSet<> KnownFunctions; 942 for (const auto &Function : TLItems.Functions) { 943 // Check for duplicate global functions. 944 if (!KnownFunctions.insert(Function.Name).second) { 945 emitError(llvm::Twine("multiple definitions of global function '") + 946 Function.Name + "'"); 947 continue; 948 } 949 950 GlobalFunctionInfo GFI; 951 convertAvailability(Function.Availability, GFI, Function.Name); 952 GFI.setSwiftPrivate(Function.SwiftPrivate); 953 GFI.SwiftName = std::string(Function.SwiftName); 954 convertParams(Function.Params, GFI); 955 convertNullability(Function.Nullability, Function.NullabilityOfRet, GFI, 956 Function.Name); 957 GFI.ResultType = std::string(Function.ResultType); 958 GFI.setRetainCountConvention(Function.RetainCountConvention); 959 Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion); 960 } 961 962 // Write all enumerators. 963 llvm::StringSet<> KnownEnumConstants; 964 for (const auto &EnumConstant : TLItems.EnumConstants) { 965 // Check for duplicate enumerators 966 if (!KnownEnumConstants.insert(EnumConstant.Name).second) { 967 emitError(llvm::Twine("multiple definitions of enumerator '") + 968 EnumConstant.Name + "'"); 969 continue; 970 } 971 972 EnumConstantInfo ECI; 973 convertAvailability(EnumConstant.Availability, ECI, EnumConstant.Name); 974 ECI.setSwiftPrivate(EnumConstant.SwiftPrivate); 975 ECI.SwiftName = std::string(EnumConstant.SwiftName); 976 Writer.addEnumConstant(EnumConstant.Name, ECI, SwiftVersion); 977 } 978 979 // Write all tags. 980 llvm::StringSet<> KnownTags; 981 for (const auto &Tag : TLItems.Tags) { 982 // Check for duplicate tag definitions. 983 if (!KnownTags.insert(Tag.Name).second) { 984 emitError(llvm::Twine("multiple definitions of tag '") + Tag.Name + 985 "'"); 986 continue; 987 } 988 989 TagInfo TI; 990 convertCommonType(Tag, TI, Tag.Name); 991 992 if ((Tag.SwiftRetainOp || Tag.SwiftReleaseOp) && !Tag.SwiftImportAs) { 993 emitError(llvm::Twine("should declare SwiftImportAs to use " 994 "SwiftRetainOp and SwiftReleaseOp (for ") + 995 Tag.Name + ")"); 996 continue; 997 } 998 if (Tag.SwiftReleaseOp.has_value() != Tag.SwiftRetainOp.has_value()) { 999 emitError(llvm::Twine("should declare both SwiftReleaseOp and " 1000 "SwiftRetainOp (for ") + 1001 Tag.Name + ")"); 1002 continue; 1003 } 1004 1005 if (Tag.SwiftImportAs) 1006 TI.SwiftImportAs = Tag.SwiftImportAs; 1007 if (Tag.SwiftRetainOp) 1008 TI.SwiftRetainOp = Tag.SwiftRetainOp; 1009 if (Tag.SwiftReleaseOp) 1010 TI.SwiftReleaseOp = Tag.SwiftReleaseOp; 1011 1012 if (Tag.EnumConvenienceKind) { 1013 if (Tag.EnumExtensibility) { 1014 emitError( 1015 llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") + 1016 Tag.Name + ")"); 1017 continue; 1018 } 1019 if (Tag.FlagEnum) { 1020 emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") + 1021 Tag.Name + ")"); 1022 continue; 1023 } 1024 switch (*Tag.EnumConvenienceKind) { 1025 case EnumConvenienceAliasKind::None: 1026 TI.EnumExtensibility = EnumExtensibilityKind::None; 1027 TI.setFlagEnum(false); 1028 break; 1029 case EnumConvenienceAliasKind::CFEnum: 1030 TI.EnumExtensibility = EnumExtensibilityKind::Open; 1031 TI.setFlagEnum(false); 1032 break; 1033 case EnumConvenienceAliasKind::CFOptions: 1034 TI.EnumExtensibility = EnumExtensibilityKind::Open; 1035 TI.setFlagEnum(true); 1036 break; 1037 case EnumConvenienceAliasKind::CFClosedEnum: 1038 TI.EnumExtensibility = EnumExtensibilityKind::Closed; 1039 TI.setFlagEnum(false); 1040 break; 1041 } 1042 } else { 1043 TI.EnumExtensibility = Tag.EnumExtensibility; 1044 TI.setFlagEnum(Tag.FlagEnum); 1045 } 1046 1047 Writer.addTag(Ctx, Tag.Name, TI, SwiftVersion); 1048 } 1049 1050 // Write all typedefs. 1051 llvm::StringSet<> KnownTypedefs; 1052 for (const auto &Typedef : TLItems.Typedefs) { 1053 // Check for duplicate typedef definitions. 1054 if (!KnownTypedefs.insert(Typedef.Name).second) { 1055 emitError(llvm::Twine("multiple definitions of typedef '") + 1056 Typedef.Name + "'"); 1057 continue; 1058 } 1059 1060 TypedefInfo TInfo; 1061 convertCommonType(Typedef, TInfo, Typedef.Name); 1062 TInfo.SwiftWrapper = Typedef.SwiftType; 1063 1064 Writer.addTypedef(Ctx, Typedef.Name, TInfo, SwiftVersion); 1065 } 1066 } 1067 1068 bool convertModule() { 1069 // Write the top-level items. 1070 convertTopLevelItems(/* context */ std::nullopt, M.TopLevel, 1071 VersionTuple()); 1072 1073 // Convert the versioned information. 1074 for (const auto &Versioned : M.SwiftVersions) 1075 convertTopLevelItems(/* context */ std::nullopt, Versioned.Items, 1076 Versioned.Version); 1077 1078 if (!ErrorOccured) 1079 Writer.writeToStream(OS); 1080 1081 return ErrorOccured; 1082 } 1083 }; 1084 } // namespace 1085 1086 static bool compile(const Module &M, const FileEntry *SourceFile, 1087 llvm::raw_ostream &OS, 1088 llvm::SourceMgr::DiagHandlerTy DiagHandler, 1089 void *DiagHandlerCtxt) { 1090 YAMLConverter C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt); 1091 return C.convertModule(); 1092 } 1093 1094 /// Simple diagnostic handler that prints diagnostics to standard error. 1095 static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context) { 1096 Diag.print(nullptr, llvm::errs()); 1097 } 1098 1099 bool api_notes::compileAPINotes(StringRef YAMLInput, 1100 const FileEntry *SourceFile, 1101 llvm::raw_ostream &OS, 1102 llvm::SourceMgr::DiagHandlerTy DiagHandler, 1103 void *DiagHandlerCtxt) { 1104 Module TheModule; 1105 1106 if (!DiagHandler) 1107 DiagHandler = &printDiagnostic; 1108 1109 if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt)) 1110 return true; 1111 1112 return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt); 1113 } 1114