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 <type_traits> 27 #include <vector> 28 29 using namespace clang; 30 using namespace api_notes; 31 32 namespace { 33 enum class APIAvailability { 34 Available = 0, 35 None, 36 NonSwift, 37 }; 38 } // namespace 39 40 namespace llvm { 41 namespace yaml { 42 template <> struct ScalarEnumerationTraits<APIAvailability> { 43 static void enumeration(IO &IO, APIAvailability &AA) { 44 IO.enumCase(AA, "none", APIAvailability::None); 45 IO.enumCase(AA, "nonswift", APIAvailability::NonSwift); 46 IO.enumCase(AA, "available", APIAvailability::Available); 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 int Position; 73 std::optional<bool> NoEscape = false; 74 std::optional<bool> Lifetimebound = false; 75 std::optional<NullabilityKind> Nullability; 76 std::optional<RetainCountConventionKind> RetainCountConvention; 77 StringRef Type; 78 }; 79 80 typedef std::vector<Param> ParamsSeq; 81 } // namespace 82 83 LLVM_YAML_IS_SEQUENCE_VECTOR(Param) 84 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(NullabilityKind) 85 86 namespace llvm { 87 namespace yaml { 88 template <> struct ScalarEnumerationTraits<NullabilityKind> { 89 static void enumeration(IO &IO, NullabilityKind &NK) { 90 IO.enumCase(NK, "Nonnull", NullabilityKind::NonNull); 91 IO.enumCase(NK, "Optional", NullabilityKind::Nullable); 92 IO.enumCase(NK, "Unspecified", NullabilityKind::Unspecified); 93 IO.enumCase(NK, "NullableResult", NullabilityKind::NullableResult); 94 // TODO: Mapping this to it's own value would allow for better cross 95 // checking. Also the default should be Unknown. 96 IO.enumCase(NK, "Scalar", NullabilityKind::Unspecified); 97 98 // Aliases for compatibility with existing APINotes. 99 IO.enumCase(NK, "N", NullabilityKind::NonNull); 100 IO.enumCase(NK, "O", NullabilityKind::Nullable); 101 IO.enumCase(NK, "U", NullabilityKind::Unspecified); 102 IO.enumCase(NK, "S", NullabilityKind::Unspecified); 103 } 104 }; 105 106 template <> struct ScalarEnumerationTraits<RetainCountConventionKind> { 107 static void enumeration(IO &IO, RetainCountConventionKind &RCCK) { 108 IO.enumCase(RCCK, "none", RetainCountConventionKind::None); 109 IO.enumCase(RCCK, "CFReturnsRetained", 110 RetainCountConventionKind::CFReturnsRetained); 111 IO.enumCase(RCCK, "CFReturnsNotRetained", 112 RetainCountConventionKind::CFReturnsNotRetained); 113 IO.enumCase(RCCK, "NSReturnsRetained", 114 RetainCountConventionKind::NSReturnsRetained); 115 IO.enumCase(RCCK, "NSReturnsNotRetained", 116 RetainCountConventionKind::NSReturnsNotRetained); 117 } 118 }; 119 120 template <> struct MappingTraits<Param> { 121 static void mapping(IO &IO, Param &P) { 122 IO.mapRequired("Position", P.Position); 123 IO.mapOptional("Nullability", P.Nullability, std::nullopt); 124 IO.mapOptional("RetainCountConvention", P.RetainCountConvention); 125 IO.mapOptional("NoEscape", P.NoEscape); 126 IO.mapOptional("Lifetimebound", P.Lifetimebound); 127 IO.mapOptional("Type", P.Type, StringRef("")); 128 } 129 }; 130 } // namespace yaml 131 } // namespace llvm 132 133 namespace { 134 typedef std::vector<NullabilityKind> NullabilitySeq; 135 136 struct AvailabilityItem { 137 APIAvailability Mode = APIAvailability::Available; 138 StringRef Msg; 139 }; 140 141 /// Old attribute deprecated in favor of SwiftName. 142 enum class FactoryAsInitKind { 143 /// Infer based on name and type (the default). 144 Infer, 145 /// Treat as a class method. 146 AsClassMethod, 147 /// Treat as an initializer. 148 AsInitializer, 149 }; 150 151 struct Method { 152 StringRef Selector; 153 MethodKind Kind; 154 ParamsSeq Params; 155 NullabilitySeq Nullability; 156 std::optional<NullabilityKind> NullabilityOfRet; 157 std::optional<RetainCountConventionKind> RetainCountConvention; 158 AvailabilityItem Availability; 159 std::optional<bool> SwiftPrivate; 160 StringRef SwiftName; 161 FactoryAsInitKind FactoryAsInit = FactoryAsInitKind::Infer; 162 bool DesignatedInit = false; 163 bool Required = false; 164 StringRef ResultType; 165 StringRef SwiftReturnOwnership; 166 }; 167 168 typedef std::vector<Method> MethodsSeq; 169 } // namespace 170 171 LLVM_YAML_IS_SEQUENCE_VECTOR(Method) 172 173 namespace llvm { 174 namespace yaml { 175 template <> struct ScalarEnumerationTraits<FactoryAsInitKind> { 176 static void enumeration(IO &IO, FactoryAsInitKind &FIK) { 177 IO.enumCase(FIK, "A", FactoryAsInitKind::Infer); 178 IO.enumCase(FIK, "C", FactoryAsInitKind::AsClassMethod); 179 IO.enumCase(FIK, "I", FactoryAsInitKind::AsInitializer); 180 } 181 }; 182 183 template <> struct MappingTraits<Method> { 184 static void mapping(IO &IO, Method &M) { 185 IO.mapRequired("Selector", M.Selector); 186 IO.mapRequired("MethodKind", M.Kind); 187 IO.mapOptional("Parameters", M.Params); 188 IO.mapOptional("Nullability", M.Nullability); 189 IO.mapOptional("NullabilityOfRet", M.NullabilityOfRet, std::nullopt); 190 IO.mapOptional("RetainCountConvention", M.RetainCountConvention); 191 IO.mapOptional("Availability", M.Availability.Mode, 192 APIAvailability::Available); 193 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); 194 IO.mapOptional("SwiftPrivate", M.SwiftPrivate); 195 IO.mapOptional("SwiftName", M.SwiftName, StringRef("")); 196 IO.mapOptional("FactoryAsInit", M.FactoryAsInit, FactoryAsInitKind::Infer); 197 IO.mapOptional("DesignatedInit", M.DesignatedInit, false); 198 IO.mapOptional("Required", M.Required, false); 199 IO.mapOptional("ResultType", M.ResultType, StringRef("")); 200 IO.mapOptional("SwiftReturnOwnership", M.SwiftReturnOwnership, 201 StringRef("")); 202 } 203 }; 204 } // namespace yaml 205 } // namespace llvm 206 207 namespace { 208 struct Property { 209 StringRef Name; 210 std::optional<MethodKind> Kind; 211 std::optional<NullabilityKind> Nullability; 212 AvailabilityItem Availability; 213 std::optional<bool> SwiftPrivate; 214 StringRef SwiftName; 215 std::optional<bool> SwiftImportAsAccessors; 216 StringRef Type; 217 }; 218 219 typedef std::vector<Property> PropertiesSeq; 220 } // namespace 221 222 LLVM_YAML_IS_SEQUENCE_VECTOR(Property) 223 224 namespace llvm { 225 namespace yaml { 226 template <> struct MappingTraits<Property> { 227 static void mapping(IO &IO, Property &P) { 228 IO.mapRequired("Name", P.Name); 229 IO.mapOptional("PropertyKind", P.Kind); 230 IO.mapOptional("Nullability", P.Nullability, std::nullopt); 231 IO.mapOptional("Availability", P.Availability.Mode, 232 APIAvailability::Available); 233 IO.mapOptional("AvailabilityMsg", P.Availability.Msg, StringRef("")); 234 IO.mapOptional("SwiftPrivate", P.SwiftPrivate); 235 IO.mapOptional("SwiftName", P.SwiftName, StringRef("")); 236 IO.mapOptional("SwiftImportAsAccessors", P.SwiftImportAsAccessors); 237 IO.mapOptional("Type", P.Type, StringRef("")); 238 } 239 }; 240 } // namespace yaml 241 } // namespace llvm 242 243 namespace { 244 struct Class { 245 StringRef Name; 246 bool AuditedForNullability = false; 247 AvailabilityItem Availability; 248 std::optional<bool> SwiftPrivate; 249 StringRef SwiftName; 250 std::optional<StringRef> SwiftBridge; 251 std::optional<StringRef> NSErrorDomain; 252 std::optional<bool> SwiftImportAsNonGeneric; 253 std::optional<bool> SwiftObjCMembers; 254 MethodsSeq Methods; 255 PropertiesSeq Properties; 256 }; 257 258 typedef std::vector<Class> ClassesSeq; 259 } // namespace 260 261 LLVM_YAML_IS_SEQUENCE_VECTOR(Class) 262 263 namespace llvm { 264 namespace yaml { 265 template <> struct MappingTraits<Class> { 266 static void mapping(IO &IO, Class &C) { 267 IO.mapRequired("Name", C.Name); 268 IO.mapOptional("AuditedForNullability", C.AuditedForNullability, false); 269 IO.mapOptional("Availability", C.Availability.Mode, 270 APIAvailability::Available); 271 IO.mapOptional("AvailabilityMsg", C.Availability.Msg, StringRef("")); 272 IO.mapOptional("SwiftPrivate", C.SwiftPrivate); 273 IO.mapOptional("SwiftName", C.SwiftName, StringRef("")); 274 IO.mapOptional("SwiftBridge", C.SwiftBridge); 275 IO.mapOptional("NSErrorDomain", C.NSErrorDomain); 276 IO.mapOptional("SwiftImportAsNonGeneric", C.SwiftImportAsNonGeneric); 277 IO.mapOptional("SwiftObjCMembers", C.SwiftObjCMembers); 278 IO.mapOptional("Methods", C.Methods); 279 IO.mapOptional("Properties", C.Properties); 280 } 281 }; 282 } // namespace yaml 283 } // namespace llvm 284 285 namespace { 286 struct Function { 287 StringRef Name; 288 ParamsSeq Params; 289 NullabilitySeq Nullability; 290 std::optional<NullabilityKind> NullabilityOfRet; 291 std::optional<api_notes::RetainCountConventionKind> RetainCountConvention; 292 AvailabilityItem Availability; 293 std::optional<bool> SwiftPrivate; 294 StringRef SwiftName; 295 StringRef Type; 296 StringRef ResultType; 297 StringRef SwiftReturnOwnership; 298 }; 299 300 typedef std::vector<Function> FunctionsSeq; 301 } // namespace 302 303 LLVM_YAML_IS_SEQUENCE_VECTOR(Function) 304 305 namespace llvm { 306 namespace yaml { 307 template <> struct MappingTraits<Function> { 308 static void mapping(IO &IO, Function &F) { 309 IO.mapRequired("Name", F.Name); 310 IO.mapOptional("Parameters", F.Params); 311 IO.mapOptional("Nullability", F.Nullability); 312 IO.mapOptional("NullabilityOfRet", F.NullabilityOfRet, std::nullopt); 313 IO.mapOptional("RetainCountConvention", F.RetainCountConvention); 314 IO.mapOptional("Availability", F.Availability.Mode, 315 APIAvailability::Available); 316 IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef("")); 317 IO.mapOptional("SwiftPrivate", F.SwiftPrivate); 318 IO.mapOptional("SwiftName", F.SwiftName, StringRef("")); 319 IO.mapOptional("ResultType", F.ResultType, StringRef("")); 320 IO.mapOptional("SwiftReturnOwnership", F.SwiftReturnOwnership, 321 StringRef("")); 322 } 323 }; 324 } // namespace yaml 325 } // namespace llvm 326 327 namespace { 328 struct GlobalVariable { 329 StringRef Name; 330 std::optional<NullabilityKind> Nullability; 331 AvailabilityItem Availability; 332 std::optional<bool> SwiftPrivate; 333 StringRef SwiftName; 334 StringRef Type; 335 }; 336 337 typedef std::vector<GlobalVariable> GlobalVariablesSeq; 338 } // namespace 339 340 LLVM_YAML_IS_SEQUENCE_VECTOR(GlobalVariable) 341 342 namespace llvm { 343 namespace yaml { 344 template <> struct MappingTraits<GlobalVariable> { 345 static void mapping(IO &IO, GlobalVariable &GV) { 346 IO.mapRequired("Name", GV.Name); 347 IO.mapOptional("Nullability", GV.Nullability, std::nullopt); 348 IO.mapOptional("Availability", GV.Availability.Mode, 349 APIAvailability::Available); 350 IO.mapOptional("AvailabilityMsg", GV.Availability.Msg, StringRef("")); 351 IO.mapOptional("SwiftPrivate", GV.SwiftPrivate); 352 IO.mapOptional("SwiftName", GV.SwiftName, StringRef("")); 353 IO.mapOptional("Type", GV.Type, StringRef("")); 354 } 355 }; 356 } // namespace yaml 357 } // namespace llvm 358 359 namespace { 360 struct EnumConstant { 361 StringRef Name; 362 AvailabilityItem Availability; 363 std::optional<bool> SwiftPrivate; 364 StringRef SwiftName; 365 }; 366 367 typedef std::vector<EnumConstant> EnumConstantsSeq; 368 } // namespace 369 370 LLVM_YAML_IS_SEQUENCE_VECTOR(EnumConstant) 371 372 namespace llvm { 373 namespace yaml { 374 template <> struct MappingTraits<EnumConstant> { 375 static void mapping(IO &IO, EnumConstant &EC) { 376 IO.mapRequired("Name", EC.Name); 377 IO.mapOptional("Availability", EC.Availability.Mode, 378 APIAvailability::Available); 379 IO.mapOptional("AvailabilityMsg", EC.Availability.Msg, StringRef("")); 380 IO.mapOptional("SwiftPrivate", EC.SwiftPrivate); 381 IO.mapOptional("SwiftName", EC.SwiftName, StringRef("")); 382 } 383 }; 384 } // namespace yaml 385 } // namespace llvm 386 387 namespace { 388 /// Syntactic sugar for EnumExtensibility and FlagEnum 389 enum class EnumConvenienceAliasKind { 390 /// EnumExtensibility: none, FlagEnum: false 391 None, 392 /// EnumExtensibility: open, FlagEnum: false 393 CFEnum, 394 /// EnumExtensibility: open, FlagEnum: true 395 CFOptions, 396 /// EnumExtensibility: closed, FlagEnum: false 397 CFClosedEnum 398 }; 399 } // namespace 400 401 namespace llvm { 402 namespace yaml { 403 template <> struct ScalarEnumerationTraits<EnumConvenienceAliasKind> { 404 static void enumeration(IO &IO, EnumConvenienceAliasKind &ECAK) { 405 IO.enumCase(ECAK, "none", EnumConvenienceAliasKind::None); 406 IO.enumCase(ECAK, "CFEnum", EnumConvenienceAliasKind::CFEnum); 407 IO.enumCase(ECAK, "NSEnum", EnumConvenienceAliasKind::CFEnum); 408 IO.enumCase(ECAK, "CFOptions", EnumConvenienceAliasKind::CFOptions); 409 IO.enumCase(ECAK, "NSOptions", EnumConvenienceAliasKind::CFOptions); 410 IO.enumCase(ECAK, "CFClosedEnum", EnumConvenienceAliasKind::CFClosedEnum); 411 IO.enumCase(ECAK, "NSClosedEnum", EnumConvenienceAliasKind::CFClosedEnum); 412 } 413 }; 414 } // namespace yaml 415 } // namespace llvm 416 417 namespace { 418 struct Field { 419 StringRef Name; 420 std::optional<NullabilityKind> Nullability; 421 AvailabilityItem Availability; 422 std::optional<bool> SwiftPrivate; 423 StringRef SwiftName; 424 StringRef Type; 425 }; 426 427 typedef std::vector<Field> FieldsSeq; 428 } // namespace 429 430 LLVM_YAML_IS_SEQUENCE_VECTOR(Field) 431 432 namespace llvm { 433 namespace yaml { 434 template <> struct MappingTraits<Field> { 435 static void mapping(IO &IO, Field &F) { 436 IO.mapRequired("Name", F.Name); 437 IO.mapOptional("Nullability", F.Nullability, std::nullopt); 438 IO.mapOptional("Availability", F.Availability.Mode, 439 APIAvailability::Available); 440 IO.mapOptional("AvailabilityMsg", F.Availability.Msg, StringRef("")); 441 IO.mapOptional("SwiftPrivate", F.SwiftPrivate); 442 IO.mapOptional("SwiftName", F.SwiftName, StringRef("")); 443 IO.mapOptional("Type", F.Type, StringRef("")); 444 } 445 }; 446 } // namespace yaml 447 } // namespace llvm 448 449 namespace { 450 struct Tag; 451 typedef std::vector<Tag> TagsSeq; 452 453 struct Tag { 454 StringRef Name; 455 AvailabilityItem Availability; 456 StringRef SwiftName; 457 std::optional<bool> SwiftPrivate; 458 std::optional<StringRef> SwiftBridge; 459 std::optional<StringRef> NSErrorDomain; 460 std::optional<std::string> SwiftImportAs; 461 std::optional<std::string> SwiftRetainOp; 462 std::optional<std::string> SwiftReleaseOp; 463 std::optional<std::string> SwiftDefaultOwnership; 464 std::optional<std::string> SwiftConformance; 465 std::optional<EnumExtensibilityKind> EnumExtensibility; 466 std::optional<bool> FlagEnum; 467 std::optional<EnumConvenienceAliasKind> EnumConvenienceKind; 468 std::optional<bool> SwiftCopyable; 469 std::optional<bool> SwiftEscapable; 470 FunctionsSeq Methods; 471 FieldsSeq Fields; 472 473 /// Tags that are declared within the current tag. Only the tags that have 474 /// corresponding API Notes will be listed. 475 TagsSeq Tags; 476 }; 477 } // namespace 478 479 LLVM_YAML_IS_SEQUENCE_VECTOR(Tag) 480 481 namespace llvm { 482 namespace yaml { 483 template <> struct ScalarEnumerationTraits<EnumExtensibilityKind> { 484 static void enumeration(IO &IO, EnumExtensibilityKind &EEK) { 485 IO.enumCase(EEK, "none", EnumExtensibilityKind::None); 486 IO.enumCase(EEK, "open", EnumExtensibilityKind::Open); 487 IO.enumCase(EEK, "closed", EnumExtensibilityKind::Closed); 488 } 489 }; 490 491 template <> struct MappingTraits<Tag> { 492 static void mapping(IO &IO, Tag &T) { 493 IO.mapRequired("Name", T.Name); 494 IO.mapOptional("Availability", T.Availability.Mode, 495 APIAvailability::Available); 496 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 497 IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 498 IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 499 IO.mapOptional("SwiftBridge", T.SwiftBridge); 500 IO.mapOptional("NSErrorDomain", T.NSErrorDomain); 501 IO.mapOptional("SwiftImportAs", T.SwiftImportAs); 502 IO.mapOptional("SwiftReleaseOp", T.SwiftReleaseOp); 503 IO.mapOptional("SwiftRetainOp", T.SwiftRetainOp); 504 IO.mapOptional("SwiftDefaultOwnership", T.SwiftDefaultOwnership); 505 IO.mapOptional("SwiftConformsTo", T.SwiftConformance); 506 IO.mapOptional("EnumExtensibility", T.EnumExtensibility); 507 IO.mapOptional("FlagEnum", T.FlagEnum); 508 IO.mapOptional("EnumKind", T.EnumConvenienceKind); 509 IO.mapOptional("SwiftCopyable", T.SwiftCopyable); 510 IO.mapOptional("SwiftEscapable", T.SwiftEscapable); 511 IO.mapOptional("Methods", T.Methods); 512 IO.mapOptional("Fields", T.Fields); 513 IO.mapOptional("Tags", T.Tags); 514 } 515 }; 516 } // namespace yaml 517 } // namespace llvm 518 519 namespace { 520 struct Typedef { 521 StringRef Name; 522 AvailabilityItem Availability; 523 StringRef SwiftName; 524 std::optional<bool> SwiftPrivate; 525 std::optional<StringRef> SwiftBridge; 526 std::optional<StringRef> NSErrorDomain; 527 std::optional<SwiftNewTypeKind> SwiftType; 528 }; 529 530 typedef std::vector<Typedef> TypedefsSeq; 531 } // namespace 532 533 LLVM_YAML_IS_SEQUENCE_VECTOR(Typedef) 534 535 namespace llvm { 536 namespace yaml { 537 template <> struct ScalarEnumerationTraits<SwiftNewTypeKind> { 538 static void enumeration(IO &IO, SwiftNewTypeKind &SWK) { 539 IO.enumCase(SWK, "none", SwiftNewTypeKind::None); 540 IO.enumCase(SWK, "struct", SwiftNewTypeKind::Struct); 541 IO.enumCase(SWK, "enum", SwiftNewTypeKind::Enum); 542 } 543 }; 544 545 template <> struct MappingTraits<Typedef> { 546 static void mapping(IO &IO, Typedef &T) { 547 IO.mapRequired("Name", T.Name); 548 IO.mapOptional("Availability", T.Availability.Mode, 549 APIAvailability::Available); 550 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 551 IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 552 IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 553 IO.mapOptional("SwiftBridge", T.SwiftBridge); 554 IO.mapOptional("NSErrorDomain", T.NSErrorDomain); 555 IO.mapOptional("SwiftWrapper", T.SwiftType); 556 } 557 }; 558 } // namespace yaml 559 } // namespace llvm 560 561 namespace { 562 struct Namespace; 563 typedef std::vector<Namespace> NamespacesSeq; 564 565 struct TopLevelItems { 566 ClassesSeq Classes; 567 ClassesSeq Protocols; 568 FunctionsSeq Functions; 569 GlobalVariablesSeq Globals; 570 EnumConstantsSeq EnumConstants; 571 TagsSeq Tags; 572 TypedefsSeq Typedefs; 573 NamespacesSeq Namespaces; 574 }; 575 } // namespace 576 577 namespace llvm { 578 namespace yaml { 579 static void mapTopLevelItems(IO &IO, TopLevelItems &TLI) { 580 IO.mapOptional("Classes", TLI.Classes); 581 IO.mapOptional("Protocols", TLI.Protocols); 582 IO.mapOptional("Functions", TLI.Functions); 583 IO.mapOptional("Globals", TLI.Globals); 584 IO.mapOptional("Enumerators", TLI.EnumConstants); 585 IO.mapOptional("Tags", TLI.Tags); 586 IO.mapOptional("Typedefs", TLI.Typedefs); 587 IO.mapOptional("Namespaces", TLI.Namespaces); 588 } 589 } // namespace yaml 590 } // namespace llvm 591 592 namespace { 593 struct Namespace { 594 StringRef Name; 595 AvailabilityItem Availability; 596 StringRef SwiftName; 597 std::optional<bool> SwiftPrivate; 598 TopLevelItems Items; 599 }; 600 } // namespace 601 602 LLVM_YAML_IS_SEQUENCE_VECTOR(Namespace) 603 604 namespace llvm { 605 namespace yaml { 606 template <> struct MappingTraits<Namespace> { 607 static void mapping(IO &IO, Namespace &T) { 608 IO.mapRequired("Name", T.Name); 609 IO.mapOptional("Availability", T.Availability.Mode, 610 APIAvailability::Available); 611 IO.mapOptional("AvailabilityMsg", T.Availability.Msg, StringRef("")); 612 IO.mapOptional("SwiftPrivate", T.SwiftPrivate); 613 IO.mapOptional("SwiftName", T.SwiftName, StringRef("")); 614 mapTopLevelItems(IO, T.Items); 615 } 616 }; 617 } // namespace yaml 618 } // namespace llvm 619 620 namespace { 621 struct Versioned { 622 VersionTuple Version; 623 TopLevelItems Items; 624 }; 625 626 typedef std::vector<Versioned> VersionedSeq; 627 } // namespace 628 629 LLVM_YAML_IS_SEQUENCE_VECTOR(Versioned) 630 631 namespace llvm { 632 namespace yaml { 633 template <> struct MappingTraits<Versioned> { 634 static void mapping(IO &IO, Versioned &V) { 635 IO.mapRequired("Version", V.Version); 636 mapTopLevelItems(IO, V.Items); 637 } 638 }; 639 } // namespace yaml 640 } // namespace llvm 641 642 namespace { 643 struct Module { 644 StringRef Name; 645 AvailabilityItem Availability; 646 TopLevelItems TopLevel; 647 VersionedSeq SwiftVersions; 648 649 std::optional<bool> SwiftInferImportAsMember; 650 651 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 652 LLVM_DUMP_METHOD void dump() /*const*/; 653 #endif 654 }; 655 } // namespace 656 657 namespace llvm { 658 namespace yaml { 659 template <> struct MappingTraits<Module> { 660 static void mapping(IO &IO, Module &M) { 661 IO.mapRequired("Name", M.Name); 662 IO.mapOptional("Availability", M.Availability.Mode, 663 APIAvailability::Available); 664 IO.mapOptional("AvailabilityMsg", M.Availability.Msg, StringRef("")); 665 IO.mapOptional("SwiftInferImportAsMember", M.SwiftInferImportAsMember); 666 mapTopLevelItems(IO, M.TopLevel); 667 IO.mapOptional("SwiftVersions", M.SwiftVersions); 668 } 669 }; 670 } // namespace yaml 671 } // namespace llvm 672 673 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) 674 LLVM_DUMP_METHOD void Module::dump() { 675 llvm::yaml::Output OS(llvm::errs()); 676 OS << *this; 677 } 678 #endif 679 680 namespace { 681 bool parseAPINotes(StringRef YI, Module &M, llvm::SourceMgr::DiagHandlerTy Diag, 682 void *DiagContext) { 683 llvm::yaml::Input IS(YI, nullptr, Diag, DiagContext); 684 IS >> M; 685 return static_cast<bool>(IS.error()); 686 } 687 } // namespace 688 689 bool clang::api_notes::parseAndDumpAPINotes(StringRef YI, 690 llvm::raw_ostream &OS) { 691 Module M; 692 if (parseAPINotes(YI, M, nullptr, nullptr)) 693 return true; 694 695 llvm::yaml::Output YOS(OS); 696 YOS << M; 697 698 return false; 699 } 700 701 namespace { 702 using namespace api_notes; 703 704 class YAMLConverter { 705 const Module &M; 706 APINotesWriter Writer; 707 llvm::raw_ostream &OS; 708 llvm::SourceMgr::DiagHandlerTy DiagHandler; 709 void *DiagHandlerCtxt; 710 bool ErrorOccured; 711 712 /// Emit a diagnostic 713 bool emitError(llvm::Twine Message) { 714 DiagHandler( 715 llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Message.str()), 716 DiagHandlerCtxt); 717 ErrorOccured = true; 718 return true; 719 } 720 721 public: 722 YAMLConverter(const Module &TheModule, const FileEntry *SourceFile, 723 llvm::raw_ostream &OS, 724 llvm::SourceMgr::DiagHandlerTy DiagHandler, 725 void *DiagHandlerCtxt) 726 : M(TheModule), Writer(TheModule.Name, SourceFile), OS(OS), 727 DiagHandler(DiagHandler), DiagHandlerCtxt(DiagHandlerCtxt), 728 ErrorOccured(false) {} 729 730 void convertAvailability(const AvailabilityItem &Availability, 731 CommonEntityInfo &CEI, llvm::StringRef APIName) { 732 // Populate the unavailability information. 733 CEI.Unavailable = (Availability.Mode == APIAvailability::None); 734 CEI.UnavailableInSwift = (Availability.Mode == APIAvailability::NonSwift); 735 if (CEI.Unavailable || CEI.UnavailableInSwift) { 736 CEI.UnavailableMsg = std::string(Availability.Msg); 737 } else { 738 if (!Availability.Msg.empty()) 739 emitError(llvm::Twine("availability message for available API '") + 740 APIName + "' will not be used"); 741 } 742 } 743 744 void convertParams(const ParamsSeq &Params, FunctionInfo &OutInfo, 745 std::optional<ParamInfo> &thisOrSelf) { 746 for (const auto &P : Params) { 747 ParamInfo PI; 748 if (P.Nullability) 749 PI.setNullabilityAudited(*P.Nullability); 750 PI.setNoEscape(P.NoEscape); 751 PI.setLifetimebound(P.Lifetimebound); 752 PI.setType(std::string(P.Type)); 753 PI.setRetainCountConvention(P.RetainCountConvention); 754 if (static_cast<int>(OutInfo.Params.size()) <= P.Position) 755 OutInfo.Params.resize(P.Position + 1); 756 if (P.Position == -1) 757 thisOrSelf = PI; 758 else if (P.Position >= 0) 759 OutInfo.Params[P.Position] |= PI; 760 else 761 emitError("invalid parameter position " + llvm::itostr(P.Position)); 762 } 763 } 764 765 void convertNullability(const NullabilitySeq &Nullability, 766 std::optional<NullabilityKind> ReturnNullability, 767 FunctionInfo &OutInfo, llvm::StringRef APIName) { 768 if (Nullability.size() > FunctionInfo::getMaxNullabilityIndex()) { 769 emitError(llvm::Twine("nullability info for '") + APIName + 770 "' does not fit"); 771 return; 772 } 773 774 bool audited = false; 775 unsigned int idx = 1; 776 for (const auto &N : Nullability) 777 OutInfo.addTypeInfo(idx++, N); 778 audited = Nullability.size() > 0 || ReturnNullability; 779 if (audited) 780 OutInfo.addTypeInfo(0, 781 ReturnNullability.value_or(NullabilityKind::NonNull)); 782 if (!audited) 783 return; 784 OutInfo.NullabilityAudited = audited; 785 OutInfo.NumAdjustedNullable = idx; 786 } 787 788 /// Convert the common parts of an entity from YAML. 789 template <typename T> 790 void convertCommonEntity(const T &Common, CommonEntityInfo &Info, 791 StringRef APIName) { 792 convertAvailability(Common.Availability, Info, APIName); 793 Info.setSwiftPrivate(Common.SwiftPrivate); 794 Info.SwiftName = std::string(Common.SwiftName); 795 } 796 797 /// Convert the common parts of a type entity from YAML. 798 template <typename T> 799 void convertCommonType(const T &Common, CommonTypeInfo &Info, 800 StringRef APIName) { 801 convertCommonEntity(Common, Info, APIName); 802 if (Common.SwiftBridge) 803 Info.setSwiftBridge(std::string(*Common.SwiftBridge)); 804 Info.setNSErrorDomain(Common.NSErrorDomain); 805 } 806 807 // Translate from Method into ObjCMethodInfo and write it out. 808 void convertMethod(const Method &M, ContextID ClassID, StringRef ClassName, 809 VersionTuple SwiftVersion) { 810 ObjCMethodInfo MI; 811 convertCommonEntity(M, MI, M.Selector); 812 813 // Check if the selector ends with ':' to determine if it takes arguments. 814 bool takesArguments = M.Selector.ends_with(":"); 815 816 // Split the selector into pieces. 817 llvm::SmallVector<StringRef, 4> Args; 818 M.Selector.split(Args, ":", /*MaxSplit*/ -1, /*KeepEmpty*/ false); 819 if (!takesArguments && Args.size() > 1) { 820 emitError("selector '" + M.Selector + "' is missing a ':' at the end"); 821 return; 822 } 823 824 // Construct ObjCSelectorRef. 825 api_notes::ObjCSelectorRef Selector; 826 Selector.NumArgs = !takesArguments ? 0 : Args.size(); 827 Selector.Identifiers = Args; 828 829 // Translate the initializer info. 830 MI.DesignatedInit = M.DesignatedInit; 831 MI.RequiredInit = M.Required; 832 if (M.FactoryAsInit != FactoryAsInitKind::Infer) 833 emitError("'FactoryAsInit' is no longer valid; use 'SwiftName' instead"); 834 835 MI.ResultType = std::string(M.ResultType); 836 MI.SwiftReturnOwnership = std::string(M.SwiftReturnOwnership); 837 838 // Translate parameter information. 839 convertParams(M.Params, MI, MI.Self); 840 841 // Translate nullability info. 842 convertNullability(M.Nullability, M.NullabilityOfRet, MI, M.Selector); 843 844 MI.setRetainCountConvention(M.RetainCountConvention); 845 846 // Write it. 847 Writer.addObjCMethod(ClassID, Selector, M.Kind == MethodKind::Instance, MI, 848 SwiftVersion); 849 } 850 851 template <typename T> 852 void convertVariable(const T &Entity, VariableInfo &VI) { 853 convertAvailability(Entity.Availability, VI, Entity.Name); 854 VI.setSwiftPrivate(Entity.SwiftPrivate); 855 VI.SwiftName = std::string(Entity.SwiftName); 856 if (Entity.Nullability) 857 VI.setNullabilityAudited(*Entity.Nullability); 858 VI.setType(std::string(Entity.Type)); 859 } 860 861 void convertContext(std::optional<ContextID> ParentContextID, const Class &C, 862 ContextKind Kind, VersionTuple SwiftVersion) { 863 // Write the class. 864 ContextInfo CI; 865 convertCommonType(C, CI, C.Name); 866 867 if (C.AuditedForNullability) 868 CI.setDefaultNullability(NullabilityKind::NonNull); 869 if (C.SwiftImportAsNonGeneric) 870 CI.setSwiftImportAsNonGeneric(*C.SwiftImportAsNonGeneric); 871 if (C.SwiftObjCMembers) 872 CI.setSwiftObjCMembers(*C.SwiftObjCMembers); 873 874 ContextID CtxID = 875 Writer.addContext(ParentContextID, C.Name, Kind, CI, SwiftVersion); 876 877 // Write all methods. 878 llvm::StringMap<std::pair<bool, bool>> KnownMethods; 879 for (const auto &method : C.Methods) { 880 // Check for duplicate method definitions. 881 bool IsInstanceMethod = method.Kind == MethodKind::Instance; 882 bool &Known = IsInstanceMethod ? KnownMethods[method.Selector].first 883 : KnownMethods[method.Selector].second; 884 if (Known) { 885 emitError(llvm::Twine("duplicate definition of method '") + 886 (IsInstanceMethod ? "-" : "+") + "[" + C.Name + " " + 887 method.Selector + "]'"); 888 continue; 889 } 890 Known = true; 891 892 convertMethod(method, CtxID, C.Name, SwiftVersion); 893 } 894 895 // Write all properties. 896 llvm::StringSet<> KnownInstanceProperties; 897 llvm::StringSet<> KnownClassProperties; 898 for (const auto &Property : C.Properties) { 899 // Check for duplicate property definitions. 900 if ((!Property.Kind || *Property.Kind == MethodKind::Instance) && 901 !KnownInstanceProperties.insert(Property.Name).second) { 902 emitError(llvm::Twine("duplicate definition of instance property '") + 903 C.Name + "." + Property.Name + "'"); 904 continue; 905 } 906 907 if ((!Property.Kind || *Property.Kind == MethodKind::Class) && 908 !KnownClassProperties.insert(Property.Name).second) { 909 emitError(llvm::Twine("duplicate definition of class property '") + 910 C.Name + "." + Property.Name + "'"); 911 continue; 912 } 913 914 // Translate from Property into ObjCPropertyInfo. 915 ObjCPropertyInfo PI; 916 convertVariable(Property, PI); 917 if (Property.SwiftImportAsAccessors) 918 PI.setSwiftImportAsAccessors(*Property.SwiftImportAsAccessors); 919 920 // Add both instance and class properties with this name. 921 if (Property.Kind) { 922 Writer.addObjCProperty(CtxID, Property.Name, 923 *Property.Kind == MethodKind::Instance, PI, 924 SwiftVersion); 925 } else { 926 Writer.addObjCProperty(CtxID, Property.Name, true, PI, SwiftVersion); 927 Writer.addObjCProperty(CtxID, Property.Name, false, PI, SwiftVersion); 928 } 929 } 930 } 931 932 void convertNamespaceContext(std::optional<ContextID> ParentContextID, 933 const Namespace &TheNamespace, 934 VersionTuple SwiftVersion) { 935 // Write the namespace. 936 ContextInfo CI; 937 convertCommonEntity(TheNamespace, CI, TheNamespace.Name); 938 939 ContextID CtxID = 940 Writer.addContext(ParentContextID, TheNamespace.Name, 941 ContextKind::Namespace, CI, SwiftVersion); 942 943 convertTopLevelItems(Context(CtxID, ContextKind::Namespace), 944 TheNamespace.Items, SwiftVersion); 945 } 946 947 template <typename FuncOrMethodInfo> 948 void convertFunction(const Function &Function, FuncOrMethodInfo &FI) { 949 convertAvailability(Function.Availability, FI, Function.Name); 950 FI.setSwiftPrivate(Function.SwiftPrivate); 951 FI.SwiftName = std::string(Function.SwiftName); 952 std::optional<ParamInfo> This; 953 convertParams(Function.Params, FI, This); 954 if constexpr (std::is_same_v<FuncOrMethodInfo, CXXMethodInfo>) 955 FI.This = This; 956 else if (This) 957 emitError("implicit instance parameter is only permitted on C++ and " 958 "Objective-C methods"); 959 convertNullability(Function.Nullability, Function.NullabilityOfRet, FI, 960 Function.Name); 961 FI.ResultType = std::string(Function.ResultType); 962 FI.SwiftReturnOwnership = std::string(Function.SwiftReturnOwnership); 963 FI.setRetainCountConvention(Function.RetainCountConvention); 964 } 965 966 void convertTagContext(std::optional<Context> ParentContext, const Tag &T, 967 VersionTuple SwiftVersion) { 968 TagInfo TI; 969 std::optional<ContextID> ParentContextID = 970 ParentContext ? std::optional<ContextID>(ParentContext->id) 971 : std::nullopt; 972 convertCommonType(T, TI, T.Name); 973 974 if ((T.SwiftRetainOp || T.SwiftReleaseOp) && !T.SwiftImportAs) { 975 emitError(llvm::Twine("should declare SwiftImportAs to use " 976 "SwiftRetainOp and SwiftReleaseOp (for ") + 977 T.Name + ")"); 978 return; 979 } 980 if (T.SwiftReleaseOp.has_value() != T.SwiftRetainOp.has_value()) { 981 emitError(llvm::Twine("should declare both SwiftReleaseOp and " 982 "SwiftRetainOp (for ") + 983 T.Name + ")"); 984 return; 985 } 986 987 if (T.SwiftImportAs) 988 TI.SwiftImportAs = T.SwiftImportAs; 989 if (T.SwiftRetainOp) 990 TI.SwiftRetainOp = T.SwiftRetainOp; 991 if (T.SwiftReleaseOp) 992 TI.SwiftReleaseOp = T.SwiftReleaseOp; 993 if (T.SwiftConformance) 994 TI.SwiftConformance = T.SwiftConformance; 995 if (T.SwiftDefaultOwnership) 996 TI.SwiftDefaultOwnership = T.SwiftDefaultOwnership; 997 998 if (T.SwiftCopyable) 999 TI.setSwiftCopyable(T.SwiftCopyable); 1000 if (T.SwiftEscapable) 1001 TI.setSwiftEscapable(T.SwiftEscapable); 1002 1003 if (T.EnumConvenienceKind) { 1004 if (T.EnumExtensibility) { 1005 emitError( 1006 llvm::Twine("cannot mix EnumKind and EnumExtensibility (for ") + 1007 T.Name + ")"); 1008 return; 1009 } 1010 if (T.FlagEnum) { 1011 emitError(llvm::Twine("cannot mix EnumKind and FlagEnum (for ") + 1012 T.Name + ")"); 1013 return; 1014 } 1015 switch (*T.EnumConvenienceKind) { 1016 case EnumConvenienceAliasKind::None: 1017 TI.EnumExtensibility = EnumExtensibilityKind::None; 1018 TI.setFlagEnum(false); 1019 break; 1020 case EnumConvenienceAliasKind::CFEnum: 1021 TI.EnumExtensibility = EnumExtensibilityKind::Open; 1022 TI.setFlagEnum(false); 1023 break; 1024 case EnumConvenienceAliasKind::CFOptions: 1025 TI.EnumExtensibility = EnumExtensibilityKind::Open; 1026 TI.setFlagEnum(true); 1027 break; 1028 case EnumConvenienceAliasKind::CFClosedEnum: 1029 TI.EnumExtensibility = EnumExtensibilityKind::Closed; 1030 TI.setFlagEnum(false); 1031 break; 1032 } 1033 } else { 1034 TI.EnumExtensibility = T.EnumExtensibility; 1035 TI.setFlagEnum(T.FlagEnum); 1036 } 1037 1038 Writer.addTag(ParentContext, T.Name, TI, SwiftVersion); 1039 1040 ContextInfo CI; 1041 auto TagCtxID = Writer.addContext(ParentContextID, T.Name, ContextKind::Tag, 1042 CI, SwiftVersion); 1043 Context TagCtx(TagCtxID, ContextKind::Tag); 1044 1045 for (const auto &Field : T.Fields) { 1046 FieldInfo FI; 1047 convertVariable(Field, FI); 1048 Writer.addField(TagCtxID, Field.Name, FI, SwiftVersion); 1049 } 1050 1051 for (const auto &CXXMethod : T.Methods) { 1052 CXXMethodInfo MI; 1053 convertFunction(CXXMethod, MI); 1054 Writer.addCXXMethod(TagCtxID, CXXMethod.Name, MI, SwiftVersion); 1055 } 1056 1057 // Convert nested tags. 1058 for (const auto &Tag : T.Tags) 1059 convertTagContext(TagCtx, Tag, SwiftVersion); 1060 } 1061 1062 void convertTopLevelItems(std::optional<Context> Ctx, 1063 const TopLevelItems &TLItems, 1064 VersionTuple SwiftVersion) { 1065 std::optional<ContextID> CtxID = 1066 Ctx ? std::optional(Ctx->id) : std::nullopt; 1067 1068 // Write all classes. 1069 llvm::StringSet<> KnownClasses; 1070 for (const auto &Class : TLItems.Classes) { 1071 // Check for duplicate class definitions. 1072 if (!KnownClasses.insert(Class.Name).second) { 1073 emitError(llvm::Twine("multiple definitions of class '") + Class.Name + 1074 "'"); 1075 continue; 1076 } 1077 1078 convertContext(CtxID, Class, ContextKind::ObjCClass, SwiftVersion); 1079 } 1080 1081 // Write all protocols. 1082 llvm::StringSet<> KnownProtocols; 1083 for (const auto &Protocol : TLItems.Protocols) { 1084 // Check for duplicate protocol definitions. 1085 if (!KnownProtocols.insert(Protocol.Name).second) { 1086 emitError(llvm::Twine("multiple definitions of protocol '") + 1087 Protocol.Name + "'"); 1088 continue; 1089 } 1090 1091 convertContext(CtxID, Protocol, ContextKind::ObjCProtocol, SwiftVersion); 1092 } 1093 1094 // Write all namespaces. 1095 llvm::StringSet<> KnownNamespaces; 1096 for (const auto &Namespace : TLItems.Namespaces) { 1097 // Check for duplicate namespace definitions. 1098 if (!KnownNamespaces.insert(Namespace.Name).second) { 1099 emitError(llvm::Twine("multiple definitions of namespace '") + 1100 Namespace.Name + "'"); 1101 continue; 1102 } 1103 1104 convertNamespaceContext(CtxID, Namespace, SwiftVersion); 1105 } 1106 1107 // Write all global variables. 1108 llvm::StringSet<> KnownGlobals; 1109 for (const auto &Global : TLItems.Globals) { 1110 // Check for duplicate global variables. 1111 if (!KnownGlobals.insert(Global.Name).second) { 1112 emitError(llvm::Twine("multiple definitions of global variable '") + 1113 Global.Name + "'"); 1114 continue; 1115 } 1116 1117 GlobalVariableInfo GVI; 1118 convertVariable(Global, GVI); 1119 Writer.addGlobalVariable(Ctx, Global.Name, GVI, SwiftVersion); 1120 } 1121 1122 // Write all global functions. 1123 llvm::StringSet<> KnownFunctions; 1124 for (const auto &Function : TLItems.Functions) { 1125 // Check for duplicate global functions. 1126 if (!KnownFunctions.insert(Function.Name).second) { 1127 emitError(llvm::Twine("multiple definitions of global function '") + 1128 Function.Name + "'"); 1129 continue; 1130 } 1131 1132 GlobalFunctionInfo GFI; 1133 convertFunction(Function, GFI); 1134 Writer.addGlobalFunction(Ctx, Function.Name, GFI, SwiftVersion); 1135 } 1136 1137 // Write all enumerators. 1138 llvm::StringSet<> KnownEnumConstants; 1139 for (const auto &EnumConstant : TLItems.EnumConstants) { 1140 // Check for duplicate enumerators 1141 if (!KnownEnumConstants.insert(EnumConstant.Name).second) { 1142 emitError(llvm::Twine("multiple definitions of enumerator '") + 1143 EnumConstant.Name + "'"); 1144 continue; 1145 } 1146 1147 EnumConstantInfo ECI; 1148 convertAvailability(EnumConstant.Availability, ECI, EnumConstant.Name); 1149 ECI.setSwiftPrivate(EnumConstant.SwiftPrivate); 1150 ECI.SwiftName = std::string(EnumConstant.SwiftName); 1151 Writer.addEnumConstant(EnumConstant.Name, ECI, SwiftVersion); 1152 } 1153 1154 // Write all tags. 1155 llvm::StringSet<> KnownTags; 1156 for (const auto &Tag : TLItems.Tags) { 1157 // Check for duplicate tag definitions. 1158 if (!KnownTags.insert(Tag.Name).second) { 1159 emitError(llvm::Twine("multiple definitions of tag '") + Tag.Name + 1160 "'"); 1161 continue; 1162 } 1163 1164 convertTagContext(Ctx, Tag, SwiftVersion); 1165 } 1166 1167 // Write all typedefs. 1168 llvm::StringSet<> KnownTypedefs; 1169 for (const auto &Typedef : TLItems.Typedefs) { 1170 // Check for duplicate typedef definitions. 1171 if (!KnownTypedefs.insert(Typedef.Name).second) { 1172 emitError(llvm::Twine("multiple definitions of typedef '") + 1173 Typedef.Name + "'"); 1174 continue; 1175 } 1176 1177 TypedefInfo TInfo; 1178 convertCommonType(Typedef, TInfo, Typedef.Name); 1179 TInfo.SwiftWrapper = Typedef.SwiftType; 1180 1181 Writer.addTypedef(Ctx, Typedef.Name, TInfo, SwiftVersion); 1182 } 1183 } 1184 1185 bool convertModule() { 1186 // Write the top-level items. 1187 convertTopLevelItems(/* context */ std::nullopt, M.TopLevel, 1188 VersionTuple()); 1189 1190 // Convert the versioned information. 1191 for (const auto &Versioned : M.SwiftVersions) 1192 convertTopLevelItems(/* context */ std::nullopt, Versioned.Items, 1193 Versioned.Version); 1194 1195 if (!ErrorOccured) 1196 Writer.writeToStream(OS); 1197 1198 return ErrorOccured; 1199 } 1200 }; 1201 } // namespace 1202 1203 static bool compile(const Module &M, const FileEntry *SourceFile, 1204 llvm::raw_ostream &OS, 1205 llvm::SourceMgr::DiagHandlerTy DiagHandler, 1206 void *DiagHandlerCtxt) { 1207 YAMLConverter C(M, SourceFile, OS, DiagHandler, DiagHandlerCtxt); 1208 return C.convertModule(); 1209 } 1210 1211 /// Simple diagnostic handler that prints diagnostics to standard error. 1212 static void printDiagnostic(const llvm::SMDiagnostic &Diag, void *Context) { 1213 Diag.print(nullptr, llvm::errs()); 1214 } 1215 1216 bool api_notes::compileAPINotes(StringRef YAMLInput, 1217 const FileEntry *SourceFile, 1218 llvm::raw_ostream &OS, 1219 llvm::SourceMgr::DiagHandlerTy DiagHandler, 1220 void *DiagHandlerCtxt) { 1221 Module TheModule; 1222 1223 if (!DiagHandler) 1224 DiagHandler = &printDiagnostic; 1225 1226 if (parseAPINotes(YAMLInput, TheModule, DiagHandler, DiagHandlerCtxt)) 1227 return true; 1228 1229 return compile(TheModule, SourceFile, OS, DiagHandler, DiagHandlerCtxt); 1230 } 1231