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
24namespace clang {
25namespace api_notes {
26using namespace llvm::support;
27
28namespace {
29/// Deserialize a version tuple.
30llvm::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.
51template <typename Derived, typename KeyType, typename UnversionedDataType>
52class VersionedTableInfo {
53public:
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.
97void 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.
120void 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.
141class IdentifierTableInfo {
142public:
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.
180class ObjCContextIDTableInfo {
181public:
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.
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>(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.
262void 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.
275class ObjCPropertyTableInfo
276 : public VersionedTableInfo<ObjCPropertyTableInfo,
277 std::tuple<uint32_t, uint32_t, uint8_t>,
278 ObjCPropertyInfo> {
279public:
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.
303void 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.
319void 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.
353class ObjCMethodTableInfo
354 : public VersionedTableInfo<ObjCMethodTableInfo,
355 std::tuple<uint32_t, uint32_t, uint8_t>,
356 ObjCMethodInfo> {
357public:
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.
385class ObjCSelectorTableInfo {
386public:
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.
431class GlobalVariableTableInfo
432 : public VersionedTableInfo<GlobalVariableTableInfo, ContextTableKey,
433 GlobalVariableInfo> {
434public:
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.
456class GlobalFunctionTableInfo
457 : public VersionedTableInfo<GlobalFunctionTableInfo, ContextTableKey,
458 GlobalFunctionInfo> {
459public:
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.
481class EnumConstantTableInfo
482 : public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
483 EnumConstantInfo> {
484public:
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.
503class TagTableInfo
504 : public VersionedTableInfo<TagTableInfo, ContextTableKey, TagInfo> {
505public:
506 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
507 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
508 auto 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.
565class TypedefTableInfo
566 : public VersionedTableInfo<TypedefTableInfo, ContextTableKey,
567 TypedefInfo> {
568public:
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
597public:
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
708std::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
723std::optional<SelectorID>
725 if (!ObjCSelectorTable || !IdentifierTable)
726 return std::nullopt;
727
728 // Translate the identifiers.
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
1606APINotesReader::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
1672 if (!HasValidControlBlock ||
1673 Implementation->readIdentifierBlock(Cursor, Scratch)) {
1674 Failed = true;
1675 return;
1676 }
1677 break;
1678
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
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
1771std::unique_ptr<APINotesReader>
1772APINotesReader::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
1783template <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
1816auto 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
1835auto 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
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
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
1886auto 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
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
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
1961auto 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
1977auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
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
1995auto 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)
__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:281
The JSON file list parser is used to communicate input to InstallAPI.
NullabilityKind
Describes the nullability of a particular type.
Definition: Specifiers.h:333
@ Result
The result type of a method or function.
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
Definition: Format.h:5394
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