Path: blob/main/contrib/llvm-project/clang/lib/APINotes/APINotesReader.cpp
35259 views
//===--- APINotesReader.cpp - API Notes Reader ------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// This file implements the \c APINotesReader class that reads source9// API notes data providing additional information about source code as10// a separate input, such as the non-nil/nilable annotations for11// method parameters.12//13//===----------------------------------------------------------------------===//14#include "clang/APINotes/APINotesReader.h"15#include "APINotesFormat.h"16#include "llvm/ADT/Hashing.h"17#include "llvm/ADT/StringExtras.h"18#include "llvm/Bitstream/BitstreamReader.h"19#include "llvm/Support/DJB.h"20#include "llvm/Support/EndianStream.h"21#include "llvm/Support/OnDiskHashTable.h"2223namespace clang {24namespace api_notes {25using namespace llvm::support;2627namespace {28/// Deserialize a version tuple.29llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {30uint8_t NumVersions = (*Data++) & 0x03;3132unsigned Major = endian::readNext<uint32_t, llvm::endianness::little>(Data);33if (NumVersions == 0)34return llvm::VersionTuple(Major);3536unsigned Minor = endian::readNext<uint32_t, llvm::endianness::little>(Data);37if (NumVersions == 1)38return llvm::VersionTuple(Major, Minor);3940unsigned Subminor =41endian::readNext<uint32_t, llvm::endianness::little>(Data);42if (NumVersions == 2)43return llvm::VersionTuple(Major, Minor, Subminor);4445unsigned Build = endian::readNext<uint32_t, llvm::endianness::little>(Data);46return llvm::VersionTuple(Major, Minor, Subminor, Build);47}4849/// An on-disk hash table whose data is versioned based on the Swift version.50template <typename Derived, typename KeyType, typename UnversionedDataType>51class VersionedTableInfo {52public:53using internal_key_type = KeyType;54using external_key_type = KeyType;55using data_type =56llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;57using hash_value_type = size_t;58using offset_type = unsigned;5960internal_key_type GetInternalKey(external_key_type Key) { return Key; }6162external_key_type GetExternalKey(internal_key_type Key) { return Key; }6364static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {65return LHS == RHS;66}6768static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {69unsigned KeyLength =70endian::readNext<uint16_t, llvm::endianness::little>(Data);71unsigned DataLength =72endian::readNext<uint16_t, llvm::endianness::little>(Data);73return {KeyLength, DataLength};74}7576static data_type ReadData(internal_key_type Key, const uint8_t *Data,77unsigned Length) {78unsigned NumElements =79endian::readNext<uint16_t, llvm::endianness::little>(Data);80data_type Result;81Result.reserve(NumElements);82for (unsigned i = 0; i != NumElements; ++i) {83auto version = ReadVersionTuple(Data);84const auto *DataBefore = Data;85(void)DataBefore;86auto UnversionedData = Derived::readUnversioned(Key, Data);87assert(Data != DataBefore &&88"Unversioned data reader didn't move pointer");89Result.push_back({version, UnversionedData});90}91return Result;92}93};9495/// Read serialized CommonEntityInfo.96void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) {97uint8_t UnavailableBits = *Data++;98Info.Unavailable = (UnavailableBits >> 1) & 0x01;99Info.UnavailableInSwift = UnavailableBits & 0x01;100if ((UnavailableBits >> 2) & 0x01)101Info.setSwiftPrivate(static_cast<bool>((UnavailableBits >> 3) & 0x01));102103unsigned MsgLength =104endian::readNext<uint16_t, llvm::endianness::little>(Data);105Info.UnavailableMsg =106std::string(reinterpret_cast<const char *>(Data),107reinterpret_cast<const char *>(Data) + MsgLength);108Data += MsgLength;109110unsigned SwiftNameLength =111endian::readNext<uint16_t, llvm::endianness::little>(Data);112Info.SwiftName =113std::string(reinterpret_cast<const char *>(Data),114reinterpret_cast<const char *>(Data) + SwiftNameLength);115Data += SwiftNameLength;116}117118/// Read serialized CommonTypeInfo.119void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {120ReadCommonEntityInfo(Data, Info);121122unsigned SwiftBridgeLength =123endian::readNext<uint16_t, llvm::endianness::little>(Data);124if (SwiftBridgeLength > 0) {125Info.setSwiftBridge(std::string(reinterpret_cast<const char *>(Data),126SwiftBridgeLength - 1));127Data += SwiftBridgeLength - 1;128}129130unsigned ErrorDomainLength =131endian::readNext<uint16_t, llvm::endianness::little>(Data);132if (ErrorDomainLength > 0) {133Info.setNSErrorDomain(std::optional<std::string>(std::string(134reinterpret_cast<const char *>(Data), ErrorDomainLength - 1)));135Data += ErrorDomainLength - 1;136}137}138139/// Used to deserialize the on-disk identifier table.140class IdentifierTableInfo {141public:142using internal_key_type = llvm::StringRef;143using external_key_type = llvm::StringRef;144using data_type = IdentifierID;145using hash_value_type = uint32_t;146using offset_type = unsigned;147148internal_key_type GetInternalKey(external_key_type Key) { return Key; }149150external_key_type GetExternalKey(internal_key_type Key) { return Key; }151152hash_value_type ComputeHash(internal_key_type Key) {153return llvm::djbHash(Key);154}155156static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {157return LHS == RHS;158}159160static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {161unsigned KeyLength =162endian::readNext<uint16_t, llvm::endianness::little>(Data);163unsigned DataLength =164endian::readNext<uint16_t, llvm::endianness::little>(Data);165return {KeyLength, DataLength};166}167168static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {169return llvm::StringRef(reinterpret_cast<const char *>(Data), Length);170}171172static data_type ReadData(internal_key_type key, const uint8_t *Data,173unsigned Length) {174return endian::readNext<uint32_t, llvm::endianness::little>(Data);175}176};177178/// Used to deserialize the on-disk table of Objective-C classes and C++179/// namespaces.180class ContextIDTableInfo {181public:182using internal_key_type = ContextTableKey;183using external_key_type = internal_key_type;184using data_type = unsigned;185using hash_value_type = size_t;186using offset_type = unsigned;187188internal_key_type GetInternalKey(external_key_type Key) { return Key; }189190external_key_type GetExternalKey(internal_key_type Key) { return Key; }191192hash_value_type ComputeHash(internal_key_type Key) {193return static_cast<size_t>(Key.hashValue());194}195196static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {197return LHS == RHS;198}199200static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {201unsigned KeyLength =202endian::readNext<uint16_t, llvm::endianness::little>(Data);203unsigned DataLength =204endian::readNext<uint16_t, llvm::endianness::little>(Data);205return {KeyLength, DataLength};206}207208static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {209auto ParentCtxID =210endian::readNext<uint32_t, llvm::endianness::little>(Data);211auto ContextKind =212endian::readNext<uint8_t, llvm::endianness::little>(Data);213auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);214return {ParentCtxID, ContextKind, NameID};215}216217static data_type ReadData(internal_key_type Key, const uint8_t *Data,218unsigned Length) {219return endian::readNext<uint32_t, llvm::endianness::little>(Data);220}221};222223/// Used to deserialize the on-disk Objective-C property table.224class ContextInfoTableInfo225: public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {226public:227static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {228return endian::readNext<uint32_t, llvm::endianness::little>(Data);229}230231hash_value_type ComputeHash(internal_key_type Key) {232return static_cast<size_t>(llvm::hash_value(Key));233}234235static ContextInfo readUnversioned(internal_key_type Key,236const uint8_t *&Data) {237ContextInfo Info;238ReadCommonTypeInfo(Data, Info);239uint8_t Payload = *Data++;240241if (Payload & 0x01)242Info.setHasDesignatedInits(true);243Payload = Payload >> 1;244245if (Payload & 0x4)246Info.setDefaultNullability(static_cast<NullabilityKind>(Payload & 0x03));247Payload >>= 3;248249if (Payload & (1 << 1))250Info.setSwiftObjCMembers(Payload & 1);251Payload >>= 2;252253if (Payload & (1 << 1))254Info.setSwiftImportAsNonGeneric(Payload & 1);255256return Info;257}258};259260/// Read serialized VariableInfo.261void ReadVariableInfo(const uint8_t *&Data, VariableInfo &Info) {262ReadCommonEntityInfo(Data, Info);263if (*Data++) {264Info.setNullabilityAudited(static_cast<NullabilityKind>(*Data));265}266++Data;267268auto TypeLen = endian::readNext<uint16_t, llvm::endianness::little>(Data);269Info.setType(std::string(Data, Data + TypeLen));270Data += TypeLen;271}272273/// Used to deserialize the on-disk Objective-C property table.274class ObjCPropertyTableInfo275: public VersionedTableInfo<ObjCPropertyTableInfo,276std::tuple<uint32_t, uint32_t, uint8_t>,277ObjCPropertyInfo> {278public:279static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {280auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);281auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);282char IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);283return {ClassID, NameID, IsInstance};284}285286hash_value_type ComputeHash(internal_key_type Key) {287return static_cast<size_t>(llvm::hash_value(Key));288}289290static ObjCPropertyInfo readUnversioned(internal_key_type Key,291const uint8_t *&Data) {292ObjCPropertyInfo Info;293ReadVariableInfo(Data, Info);294uint8_t Flags = *Data++;295if (Flags & (1 << 0))296Info.setSwiftImportAsAccessors(Flags & (1 << 1));297return Info;298}299};300301/// Read serialized ParamInfo.302void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) {303ReadVariableInfo(Data, Info);304305uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);306if (auto RawConvention = Payload & 0x7) {307auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);308Info.setRetainCountConvention(Convention);309}310Payload >>= 3;311if (Payload & 0x01)312Info.setNoEscape(Payload & 0x02);313Payload >>= 2;314assert(Payload == 0 && "Bad API notes");315}316317/// Read serialized FunctionInfo.318void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) {319ReadCommonEntityInfo(Data, Info);320321uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);322if (auto RawConvention = Payload & 0x7) {323auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);324Info.setRetainCountConvention(Convention);325}326Payload >>= 3;327Info.NullabilityAudited = Payload & 0x1;328Payload >>= 1;329assert(Payload == 0 && "Bad API notes");330331Info.NumAdjustedNullable =332endian::readNext<uint8_t, llvm::endianness::little>(Data);333Info.NullabilityPayload =334endian::readNext<uint64_t, llvm::endianness::little>(Data);335336unsigned NumParams =337endian::readNext<uint16_t, llvm::endianness::little>(Data);338while (NumParams > 0) {339ParamInfo pi;340ReadParamInfo(Data, pi);341Info.Params.push_back(pi);342--NumParams;343}344345unsigned ResultTypeLen =346endian::readNext<uint16_t, llvm::endianness::little>(Data);347Info.ResultType = std::string(Data, Data + ResultTypeLen);348Data += ResultTypeLen;349}350351/// Used to deserialize the on-disk Objective-C method table.352class ObjCMethodTableInfo353: public VersionedTableInfo<ObjCMethodTableInfo,354std::tuple<uint32_t, uint32_t, uint8_t>,355ObjCMethodInfo> {356public:357static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {358auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);359auto SelectorID =360endian::readNext<uint32_t, llvm::endianness::little>(Data);361auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);362return {ClassID, SelectorID, IsInstance};363}364365hash_value_type ComputeHash(internal_key_type Key) {366return static_cast<size_t>(llvm::hash_value(Key));367}368369static ObjCMethodInfo readUnversioned(internal_key_type Key,370const uint8_t *&Data) {371ObjCMethodInfo Info;372uint8_t Payload = *Data++;373Info.RequiredInit = Payload & 0x01;374Payload >>= 1;375Info.DesignatedInit = Payload & 0x01;376Payload >>= 1;377378ReadFunctionInfo(Data, Info);379return Info;380}381};382383/// Used to deserialize the on-disk Objective-C selector table.384class ObjCSelectorTableInfo {385public:386using internal_key_type = StoredObjCSelector;387using external_key_type = internal_key_type;388using data_type = SelectorID;389using hash_value_type = unsigned;390using offset_type = unsigned;391392internal_key_type GetInternalKey(external_key_type Key) { return Key; }393394external_key_type GetExternalKey(internal_key_type Key) { return Key; }395396hash_value_type ComputeHash(internal_key_type Key) {397return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);398}399400static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {401return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);402}403404static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {405unsigned KeyLength =406endian::readNext<uint16_t, llvm::endianness::little>(Data);407unsigned DataLength =408endian::readNext<uint16_t, llvm::endianness::little>(Data);409return {KeyLength, DataLength};410}411412static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {413internal_key_type Key;414Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(Data);415unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);416for (unsigned i = 0; i != NumIdents; ++i) {417Key.Identifiers.push_back(418endian::readNext<uint32_t, llvm::endianness::little>(Data));419}420return Key;421}422423static data_type ReadData(internal_key_type Key, const uint8_t *Data,424unsigned Length) {425return endian::readNext<uint32_t, llvm::endianness::little>(Data);426}427};428429/// Used to deserialize the on-disk global variable table.430class GlobalVariableTableInfo431: public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,432GlobalVariableInfo> {433public:434static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {435auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);436auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);437return {CtxID, NameID};438}439440hash_value_type ComputeHash(internal_key_type Key) {441return static_cast<size_t>(Key.hashValue());442}443444static GlobalVariableInfo readUnversioned(internal_key_type Key,445const uint8_t *&Data) {446GlobalVariableInfo Info;447ReadVariableInfo(Data, Info);448return Info;449}450};451452/// Used to deserialize the on-disk global function table.453class GlobalFunctionTableInfo454: public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,455GlobalFunctionInfo> {456public:457static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {458auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);459auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);460return {CtxID, NameID};461}462463hash_value_type ComputeHash(internal_key_type Key) {464return static_cast<size_t>(Key.hashValue());465}466467static GlobalFunctionInfo readUnversioned(internal_key_type Key,468const uint8_t *&Data) {469GlobalFunctionInfo Info;470ReadFunctionInfo(Data, Info);471return Info;472}473};474475/// Used to deserialize the on-disk C++ method table.476class CXXMethodTableInfo477: public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,478CXXMethodInfo> {479public:480static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {481auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);482auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);483return {CtxID, NameID};484}485486hash_value_type ComputeHash(internal_key_type Key) {487return static_cast<size_t>(Key.hashValue());488}489490static CXXMethodInfo readUnversioned(internal_key_type Key,491const uint8_t *&Data) {492CXXMethodInfo Info;493ReadFunctionInfo(Data, Info);494return Info;495}496};497498/// Used to deserialize the on-disk enumerator table.499class EnumConstantTableInfo500: public VersionedTableInfo<EnumConstantTableInfo, uint32_t,501EnumConstantInfo> {502public:503static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {504auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);505return NameID;506}507508hash_value_type ComputeHash(internal_key_type Key) {509return static_cast<size_t>(llvm::hash_value(Key));510}511512static EnumConstantInfo readUnversioned(internal_key_type Key,513const uint8_t *&Data) {514EnumConstantInfo Info;515ReadCommonEntityInfo(Data, Info);516return Info;517}518};519520/// Used to deserialize the on-disk tag table.521class TagTableInfo522: public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> {523public:524static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {525auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);526auto NameID =527endian::readNext<IdentifierID, llvm::endianness::little>(Data);528return {CtxID, NameID};529}530531hash_value_type ComputeHash(internal_key_type Key) {532return static_cast<size_t>(Key.hashValue());533}534535static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {536TagInfo Info;537538uint8_t Payload = *Data++;539if (Payload & 1)540Info.setFlagEnum(Payload & 2);541Payload >>= 2;542if (Payload > 0)543Info.EnumExtensibility =544static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);545546uint8_t Copyable =547endian::readNext<uint8_t, llvm::endianness::little>(Data);548if (Copyable == kSwiftNonCopyable)549Info.setSwiftCopyable(std::optional(false));550else if (Copyable == kSwiftCopyable)551Info.setSwiftCopyable(std::optional(true));552553unsigned ImportAsLength =554endian::readNext<uint16_t, llvm::endianness::little>(Data);555if (ImportAsLength > 0) {556Info.SwiftImportAs =557std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1);558Data += ImportAsLength - 1;559}560unsigned RetainOpLength =561endian::readNext<uint16_t, llvm::endianness::little>(Data);562if (RetainOpLength > 0) {563Info.SwiftRetainOp =564std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1);565Data += RetainOpLength - 1;566}567unsigned ReleaseOpLength =568endian::readNext<uint16_t, llvm::endianness::little>(Data);569if (ReleaseOpLength > 0) {570Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data),571ReleaseOpLength - 1);572Data += ReleaseOpLength - 1;573}574575ReadCommonTypeInfo(Data, Info);576return Info;577}578};579580/// Used to deserialize the on-disk typedef table.581class TypedefTableInfo582: public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey,583TypedefInfo> {584public:585static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {586auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);587auto nameID =588endian::readNext<IdentifierID, llvm::endianness::little>(Data);589return {CtxID, nameID};590}591592hash_value_type ComputeHash(internal_key_type Key) {593return static_cast<size_t>(Key.hashValue());594}595596static TypedefInfo readUnversioned(internal_key_type Key,597const uint8_t *&Data) {598TypedefInfo Info;599600uint8_t Payload = *Data++;601if (Payload > 0)602Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);603604ReadCommonTypeInfo(Data, Info);605return Info;606}607};608} // end anonymous namespace609610class APINotesReader::Implementation {611public:612/// The input buffer for the API notes data.613llvm::MemoryBuffer *InputBuffer;614615/// The Swift version to use for filtering.616llvm::VersionTuple SwiftVersion;617618/// The name of the module that we read from the control block.619std::string ModuleName;620621// The size and modification time of the source file from622// which this API notes file was created, if known.623std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime;624625using SerializedIdentifierTable =626llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;627628/// The identifier table.629std::unique_ptr<SerializedIdentifierTable> IdentifierTable;630631using SerializedContextIDTable =632llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;633634/// The Objective-C / C++ context ID table.635std::unique_ptr<SerializedContextIDTable> ContextIDTable;636637using SerializedContextInfoTable =638llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;639640/// The Objective-C context info table.641std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;642643using SerializedObjCPropertyTable =644llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;645646/// The Objective-C property table.647std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;648649using SerializedObjCMethodTable =650llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;651652/// The Objective-C method table.653std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;654655using SerializedCXXMethodTable =656llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;657658/// The C++ method table.659std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;660661using SerializedObjCSelectorTable =662llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;663664/// The Objective-C selector table.665std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;666667using SerializedGlobalVariableTable =668llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;669670/// The global variable table.671std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;672673using SerializedGlobalFunctionTable =674llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;675676/// The global function table.677std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;678679using SerializedEnumConstantTable =680llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;681682/// The enumerator table.683std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;684685using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;686687/// The tag table.688std::unique_ptr<SerializedTagTable> TagTable;689690using SerializedTypedefTable =691llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;692693/// The typedef table.694std::unique_ptr<SerializedTypedefTable> TypedefTable;695696/// Retrieve the identifier ID for the given string, or an empty697/// optional if the string is unknown.698std::optional<IdentifierID> getIdentifier(llvm::StringRef Str);699700/// Retrieve the selector ID for the given selector, or an empty701/// optional if the string is unknown.702std::optional<SelectorID> getSelector(ObjCSelectorRef Selector);703704bool readControlBlock(llvm::BitstreamCursor &Cursor,705llvm::SmallVectorImpl<uint64_t> &Scratch);706bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,707llvm::SmallVectorImpl<uint64_t> &Scratch);708bool readContextBlock(llvm::BitstreamCursor &Cursor,709llvm::SmallVectorImpl<uint64_t> &Scratch);710bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,711llvm::SmallVectorImpl<uint64_t> &Scratch);712bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,713llvm::SmallVectorImpl<uint64_t> &Scratch);714bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor,715llvm::SmallVectorImpl<uint64_t> &Scratch);716bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor,717llvm::SmallVectorImpl<uint64_t> &Scratch);718bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,719llvm::SmallVectorImpl<uint64_t> &Scratch);720bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,721llvm::SmallVectorImpl<uint64_t> &Scratch);722bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor,723llvm::SmallVectorImpl<uint64_t> &Scratch);724bool readTagBlock(llvm::BitstreamCursor &Cursor,725llvm::SmallVectorImpl<uint64_t> &Scratch);726bool readTypedefBlock(llvm::BitstreamCursor &Cursor,727llvm::SmallVectorImpl<uint64_t> &Scratch);728};729730std::optional<IdentifierID>731APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) {732if (!IdentifierTable)733return std::nullopt;734735if (Str.empty())736return IdentifierID(0);737738auto Known = IdentifierTable->find(Str);739if (Known == IdentifierTable->end())740return std::nullopt;741742return *Known;743}744745std::optional<SelectorID>746APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) {747if (!ObjCSelectorTable || !IdentifierTable)748return std::nullopt;749750// Translate the identifiers.751StoredObjCSelector Key;752Key.NumArgs = Selector.NumArgs;753for (auto Ident : Selector.Identifiers) {754if (auto IdentID = getIdentifier(Ident)) {755Key.Identifiers.push_back(*IdentID);756} else {757return std::nullopt;758}759}760761auto Known = ObjCSelectorTable->find(Key);762if (Known == ObjCSelectorTable->end())763return std::nullopt;764765return *Known;766}767768bool APINotesReader::Implementation::readControlBlock(769llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {770if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID))771return true;772773bool SawMetadata = false;774775llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();776if (!MaybeNext) {777// FIXME this drops the error on the floor.778consumeError(MaybeNext.takeError());779return false;780}781llvm::BitstreamEntry Next = MaybeNext.get();782783while (Next.Kind != llvm::BitstreamEntry::EndBlock) {784if (Next.Kind == llvm::BitstreamEntry::Error)785return true;786787if (Next.Kind == llvm::BitstreamEntry::SubBlock) {788// Unknown metadata sub-block, possibly for use by a future version of the789// API notes format.790if (Cursor.SkipBlock())791return true;792793MaybeNext = Cursor.advance();794if (!MaybeNext) {795// FIXME this drops the error on the floor.796consumeError(MaybeNext.takeError());797return false;798}799Next = MaybeNext.get();800continue;801}802803Scratch.clear();804llvm::StringRef BlobData;805llvm::Expected<unsigned> MaybeKind =806Cursor.readRecord(Next.ID, Scratch, &BlobData);807if (!MaybeKind) {808// FIXME this drops the error on the floor.809consumeError(MaybeKind.takeError());810return false;811}812unsigned Kind = MaybeKind.get();813814switch (Kind) {815case control_block::METADATA:816// Already saw metadata.817if (SawMetadata)818return true;819820if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)821return true;822823SawMetadata = true;824break;825826case control_block::MODULE_NAME:827ModuleName = BlobData.str();828break;829830case control_block::MODULE_OPTIONS:831break;832833case control_block::SOURCE_FILE:834SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};835break;836837default:838// Unknown metadata record, possibly for use by a future version of the839// module format.840break;841}842843MaybeNext = Cursor.advance();844if (!MaybeNext) {845// FIXME this drops the error on the floor.846consumeError(MaybeNext.takeError());847return false;848}849Next = MaybeNext.get();850}851852return !SawMetadata;853}854855bool APINotesReader::Implementation::readIdentifierBlock(856llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {857if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID))858return true;859860llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();861if (!MaybeNext) {862// FIXME this drops the error on the floor.863consumeError(MaybeNext.takeError());864return false;865}866llvm::BitstreamEntry Next = MaybeNext.get();867868while (Next.Kind != llvm::BitstreamEntry::EndBlock) {869if (Next.Kind == llvm::BitstreamEntry::Error)870return true;871872if (Next.Kind == llvm::BitstreamEntry::SubBlock) {873// Unknown sub-block, possibly for use by a future version of the874// API notes format.875if (Cursor.SkipBlock())876return true;877878MaybeNext = Cursor.advance();879if (!MaybeNext) {880// FIXME this drops the error on the floor.881consumeError(MaybeNext.takeError());882return false;883}884Next = MaybeNext.get();885continue;886}887888Scratch.clear();889llvm::StringRef BlobData;890llvm::Expected<unsigned> MaybeKind =891Cursor.readRecord(Next.ID, Scratch, &BlobData);892if (!MaybeKind) {893// FIXME this drops the error on the floor.894consumeError(MaybeKind.takeError());895return false;896}897unsigned Kind = MaybeKind.get();898switch (Kind) {899case identifier_block::IDENTIFIER_DATA: {900// Already saw identifier table.901if (IdentifierTable)902return true;903904uint32_t tableOffset;905identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);906auto base = reinterpret_cast<const uint8_t *>(BlobData.data());907908IdentifierTable.reset(SerializedIdentifierTable::Create(909base + tableOffset, base + sizeof(uint32_t), base));910break;911}912913default:914// Unknown record, possibly for use by a future version of the915// module format.916break;917}918919MaybeNext = Cursor.advance();920if (!MaybeNext) {921// FIXME this drops the error on the floor.922consumeError(MaybeNext.takeError());923return false;924}925Next = MaybeNext.get();926}927928return false;929}930931bool APINotesReader::Implementation::readContextBlock(932llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {933if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))934return true;935936llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();937if (!MaybeNext) {938// FIXME this drops the error on the floor.939consumeError(MaybeNext.takeError());940return false;941}942llvm::BitstreamEntry Next = MaybeNext.get();943944while (Next.Kind != llvm::BitstreamEntry::EndBlock) {945if (Next.Kind == llvm::BitstreamEntry::Error)946return true;947948if (Next.Kind == llvm::BitstreamEntry::SubBlock) {949// Unknown sub-block, possibly for use by a future version of the950// API notes format.951if (Cursor.SkipBlock())952return true;953954MaybeNext = Cursor.advance();955if (!MaybeNext) {956// FIXME this drops the error on the floor.957consumeError(MaybeNext.takeError());958return false;959}960Next = MaybeNext.get();961continue;962}963964Scratch.clear();965llvm::StringRef BlobData;966llvm::Expected<unsigned> MaybeKind =967Cursor.readRecord(Next.ID, Scratch, &BlobData);968if (!MaybeKind) {969// FIXME this drops the error on the floor.970consumeError(MaybeKind.takeError());971return false;972}973unsigned Kind = MaybeKind.get();974switch (Kind) {975case context_block::CONTEXT_ID_DATA: {976// Already saw Objective-C / C++ context ID table.977if (ContextIDTable)978return true;979980uint32_t tableOffset;981context_block::ContextIDLayout::readRecord(Scratch, tableOffset);982auto base = reinterpret_cast<const uint8_t *>(BlobData.data());983984ContextIDTable.reset(SerializedContextIDTable::Create(985base + tableOffset, base + sizeof(uint32_t), base));986break;987}988989case context_block::CONTEXT_INFO_DATA: {990// Already saw Objective-C / C++ context info table.991if (ContextInfoTable)992return true;993994uint32_t tableOffset;995context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);996auto base = reinterpret_cast<const uint8_t *>(BlobData.data());997998ContextInfoTable.reset(SerializedContextInfoTable::Create(999base + tableOffset, base + sizeof(uint32_t), base));1000break;1001}10021003default:1004// Unknown record, possibly for use by a future version of the1005// module format.1006break;1007}10081009MaybeNext = Cursor.advance();1010if (!MaybeNext) {1011// FIXME this drops the error on the floor.1012consumeError(MaybeNext.takeError());1013return false;1014}1015Next = MaybeNext.get();1016}10171018return false;1019}10201021bool APINotesReader::Implementation::readObjCPropertyBlock(1022llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1023if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID))1024return true;10251026llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1027if (!MaybeNext) {1028// FIXME this drops the error on the floor.1029consumeError(MaybeNext.takeError());1030return false;1031}1032llvm::BitstreamEntry Next = MaybeNext.get();10331034while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1035if (Next.Kind == llvm::BitstreamEntry::Error)1036return true;10371038if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1039// Unknown sub-block, possibly for use by a future version of the1040// API notes format.1041if (Cursor.SkipBlock())1042return true;10431044MaybeNext = Cursor.advance();1045if (!MaybeNext) {1046// FIXME this drops the error on the floor.1047consumeError(MaybeNext.takeError());1048return false;1049}1050Next = MaybeNext.get();1051continue;1052}10531054Scratch.clear();1055llvm::StringRef BlobData;1056llvm::Expected<unsigned> MaybeKind =1057Cursor.readRecord(Next.ID, Scratch, &BlobData);1058if (!MaybeKind) {1059// FIXME this drops the error on the floor.1060consumeError(MaybeKind.takeError());1061return false;1062}1063unsigned Kind = MaybeKind.get();1064switch (Kind) {1065case objc_property_block::OBJC_PROPERTY_DATA: {1066// Already saw Objective-C property table.1067if (ObjCPropertyTable)1068return true;10691070uint32_t tableOffset;1071objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,1072tableOffset);1073auto base = reinterpret_cast<const uint8_t *>(BlobData.data());10741075ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(1076base + tableOffset, base + sizeof(uint32_t), base));1077break;1078}10791080default:1081// Unknown record, possibly for use by a future version of the1082// module format.1083break;1084}10851086MaybeNext = Cursor.advance();1087if (!MaybeNext) {1088// FIXME this drops the error on the floor.1089consumeError(MaybeNext.takeError());1090return false;1091}1092Next = MaybeNext.get();1093}10941095return false;1096}10971098bool APINotesReader::Implementation::readObjCMethodBlock(1099llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1100if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID))1101return true;11021103llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1104if (!MaybeNext) {1105// FIXME this drops the error on the floor.1106consumeError(MaybeNext.takeError());1107return false;1108}1109llvm::BitstreamEntry Next = MaybeNext.get();1110while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1111if (Next.Kind == llvm::BitstreamEntry::Error)1112return true;11131114if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1115// Unknown sub-block, possibly for use by a future version of the1116// API notes format.1117if (Cursor.SkipBlock())1118return true;11191120MaybeNext = Cursor.advance();1121if (!MaybeNext) {1122// FIXME this drops the error on the floor.1123consumeError(MaybeNext.takeError());1124return false;1125}1126Next = MaybeNext.get();1127continue;1128}11291130Scratch.clear();1131llvm::StringRef BlobData;1132llvm::Expected<unsigned> MaybeKind =1133Cursor.readRecord(Next.ID, Scratch, &BlobData);1134if (!MaybeKind) {1135// FIXME this drops the error on the floor.1136consumeError(MaybeKind.takeError());1137return false;1138}1139unsigned Kind = MaybeKind.get();1140switch (Kind) {1141case objc_method_block::OBJC_METHOD_DATA: {1142// Already saw Objective-C method table.1143if (ObjCMethodTable)1144return true;11451146uint32_t tableOffset;1147objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);1148auto base = reinterpret_cast<const uint8_t *>(BlobData.data());11491150ObjCMethodTable.reset(SerializedObjCMethodTable::Create(1151base + tableOffset, base + sizeof(uint32_t), base));1152break;1153}11541155default:1156// Unknown record, possibly for use by a future version of the1157// module format.1158break;1159}11601161MaybeNext = Cursor.advance();1162if (!MaybeNext) {1163// FIXME this drops the error on the floor.1164consumeError(MaybeNext.takeError());1165return false;1166}1167Next = MaybeNext.get();1168}11691170return false;1171}11721173bool APINotesReader::Implementation::readCXXMethodBlock(1174llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1175if (Cursor.EnterSubBlock(CXX_METHOD_BLOCK_ID))1176return true;11771178llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1179if (!MaybeNext) {1180// FIXME this drops the error on the floor.1181consumeError(MaybeNext.takeError());1182return false;1183}1184llvm::BitstreamEntry Next = MaybeNext.get();1185while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1186if (Next.Kind == llvm::BitstreamEntry::Error)1187return true;11881189if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1190// Unknown sub-block, possibly for use by a future version of the1191// API notes format.1192if (Cursor.SkipBlock())1193return true;11941195MaybeNext = Cursor.advance();1196if (!MaybeNext) {1197// FIXME this drops the error on the floor.1198consumeError(MaybeNext.takeError());1199return false;1200}1201Next = MaybeNext.get();1202continue;1203}12041205Scratch.clear();1206llvm::StringRef BlobData;1207llvm::Expected<unsigned> MaybeKind =1208Cursor.readRecord(Next.ID, Scratch, &BlobData);1209if (!MaybeKind) {1210// FIXME this drops the error on the floor.1211consumeError(MaybeKind.takeError());1212return false;1213}1214unsigned Kind = MaybeKind.get();1215switch (Kind) {1216case cxx_method_block::CXX_METHOD_DATA: {1217// Already saw C++ method table.1218if (CXXMethodTable)1219return true;12201221uint32_t tableOffset;1222cxx_method_block::CXXMethodDataLayout::readRecord(Scratch, tableOffset);1223auto base = reinterpret_cast<const uint8_t *>(BlobData.data());12241225CXXMethodTable.reset(SerializedCXXMethodTable::Create(1226base + tableOffset, base + sizeof(uint32_t), base));1227break;1228}12291230default:1231// Unknown record, possibly for use by a future version of the1232// module format.1233break;1234}12351236MaybeNext = Cursor.advance();1237if (!MaybeNext) {1238// FIXME this drops the error on the floor.1239consumeError(MaybeNext.takeError());1240return false;1241}1242Next = MaybeNext.get();1243}12441245return false;1246}12471248bool APINotesReader::Implementation::readObjCSelectorBlock(1249llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1250if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID))1251return true;12521253llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1254if (!MaybeNext) {1255// FIXME this drops the error on the floor.1256consumeError(MaybeNext.takeError());1257return false;1258}1259llvm::BitstreamEntry Next = MaybeNext.get();1260while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1261if (Next.Kind == llvm::BitstreamEntry::Error)1262return true;12631264if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1265// Unknown sub-block, possibly for use by a future version of the1266// API notes format.1267if (Cursor.SkipBlock())1268return true;12691270MaybeNext = Cursor.advance();1271if (!MaybeNext) {1272// FIXME this drops the error on the floor.1273consumeError(MaybeNext.takeError());1274return false;1275}1276Next = MaybeNext.get();1277continue;1278}12791280Scratch.clear();1281llvm::StringRef BlobData;1282llvm::Expected<unsigned> MaybeKind =1283Cursor.readRecord(Next.ID, Scratch, &BlobData);1284if (!MaybeKind) {1285// FIXME this drops the error on the floor.1286consumeError(MaybeKind.takeError());1287return false;1288}1289unsigned Kind = MaybeKind.get();1290switch (Kind) {1291case objc_selector_block::OBJC_SELECTOR_DATA: {1292// Already saw Objective-C selector table.1293if (ObjCSelectorTable)1294return true;12951296uint32_t tableOffset;1297objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,1298tableOffset);1299auto base = reinterpret_cast<const uint8_t *>(BlobData.data());13001301ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(1302base + tableOffset, base + sizeof(uint32_t), base));1303break;1304}13051306default:1307// Unknown record, possibly for use by a future version of the1308// module format.1309break;1310}13111312MaybeNext = Cursor.advance();1313if (!MaybeNext) {1314// FIXME this drops the error on the floor.1315consumeError(MaybeNext.takeError());1316return false;1317}1318Next = MaybeNext.get();1319}13201321return false;1322}13231324bool APINotesReader::Implementation::readGlobalVariableBlock(1325llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1326if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID))1327return true;13281329llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1330if (!MaybeNext) {1331// FIXME this drops the error on the floor.1332consumeError(MaybeNext.takeError());1333return false;1334}1335llvm::BitstreamEntry Next = MaybeNext.get();1336while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1337if (Next.Kind == llvm::BitstreamEntry::Error)1338return true;13391340if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1341// Unknown sub-block, possibly for use by a future version of the1342// API notes format.1343if (Cursor.SkipBlock())1344return true;13451346MaybeNext = Cursor.advance();1347if (!MaybeNext) {1348// FIXME this drops the error on the floor.1349consumeError(MaybeNext.takeError());1350return false;1351}1352Next = MaybeNext.get();1353continue;1354}13551356Scratch.clear();1357llvm::StringRef BlobData;1358llvm::Expected<unsigned> MaybeKind =1359Cursor.readRecord(Next.ID, Scratch, &BlobData);1360if (!MaybeKind) {1361// FIXME this drops the error on the floor.1362consumeError(MaybeKind.takeError());1363return false;1364}1365unsigned Kind = MaybeKind.get();1366switch (Kind) {1367case global_variable_block::GLOBAL_VARIABLE_DATA: {1368// Already saw global variable table.1369if (GlobalVariableTable)1370return true;13711372uint32_t tableOffset;1373global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,1374tableOffset);1375auto base = reinterpret_cast<const uint8_t *>(BlobData.data());13761377GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(1378base + tableOffset, base + sizeof(uint32_t), base));1379break;1380}13811382default:1383// Unknown record, possibly for use by a future version of the1384// module format.1385break;1386}13871388MaybeNext = Cursor.advance();1389if (!MaybeNext) {1390// FIXME this drops the error on the floor.1391consumeError(MaybeNext.takeError());1392return false;1393}1394Next = MaybeNext.get();1395}13961397return false;1398}13991400bool APINotesReader::Implementation::readGlobalFunctionBlock(1401llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1402if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID))1403return true;14041405llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1406if (!MaybeNext) {1407// FIXME this drops the error on the floor.1408consumeError(MaybeNext.takeError());1409return false;1410}1411llvm::BitstreamEntry Next = MaybeNext.get();1412while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1413if (Next.Kind == llvm::BitstreamEntry::Error)1414return true;14151416if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1417// Unknown sub-block, possibly for use by a future version of the1418// API notes format.1419if (Cursor.SkipBlock())1420return true;14211422MaybeNext = Cursor.advance();1423if (!MaybeNext) {1424// FIXME this drops the error on the floor.1425consumeError(MaybeNext.takeError());1426return false;1427}1428Next = MaybeNext.get();1429continue;1430}14311432Scratch.clear();1433llvm::StringRef BlobData;1434llvm::Expected<unsigned> MaybeKind =1435Cursor.readRecord(Next.ID, Scratch, &BlobData);1436if (!MaybeKind) {1437// FIXME this drops the error on the floor.1438consumeError(MaybeKind.takeError());1439return false;1440}1441unsigned Kind = MaybeKind.get();1442switch (Kind) {1443case global_function_block::GLOBAL_FUNCTION_DATA: {1444// Already saw global function table.1445if (GlobalFunctionTable)1446return true;14471448uint32_t tableOffset;1449global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,1450tableOffset);1451auto base = reinterpret_cast<const uint8_t *>(BlobData.data());14521453GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(1454base + tableOffset, base + sizeof(uint32_t), base));1455break;1456}14571458default:1459// Unknown record, possibly for use by a future version of the1460// module format.1461break;1462}14631464MaybeNext = Cursor.advance();1465if (!MaybeNext) {1466// FIXME this drops the error on the floor.1467consumeError(MaybeNext.takeError());1468return false;1469}1470Next = MaybeNext.get();1471}14721473return false;1474}14751476bool APINotesReader::Implementation::readEnumConstantBlock(1477llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1478if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID))1479return true;14801481llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1482if (!MaybeNext) {1483// FIXME this drops the error on the floor.1484consumeError(MaybeNext.takeError());1485return false;1486}1487llvm::BitstreamEntry Next = MaybeNext.get();1488while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1489if (Next.Kind == llvm::BitstreamEntry::Error)1490return true;14911492if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1493// Unknown sub-block, possibly for use by a future version of the1494// API notes format.1495if (Cursor.SkipBlock())1496return true;14971498MaybeNext = Cursor.advance();1499if (!MaybeNext) {1500// FIXME this drops the error on the floor.1501consumeError(MaybeNext.takeError());1502return false;1503}1504Next = MaybeNext.get();1505continue;1506}15071508Scratch.clear();1509llvm::StringRef BlobData;1510llvm::Expected<unsigned> MaybeKind =1511Cursor.readRecord(Next.ID, Scratch, &BlobData);1512if (!MaybeKind) {1513// FIXME this drops the error on the floor.1514consumeError(MaybeKind.takeError());1515return false;1516}1517unsigned Kind = MaybeKind.get();1518switch (Kind) {1519case enum_constant_block::ENUM_CONSTANT_DATA: {1520// Already saw enumerator table.1521if (EnumConstantTable)1522return true;15231524uint32_t tableOffset;1525enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,1526tableOffset);1527auto base = reinterpret_cast<const uint8_t *>(BlobData.data());15281529EnumConstantTable.reset(SerializedEnumConstantTable::Create(1530base + tableOffset, base + sizeof(uint32_t), base));1531break;1532}15331534default:1535// Unknown record, possibly for use by a future version of the1536// module format.1537break;1538}15391540MaybeNext = Cursor.advance();1541if (!MaybeNext) {1542// FIXME this drops the error on the floor.1543consumeError(MaybeNext.takeError());1544return false;1545}1546Next = MaybeNext.get();1547}15481549return false;1550}15511552bool APINotesReader::Implementation::readTagBlock(1553llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1554if (Cursor.EnterSubBlock(TAG_BLOCK_ID))1555return true;15561557llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1558if (!MaybeNext) {1559// FIXME this drops the error on the floor.1560consumeError(MaybeNext.takeError());1561return false;1562}1563llvm::BitstreamEntry Next = MaybeNext.get();1564while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1565if (Next.Kind == llvm::BitstreamEntry::Error)1566return true;15671568if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1569// Unknown sub-block, possibly for use by a future version of the1570// API notes format.1571if (Cursor.SkipBlock())1572return true;15731574MaybeNext = Cursor.advance();1575if (!MaybeNext) {1576// FIXME this drops the error on the floor.1577consumeError(MaybeNext.takeError());1578return false;1579}1580Next = MaybeNext.get();1581continue;1582}15831584Scratch.clear();1585llvm::StringRef BlobData;1586llvm::Expected<unsigned> MaybeKind =1587Cursor.readRecord(Next.ID, Scratch, &BlobData);1588if (!MaybeKind) {1589// FIXME this drops the error on the floor.1590consumeError(MaybeKind.takeError());1591return false;1592}1593unsigned Kind = MaybeKind.get();1594switch (Kind) {1595case tag_block::TAG_DATA: {1596// Already saw tag table.1597if (TagTable)1598return true;15991600uint32_t tableOffset;1601tag_block::TagDataLayout::readRecord(Scratch, tableOffset);1602auto base = reinterpret_cast<const uint8_t *>(BlobData.data());16031604TagTable.reset(SerializedTagTable::Create(base + tableOffset,1605base + sizeof(uint32_t), base));1606break;1607}16081609default:1610// Unknown record, possibly for use by a future version of the1611// module format.1612break;1613}16141615MaybeNext = Cursor.advance();1616if (!MaybeNext) {1617// FIXME this drops the error on the floor.1618consumeError(MaybeNext.takeError());1619return false;1620}1621Next = MaybeNext.get();1622}16231624return false;1625}16261627bool APINotesReader::Implementation::readTypedefBlock(1628llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {1629if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID))1630return true;16311632llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();1633if (!MaybeNext) {1634// FIXME this drops the error on the floor.1635consumeError(MaybeNext.takeError());1636return false;1637}1638llvm::BitstreamEntry Next = MaybeNext.get();1639while (Next.Kind != llvm::BitstreamEntry::EndBlock) {1640if (Next.Kind == llvm::BitstreamEntry::Error)1641return true;16421643if (Next.Kind == llvm::BitstreamEntry::SubBlock) {1644// Unknown sub-block, possibly for use by a future version of the1645// API notes format.1646if (Cursor.SkipBlock())1647return true;16481649MaybeNext = Cursor.advance();1650if (!MaybeNext) {1651// FIXME this drops the error on the floor.1652consumeError(MaybeNext.takeError());1653return false;1654}1655Next = MaybeNext.get();1656continue;1657}16581659Scratch.clear();1660llvm::StringRef BlobData;1661llvm::Expected<unsigned> MaybeKind =1662Cursor.readRecord(Next.ID, Scratch, &BlobData);1663if (!MaybeKind) {1664// FIXME this drops the error on the floor.1665consumeError(MaybeKind.takeError());1666return false;1667}1668unsigned Kind = MaybeKind.get();1669switch (Kind) {1670case typedef_block::TYPEDEF_DATA: {1671// Already saw typedef table.1672if (TypedefTable)1673return true;16741675uint32_t tableOffset;1676typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);1677auto base = reinterpret_cast<const uint8_t *>(BlobData.data());16781679TypedefTable.reset(SerializedTypedefTable::Create(1680base + tableOffset, base + sizeof(uint32_t), base));1681break;1682}16831684default:1685// Unknown record, possibly for use by a future version of the1686// module format.1687break;1688}16891690MaybeNext = Cursor.advance();1691if (!MaybeNext) {1692// FIXME this drops the error on the floor.1693consumeError(MaybeNext.takeError());1694return false;1695}1696Next = MaybeNext.get();1697}16981699return false;1700}17011702APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,1703llvm::VersionTuple SwiftVersion, bool &Failed)1704: Implementation(new class Implementation) {1705Failed = false;17061707// Initialize the input buffer.1708Implementation->InputBuffer = InputBuffer;1709Implementation->SwiftVersion = SwiftVersion;1710llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);17111712// Validate signature.1713for (auto byte : API_NOTES_SIGNATURE) {1714if (Cursor.AtEndOfStream()) {1715Failed = true;1716return;1717}1718if (llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead =1719Cursor.Read(8)) {1720if (maybeRead.get() != byte) {1721Failed = true;1722return;1723}1724} else {1725// FIXME this drops the error on the floor.1726consumeError(maybeRead.takeError());1727Failed = true;1728return;1729}1730}17311732// Look at all of the blocks.1733bool HasValidControlBlock = false;1734llvm::SmallVector<uint64_t, 64> Scratch;1735while (!Cursor.AtEndOfStream()) {1736llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();1737if (!MaybeTopLevelEntry) {1738// FIXME this drops the error on the floor.1739consumeError(MaybeTopLevelEntry.takeError());1740Failed = true;1741return;1742}1743llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();17441745if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)1746break;17471748switch (TopLevelEntry.ID) {1749case llvm::bitc::BLOCKINFO_BLOCK_ID:1750if (!Cursor.ReadBlockInfoBlock()) {1751Failed = true;1752break;1753}1754break;17551756case CONTROL_BLOCK_ID:1757// Only allow a single control block.1758if (HasValidControlBlock ||1759Implementation->readControlBlock(Cursor, Scratch)) {1760Failed = true;1761return;1762}17631764HasValidControlBlock = true;1765break;17661767case IDENTIFIER_BLOCK_ID:1768if (!HasValidControlBlock ||1769Implementation->readIdentifierBlock(Cursor, Scratch)) {1770Failed = true;1771return;1772}1773break;17741775case OBJC_CONTEXT_BLOCK_ID:1776if (!HasValidControlBlock ||1777Implementation->readContextBlock(Cursor, Scratch)) {1778Failed = true;1779return;1780}17811782break;17831784case OBJC_PROPERTY_BLOCK_ID:1785if (!HasValidControlBlock ||1786Implementation->readObjCPropertyBlock(Cursor, Scratch)) {1787Failed = true;1788return;1789}1790break;17911792case OBJC_METHOD_BLOCK_ID:1793if (!HasValidControlBlock ||1794Implementation->readObjCMethodBlock(Cursor, Scratch)) {1795Failed = true;1796return;1797}1798break;17991800case CXX_METHOD_BLOCK_ID:1801if (!HasValidControlBlock ||1802Implementation->readCXXMethodBlock(Cursor, Scratch)) {1803Failed = true;1804return;1805}1806break;18071808case OBJC_SELECTOR_BLOCK_ID:1809if (!HasValidControlBlock ||1810Implementation->readObjCSelectorBlock(Cursor, Scratch)) {1811Failed = true;1812return;1813}1814break;18151816case GLOBAL_VARIABLE_BLOCK_ID:1817if (!HasValidControlBlock ||1818Implementation->readGlobalVariableBlock(Cursor, Scratch)) {1819Failed = true;1820return;1821}1822break;18231824case GLOBAL_FUNCTION_BLOCK_ID:1825if (!HasValidControlBlock ||1826Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {1827Failed = true;1828return;1829}1830break;18311832case ENUM_CONSTANT_BLOCK_ID:1833if (!HasValidControlBlock ||1834Implementation->readEnumConstantBlock(Cursor, Scratch)) {1835Failed = true;1836return;1837}1838break;18391840case TAG_BLOCK_ID:1841if (!HasValidControlBlock ||1842Implementation->readTagBlock(Cursor, Scratch)) {1843Failed = true;1844return;1845}1846break;18471848case TYPEDEF_BLOCK_ID:1849if (!HasValidControlBlock ||1850Implementation->readTypedefBlock(Cursor, Scratch)) {1851Failed = true;1852return;1853}1854break;18551856default:1857// Unknown top-level block, possibly for use by a future version of the1858// module format.1859if (Cursor.SkipBlock()) {1860Failed = true;1861return;1862}1863break;1864}1865}18661867if (!Cursor.AtEndOfStream()) {1868Failed = true;1869return;1870}1871}18721873APINotesReader::~APINotesReader() { delete Implementation->InputBuffer; }18741875std::unique_ptr<APINotesReader>1876APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,1877llvm::VersionTuple SwiftVersion) {1878bool Failed = false;1879std::unique_ptr<APINotesReader> Reader(1880new APINotesReader(InputBuffer.release(), SwiftVersion, Failed));1881if (Failed)1882return nullptr;18831884return Reader;1885}18861887template <typename T>1888APINotesReader::VersionedInfo<T>::VersionedInfo(1889llvm::VersionTuple Version,1890llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)1891: Results(std::move(R)) {18921893assert(!Results.empty());1894assert(std::is_sorted(1895Results.begin(), Results.end(),1896[](const std::pair<llvm::VersionTuple, T> &left,1897const std::pair<llvm::VersionTuple, T> &right) -> bool {1898assert(left.first != right.first && "two entries for the same version");1899return left.first < right.first;1900}));19011902Selected = std::nullopt;1903for (unsigned i = 0, n = Results.size(); i != n; ++i) {1904if (!Version.empty() && Results[i].first >= Version) {1905// If the current version is "4", then entries for 4 are better than1906// entries for 5, but both are valid. Because entries are sorted, we get1907// that behavior by picking the first match.1908Selected = i;1909break;1910}1911}19121913// If we didn't find a match but we have an unversioned result, use the1914// unversioned result. This will always be the first entry because we encode1915// it as version 0.1916if (!Selected && Results[0].first.empty())1917Selected = 0;1918}19191920auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)1921-> std::optional<ContextID> {1922if (!Implementation->ContextIDTable)1923return std::nullopt;19241925std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);1926if (!ClassID)1927return std::nullopt;19281929// ObjC classes can't be declared in C++ namespaces, so use -1 as the global1930// context.1931auto KnownID = Implementation->ContextIDTable->find(1932ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));1933if (KnownID == Implementation->ContextIDTable->end())1934return std::nullopt;19351936return ContextID(*KnownID);1937}19381939auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)1940-> VersionedInfo<ContextInfo> {1941if (!Implementation->ContextInfoTable)1942return std::nullopt;19431944std::optional<ContextID> CtxID = lookupObjCClassID(Name);1945if (!CtxID)1946return std::nullopt;19471948auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);1949if (KnownInfo == Implementation->ContextInfoTable->end())1950return std::nullopt;19511952return {Implementation->SwiftVersion, *KnownInfo};1953}19541955auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)1956-> std::optional<ContextID> {1957if (!Implementation->ContextIDTable)1958return std::nullopt;19591960std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);1961if (!classID)1962return std::nullopt;19631964// ObjC classes can't be declared in C++ namespaces, so use -1 as the global1965// context.1966auto KnownID = Implementation->ContextIDTable->find(1967ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));1968if (KnownID == Implementation->ContextIDTable->end())1969return std::nullopt;19701971return ContextID(*KnownID);1972}19731974auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)1975-> VersionedInfo<ContextInfo> {1976if (!Implementation->ContextInfoTable)1977return std::nullopt;19781979std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);1980if (!CtxID)1981return std::nullopt;19821983auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);1984if (KnownInfo == Implementation->ContextInfoTable->end())1985return std::nullopt;19861987return {Implementation->SwiftVersion, *KnownInfo};1988}19891990auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,1991bool IsInstance)1992-> VersionedInfo<ObjCPropertyInfo> {1993if (!Implementation->ObjCPropertyTable)1994return std::nullopt;19951996std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name);1997if (!PropertyID)1998return std::nullopt;19992000auto Known = Implementation->ObjCPropertyTable->find(2001std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance));2002if (Known == Implementation->ObjCPropertyTable->end())2003return std::nullopt;20042005return {Implementation->SwiftVersion, *Known};2006}20072008auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,2009bool IsInstanceMethod)2010-> VersionedInfo<ObjCMethodInfo> {2011if (!Implementation->ObjCMethodTable)2012return std::nullopt;20132014std::optional<SelectorID> SelID = Implementation->getSelector(Selector);2015if (!SelID)2016return std::nullopt;20172018auto Known = Implementation->ObjCMethodTable->find(2019ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,2020IsInstanceMethod});2021if (Known == Implementation->ObjCMethodTable->end())2022return std::nullopt;20232024return {Implementation->SwiftVersion, *Known};2025}20262027auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)2028-> VersionedInfo<CXXMethodInfo> {2029if (!Implementation->CXXMethodTable)2030return std::nullopt;20312032std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);2033if (!NameID)2034return std::nullopt;20352036auto Known = Implementation->CXXMethodTable->find(2037SingleDeclTableKey(CtxID.Value, *NameID));2038if (Known == Implementation->CXXMethodTable->end())2039return std::nullopt;20402041return {Implementation->SwiftVersion, *Known};2042}20432044auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name,2045std::optional<Context> Ctx)2046-> VersionedInfo<GlobalVariableInfo> {2047if (!Implementation->GlobalVariableTable)2048return std::nullopt;20492050std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);2051if (!NameID)2052return std::nullopt;20532054SingleDeclTableKey Key(Ctx, *NameID);20552056auto Known = Implementation->GlobalVariableTable->find(Key);2057if (Known == Implementation->GlobalVariableTable->end())2058return std::nullopt;20592060return {Implementation->SwiftVersion, *Known};2061}20622063auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,2064std::optional<Context> Ctx)2065-> VersionedInfo<GlobalFunctionInfo> {2066if (!Implementation->GlobalFunctionTable)2067return std::nullopt;20682069std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);2070if (!NameID)2071return std::nullopt;20722073SingleDeclTableKey Key(Ctx, *NameID);20742075auto Known = Implementation->GlobalFunctionTable->find(Key);2076if (Known == Implementation->GlobalFunctionTable->end())2077return std::nullopt;20782079return {Implementation->SwiftVersion, *Known};2080}20812082auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)2083-> VersionedInfo<EnumConstantInfo> {2084if (!Implementation->EnumConstantTable)2085return std::nullopt;20862087std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);2088if (!NameID)2089return std::nullopt;20902091auto Known = Implementation->EnumConstantTable->find(*NameID);2092if (Known == Implementation->EnumConstantTable->end())2093return std::nullopt;20942095return {Implementation->SwiftVersion, *Known};2096}20972098auto APINotesReader::lookupTagID(llvm::StringRef Name,2099std::optional<Context> ParentCtx)2100-> std::optional<ContextID> {2101if (!Implementation->ContextIDTable)2102return std::nullopt;21032104std::optional<IdentifierID> TagID = Implementation->getIdentifier(Name);2105if (!TagID)2106return std::nullopt;21072108auto KnownID = Implementation->ContextIDTable->find(2109ContextTableKey(ParentCtx, ContextKind::Tag, *TagID));2110if (KnownID == Implementation->ContextIDTable->end())2111return std::nullopt;21122113return ContextID(*KnownID);2114}21152116auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)2117-> VersionedInfo<TagInfo> {2118if (!Implementation->TagTable)2119return std::nullopt;21202121std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);2122if (!NameID)2123return std::nullopt;21242125SingleDeclTableKey Key(Ctx, *NameID);21262127auto Known = Implementation->TagTable->find(Key);2128if (Known == Implementation->TagTable->end())2129return std::nullopt;21302131return {Implementation->SwiftVersion, *Known};2132}21332134auto APINotesReader::lookupTypedef(llvm::StringRef Name,2135std::optional<Context> Ctx)2136-> VersionedInfo<TypedefInfo> {2137if (!Implementation->TypedefTable)2138return std::nullopt;21392140std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);2141if (!NameID)2142return std::nullopt;21432144SingleDeclTableKey Key(Ctx, *NameID);21452146auto Known = Implementation->TypedefTable->find(Key);2147if (Known == Implementation->TypedefTable->end())2148return std::nullopt;21492150return {Implementation->SwiftVersion, *Known};2151}21522153auto APINotesReader::lookupNamespaceID(2154llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)2155-> std::optional<ContextID> {2156if (!Implementation->ContextIDTable)2157return std::nullopt;21582159std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);2160if (!NamespaceID)2161return std::nullopt;21622163uint32_t RawParentNamespaceID =2164ParentNamespaceID ? ParentNamespaceID->Value : -1;2165auto KnownID = Implementation->ContextIDTable->find(2166{RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});2167if (KnownID == Implementation->ContextIDTable->end())2168return std::nullopt;21692170return ContextID(*KnownID);2171}21722173} // namespace api_notes2174} // namespace clang217521762177