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