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