1 //===--- APINotesReader.cpp - API Notes 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 // This file implements the \c APINotesReader class that reads source 10 // API notes data providing additional information about source code as 11 // a separate input, such as the non-nil/nilable annotations for 12 // method parameters. 13 // 14 //===----------------------------------------------------------------------===// 15 #include "clang/APINotes/APINotesReader.h" 16 #include "APINotesFormat.h" 17 #include "llvm/ADT/Hashing.h" 18 #include "llvm/ADT/StringExtras.h" 19 #include "llvm/Bitstream/BitstreamReader.h" 20 #include "llvm/Support/DJB.h" 21 #include "llvm/Support/EndianStream.h" 22 #include "llvm/Support/OnDiskHashTable.h" 23 24 namespace clang { 25 namespace api_notes { 26 using namespace llvm::support; 27 28 namespace { 29 /// Deserialize a version tuple. 30 llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) { 31 uint8_t NumVersions = (*Data++) & 0x03; 32 33 unsigned Major = endian::readNext<uint32_t, llvm::endianness::little>(Data); 34 if (NumVersions == 0) 35 return llvm::VersionTuple(Major); 36 37 unsigned Minor = endian::readNext<uint32_t, llvm::endianness::little>(Data); 38 if (NumVersions == 1) 39 return llvm::VersionTuple(Major, Minor); 40 41 unsigned Subminor = 42 endian::readNext<uint32_t, llvm::endianness::little>(Data); 43 if (NumVersions == 2) 44 return llvm::VersionTuple(Major, Minor, Subminor); 45 46 unsigned Build = endian::readNext<uint32_t, llvm::endianness::little>(Data); 47 return llvm::VersionTuple(Major, Minor, Subminor, Build); 48 } 49 50 /// An on-disk hash table whose data is versioned based on the Swift version. 51 template <typename Derived, typename KeyType, typename UnversionedDataType> 52 class VersionedTableInfo { 53 public: 54 using internal_key_type = KeyType; 55 using external_key_type = KeyType; 56 using data_type = 57 llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>; 58 using hash_value_type = size_t; 59 using offset_type = unsigned; 60 61 internal_key_type GetInternalKey(external_key_type Key) { return Key; } 62 63 external_key_type GetExternalKey(internal_key_type Key) { return Key; } 64 65 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { 66 return LHS == RHS; 67 } 68 69 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) { 70 unsigned KeyLength = 71 endian::readNext<uint16_t, llvm::endianness::little>(Data); 72 unsigned DataLength = 73 endian::readNext<uint16_t, llvm::endianness::little>(Data); 74 return {KeyLength, DataLength}; 75 } 76 77 static data_type ReadData(internal_key_type Key, const uint8_t *Data, 78 unsigned Length) { 79 unsigned NumElements = 80 endian::readNext<uint16_t, llvm::endianness::little>(Data); 81 data_type Result; 82 Result.reserve(NumElements); 83 for (unsigned i = 0; i != NumElements; ++i) { 84 auto version = ReadVersionTuple(Data); 85 const auto *DataBefore = Data; 86 (void)DataBefore; 87 auto UnversionedData = Derived::readUnversioned(Key, Data); 88 assert(Data != DataBefore && 89 "Unversioned data reader didn't move pointer"); 90 Result.push_back({version, UnversionedData}); 91 } 92 return Result; 93 } 94 }; 95 96 /// Read serialized CommonEntityInfo. 97 void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) { 98 uint8_t UnavailableBits = *Data++; 99 Info.Unavailable = (UnavailableBits >> 1) & 0x01; 100 Info.UnavailableInSwift = UnavailableBits & 0x01; 101 if ((UnavailableBits >> 2) & 0x01) 102 Info.setSwiftPrivate(static_cast<bool>((UnavailableBits >> 3) & 0x01)); 103 104 unsigned MsgLength = 105 endian::readNext<uint16_t, llvm::endianness::little>(Data); 106 Info.UnavailableMsg = 107 std::string(reinterpret_cast<const char *>(Data), 108 reinterpret_cast<const char *>(Data) + MsgLength); 109 Data += MsgLength; 110 111 unsigned SwiftNameLength = 112 endian::readNext<uint16_t, llvm::endianness::little>(Data); 113 Info.SwiftName = 114 std::string(reinterpret_cast<const char *>(Data), 115 reinterpret_cast<const char *>(Data) + SwiftNameLength); 116 Data += SwiftNameLength; 117 } 118 119 /// Read serialized CommonTypeInfo. 120 void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) { 121 ReadCommonEntityInfo(Data, Info); 122 123 unsigned SwiftBridgeLength = 124 endian::readNext<uint16_t, llvm::endianness::little>(Data); 125 if (SwiftBridgeLength > 0) { 126 Info.setSwiftBridge(std::string(reinterpret_cast<const char *>(Data), 127 SwiftBridgeLength - 1)); 128 Data += SwiftBridgeLength - 1; 129 } 130 131 unsigned ErrorDomainLength = 132 endian::readNext<uint16_t, llvm::endianness::little>(Data); 133 if (ErrorDomainLength > 0) { 134 Info.setNSErrorDomain(std::optional<std::string>(std::string( 135 reinterpret_cast<const char *>(Data), ErrorDomainLength - 1))); 136 Data += ErrorDomainLength - 1; 137 } 138 } 139 140 /// Used to deserialize the on-disk identifier table. 141 class IdentifierTableInfo { 142 public: 143 using internal_key_type = llvm::StringRef; 144 using external_key_type = llvm::StringRef; 145 using data_type = IdentifierID; 146 using hash_value_type = uint32_t; 147 using offset_type = unsigned; 148 149 internal_key_type GetInternalKey(external_key_type Key) { return Key; } 150 151 external_key_type GetExternalKey(internal_key_type Key) { return Key; } 152 153 hash_value_type ComputeHash(internal_key_type Key) { 154 return llvm::djbHash(Key); 155 } 156 157 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { 158 return LHS == RHS; 159 } 160 161 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) { 162 unsigned KeyLength = 163 endian::readNext<uint16_t, llvm::endianness::little>(Data); 164 unsigned DataLength = 165 endian::readNext<uint16_t, llvm::endianness::little>(Data); 166 return {KeyLength, DataLength}; 167 } 168 169 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 170 return llvm::StringRef(reinterpret_cast<const char *>(Data), Length); 171 } 172 173 static data_type ReadData(internal_key_type key, const uint8_t *Data, 174 unsigned Length) { 175 return endian::readNext<uint32_t, llvm::endianness::little>(Data); 176 } 177 }; 178 179 /// Used to deserialize the on-disk table of Objective-C classes and C++ 180 /// namespaces. 181 class ContextIDTableInfo { 182 public: 183 using internal_key_type = ContextTableKey; 184 using external_key_type = internal_key_type; 185 using data_type = unsigned; 186 using hash_value_type = size_t; 187 using offset_type = unsigned; 188 189 internal_key_type GetInternalKey(external_key_type Key) { return Key; } 190 191 external_key_type GetExternalKey(internal_key_type Key) { return Key; } 192 193 hash_value_type ComputeHash(internal_key_type Key) { 194 return static_cast<size_t>(Key.hashValue()); 195 } 196 197 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { 198 return LHS == RHS; 199 } 200 201 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) { 202 unsigned KeyLength = 203 endian::readNext<uint16_t, llvm::endianness::little>(Data); 204 unsigned DataLength = 205 endian::readNext<uint16_t, llvm::endianness::little>(Data); 206 return {KeyLength, DataLength}; 207 } 208 209 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 210 auto ParentCtxID = 211 endian::readNext<uint32_t, llvm::endianness::little>(Data); 212 auto ContextKind = 213 endian::readNext<uint8_t, llvm::endianness::little>(Data); 214 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 215 return {ParentCtxID, ContextKind, NameID}; 216 } 217 218 static data_type ReadData(internal_key_type Key, const uint8_t *Data, 219 unsigned Length) { 220 return endian::readNext<uint32_t, llvm::endianness::little>(Data); 221 } 222 }; 223 224 /// Used to deserialize the on-disk Objective-C property table. 225 class ContextInfoTableInfo 226 : public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> { 227 public: 228 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 229 return endian::readNext<uint32_t, llvm::endianness::little>(Data); 230 } 231 232 hash_value_type ComputeHash(internal_key_type Key) { 233 return static_cast<size_t>(llvm::hash_value(Key)); 234 } 235 236 static ContextInfo readUnversioned(internal_key_type Key, 237 const uint8_t *&Data) { 238 ContextInfo Info; 239 ReadCommonTypeInfo(Data, Info); 240 uint8_t Payload = *Data++; 241 242 if (Payload & 0x01) 243 Info.setHasDesignatedInits(true); 244 Payload = Payload >> 1; 245 246 if (Payload & 0x4) 247 Info.setDefaultNullability(static_cast<NullabilityKind>(Payload & 0x03)); 248 Payload >>= 3; 249 250 if (Payload & (1 << 1)) 251 Info.setSwiftObjCMembers(Payload & 1); 252 Payload >>= 2; 253 254 if (Payload & (1 << 1)) 255 Info.setSwiftImportAsNonGeneric(Payload & 1); 256 257 return Info; 258 } 259 }; 260 261 /// Read serialized VariableInfo. 262 void ReadVariableInfo(const uint8_t *&Data, VariableInfo &Info) { 263 ReadCommonEntityInfo(Data, Info); 264 if (*Data++) { 265 Info.setNullabilityAudited(static_cast<NullabilityKind>(*Data)); 266 } 267 ++Data; 268 269 auto TypeLen = endian::readNext<uint16_t, llvm::endianness::little>(Data); 270 Info.setType(std::string(Data, Data + TypeLen)); 271 Data += TypeLen; 272 } 273 274 /// Used to deserialize the on-disk Objective-C property table. 275 class ObjCPropertyTableInfo 276 : public VersionedTableInfo<ObjCPropertyTableInfo, 277 std::tuple<uint32_t, uint32_t, uint8_t>, 278 ObjCPropertyInfo> { 279 public: 280 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 281 auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 282 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 283 char IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data); 284 return {ClassID, NameID, IsInstance}; 285 } 286 287 hash_value_type ComputeHash(internal_key_type Key) { 288 return static_cast<size_t>(llvm::hash_value(Key)); 289 } 290 291 static ObjCPropertyInfo readUnversioned(internal_key_type Key, 292 const uint8_t *&Data) { 293 ObjCPropertyInfo Info; 294 ReadVariableInfo(Data, Info); 295 uint8_t Flags = *Data++; 296 if (Flags & (1 << 0)) 297 Info.setSwiftImportAsAccessors(Flags & (1 << 1)); 298 return Info; 299 } 300 }; 301 302 /// Read serialized ParamInfo. 303 void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) { 304 ReadVariableInfo(Data, Info); 305 306 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data); 307 if (auto RawConvention = Payload & 0x7) { 308 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1); 309 Info.setRetainCountConvention(Convention); 310 } 311 Payload >>= 3; 312 if (Payload & 0x01) 313 Info.setNoEscape(Payload & 0x02); 314 Payload >>= 2; 315 assert(Payload == 0 && "Bad API notes"); 316 } 317 318 /// Read serialized FunctionInfo. 319 void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) { 320 ReadCommonEntityInfo(Data, Info); 321 322 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data); 323 if (auto RawConvention = Payload & 0x7) { 324 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1); 325 Info.setRetainCountConvention(Convention); 326 } 327 Payload >>= 3; 328 Info.NullabilityAudited = Payload & 0x1; 329 Payload >>= 1; 330 assert(Payload == 0 && "Bad API notes"); 331 332 Info.NumAdjustedNullable = 333 endian::readNext<uint8_t, llvm::endianness::little>(Data); 334 Info.NullabilityPayload = 335 endian::readNext<uint64_t, llvm::endianness::little>(Data); 336 337 unsigned NumParams = 338 endian::readNext<uint16_t, llvm::endianness::little>(Data); 339 while (NumParams > 0) { 340 ParamInfo pi; 341 ReadParamInfo(Data, pi); 342 Info.Params.push_back(pi); 343 --NumParams; 344 } 345 346 unsigned ResultTypeLen = 347 endian::readNext<uint16_t, llvm::endianness::little>(Data); 348 Info.ResultType = std::string(Data, Data + ResultTypeLen); 349 Data += ResultTypeLen; 350 } 351 352 /// Used to deserialize the on-disk Objective-C method table. 353 class ObjCMethodTableInfo 354 : public VersionedTableInfo<ObjCMethodTableInfo, 355 std::tuple<uint32_t, uint32_t, uint8_t>, 356 ObjCMethodInfo> { 357 public: 358 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 359 auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 360 auto SelectorID = 361 endian::readNext<uint32_t, llvm::endianness::little>(Data); 362 auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data); 363 return {ClassID, SelectorID, IsInstance}; 364 } 365 366 hash_value_type ComputeHash(internal_key_type Key) { 367 return static_cast<size_t>(llvm::hash_value(Key)); 368 } 369 370 static ObjCMethodInfo readUnversioned(internal_key_type Key, 371 const uint8_t *&Data) { 372 ObjCMethodInfo Info; 373 uint8_t Payload = *Data++; 374 Info.RequiredInit = Payload & 0x01; 375 Payload >>= 1; 376 Info.DesignatedInit = Payload & 0x01; 377 Payload >>= 1; 378 379 ReadFunctionInfo(Data, Info); 380 return Info; 381 } 382 }; 383 384 /// Used to deserialize the on-disk Objective-C selector table. 385 class ObjCSelectorTableInfo { 386 public: 387 using internal_key_type = StoredObjCSelector; 388 using external_key_type = internal_key_type; 389 using data_type = SelectorID; 390 using hash_value_type = unsigned; 391 using offset_type = unsigned; 392 393 internal_key_type GetInternalKey(external_key_type Key) { return Key; } 394 395 external_key_type GetExternalKey(internal_key_type Key) { return Key; } 396 397 hash_value_type ComputeHash(internal_key_type Key) { 398 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key); 399 } 400 401 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) { 402 return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS); 403 } 404 405 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) { 406 unsigned KeyLength = 407 endian::readNext<uint16_t, llvm::endianness::little>(Data); 408 unsigned DataLength = 409 endian::readNext<uint16_t, llvm::endianness::little>(Data); 410 return {KeyLength, DataLength}; 411 } 412 413 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 414 internal_key_type Key; 415 Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(Data); 416 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t); 417 for (unsigned i = 0; i != NumIdents; ++i) { 418 Key.Identifiers.push_back( 419 endian::readNext<uint32_t, llvm::endianness::little>(Data)); 420 } 421 return Key; 422 } 423 424 static data_type ReadData(internal_key_type Key, const uint8_t *Data, 425 unsigned Length) { 426 return endian::readNext<uint32_t, llvm::endianness::little>(Data); 427 } 428 }; 429 430 /// Used to deserialize the on-disk global variable table. 431 class GlobalVariableTableInfo 432 : public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey, 433 GlobalVariableInfo> { 434 public: 435 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 436 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 437 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 438 return {CtxID, NameID}; 439 } 440 441 hash_value_type ComputeHash(internal_key_type Key) { 442 return static_cast<size_t>(Key.hashValue()); 443 } 444 445 static GlobalVariableInfo readUnversioned(internal_key_type Key, 446 const uint8_t *&Data) { 447 GlobalVariableInfo Info; 448 ReadVariableInfo(Data, Info); 449 return Info; 450 } 451 }; 452 453 /// Used to deserialize the on-disk global function table. 454 class GlobalFunctionTableInfo 455 : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey, 456 GlobalFunctionInfo> { 457 public: 458 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 459 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 460 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 461 return {CtxID, NameID}; 462 } 463 464 hash_value_type ComputeHash(internal_key_type Key) { 465 return static_cast<size_t>(Key.hashValue()); 466 } 467 468 static GlobalFunctionInfo readUnversioned(internal_key_type Key, 469 const uint8_t *&Data) { 470 GlobalFunctionInfo Info; 471 ReadFunctionInfo(Data, Info); 472 return Info; 473 } 474 }; 475 476 /// Used to deserialize the on-disk C++ method table. 477 class CXXMethodTableInfo 478 : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey, 479 CXXMethodInfo> { 480 public: 481 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 482 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 483 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 484 return {CtxID, NameID}; 485 } 486 487 hash_value_type ComputeHash(internal_key_type Key) { 488 return static_cast<size_t>(Key.hashValue()); 489 } 490 491 static CXXMethodInfo readUnversioned(internal_key_type Key, 492 const uint8_t *&Data) { 493 CXXMethodInfo Info; 494 ReadFunctionInfo(Data, Info); 495 return Info; 496 } 497 }; 498 499 /// Used to deserialize the on-disk enumerator table. 500 class EnumConstantTableInfo 501 : public VersionedTableInfo<EnumConstantTableInfo, uint32_t, 502 EnumConstantInfo> { 503 public: 504 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 505 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 506 return NameID; 507 } 508 509 hash_value_type ComputeHash(internal_key_type Key) { 510 return static_cast<size_t>(llvm::hash_value(Key)); 511 } 512 513 static EnumConstantInfo readUnversioned(internal_key_type Key, 514 const uint8_t *&Data) { 515 EnumConstantInfo Info; 516 ReadCommonEntityInfo(Data, Info); 517 return Info; 518 } 519 }; 520 521 /// Used to deserialize the on-disk tag table. 522 class TagTableInfo 523 : public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> { 524 public: 525 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 526 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 527 auto NameID = 528 endian::readNext<IdentifierID, llvm::endianness::little>(Data); 529 return {CtxID, NameID}; 530 } 531 532 hash_value_type ComputeHash(internal_key_type Key) { 533 return static_cast<size_t>(Key.hashValue()); 534 } 535 536 static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) { 537 TagInfo Info; 538 539 uint8_t Payload = *Data++; 540 if (Payload & 1) 541 Info.setFlagEnum(Payload & 2); 542 Payload >>= 2; 543 if (Payload > 0) 544 Info.EnumExtensibility = 545 static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1); 546 547 uint8_t Copyable = 548 endian::readNext<uint8_t, llvm::endianness::little>(Data); 549 if (Copyable == kSwiftNonCopyable) 550 Info.setSwiftCopyable(std::optional(false)); 551 else if (Copyable == kSwiftCopyable) 552 Info.setSwiftCopyable(std::optional(true)); 553 554 unsigned ImportAsLength = 555 endian::readNext<uint16_t, llvm::endianness::little>(Data); 556 if (ImportAsLength > 0) { 557 Info.SwiftImportAs = 558 std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1); 559 Data += ImportAsLength - 1; 560 } 561 unsigned RetainOpLength = 562 endian::readNext<uint16_t, llvm::endianness::little>(Data); 563 if (RetainOpLength > 0) { 564 Info.SwiftRetainOp = 565 std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1); 566 Data += RetainOpLength - 1; 567 } 568 unsigned ReleaseOpLength = 569 endian::readNext<uint16_t, llvm::endianness::little>(Data); 570 if (ReleaseOpLength > 0) { 571 Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data), 572 ReleaseOpLength - 1); 573 Data += ReleaseOpLength - 1; 574 } 575 576 ReadCommonTypeInfo(Data, Info); 577 return Info; 578 } 579 }; 580 581 /// Used to deserialize the on-disk typedef table. 582 class TypedefTableInfo 583 : public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey, 584 TypedefInfo> { 585 public: 586 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) { 587 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data); 588 auto nameID = 589 endian::readNext<IdentifierID, llvm::endianness::little>(Data); 590 return {CtxID, nameID}; 591 } 592 593 hash_value_type ComputeHash(internal_key_type Key) { 594 return static_cast<size_t>(Key.hashValue()); 595 } 596 597 static TypedefInfo readUnversioned(internal_key_type Key, 598 const uint8_t *&Data) { 599 TypedefInfo Info; 600 601 uint8_t Payload = *Data++; 602 if (Payload > 0) 603 Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1); 604 605 ReadCommonTypeInfo(Data, Info); 606 return Info; 607 } 608 }; 609 } // end anonymous namespace 610 611 class APINotesReader::Implementation { 612 public: 613 /// The input buffer for the API notes data. 614 llvm::MemoryBuffer *InputBuffer; 615 616 /// The Swift version to use for filtering. 617 llvm::VersionTuple SwiftVersion; 618 619 /// The name of the module that we read from the control block. 620 std::string ModuleName; 621 622 // The size and modification time of the source file from 623 // which this API notes file was created, if known. 624 std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime; 625 626 using SerializedIdentifierTable = 627 llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>; 628 629 /// The identifier table. 630 std::unique_ptr<SerializedIdentifierTable> IdentifierTable; 631 632 using SerializedContextIDTable = 633 llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>; 634 635 /// The Objective-C / C++ context ID table. 636 std::unique_ptr<SerializedContextIDTable> ContextIDTable; 637 638 using SerializedContextInfoTable = 639 llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>; 640 641 /// The Objective-C context info table. 642 std::unique_ptr<SerializedContextInfoTable> ContextInfoTable; 643 644 using SerializedObjCPropertyTable = 645 llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>; 646 647 /// The Objective-C property table. 648 std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable; 649 650 using SerializedObjCMethodTable = 651 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>; 652 653 /// The Objective-C method table. 654 std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable; 655 656 using SerializedCXXMethodTable = 657 llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>; 658 659 /// The C++ method table. 660 std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable; 661 662 using SerializedObjCSelectorTable = 663 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>; 664 665 /// The Objective-C selector table. 666 std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable; 667 668 using SerializedGlobalVariableTable = 669 llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>; 670 671 /// The global variable table. 672 std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable; 673 674 using SerializedGlobalFunctionTable = 675 llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>; 676 677 /// The global function table. 678 std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable; 679 680 using SerializedEnumConstantTable = 681 llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>; 682 683 /// The enumerator table. 684 std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable; 685 686 using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>; 687 688 /// The tag table. 689 std::unique_ptr<SerializedTagTable> TagTable; 690 691 using SerializedTypedefTable = 692 llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>; 693 694 /// The typedef table. 695 std::unique_ptr<SerializedTypedefTable> TypedefTable; 696 697 /// Retrieve the identifier ID for the given string, or an empty 698 /// optional if the string is unknown. 699 std::optional<IdentifierID> getIdentifier(llvm::StringRef Str); 700 701 /// Retrieve the selector ID for the given selector, or an empty 702 /// optional if the string is unknown. 703 std::optional<SelectorID> getSelector(ObjCSelectorRef Selector); 704 705 bool readControlBlock(llvm::BitstreamCursor &Cursor, 706 llvm::SmallVectorImpl<uint64_t> &Scratch); 707 bool readIdentifierBlock(llvm::BitstreamCursor &Cursor, 708 llvm::SmallVectorImpl<uint64_t> &Scratch); 709 bool readContextBlock(llvm::BitstreamCursor &Cursor, 710 llvm::SmallVectorImpl<uint64_t> &Scratch); 711 bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor, 712 llvm::SmallVectorImpl<uint64_t> &Scratch); 713 bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor, 714 llvm::SmallVectorImpl<uint64_t> &Scratch); 715 bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor, 716 llvm::SmallVectorImpl<uint64_t> &Scratch); 717 bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor, 718 llvm::SmallVectorImpl<uint64_t> &Scratch); 719 bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor, 720 llvm::SmallVectorImpl<uint64_t> &Scratch); 721 bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor, 722 llvm::SmallVectorImpl<uint64_t> &Scratch); 723 bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor, 724 llvm::SmallVectorImpl<uint64_t> &Scratch); 725 bool readTagBlock(llvm::BitstreamCursor &Cursor, 726 llvm::SmallVectorImpl<uint64_t> &Scratch); 727 bool readTypedefBlock(llvm::BitstreamCursor &Cursor, 728 llvm::SmallVectorImpl<uint64_t> &Scratch); 729 }; 730 731 std::optional<IdentifierID> 732 APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) { 733 if (!IdentifierTable) 734 return std::nullopt; 735 736 if (Str.empty()) 737 return IdentifierID(0); 738 739 auto Known = IdentifierTable->find(Str); 740 if (Known == IdentifierTable->end()) 741 return std::nullopt; 742 743 return *Known; 744 } 745 746 std::optional<SelectorID> 747 APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) { 748 if (!ObjCSelectorTable || !IdentifierTable) 749 return std::nullopt; 750 751 // Translate the identifiers. 752 StoredObjCSelector Key; 753 Key.NumArgs = Selector.NumArgs; 754 for (auto Ident : Selector.Identifiers) { 755 if (auto IdentID = getIdentifier(Ident)) { 756 Key.Identifiers.push_back(*IdentID); 757 } else { 758 return std::nullopt; 759 } 760 } 761 762 auto Known = ObjCSelectorTable->find(Key); 763 if (Known == ObjCSelectorTable->end()) 764 return std::nullopt; 765 766 return *Known; 767 } 768 769 bool APINotesReader::Implementation::readControlBlock( 770 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 771 if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID)) 772 return true; 773 774 bool SawMetadata = false; 775 776 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 777 if (!MaybeNext) { 778 // FIXME this drops the error on the floor. 779 consumeError(MaybeNext.takeError()); 780 return false; 781 } 782 llvm::BitstreamEntry Next = MaybeNext.get(); 783 784 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 785 if (Next.Kind == llvm::BitstreamEntry::Error) 786 return true; 787 788 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 789 // Unknown metadata sub-block, possibly for use by a future version of the 790 // API notes format. 791 if (Cursor.SkipBlock()) 792 return true; 793 794 MaybeNext = Cursor.advance(); 795 if (!MaybeNext) { 796 // FIXME this drops the error on the floor. 797 consumeError(MaybeNext.takeError()); 798 return false; 799 } 800 Next = MaybeNext.get(); 801 continue; 802 } 803 804 Scratch.clear(); 805 llvm::StringRef BlobData; 806 llvm::Expected<unsigned> MaybeKind = 807 Cursor.readRecord(Next.ID, Scratch, &BlobData); 808 if (!MaybeKind) { 809 // FIXME this drops the error on the floor. 810 consumeError(MaybeKind.takeError()); 811 return false; 812 } 813 unsigned Kind = MaybeKind.get(); 814 815 switch (Kind) { 816 case control_block::METADATA: 817 // Already saw metadata. 818 if (SawMetadata) 819 return true; 820 821 if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR) 822 return true; 823 824 SawMetadata = true; 825 break; 826 827 case control_block::MODULE_NAME: 828 ModuleName = BlobData.str(); 829 break; 830 831 case control_block::MODULE_OPTIONS: 832 break; 833 834 case control_block::SOURCE_FILE: 835 SourceFileSizeAndModTime = {Scratch[0], Scratch[1]}; 836 break; 837 838 default: 839 // Unknown metadata record, possibly for use by a future version of the 840 // module format. 841 break; 842 } 843 844 MaybeNext = Cursor.advance(); 845 if (!MaybeNext) { 846 // FIXME this drops the error on the floor. 847 consumeError(MaybeNext.takeError()); 848 return false; 849 } 850 Next = MaybeNext.get(); 851 } 852 853 return !SawMetadata; 854 } 855 856 bool APINotesReader::Implementation::readIdentifierBlock( 857 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 858 if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID)) 859 return true; 860 861 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 862 if (!MaybeNext) { 863 // FIXME this drops the error on the floor. 864 consumeError(MaybeNext.takeError()); 865 return false; 866 } 867 llvm::BitstreamEntry Next = MaybeNext.get(); 868 869 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 870 if (Next.Kind == llvm::BitstreamEntry::Error) 871 return true; 872 873 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 874 // Unknown sub-block, possibly for use by a future version of the 875 // API notes format. 876 if (Cursor.SkipBlock()) 877 return true; 878 879 MaybeNext = Cursor.advance(); 880 if (!MaybeNext) { 881 // FIXME this drops the error on the floor. 882 consumeError(MaybeNext.takeError()); 883 return false; 884 } 885 Next = MaybeNext.get(); 886 continue; 887 } 888 889 Scratch.clear(); 890 llvm::StringRef BlobData; 891 llvm::Expected<unsigned> MaybeKind = 892 Cursor.readRecord(Next.ID, Scratch, &BlobData); 893 if (!MaybeKind) { 894 // FIXME this drops the error on the floor. 895 consumeError(MaybeKind.takeError()); 896 return false; 897 } 898 unsigned Kind = MaybeKind.get(); 899 switch (Kind) { 900 case identifier_block::IDENTIFIER_DATA: { 901 // Already saw identifier table. 902 if (IdentifierTable) 903 return true; 904 905 uint32_t tableOffset; 906 identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset); 907 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 908 909 IdentifierTable.reset(SerializedIdentifierTable::Create( 910 base + tableOffset, base + sizeof(uint32_t), base)); 911 break; 912 } 913 914 default: 915 // Unknown record, possibly for use by a future version of the 916 // module format. 917 break; 918 } 919 920 MaybeNext = Cursor.advance(); 921 if (!MaybeNext) { 922 // FIXME this drops the error on the floor. 923 consumeError(MaybeNext.takeError()); 924 return false; 925 } 926 Next = MaybeNext.get(); 927 } 928 929 return false; 930 } 931 932 bool APINotesReader::Implementation::readContextBlock( 933 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 934 if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID)) 935 return true; 936 937 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 938 if (!MaybeNext) { 939 // FIXME this drops the error on the floor. 940 consumeError(MaybeNext.takeError()); 941 return false; 942 } 943 llvm::BitstreamEntry Next = MaybeNext.get(); 944 945 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 946 if (Next.Kind == llvm::BitstreamEntry::Error) 947 return true; 948 949 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 950 // Unknown sub-block, possibly for use by a future version of the 951 // API notes format. 952 if (Cursor.SkipBlock()) 953 return true; 954 955 MaybeNext = Cursor.advance(); 956 if (!MaybeNext) { 957 // FIXME this drops the error on the floor. 958 consumeError(MaybeNext.takeError()); 959 return false; 960 } 961 Next = MaybeNext.get(); 962 continue; 963 } 964 965 Scratch.clear(); 966 llvm::StringRef BlobData; 967 llvm::Expected<unsigned> MaybeKind = 968 Cursor.readRecord(Next.ID, Scratch, &BlobData); 969 if (!MaybeKind) { 970 // FIXME this drops the error on the floor. 971 consumeError(MaybeKind.takeError()); 972 return false; 973 } 974 unsigned Kind = MaybeKind.get(); 975 switch (Kind) { 976 case context_block::CONTEXT_ID_DATA: { 977 // Already saw Objective-C / C++ context ID table. 978 if (ContextIDTable) 979 return true; 980 981 uint32_t tableOffset; 982 context_block::ContextIDLayout::readRecord(Scratch, tableOffset); 983 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 984 985 ContextIDTable.reset(SerializedContextIDTable::Create( 986 base + tableOffset, base + sizeof(uint32_t), base)); 987 break; 988 } 989 990 case context_block::CONTEXT_INFO_DATA: { 991 // Already saw Objective-C / C++ context info table. 992 if (ContextInfoTable) 993 return true; 994 995 uint32_t tableOffset; 996 context_block::ContextInfoLayout::readRecord(Scratch, tableOffset); 997 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 998 999 ContextInfoTable.reset(SerializedContextInfoTable::Create( 1000 base + tableOffset, base + sizeof(uint32_t), base)); 1001 break; 1002 } 1003 1004 default: 1005 // Unknown record, possibly for use by a future version of the 1006 // module format. 1007 break; 1008 } 1009 1010 MaybeNext = Cursor.advance(); 1011 if (!MaybeNext) { 1012 // FIXME this drops the error on the floor. 1013 consumeError(MaybeNext.takeError()); 1014 return false; 1015 } 1016 Next = MaybeNext.get(); 1017 } 1018 1019 return false; 1020 } 1021 1022 bool APINotesReader::Implementation::readObjCPropertyBlock( 1023 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1024 if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID)) 1025 return true; 1026 1027 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1028 if (!MaybeNext) { 1029 // FIXME this drops the error on the floor. 1030 consumeError(MaybeNext.takeError()); 1031 return false; 1032 } 1033 llvm::BitstreamEntry Next = MaybeNext.get(); 1034 1035 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1036 if (Next.Kind == llvm::BitstreamEntry::Error) 1037 return true; 1038 1039 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1040 // Unknown sub-block, possibly for use by a future version of the 1041 // API notes format. 1042 if (Cursor.SkipBlock()) 1043 return true; 1044 1045 MaybeNext = Cursor.advance(); 1046 if (!MaybeNext) { 1047 // FIXME this drops the error on the floor. 1048 consumeError(MaybeNext.takeError()); 1049 return false; 1050 } 1051 Next = MaybeNext.get(); 1052 continue; 1053 } 1054 1055 Scratch.clear(); 1056 llvm::StringRef BlobData; 1057 llvm::Expected<unsigned> MaybeKind = 1058 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1059 if (!MaybeKind) { 1060 // FIXME this drops the error on the floor. 1061 consumeError(MaybeKind.takeError()); 1062 return false; 1063 } 1064 unsigned Kind = MaybeKind.get(); 1065 switch (Kind) { 1066 case objc_property_block::OBJC_PROPERTY_DATA: { 1067 // Already saw Objective-C property table. 1068 if (ObjCPropertyTable) 1069 return true; 1070 1071 uint32_t tableOffset; 1072 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch, 1073 tableOffset); 1074 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1075 1076 ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create( 1077 base + tableOffset, base + sizeof(uint32_t), base)); 1078 break; 1079 } 1080 1081 default: 1082 // Unknown record, possibly for use by a future version of the 1083 // module format. 1084 break; 1085 } 1086 1087 MaybeNext = Cursor.advance(); 1088 if (!MaybeNext) { 1089 // FIXME this drops the error on the floor. 1090 consumeError(MaybeNext.takeError()); 1091 return false; 1092 } 1093 Next = MaybeNext.get(); 1094 } 1095 1096 return false; 1097 } 1098 1099 bool APINotesReader::Implementation::readObjCMethodBlock( 1100 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1101 if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID)) 1102 return true; 1103 1104 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1105 if (!MaybeNext) { 1106 // FIXME this drops the error on the floor. 1107 consumeError(MaybeNext.takeError()); 1108 return false; 1109 } 1110 llvm::BitstreamEntry Next = MaybeNext.get(); 1111 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1112 if (Next.Kind == llvm::BitstreamEntry::Error) 1113 return true; 1114 1115 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1116 // Unknown sub-block, possibly for use by a future version of the 1117 // API notes format. 1118 if (Cursor.SkipBlock()) 1119 return true; 1120 1121 MaybeNext = Cursor.advance(); 1122 if (!MaybeNext) { 1123 // FIXME this drops the error on the floor. 1124 consumeError(MaybeNext.takeError()); 1125 return false; 1126 } 1127 Next = MaybeNext.get(); 1128 continue; 1129 } 1130 1131 Scratch.clear(); 1132 llvm::StringRef BlobData; 1133 llvm::Expected<unsigned> MaybeKind = 1134 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1135 if (!MaybeKind) { 1136 // FIXME this drops the error on the floor. 1137 consumeError(MaybeKind.takeError()); 1138 return false; 1139 } 1140 unsigned Kind = MaybeKind.get(); 1141 switch (Kind) { 1142 case objc_method_block::OBJC_METHOD_DATA: { 1143 // Already saw Objective-C method table. 1144 if (ObjCMethodTable) 1145 return true; 1146 1147 uint32_t tableOffset; 1148 objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset); 1149 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1150 1151 ObjCMethodTable.reset(SerializedObjCMethodTable::Create( 1152 base + tableOffset, base + sizeof(uint32_t), base)); 1153 break; 1154 } 1155 1156 default: 1157 // Unknown record, possibly for use by a future version of the 1158 // module format. 1159 break; 1160 } 1161 1162 MaybeNext = Cursor.advance(); 1163 if (!MaybeNext) { 1164 // FIXME this drops the error on the floor. 1165 consumeError(MaybeNext.takeError()); 1166 return false; 1167 } 1168 Next = MaybeNext.get(); 1169 } 1170 1171 return false; 1172 } 1173 1174 bool APINotesReader::Implementation::readCXXMethodBlock( 1175 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1176 if (Cursor.EnterSubBlock(CXX_METHOD_BLOCK_ID)) 1177 return true; 1178 1179 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1180 if (!MaybeNext) { 1181 // FIXME this drops the error on the floor. 1182 consumeError(MaybeNext.takeError()); 1183 return false; 1184 } 1185 llvm::BitstreamEntry Next = MaybeNext.get(); 1186 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1187 if (Next.Kind == llvm::BitstreamEntry::Error) 1188 return true; 1189 1190 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1191 // Unknown sub-block, possibly for use by a future version of the 1192 // API notes format. 1193 if (Cursor.SkipBlock()) 1194 return true; 1195 1196 MaybeNext = Cursor.advance(); 1197 if (!MaybeNext) { 1198 // FIXME this drops the error on the floor. 1199 consumeError(MaybeNext.takeError()); 1200 return false; 1201 } 1202 Next = MaybeNext.get(); 1203 continue; 1204 } 1205 1206 Scratch.clear(); 1207 llvm::StringRef BlobData; 1208 llvm::Expected<unsigned> MaybeKind = 1209 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1210 if (!MaybeKind) { 1211 // FIXME this drops the error on the floor. 1212 consumeError(MaybeKind.takeError()); 1213 return false; 1214 } 1215 unsigned Kind = MaybeKind.get(); 1216 switch (Kind) { 1217 case cxx_method_block::CXX_METHOD_DATA: { 1218 // Already saw C++ method table. 1219 if (CXXMethodTable) 1220 return true; 1221 1222 uint32_t tableOffset; 1223 cxx_method_block::CXXMethodDataLayout::readRecord(Scratch, tableOffset); 1224 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1225 1226 CXXMethodTable.reset(SerializedCXXMethodTable::Create( 1227 base + tableOffset, base + sizeof(uint32_t), base)); 1228 break; 1229 } 1230 1231 default: 1232 // Unknown record, possibly for use by a future version of the 1233 // module format. 1234 break; 1235 } 1236 1237 MaybeNext = Cursor.advance(); 1238 if (!MaybeNext) { 1239 // FIXME this drops the error on the floor. 1240 consumeError(MaybeNext.takeError()); 1241 return false; 1242 } 1243 Next = MaybeNext.get(); 1244 } 1245 1246 return false; 1247 } 1248 1249 bool APINotesReader::Implementation::readObjCSelectorBlock( 1250 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1251 if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID)) 1252 return true; 1253 1254 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1255 if (!MaybeNext) { 1256 // FIXME this drops the error on the floor. 1257 consumeError(MaybeNext.takeError()); 1258 return false; 1259 } 1260 llvm::BitstreamEntry Next = MaybeNext.get(); 1261 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1262 if (Next.Kind == llvm::BitstreamEntry::Error) 1263 return true; 1264 1265 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1266 // Unknown sub-block, possibly for use by a future version of the 1267 // API notes format. 1268 if (Cursor.SkipBlock()) 1269 return true; 1270 1271 MaybeNext = Cursor.advance(); 1272 if (!MaybeNext) { 1273 // FIXME this drops the error on the floor. 1274 consumeError(MaybeNext.takeError()); 1275 return false; 1276 } 1277 Next = MaybeNext.get(); 1278 continue; 1279 } 1280 1281 Scratch.clear(); 1282 llvm::StringRef BlobData; 1283 llvm::Expected<unsigned> MaybeKind = 1284 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1285 if (!MaybeKind) { 1286 // FIXME this drops the error on the floor. 1287 consumeError(MaybeKind.takeError()); 1288 return false; 1289 } 1290 unsigned Kind = MaybeKind.get(); 1291 switch (Kind) { 1292 case objc_selector_block::OBJC_SELECTOR_DATA: { 1293 // Already saw Objective-C selector table. 1294 if (ObjCSelectorTable) 1295 return true; 1296 1297 uint32_t tableOffset; 1298 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch, 1299 tableOffset); 1300 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1301 1302 ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create( 1303 base + tableOffset, base + sizeof(uint32_t), base)); 1304 break; 1305 } 1306 1307 default: 1308 // Unknown record, possibly for use by a future version of the 1309 // module format. 1310 break; 1311 } 1312 1313 MaybeNext = Cursor.advance(); 1314 if (!MaybeNext) { 1315 // FIXME this drops the error on the floor. 1316 consumeError(MaybeNext.takeError()); 1317 return false; 1318 } 1319 Next = MaybeNext.get(); 1320 } 1321 1322 return false; 1323 } 1324 1325 bool APINotesReader::Implementation::readGlobalVariableBlock( 1326 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1327 if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID)) 1328 return true; 1329 1330 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1331 if (!MaybeNext) { 1332 // FIXME this drops the error on the floor. 1333 consumeError(MaybeNext.takeError()); 1334 return false; 1335 } 1336 llvm::BitstreamEntry Next = MaybeNext.get(); 1337 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1338 if (Next.Kind == llvm::BitstreamEntry::Error) 1339 return true; 1340 1341 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1342 // Unknown sub-block, possibly for use by a future version of the 1343 // API notes format. 1344 if (Cursor.SkipBlock()) 1345 return true; 1346 1347 MaybeNext = Cursor.advance(); 1348 if (!MaybeNext) { 1349 // FIXME this drops the error on the floor. 1350 consumeError(MaybeNext.takeError()); 1351 return false; 1352 } 1353 Next = MaybeNext.get(); 1354 continue; 1355 } 1356 1357 Scratch.clear(); 1358 llvm::StringRef BlobData; 1359 llvm::Expected<unsigned> MaybeKind = 1360 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1361 if (!MaybeKind) { 1362 // FIXME this drops the error on the floor. 1363 consumeError(MaybeKind.takeError()); 1364 return false; 1365 } 1366 unsigned Kind = MaybeKind.get(); 1367 switch (Kind) { 1368 case global_variable_block::GLOBAL_VARIABLE_DATA: { 1369 // Already saw global variable table. 1370 if (GlobalVariableTable) 1371 return true; 1372 1373 uint32_t tableOffset; 1374 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch, 1375 tableOffset); 1376 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1377 1378 GlobalVariableTable.reset(SerializedGlobalVariableTable::Create( 1379 base + tableOffset, base + sizeof(uint32_t), base)); 1380 break; 1381 } 1382 1383 default: 1384 // Unknown record, possibly for use by a future version of the 1385 // module format. 1386 break; 1387 } 1388 1389 MaybeNext = Cursor.advance(); 1390 if (!MaybeNext) { 1391 // FIXME this drops the error on the floor. 1392 consumeError(MaybeNext.takeError()); 1393 return false; 1394 } 1395 Next = MaybeNext.get(); 1396 } 1397 1398 return false; 1399 } 1400 1401 bool APINotesReader::Implementation::readGlobalFunctionBlock( 1402 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1403 if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID)) 1404 return true; 1405 1406 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1407 if (!MaybeNext) { 1408 // FIXME this drops the error on the floor. 1409 consumeError(MaybeNext.takeError()); 1410 return false; 1411 } 1412 llvm::BitstreamEntry Next = MaybeNext.get(); 1413 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1414 if (Next.Kind == llvm::BitstreamEntry::Error) 1415 return true; 1416 1417 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1418 // Unknown sub-block, possibly for use by a future version of the 1419 // API notes format. 1420 if (Cursor.SkipBlock()) 1421 return true; 1422 1423 MaybeNext = Cursor.advance(); 1424 if (!MaybeNext) { 1425 // FIXME this drops the error on the floor. 1426 consumeError(MaybeNext.takeError()); 1427 return false; 1428 } 1429 Next = MaybeNext.get(); 1430 continue; 1431 } 1432 1433 Scratch.clear(); 1434 llvm::StringRef BlobData; 1435 llvm::Expected<unsigned> MaybeKind = 1436 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1437 if (!MaybeKind) { 1438 // FIXME this drops the error on the floor. 1439 consumeError(MaybeKind.takeError()); 1440 return false; 1441 } 1442 unsigned Kind = MaybeKind.get(); 1443 switch (Kind) { 1444 case global_function_block::GLOBAL_FUNCTION_DATA: { 1445 // Already saw global function table. 1446 if (GlobalFunctionTable) 1447 return true; 1448 1449 uint32_t tableOffset; 1450 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch, 1451 tableOffset); 1452 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1453 1454 GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create( 1455 base + tableOffset, base + sizeof(uint32_t), base)); 1456 break; 1457 } 1458 1459 default: 1460 // Unknown record, possibly for use by a future version of the 1461 // module format. 1462 break; 1463 } 1464 1465 MaybeNext = Cursor.advance(); 1466 if (!MaybeNext) { 1467 // FIXME this drops the error on the floor. 1468 consumeError(MaybeNext.takeError()); 1469 return false; 1470 } 1471 Next = MaybeNext.get(); 1472 } 1473 1474 return false; 1475 } 1476 1477 bool APINotesReader::Implementation::readEnumConstantBlock( 1478 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1479 if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID)) 1480 return true; 1481 1482 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1483 if (!MaybeNext) { 1484 // FIXME this drops the error on the floor. 1485 consumeError(MaybeNext.takeError()); 1486 return false; 1487 } 1488 llvm::BitstreamEntry Next = MaybeNext.get(); 1489 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1490 if (Next.Kind == llvm::BitstreamEntry::Error) 1491 return true; 1492 1493 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1494 // Unknown sub-block, possibly for use by a future version of the 1495 // API notes format. 1496 if (Cursor.SkipBlock()) 1497 return true; 1498 1499 MaybeNext = Cursor.advance(); 1500 if (!MaybeNext) { 1501 // FIXME this drops the error on the floor. 1502 consumeError(MaybeNext.takeError()); 1503 return false; 1504 } 1505 Next = MaybeNext.get(); 1506 continue; 1507 } 1508 1509 Scratch.clear(); 1510 llvm::StringRef BlobData; 1511 llvm::Expected<unsigned> MaybeKind = 1512 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1513 if (!MaybeKind) { 1514 // FIXME this drops the error on the floor. 1515 consumeError(MaybeKind.takeError()); 1516 return false; 1517 } 1518 unsigned Kind = MaybeKind.get(); 1519 switch (Kind) { 1520 case enum_constant_block::ENUM_CONSTANT_DATA: { 1521 // Already saw enumerator table. 1522 if (EnumConstantTable) 1523 return true; 1524 1525 uint32_t tableOffset; 1526 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch, 1527 tableOffset); 1528 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1529 1530 EnumConstantTable.reset(SerializedEnumConstantTable::Create( 1531 base + tableOffset, base + sizeof(uint32_t), base)); 1532 break; 1533 } 1534 1535 default: 1536 // Unknown record, possibly for use by a future version of the 1537 // module format. 1538 break; 1539 } 1540 1541 MaybeNext = Cursor.advance(); 1542 if (!MaybeNext) { 1543 // FIXME this drops the error on the floor. 1544 consumeError(MaybeNext.takeError()); 1545 return false; 1546 } 1547 Next = MaybeNext.get(); 1548 } 1549 1550 return false; 1551 } 1552 1553 bool APINotesReader::Implementation::readTagBlock( 1554 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1555 if (Cursor.EnterSubBlock(TAG_BLOCK_ID)) 1556 return true; 1557 1558 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1559 if (!MaybeNext) { 1560 // FIXME this drops the error on the floor. 1561 consumeError(MaybeNext.takeError()); 1562 return false; 1563 } 1564 llvm::BitstreamEntry Next = MaybeNext.get(); 1565 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1566 if (Next.Kind == llvm::BitstreamEntry::Error) 1567 return true; 1568 1569 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1570 // Unknown sub-block, possibly for use by a future version of the 1571 // API notes format. 1572 if (Cursor.SkipBlock()) 1573 return true; 1574 1575 MaybeNext = Cursor.advance(); 1576 if (!MaybeNext) { 1577 // FIXME this drops the error on the floor. 1578 consumeError(MaybeNext.takeError()); 1579 return false; 1580 } 1581 Next = MaybeNext.get(); 1582 continue; 1583 } 1584 1585 Scratch.clear(); 1586 llvm::StringRef BlobData; 1587 llvm::Expected<unsigned> MaybeKind = 1588 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1589 if (!MaybeKind) { 1590 // FIXME this drops the error on the floor. 1591 consumeError(MaybeKind.takeError()); 1592 return false; 1593 } 1594 unsigned Kind = MaybeKind.get(); 1595 switch (Kind) { 1596 case tag_block::TAG_DATA: { 1597 // Already saw tag table. 1598 if (TagTable) 1599 return true; 1600 1601 uint32_t tableOffset; 1602 tag_block::TagDataLayout::readRecord(Scratch, tableOffset); 1603 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1604 1605 TagTable.reset(SerializedTagTable::Create(base + tableOffset, 1606 base + sizeof(uint32_t), base)); 1607 break; 1608 } 1609 1610 default: 1611 // Unknown record, possibly for use by a future version of the 1612 // module format. 1613 break; 1614 } 1615 1616 MaybeNext = Cursor.advance(); 1617 if (!MaybeNext) { 1618 // FIXME this drops the error on the floor. 1619 consumeError(MaybeNext.takeError()); 1620 return false; 1621 } 1622 Next = MaybeNext.get(); 1623 } 1624 1625 return false; 1626 } 1627 1628 bool APINotesReader::Implementation::readTypedefBlock( 1629 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) { 1630 if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID)) 1631 return true; 1632 1633 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance(); 1634 if (!MaybeNext) { 1635 // FIXME this drops the error on the floor. 1636 consumeError(MaybeNext.takeError()); 1637 return false; 1638 } 1639 llvm::BitstreamEntry Next = MaybeNext.get(); 1640 while (Next.Kind != llvm::BitstreamEntry::EndBlock) { 1641 if (Next.Kind == llvm::BitstreamEntry::Error) 1642 return true; 1643 1644 if (Next.Kind == llvm::BitstreamEntry::SubBlock) { 1645 // Unknown sub-block, possibly for use by a future version of the 1646 // API notes format. 1647 if (Cursor.SkipBlock()) 1648 return true; 1649 1650 MaybeNext = Cursor.advance(); 1651 if (!MaybeNext) { 1652 // FIXME this drops the error on the floor. 1653 consumeError(MaybeNext.takeError()); 1654 return false; 1655 } 1656 Next = MaybeNext.get(); 1657 continue; 1658 } 1659 1660 Scratch.clear(); 1661 llvm::StringRef BlobData; 1662 llvm::Expected<unsigned> MaybeKind = 1663 Cursor.readRecord(Next.ID, Scratch, &BlobData); 1664 if (!MaybeKind) { 1665 // FIXME this drops the error on the floor. 1666 consumeError(MaybeKind.takeError()); 1667 return false; 1668 } 1669 unsigned Kind = MaybeKind.get(); 1670 switch (Kind) { 1671 case typedef_block::TYPEDEF_DATA: { 1672 // Already saw typedef table. 1673 if (TypedefTable) 1674 return true; 1675 1676 uint32_t tableOffset; 1677 typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset); 1678 auto base = reinterpret_cast<const uint8_t *>(BlobData.data()); 1679 1680 TypedefTable.reset(SerializedTypedefTable::Create( 1681 base + tableOffset, base + sizeof(uint32_t), base)); 1682 break; 1683 } 1684 1685 default: 1686 // Unknown record, possibly for use by a future version of the 1687 // module format. 1688 break; 1689 } 1690 1691 MaybeNext = Cursor.advance(); 1692 if (!MaybeNext) { 1693 // FIXME this drops the error on the floor. 1694 consumeError(MaybeNext.takeError()); 1695 return false; 1696 } 1697 Next = MaybeNext.get(); 1698 } 1699 1700 return false; 1701 } 1702 1703 APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer, 1704 llvm::VersionTuple SwiftVersion, bool &Failed) 1705 : Implementation(new class Implementation) { 1706 Failed = false; 1707 1708 // Initialize the input buffer. 1709 Implementation->InputBuffer = InputBuffer; 1710 Implementation->SwiftVersion = SwiftVersion; 1711 llvm::BitstreamCursor Cursor(*Implementation->InputBuffer); 1712 1713 // Validate signature. 1714 for (auto byte : API_NOTES_SIGNATURE) { 1715 if (Cursor.AtEndOfStream()) { 1716 Failed = true; 1717 return; 1718 } 1719 if (llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead = 1720 Cursor.Read(8)) { 1721 if (maybeRead.get() != byte) { 1722 Failed = true; 1723 return; 1724 } 1725 } else { 1726 // FIXME this drops the error on the floor. 1727 consumeError(maybeRead.takeError()); 1728 Failed = true; 1729 return; 1730 } 1731 } 1732 1733 // Look at all of the blocks. 1734 bool HasValidControlBlock = false; 1735 llvm::SmallVector<uint64_t, 64> Scratch; 1736 while (!Cursor.AtEndOfStream()) { 1737 llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance(); 1738 if (!MaybeTopLevelEntry) { 1739 // FIXME this drops the error on the floor. 1740 consumeError(MaybeTopLevelEntry.takeError()); 1741 Failed = true; 1742 return; 1743 } 1744 llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get(); 1745 1746 if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock) 1747 break; 1748 1749 switch (TopLevelEntry.ID) { 1750 case llvm::bitc::BLOCKINFO_BLOCK_ID: 1751 if (!Cursor.ReadBlockInfoBlock()) { 1752 Failed = true; 1753 break; 1754 } 1755 break; 1756 1757 case CONTROL_BLOCK_ID: 1758 // Only allow a single control block. 1759 if (HasValidControlBlock || 1760 Implementation->readControlBlock(Cursor, Scratch)) { 1761 Failed = true; 1762 return; 1763 } 1764 1765 HasValidControlBlock = true; 1766 break; 1767 1768 case IDENTIFIER_BLOCK_ID: 1769 if (!HasValidControlBlock || 1770 Implementation->readIdentifierBlock(Cursor, Scratch)) { 1771 Failed = true; 1772 return; 1773 } 1774 break; 1775 1776 case OBJC_CONTEXT_BLOCK_ID: 1777 if (!HasValidControlBlock || 1778 Implementation->readContextBlock(Cursor, Scratch)) { 1779 Failed = true; 1780 return; 1781 } 1782 1783 break; 1784 1785 case OBJC_PROPERTY_BLOCK_ID: 1786 if (!HasValidControlBlock || 1787 Implementation->readObjCPropertyBlock(Cursor, Scratch)) { 1788 Failed = true; 1789 return; 1790 } 1791 break; 1792 1793 case OBJC_METHOD_BLOCK_ID: 1794 if (!HasValidControlBlock || 1795 Implementation->readObjCMethodBlock(Cursor, Scratch)) { 1796 Failed = true; 1797 return; 1798 } 1799 break; 1800 1801 case CXX_METHOD_BLOCK_ID: 1802 if (!HasValidControlBlock || 1803 Implementation->readCXXMethodBlock(Cursor, Scratch)) { 1804 Failed = true; 1805 return; 1806 } 1807 break; 1808 1809 case OBJC_SELECTOR_BLOCK_ID: 1810 if (!HasValidControlBlock || 1811 Implementation->readObjCSelectorBlock(Cursor, Scratch)) { 1812 Failed = true; 1813 return; 1814 } 1815 break; 1816 1817 case GLOBAL_VARIABLE_BLOCK_ID: 1818 if (!HasValidControlBlock || 1819 Implementation->readGlobalVariableBlock(Cursor, Scratch)) { 1820 Failed = true; 1821 return; 1822 } 1823 break; 1824 1825 case GLOBAL_FUNCTION_BLOCK_ID: 1826 if (!HasValidControlBlock || 1827 Implementation->readGlobalFunctionBlock(Cursor, Scratch)) { 1828 Failed = true; 1829 return; 1830 } 1831 break; 1832 1833 case ENUM_CONSTANT_BLOCK_ID: 1834 if (!HasValidControlBlock || 1835 Implementation->readEnumConstantBlock(Cursor, Scratch)) { 1836 Failed = true; 1837 return; 1838 } 1839 break; 1840 1841 case TAG_BLOCK_ID: 1842 if (!HasValidControlBlock || 1843 Implementation->readTagBlock(Cursor, Scratch)) { 1844 Failed = true; 1845 return; 1846 } 1847 break; 1848 1849 case TYPEDEF_BLOCK_ID: 1850 if (!HasValidControlBlock || 1851 Implementation->readTypedefBlock(Cursor, Scratch)) { 1852 Failed = true; 1853 return; 1854 } 1855 break; 1856 1857 default: 1858 // Unknown top-level block, possibly for use by a future version of the 1859 // module format. 1860 if (Cursor.SkipBlock()) { 1861 Failed = true; 1862 return; 1863 } 1864 break; 1865 } 1866 } 1867 1868 if (!Cursor.AtEndOfStream()) { 1869 Failed = true; 1870 return; 1871 } 1872 } 1873 1874 APINotesReader::~APINotesReader() { delete Implementation->InputBuffer; } 1875 1876 std::unique_ptr<APINotesReader> 1877 APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer, 1878 llvm::VersionTuple SwiftVersion) { 1879 bool Failed = false; 1880 std::unique_ptr<APINotesReader> Reader( 1881 new APINotesReader(InputBuffer.release(), SwiftVersion, Failed)); 1882 if (Failed) 1883 return nullptr; 1884 1885 return Reader; 1886 } 1887 1888 template <typename T> 1889 APINotesReader::VersionedInfo<T>::VersionedInfo( 1890 llvm::VersionTuple Version, 1891 llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R) 1892 : Results(std::move(R)) { 1893 1894 assert(!Results.empty()); 1895 assert(std::is_sorted( 1896 Results.begin(), Results.end(), 1897 [](const std::pair<llvm::VersionTuple, T> &left, 1898 const std::pair<llvm::VersionTuple, T> &right) -> bool { 1899 assert(left.first != right.first && "two entries for the same version"); 1900 return left.first < right.first; 1901 })); 1902 1903 Selected = std::nullopt; 1904 for (unsigned i = 0, n = Results.size(); i != n; ++i) { 1905 if (!Version.empty() && Results[i].first >= Version) { 1906 // If the current version is "4", then entries for 4 are better than 1907 // entries for 5, but both are valid. Because entries are sorted, we get 1908 // that behavior by picking the first match. 1909 Selected = i; 1910 break; 1911 } 1912 } 1913 1914 // If we didn't find a match but we have an unversioned result, use the 1915 // unversioned result. This will always be the first entry because we encode 1916 // it as version 0. 1917 if (!Selected && Results[0].first.empty()) 1918 Selected = 0; 1919 } 1920 1921 auto APINotesReader::lookupObjCClassID(llvm::StringRef Name) 1922 -> std::optional<ContextID> { 1923 if (!Implementation->ContextIDTable) 1924 return std::nullopt; 1925 1926 std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name); 1927 if (!ClassID) 1928 return std::nullopt; 1929 1930 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global 1931 // context. 1932 auto KnownID = Implementation->ContextIDTable->find( 1933 ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID)); 1934 if (KnownID == Implementation->ContextIDTable->end()) 1935 return std::nullopt; 1936 1937 return ContextID(*KnownID); 1938 } 1939 1940 auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name) 1941 -> VersionedInfo<ContextInfo> { 1942 if (!Implementation->ContextInfoTable) 1943 return std::nullopt; 1944 1945 std::optional<ContextID> CtxID = lookupObjCClassID(Name); 1946 if (!CtxID) 1947 return std::nullopt; 1948 1949 auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value); 1950 if (KnownInfo == Implementation->ContextInfoTable->end()) 1951 return std::nullopt; 1952 1953 return {Implementation->SwiftVersion, *KnownInfo}; 1954 } 1955 1956 auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name) 1957 -> std::optional<ContextID> { 1958 if (!Implementation->ContextIDTable) 1959 return std::nullopt; 1960 1961 std::optional<IdentifierID> classID = Implementation->getIdentifier(Name); 1962 if (!classID) 1963 return std::nullopt; 1964 1965 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global 1966 // context. 1967 auto KnownID = Implementation->ContextIDTable->find( 1968 ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID)); 1969 if (KnownID == Implementation->ContextIDTable->end()) 1970 return std::nullopt; 1971 1972 return ContextID(*KnownID); 1973 } 1974 1975 auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name) 1976 -> VersionedInfo<ContextInfo> { 1977 if (!Implementation->ContextInfoTable) 1978 return std::nullopt; 1979 1980 std::optional<ContextID> CtxID = lookupObjCProtocolID(Name); 1981 if (!CtxID) 1982 return std::nullopt; 1983 1984 auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value); 1985 if (KnownInfo == Implementation->ContextInfoTable->end()) 1986 return std::nullopt; 1987 1988 return {Implementation->SwiftVersion, *KnownInfo}; 1989 } 1990 1991 auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name, 1992 bool IsInstance) 1993 -> VersionedInfo<ObjCPropertyInfo> { 1994 if (!Implementation->ObjCPropertyTable) 1995 return std::nullopt; 1996 1997 std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name); 1998 if (!PropertyID) 1999 return std::nullopt; 2000 2001 auto Known = Implementation->ObjCPropertyTable->find( 2002 std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance)); 2003 if (Known == Implementation->ObjCPropertyTable->end()) 2004 return std::nullopt; 2005 2006 return {Implementation->SwiftVersion, *Known}; 2007 } 2008 2009 auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector, 2010 bool IsInstanceMethod) 2011 -> VersionedInfo<ObjCMethodInfo> { 2012 if (!Implementation->ObjCMethodTable) 2013 return std::nullopt; 2014 2015 std::optional<SelectorID> SelID = Implementation->getSelector(Selector); 2016 if (!SelID) 2017 return std::nullopt; 2018 2019 auto Known = Implementation->ObjCMethodTable->find( 2020 ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID, 2021 IsInstanceMethod}); 2022 if (Known == Implementation->ObjCMethodTable->end()) 2023 return std::nullopt; 2024 2025 return {Implementation->SwiftVersion, *Known}; 2026 } 2027 2028 auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name) 2029 -> VersionedInfo<CXXMethodInfo> { 2030 if (!Implementation->CXXMethodTable) 2031 return std::nullopt; 2032 2033 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 2034 if (!NameID) 2035 return std::nullopt; 2036 2037 auto Known = Implementation->CXXMethodTable->find( 2038 SingleDeclTableKey(CtxID.Value, *NameID)); 2039 if (Known == Implementation->CXXMethodTable->end()) 2040 return std::nullopt; 2041 2042 return {Implementation->SwiftVersion, *Known}; 2043 } 2044 2045 auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name, 2046 std::optional<Context> Ctx) 2047 -> VersionedInfo<GlobalVariableInfo> { 2048 if (!Implementation->GlobalVariableTable) 2049 return std::nullopt; 2050 2051 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 2052 if (!NameID) 2053 return std::nullopt; 2054 2055 SingleDeclTableKey Key(Ctx, *NameID); 2056 2057 auto Known = Implementation->GlobalVariableTable->find(Key); 2058 if (Known == Implementation->GlobalVariableTable->end()) 2059 return std::nullopt; 2060 2061 return {Implementation->SwiftVersion, *Known}; 2062 } 2063 2064 auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name, 2065 std::optional<Context> Ctx) 2066 -> VersionedInfo<GlobalFunctionInfo> { 2067 if (!Implementation->GlobalFunctionTable) 2068 return std::nullopt; 2069 2070 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 2071 if (!NameID) 2072 return std::nullopt; 2073 2074 SingleDeclTableKey Key(Ctx, *NameID); 2075 2076 auto Known = Implementation->GlobalFunctionTable->find(Key); 2077 if (Known == Implementation->GlobalFunctionTable->end()) 2078 return std::nullopt; 2079 2080 return {Implementation->SwiftVersion, *Known}; 2081 } 2082 2083 auto APINotesReader::lookupEnumConstant(llvm::StringRef Name) 2084 -> VersionedInfo<EnumConstantInfo> { 2085 if (!Implementation->EnumConstantTable) 2086 return std::nullopt; 2087 2088 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 2089 if (!NameID) 2090 return std::nullopt; 2091 2092 auto Known = Implementation->EnumConstantTable->find(*NameID); 2093 if (Known == Implementation->EnumConstantTable->end()) 2094 return std::nullopt; 2095 2096 return {Implementation->SwiftVersion, *Known}; 2097 } 2098 2099 auto APINotesReader::lookupTagID(llvm::StringRef Name, 2100 std::optional<Context> ParentCtx) 2101 -> std::optional<ContextID> { 2102 if (!Implementation->ContextIDTable) 2103 return std::nullopt; 2104 2105 std::optional<IdentifierID> TagID = Implementation->getIdentifier(Name); 2106 if (!TagID) 2107 return std::nullopt; 2108 2109 auto KnownID = Implementation->ContextIDTable->find( 2110 ContextTableKey(ParentCtx, ContextKind::Tag, *TagID)); 2111 if (KnownID == Implementation->ContextIDTable->end()) 2112 return std::nullopt; 2113 2114 return ContextID(*KnownID); 2115 } 2116 2117 auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx) 2118 -> VersionedInfo<TagInfo> { 2119 if (!Implementation->TagTable) 2120 return std::nullopt; 2121 2122 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 2123 if (!NameID) 2124 return std::nullopt; 2125 2126 SingleDeclTableKey Key(Ctx, *NameID); 2127 2128 auto Known = Implementation->TagTable->find(Key); 2129 if (Known == Implementation->TagTable->end()) 2130 return std::nullopt; 2131 2132 return {Implementation->SwiftVersion, *Known}; 2133 } 2134 2135 auto APINotesReader::lookupTypedef(llvm::StringRef Name, 2136 std::optional<Context> Ctx) 2137 -> VersionedInfo<TypedefInfo> { 2138 if (!Implementation->TypedefTable) 2139 return std::nullopt; 2140 2141 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name); 2142 if (!NameID) 2143 return std::nullopt; 2144 2145 SingleDeclTableKey Key(Ctx, *NameID); 2146 2147 auto Known = Implementation->TypedefTable->find(Key); 2148 if (Known == Implementation->TypedefTable->end()) 2149 return std::nullopt; 2150 2151 return {Implementation->SwiftVersion, *Known}; 2152 } 2153 2154 auto APINotesReader::lookupNamespaceID( 2155 llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID) 2156 -> std::optional<ContextID> { 2157 if (!Implementation->ContextIDTable) 2158 return std::nullopt; 2159 2160 std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name); 2161 if (!NamespaceID) 2162 return std::nullopt; 2163 2164 uint32_t RawParentNamespaceID = 2165 ParentNamespaceID ? ParentNamespaceID->Value : -1; 2166 auto KnownID = Implementation->ContextIDTable->find( 2167 {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID}); 2168 if (KnownID == Implementation->ContextIDTable->end()) 2169 return std::nullopt; 2170 2171 return ContextID(*KnownID); 2172 } 2173 2174 } // namespace api_notes 2175 } // namespace clang 2176