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