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