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