brintos

brintos / llvm-project-archived public Read only

0
0
Text · 72.4 KiB · 7f9bb5f Raw
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