clang 20.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 table of Objective-C classes and C++
180/// namespaces.
181class ContextIDTableInfo {
182public:
183 using internal_key_type = ContextTableKey;
184 using external_key_type = internal_key_type;
185 using data_type = unsigned;
186 using hash_value_type = size_t;
187 using offset_type = unsigned;
188
189 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
190
191 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
192
193 hash_value_type ComputeHash(internal_key_type Key) {
194 return static_cast<size_t>(Key.hashValue());
195 }
196
197 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
198 return LHS == RHS;
199 }
200
201 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
202 unsigned KeyLength =
203 endian::readNext<uint16_t, llvm::endianness::little>(Data);
204 unsigned DataLength =
205 endian::readNext<uint16_t, llvm::endianness::little>(Data);
206 return {KeyLength, DataLength};
207 }
208
209 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
210 auto ParentCtxID =
211 endian::readNext<uint32_t, llvm::endianness::little>(Data);
212 auto ContextKind =
213 endian::readNext<uint8_t, llvm::endianness::little>(Data);
214 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
215 return {ParentCtxID, ContextKind, NameID};
216 }
217
218 static data_type ReadData(internal_key_type Key, const uint8_t *Data,
219 unsigned Length) {
220 return endian::readNext<uint32_t, llvm::endianness::little>(Data);
221 }
222};
223
224/// Used to deserialize the on-disk Objective-C property table.
225class ContextInfoTableInfo
226 : public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
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 ContextInfo readUnversioned(internal_key_type Key,
237 const uint8_t *&Data) {
238 ContextInfo 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, SingleDeclTableKey,
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 NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
438 return {CtxID, NameID};
439 }
440
441 hash_value_type ComputeHash(internal_key_type Key) {
442 return static_cast<size_t>(Key.hashValue());
443 }
444
445 static GlobalVariableInfo readUnversioned(internal_key_type Key,
446 const uint8_t *&Data) {
447 GlobalVariableInfo Info;
448 ReadVariableInfo(Data, Info);
449 return Info;
450 }
451};
452
453/// Used to deserialize the on-disk global function table.
454class GlobalFunctionTableInfo
455 : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
456 GlobalFunctionInfo> {
457public:
458 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
459 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
460 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
461 return {CtxID, NameID};
462 }
463
464 hash_value_type ComputeHash(internal_key_type Key) {
465 return static_cast<size_t>(Key.hashValue());
466 }
467
468 static GlobalFunctionInfo readUnversioned(internal_key_type Key,
469 const uint8_t *&Data) {
470 GlobalFunctionInfo Info;
471 ReadFunctionInfo(Data, Info);
472 return Info;
473 }
474};
475
476/// Used to deserialize the on-disk C++ method table.
477class CXXMethodTableInfo
478 : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
479 CXXMethodInfo> {
480public:
481 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
482 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
483 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
484 return {CtxID, NameID};
485 }
486
487 hash_value_type ComputeHash(internal_key_type Key) {
488 return static_cast<size_t>(Key.hashValue());
489 }
490
491 static CXXMethodInfo readUnversioned(internal_key_type Key,
492 const uint8_t *&Data) {
493 CXXMethodInfo Info;
494 ReadFunctionInfo(Data, Info);
495 return Info;
496 }
497};
498
499/// Used to deserialize the on-disk enumerator table.
500class EnumConstantTableInfo
501 : public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
502 EnumConstantInfo> {
503public:
504 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
505 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
506 return NameID;
507 }
508
509 hash_value_type ComputeHash(internal_key_type Key) {
510 return static_cast<size_t>(llvm::hash_value(Key));
511 }
512
513 static EnumConstantInfo readUnversioned(internal_key_type Key,
514 const uint8_t *&Data) {
515 EnumConstantInfo Info;
516 ReadCommonEntityInfo(Data, Info);
517 return Info;
518 }
519};
520
521/// Used to deserialize the on-disk tag table.
522class TagTableInfo
523 : public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> {
524public:
525 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
526 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
527 auto NameID =
528 endian::readNext<IdentifierID, llvm::endianness::little>(Data);
529 return {CtxID, NameID};
530 }
531
532 hash_value_type ComputeHash(internal_key_type Key) {
533 return static_cast<size_t>(Key.hashValue());
534 }
535
536 static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {
537 TagInfo Info;
538
539 uint8_t Payload = *Data++;
540 if (Payload & 1)
541 Info.setFlagEnum(Payload & 2);
542 Payload >>= 2;
543 if (Payload > 0)
544 Info.EnumExtensibility =
545 static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);
546
547 uint8_t Copyable =
548 endian::readNext<uint8_t, llvm::endianness::little>(Data);
549 if (Copyable == kSwiftNonCopyable)
550 Info.setSwiftCopyable(std::optional(false));
551 else if (Copyable == kSwiftCopyable)
552 Info.setSwiftCopyable(std::optional(true));
553
554 unsigned ImportAsLength =
555 endian::readNext<uint16_t, llvm::endianness::little>(Data);
556 if (ImportAsLength > 0) {
557 Info.SwiftImportAs =
558 std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1);
559 Data += ImportAsLength - 1;
560 }
561 unsigned RetainOpLength =
562 endian::readNext<uint16_t, llvm::endianness::little>(Data);
563 if (RetainOpLength > 0) {
564 Info.SwiftRetainOp =
565 std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1);
566 Data += RetainOpLength - 1;
567 }
568 unsigned ReleaseOpLength =
569 endian::readNext<uint16_t, llvm::endianness::little>(Data);
570 if (ReleaseOpLength > 0) {
571 Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data),
572 ReleaseOpLength - 1);
573 Data += ReleaseOpLength - 1;
574 }
575 if (unsigned ConformanceLength =
576 endian::readNext<uint16_t, llvm::endianness::little>(Data)) {
577 Info.SwiftConformance = std::string(reinterpret_cast<const char *>(Data),
578 ConformanceLength - 1);
579 Data += ConformanceLength - 1;
580 }
581
582 ReadCommonTypeInfo(Data, Info);
583 return Info;
584 }
585};
586
587/// Used to deserialize the on-disk typedef table.
588class TypedefTableInfo
589 : public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey,
590 TypedefInfo> {
591public:
592 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
593 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
594 auto nameID =
595 endian::readNext<IdentifierID, llvm::endianness::little>(Data);
596 return {CtxID, nameID};
597 }
598
599 hash_value_type ComputeHash(internal_key_type Key) {
600 return static_cast<size_t>(Key.hashValue());
601 }
602
603 static TypedefInfo readUnversioned(internal_key_type Key,
604 const uint8_t *&Data) {
605 TypedefInfo Info;
606
607 uint8_t Payload = *Data++;
608 if (Payload > 0)
609 Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);
610
611 ReadCommonTypeInfo(Data, Info);
612 return Info;
613 }
614};
615} // end anonymous namespace
616
618public:
619 /// The input buffer for the API notes data.
620 llvm::MemoryBuffer *InputBuffer;
621
622 /// The Swift version to use for filtering.
623 llvm::VersionTuple SwiftVersion;
624
625 /// The name of the module that we read from the control block.
626 std::string ModuleName;
627
628 // The size and modification time of the source file from
629 // which this API notes file was created, if known.
630 std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime;
631
633 llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;
634
635 /// The identifier table.
636 std::unique_ptr<SerializedIdentifierTable> IdentifierTable;
637
639 llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;
640
641 /// The Objective-C / C++ context ID table.
642 std::unique_ptr<SerializedContextIDTable> ContextIDTable;
643
645 llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;
646
647 /// The Objective-C context info table.
648 std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;
649
651 llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
652
653 /// The Objective-C property table.
654 std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;
655
657 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
658
659 /// The Objective-C method table.
660 std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
661
663 llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
664
665 /// The C++ method table.
666 std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
667
669 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
670
671 /// The Objective-C selector table.
672 std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;
673
675 llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;
676
677 /// The global variable table.
678 std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;
679
681 llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;
682
683 /// The global function table.
684 std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;
685
687 llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
688
689 /// The enumerator table.
690 std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;
691
692 using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;
693
694 /// The tag table.
695 std::unique_ptr<SerializedTagTable> TagTable;
696
698 llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;
699
700 /// The typedef table.
701 std::unique_ptr<SerializedTypedefTable> TypedefTable;
702
703 /// Retrieve the identifier ID for the given string, or an empty
704 /// optional if the string is unknown.
705 std::optional<IdentifierID> getIdentifier(llvm::StringRef Str);
706
707 /// Retrieve the selector ID for the given selector, or an empty
708 /// optional if the string is unknown.
709 std::optional<SelectorID> getSelector(ObjCSelectorRef Selector);
710
711 bool readControlBlock(llvm::BitstreamCursor &Cursor,
713 bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,
715 bool readContextBlock(llvm::BitstreamCursor &Cursor,
717 bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
719 bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
721 bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor,
723 bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor,
725 bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,
727 bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
729 bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor,
731 bool readTagBlock(llvm::BitstreamCursor &Cursor,
733 bool readTypedefBlock(llvm::BitstreamCursor &Cursor,
735};
736
737std::optional<IdentifierID>
739 if (!IdentifierTable)
740 return std::nullopt;
741
742 if (Str.empty())
743 return IdentifierID(0);
744
745 auto Known = IdentifierTable->find(Str);
746 if (Known == IdentifierTable->end())
747 return std::nullopt;
748
749 return *Known;
750}
751
752std::optional<SelectorID>
754 if (!ObjCSelectorTable || !IdentifierTable)
755 return std::nullopt;
756
757 // Translate the identifiers.
759 Key.NumArgs = Selector.NumArgs;
760 for (auto Ident : Selector.Identifiers) {
761 if (auto IdentID = getIdentifier(Ident)) {
762 Key.Identifiers.push_back(*IdentID);
763 } else {
764 return std::nullopt;
765 }
766 }
767
768 auto Known = ObjCSelectorTable->find(Key);
769 if (Known == ObjCSelectorTable->end())
770 return std::nullopt;
771
772 return *Known;
773}
774
776 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
777 if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID))
778 return true;
779
780 bool SawMetadata = false;
781
782 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
783 if (!MaybeNext) {
784 // FIXME this drops the error on the floor.
785 consumeError(MaybeNext.takeError());
786 return false;
787 }
788 llvm::BitstreamEntry Next = MaybeNext.get();
789
790 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
791 if (Next.Kind == llvm::BitstreamEntry::Error)
792 return true;
793
794 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
795 // Unknown metadata sub-block, possibly for use by a future version of the
796 // API notes format.
797 if (Cursor.SkipBlock())
798 return true;
799
800 MaybeNext = Cursor.advance();
801 if (!MaybeNext) {
802 // FIXME this drops the error on the floor.
803 consumeError(MaybeNext.takeError());
804 return false;
805 }
806 Next = MaybeNext.get();
807 continue;
808 }
809
810 Scratch.clear();
811 llvm::StringRef BlobData;
812 llvm::Expected<unsigned> MaybeKind =
813 Cursor.readRecord(Next.ID, Scratch, &BlobData);
814 if (!MaybeKind) {
815 // FIXME this drops the error on the floor.
816 consumeError(MaybeKind.takeError());
817 return false;
818 }
819 unsigned Kind = MaybeKind.get();
820
821 switch (Kind) {
823 // Already saw metadata.
824 if (SawMetadata)
825 return true;
826
827 if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)
828 return true;
829
830 SawMetadata = true;
831 break;
832
834 ModuleName = BlobData.str();
835 break;
836
838 break;
839
841 SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
842 break;
843
844 default:
845 // Unknown metadata record, possibly for use by a future version of the
846 // module format.
847 break;
848 }
849
850 MaybeNext = Cursor.advance();
851 if (!MaybeNext) {
852 // FIXME this drops the error on the floor.
853 consumeError(MaybeNext.takeError());
854 return false;
855 }
856 Next = MaybeNext.get();
857 }
858
859 return !SawMetadata;
860}
861
863 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
864 if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID))
865 return true;
866
867 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
868 if (!MaybeNext) {
869 // FIXME this drops the error on the floor.
870 consumeError(MaybeNext.takeError());
871 return false;
872 }
873 llvm::BitstreamEntry Next = MaybeNext.get();
874
875 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
876 if (Next.Kind == llvm::BitstreamEntry::Error)
877 return true;
878
879 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
880 // Unknown sub-block, possibly for use by a future version of the
881 // API notes format.
882 if (Cursor.SkipBlock())
883 return true;
884
885 MaybeNext = Cursor.advance();
886 if (!MaybeNext) {
887 // FIXME this drops the error on the floor.
888 consumeError(MaybeNext.takeError());
889 return false;
890 }
891 Next = MaybeNext.get();
892 continue;
893 }
894
895 Scratch.clear();
896 llvm::StringRef BlobData;
897 llvm::Expected<unsigned> MaybeKind =
898 Cursor.readRecord(Next.ID, Scratch, &BlobData);
899 if (!MaybeKind) {
900 // FIXME this drops the error on the floor.
901 consumeError(MaybeKind.takeError());
902 return false;
903 }
904 unsigned Kind = MaybeKind.get();
905 switch (Kind) {
907 // Already saw identifier table.
908 if (IdentifierTable)
909 return true;
910
911 uint32_t tableOffset;
912 identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);
913 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
914
915 IdentifierTable.reset(SerializedIdentifierTable::Create(
916 base + tableOffset, base + sizeof(uint32_t), base));
917 break;
918 }
919
920 default:
921 // Unknown record, possibly for use by a future version of the
922 // module format.
923 break;
924 }
925
926 MaybeNext = Cursor.advance();
927 if (!MaybeNext) {
928 // FIXME this drops the error on the floor.
929 consumeError(MaybeNext.takeError());
930 return false;
931 }
932 Next = MaybeNext.get();
933 }
934
935 return false;
936}
937
939 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
940 if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
941 return true;
942
943 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
944 if (!MaybeNext) {
945 // FIXME this drops the error on the floor.
946 consumeError(MaybeNext.takeError());
947 return false;
948 }
949 llvm::BitstreamEntry Next = MaybeNext.get();
950
951 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
952 if (Next.Kind == llvm::BitstreamEntry::Error)
953 return true;
954
955 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
956 // Unknown sub-block, possibly for use by a future version of the
957 // API notes format.
958 if (Cursor.SkipBlock())
959 return true;
960
961 MaybeNext = Cursor.advance();
962 if (!MaybeNext) {
963 // FIXME this drops the error on the floor.
964 consumeError(MaybeNext.takeError());
965 return false;
966 }
967 Next = MaybeNext.get();
968 continue;
969 }
970
971 Scratch.clear();
972 llvm::StringRef BlobData;
973 llvm::Expected<unsigned> MaybeKind =
974 Cursor.readRecord(Next.ID, Scratch, &BlobData);
975 if (!MaybeKind) {
976 // FIXME this drops the error on the floor.
977 consumeError(MaybeKind.takeError());
978 return false;
979 }
980 unsigned Kind = MaybeKind.get();
981 switch (Kind) {
983 // Already saw Objective-C / C++ context ID table.
984 if (ContextIDTable)
985 return true;
986
987 uint32_t tableOffset;
988 context_block::ContextIDLayout::readRecord(Scratch, tableOffset);
989 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
990
991 ContextIDTable.reset(SerializedContextIDTable::Create(
992 base + tableOffset, base + sizeof(uint32_t), base));
993 break;
994 }
995
997 // Already saw Objective-C / C++ context info table.
998 if (ContextInfoTable)
999 return true;
1000
1001 uint32_t tableOffset;
1002 context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);
1003 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1004
1005 ContextInfoTable.reset(SerializedContextInfoTable::Create(
1006 base + tableOffset, base + sizeof(uint32_t), base));
1007 break;
1008 }
1009
1010 default:
1011 // Unknown record, possibly for use by a future version of the
1012 // module format.
1013 break;
1014 }
1015
1016 MaybeNext = Cursor.advance();
1017 if (!MaybeNext) {
1018 // FIXME this drops the error on the floor.
1019 consumeError(MaybeNext.takeError());
1020 return false;
1021 }
1022 Next = MaybeNext.get();
1023 }
1024
1025 return false;
1026}
1027
1029 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1030 if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID))
1031 return true;
1032
1033 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1034 if (!MaybeNext) {
1035 // FIXME this drops the error on the floor.
1036 consumeError(MaybeNext.takeError());
1037 return false;
1038 }
1039 llvm::BitstreamEntry Next = MaybeNext.get();
1040
1041 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1042 if (Next.Kind == llvm::BitstreamEntry::Error)
1043 return true;
1044
1045 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1046 // Unknown sub-block, possibly for use by a future version of the
1047 // API notes format.
1048 if (Cursor.SkipBlock())
1049 return true;
1050
1051 MaybeNext = Cursor.advance();
1052 if (!MaybeNext) {
1053 // FIXME this drops the error on the floor.
1054 consumeError(MaybeNext.takeError());
1055 return false;
1056 }
1057 Next = MaybeNext.get();
1058 continue;
1059 }
1060
1061 Scratch.clear();
1062 llvm::StringRef BlobData;
1063 llvm::Expected<unsigned> MaybeKind =
1064 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1065 if (!MaybeKind) {
1066 // FIXME this drops the error on the floor.
1067 consumeError(MaybeKind.takeError());
1068 return false;
1069 }
1070 unsigned Kind = MaybeKind.get();
1071 switch (Kind) {
1073 // Already saw Objective-C property table.
1074 if (ObjCPropertyTable)
1075 return true;
1076
1077 uint32_t tableOffset;
1078 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,
1079 tableOffset);
1080 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1081
1082 ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(
1083 base + tableOffset, base + sizeof(uint32_t), base));
1084 break;
1085 }
1086
1087 default:
1088 // Unknown record, possibly for use by a future version of the
1089 // module format.
1090 break;
1091 }
1092
1093 MaybeNext = Cursor.advance();
1094 if (!MaybeNext) {
1095 // FIXME this drops the error on the floor.
1096 consumeError(MaybeNext.takeError());
1097 return false;
1098 }
1099 Next = MaybeNext.get();
1100 }
1101
1102 return false;
1103}
1104
1106 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1107 if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID))
1108 return true;
1109
1110 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1111 if (!MaybeNext) {
1112 // FIXME this drops the error on the floor.
1113 consumeError(MaybeNext.takeError());
1114 return false;
1115 }
1116 llvm::BitstreamEntry Next = MaybeNext.get();
1117 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1118 if (Next.Kind == llvm::BitstreamEntry::Error)
1119 return true;
1120
1121 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1122 // Unknown sub-block, possibly for use by a future version of the
1123 // API notes format.
1124 if (Cursor.SkipBlock())
1125 return true;
1126
1127 MaybeNext = Cursor.advance();
1128 if (!MaybeNext) {
1129 // FIXME this drops the error on the floor.
1130 consumeError(MaybeNext.takeError());
1131 return false;
1132 }
1133 Next = MaybeNext.get();
1134 continue;
1135 }
1136
1137 Scratch.clear();
1138 llvm::StringRef BlobData;
1139 llvm::Expected<unsigned> MaybeKind =
1140 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1141 if (!MaybeKind) {
1142 // FIXME this drops the error on the floor.
1143 consumeError(MaybeKind.takeError());
1144 return false;
1145 }
1146 unsigned Kind = MaybeKind.get();
1147 switch (Kind) {
1149 // Already saw Objective-C method table.
1150 if (ObjCMethodTable)
1151 return true;
1152
1153 uint32_t tableOffset;
1154 objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);
1155 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1156
1157 ObjCMethodTable.reset(SerializedObjCMethodTable::Create(
1158 base + tableOffset, base + sizeof(uint32_t), base));
1159 break;
1160 }
1161
1162 default:
1163 // Unknown record, possibly for use by a future version of the
1164 // module format.
1165 break;
1166 }
1167
1168 MaybeNext = Cursor.advance();
1169 if (!MaybeNext) {
1170 // FIXME this drops the error on the floor.
1171 consumeError(MaybeNext.takeError());
1172 return false;
1173 }
1174 Next = MaybeNext.get();
1175 }
1176
1177 return false;
1178}
1179
1181 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1182 if (Cursor.EnterSubBlock(CXX_METHOD_BLOCK_ID))
1183 return true;
1184
1185 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1186 if (!MaybeNext) {
1187 // FIXME this drops the error on the floor.
1188 consumeError(MaybeNext.takeError());
1189 return false;
1190 }
1191 llvm::BitstreamEntry Next = MaybeNext.get();
1192 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1193 if (Next.Kind == llvm::BitstreamEntry::Error)
1194 return true;
1195
1196 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1197 // Unknown sub-block, possibly for use by a future version of the
1198 // API notes format.
1199 if (Cursor.SkipBlock())
1200 return true;
1201
1202 MaybeNext = Cursor.advance();
1203 if (!MaybeNext) {
1204 // FIXME this drops the error on the floor.
1205 consumeError(MaybeNext.takeError());
1206 return false;
1207 }
1208 Next = MaybeNext.get();
1209 continue;
1210 }
1211
1212 Scratch.clear();
1213 llvm::StringRef BlobData;
1214 llvm::Expected<unsigned> MaybeKind =
1215 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1216 if (!MaybeKind) {
1217 // FIXME this drops the error on the floor.
1218 consumeError(MaybeKind.takeError());
1219 return false;
1220 }
1221 unsigned Kind = MaybeKind.get();
1222 switch (Kind) {
1224 // Already saw C++ method table.
1225 if (CXXMethodTable)
1226 return true;
1227
1228 uint32_t tableOffset;
1229 cxx_method_block::CXXMethodDataLayout::readRecord(Scratch, tableOffset);
1230 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1231
1232 CXXMethodTable.reset(SerializedCXXMethodTable::Create(
1233 base + tableOffset, base + sizeof(uint32_t), base));
1234 break;
1235 }
1236
1237 default:
1238 // Unknown record, possibly for use by a future version of the
1239 // module format.
1240 break;
1241 }
1242
1243 MaybeNext = Cursor.advance();
1244 if (!MaybeNext) {
1245 // FIXME this drops the error on the floor.
1246 consumeError(MaybeNext.takeError());
1247 return false;
1248 }
1249 Next = MaybeNext.get();
1250 }
1251
1252 return false;
1253}
1254
1256 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1257 if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID))
1258 return true;
1259
1260 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1261 if (!MaybeNext) {
1262 // FIXME this drops the error on the floor.
1263 consumeError(MaybeNext.takeError());
1264 return false;
1265 }
1266 llvm::BitstreamEntry Next = MaybeNext.get();
1267 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1268 if (Next.Kind == llvm::BitstreamEntry::Error)
1269 return true;
1270
1271 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1272 // Unknown sub-block, possibly for use by a future version of the
1273 // API notes format.
1274 if (Cursor.SkipBlock())
1275 return true;
1276
1277 MaybeNext = Cursor.advance();
1278 if (!MaybeNext) {
1279 // FIXME this drops the error on the floor.
1280 consumeError(MaybeNext.takeError());
1281 return false;
1282 }
1283 Next = MaybeNext.get();
1284 continue;
1285 }
1286
1287 Scratch.clear();
1288 llvm::StringRef BlobData;
1289 llvm::Expected<unsigned> MaybeKind =
1290 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1291 if (!MaybeKind) {
1292 // FIXME this drops the error on the floor.
1293 consumeError(MaybeKind.takeError());
1294 return false;
1295 }
1296 unsigned Kind = MaybeKind.get();
1297 switch (Kind) {
1299 // Already saw Objective-C selector table.
1300 if (ObjCSelectorTable)
1301 return true;
1302
1303 uint32_t tableOffset;
1304 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,
1305 tableOffset);
1306 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1307
1308 ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(
1309 base + tableOffset, base + sizeof(uint32_t), base));
1310 break;
1311 }
1312
1313 default:
1314 // Unknown record, possibly for use by a future version of the
1315 // module format.
1316 break;
1317 }
1318
1319 MaybeNext = Cursor.advance();
1320 if (!MaybeNext) {
1321 // FIXME this drops the error on the floor.
1322 consumeError(MaybeNext.takeError());
1323 return false;
1324 }
1325 Next = MaybeNext.get();
1326 }
1327
1328 return false;
1329}
1330
1332 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1333 if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID))
1334 return true;
1335
1336 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1337 if (!MaybeNext) {
1338 // FIXME this drops the error on the floor.
1339 consumeError(MaybeNext.takeError());
1340 return false;
1341 }
1342 llvm::BitstreamEntry Next = MaybeNext.get();
1343 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1344 if (Next.Kind == llvm::BitstreamEntry::Error)
1345 return true;
1346
1347 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1348 // Unknown sub-block, possibly for use by a future version of the
1349 // API notes format.
1350 if (Cursor.SkipBlock())
1351 return true;
1352
1353 MaybeNext = Cursor.advance();
1354 if (!MaybeNext) {
1355 // FIXME this drops the error on the floor.
1356 consumeError(MaybeNext.takeError());
1357 return false;
1358 }
1359 Next = MaybeNext.get();
1360 continue;
1361 }
1362
1363 Scratch.clear();
1364 llvm::StringRef BlobData;
1365 llvm::Expected<unsigned> MaybeKind =
1366 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1367 if (!MaybeKind) {
1368 // FIXME this drops the error on the floor.
1369 consumeError(MaybeKind.takeError());
1370 return false;
1371 }
1372 unsigned Kind = MaybeKind.get();
1373 switch (Kind) {
1375 // Already saw global variable table.
1376 if (GlobalVariableTable)
1377 return true;
1378
1379 uint32_t tableOffset;
1380 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,
1381 tableOffset);
1382 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1383
1384 GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(
1385 base + tableOffset, base + sizeof(uint32_t), base));
1386 break;
1387 }
1388
1389 default:
1390 // Unknown record, possibly for use by a future version of the
1391 // module format.
1392 break;
1393 }
1394
1395 MaybeNext = Cursor.advance();
1396 if (!MaybeNext) {
1397 // FIXME this drops the error on the floor.
1398 consumeError(MaybeNext.takeError());
1399 return false;
1400 }
1401 Next = MaybeNext.get();
1402 }
1403
1404 return false;
1405}
1406
1408 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1409 if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID))
1410 return true;
1411
1412 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1413 if (!MaybeNext) {
1414 // FIXME this drops the error on the floor.
1415 consumeError(MaybeNext.takeError());
1416 return false;
1417 }
1418 llvm::BitstreamEntry Next = MaybeNext.get();
1419 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1420 if (Next.Kind == llvm::BitstreamEntry::Error)
1421 return true;
1422
1423 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1424 // Unknown sub-block, possibly for use by a future version of the
1425 // API notes format.
1426 if (Cursor.SkipBlock())
1427 return true;
1428
1429 MaybeNext = Cursor.advance();
1430 if (!MaybeNext) {
1431 // FIXME this drops the error on the floor.
1432 consumeError(MaybeNext.takeError());
1433 return false;
1434 }
1435 Next = MaybeNext.get();
1436 continue;
1437 }
1438
1439 Scratch.clear();
1440 llvm::StringRef BlobData;
1441 llvm::Expected<unsigned> MaybeKind =
1442 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1443 if (!MaybeKind) {
1444 // FIXME this drops the error on the floor.
1445 consumeError(MaybeKind.takeError());
1446 return false;
1447 }
1448 unsigned Kind = MaybeKind.get();
1449 switch (Kind) {
1451 // Already saw global function table.
1452 if (GlobalFunctionTable)
1453 return true;
1454
1455 uint32_t tableOffset;
1456 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,
1457 tableOffset);
1458 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1459
1460 GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(
1461 base + tableOffset, base + sizeof(uint32_t), base));
1462 break;
1463 }
1464
1465 default:
1466 // Unknown record, possibly for use by a future version of the
1467 // module format.
1468 break;
1469 }
1470
1471 MaybeNext = Cursor.advance();
1472 if (!MaybeNext) {
1473 // FIXME this drops the error on the floor.
1474 consumeError(MaybeNext.takeError());
1475 return false;
1476 }
1477 Next = MaybeNext.get();
1478 }
1479
1480 return false;
1481}
1482
1484 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1485 if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID))
1486 return true;
1487
1488 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1489 if (!MaybeNext) {
1490 // FIXME this drops the error on the floor.
1491 consumeError(MaybeNext.takeError());
1492 return false;
1493 }
1494 llvm::BitstreamEntry Next = MaybeNext.get();
1495 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1496 if (Next.Kind == llvm::BitstreamEntry::Error)
1497 return true;
1498
1499 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1500 // Unknown sub-block, possibly for use by a future version of the
1501 // API notes format.
1502 if (Cursor.SkipBlock())
1503 return true;
1504
1505 MaybeNext = Cursor.advance();
1506 if (!MaybeNext) {
1507 // FIXME this drops the error on the floor.
1508 consumeError(MaybeNext.takeError());
1509 return false;
1510 }
1511 Next = MaybeNext.get();
1512 continue;
1513 }
1514
1515 Scratch.clear();
1516 llvm::StringRef BlobData;
1517 llvm::Expected<unsigned> MaybeKind =
1518 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1519 if (!MaybeKind) {
1520 // FIXME this drops the error on the floor.
1521 consumeError(MaybeKind.takeError());
1522 return false;
1523 }
1524 unsigned Kind = MaybeKind.get();
1525 switch (Kind) {
1527 // Already saw enumerator table.
1528 if (EnumConstantTable)
1529 return true;
1530
1531 uint32_t tableOffset;
1532 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,
1533 tableOffset);
1534 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1535
1536 EnumConstantTable.reset(SerializedEnumConstantTable::Create(
1537 base + tableOffset, base + sizeof(uint32_t), base));
1538 break;
1539 }
1540
1541 default:
1542 // Unknown record, possibly for use by a future version of the
1543 // module format.
1544 break;
1545 }
1546
1547 MaybeNext = Cursor.advance();
1548 if (!MaybeNext) {
1549 // FIXME this drops the error on the floor.
1550 consumeError(MaybeNext.takeError());
1551 return false;
1552 }
1553 Next = MaybeNext.get();
1554 }
1555
1556 return false;
1557}
1558
1560 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1561 if (Cursor.EnterSubBlock(TAG_BLOCK_ID))
1562 return true;
1563
1564 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1565 if (!MaybeNext) {
1566 // FIXME this drops the error on the floor.
1567 consumeError(MaybeNext.takeError());
1568 return false;
1569 }
1570 llvm::BitstreamEntry Next = MaybeNext.get();
1571 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1572 if (Next.Kind == llvm::BitstreamEntry::Error)
1573 return true;
1574
1575 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1576 // Unknown sub-block, possibly for use by a future version of the
1577 // API notes format.
1578 if (Cursor.SkipBlock())
1579 return true;
1580
1581 MaybeNext = Cursor.advance();
1582 if (!MaybeNext) {
1583 // FIXME this drops the error on the floor.
1584 consumeError(MaybeNext.takeError());
1585 return false;
1586 }
1587 Next = MaybeNext.get();
1588 continue;
1589 }
1590
1591 Scratch.clear();
1592 llvm::StringRef BlobData;
1593 llvm::Expected<unsigned> MaybeKind =
1594 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1595 if (!MaybeKind) {
1596 // FIXME this drops the error on the floor.
1597 consumeError(MaybeKind.takeError());
1598 return false;
1599 }
1600 unsigned Kind = MaybeKind.get();
1601 switch (Kind) {
1602 case tag_block::TAG_DATA: {
1603 // Already saw tag table.
1604 if (TagTable)
1605 return true;
1606
1607 uint32_t tableOffset;
1608 tag_block::TagDataLayout::readRecord(Scratch, tableOffset);
1609 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1610
1611 TagTable.reset(SerializedTagTable::Create(base + tableOffset,
1612 base + sizeof(uint32_t), base));
1613 break;
1614 }
1615
1616 default:
1617 // Unknown record, possibly for use by a future version of the
1618 // module format.
1619 break;
1620 }
1621
1622 MaybeNext = Cursor.advance();
1623 if (!MaybeNext) {
1624 // FIXME this drops the error on the floor.
1625 consumeError(MaybeNext.takeError());
1626 return false;
1627 }
1628 Next = MaybeNext.get();
1629 }
1630
1631 return false;
1632}
1633
1635 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1636 if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID))
1637 return true;
1638
1639 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1640 if (!MaybeNext) {
1641 // FIXME this drops the error on the floor.
1642 consumeError(MaybeNext.takeError());
1643 return false;
1644 }
1645 llvm::BitstreamEntry Next = MaybeNext.get();
1646 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1647 if (Next.Kind == llvm::BitstreamEntry::Error)
1648 return true;
1649
1650 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1651 // Unknown sub-block, possibly for use by a future version of the
1652 // API notes format.
1653 if (Cursor.SkipBlock())
1654 return true;
1655
1656 MaybeNext = Cursor.advance();
1657 if (!MaybeNext) {
1658 // FIXME this drops the error on the floor.
1659 consumeError(MaybeNext.takeError());
1660 return false;
1661 }
1662 Next = MaybeNext.get();
1663 continue;
1664 }
1665
1666 Scratch.clear();
1667 llvm::StringRef BlobData;
1668 llvm::Expected<unsigned> MaybeKind =
1669 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1670 if (!MaybeKind) {
1671 // FIXME this drops the error on the floor.
1672 consumeError(MaybeKind.takeError());
1673 return false;
1674 }
1675 unsigned Kind = MaybeKind.get();
1676 switch (Kind) {
1678 // Already saw typedef table.
1679 if (TypedefTable)
1680 return true;
1681
1682 uint32_t tableOffset;
1683 typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);
1684 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1685
1686 TypedefTable.reset(SerializedTypedefTable::Create(
1687 base + tableOffset, base + sizeof(uint32_t), base));
1688 break;
1689 }
1690
1691 default:
1692 // Unknown record, possibly for use by a future version of the
1693 // module format.
1694 break;
1695 }
1696
1697 MaybeNext = Cursor.advance();
1698 if (!MaybeNext) {
1699 // FIXME this drops the error on the floor.
1700 consumeError(MaybeNext.takeError());
1701 return false;
1702 }
1703 Next = MaybeNext.get();
1704 }
1705
1706 return false;
1707}
1708
1709APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1710 llvm::VersionTuple SwiftVersion, bool &Failed)
1711 : Implementation(new class Implementation) {
1712 Failed = false;
1713
1714 // Initialize the input buffer.
1717 llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);
1718
1719 // Validate signature.
1720 for (auto byte : API_NOTES_SIGNATURE) {
1721 if (Cursor.AtEndOfStream()) {
1722 Failed = true;
1723 return;
1724 }
1726 Cursor.Read(8)) {
1727 if (maybeRead.get() != byte) {
1728 Failed = true;
1729 return;
1730 }
1731 } else {
1732 // FIXME this drops the error on the floor.
1733 consumeError(maybeRead.takeError());
1734 Failed = true;
1735 return;
1736 }
1737 }
1738
1739 // Look at all of the blocks.
1740 bool HasValidControlBlock = false;
1742 while (!Cursor.AtEndOfStream()) {
1743 llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();
1744 if (!MaybeTopLevelEntry) {
1745 // FIXME this drops the error on the floor.
1746 consumeError(MaybeTopLevelEntry.takeError());
1747 Failed = true;
1748 return;
1749 }
1750 llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();
1751
1752 if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
1753 break;
1754
1755 switch (TopLevelEntry.ID) {
1756 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1757 if (!Cursor.ReadBlockInfoBlock()) {
1758 Failed = true;
1759 break;
1760 }
1761 break;
1762
1763 case CONTROL_BLOCK_ID:
1764 // Only allow a single control block.
1765 if (HasValidControlBlock ||
1766 Implementation->readControlBlock(Cursor, Scratch)) {
1767 Failed = true;
1768 return;
1769 }
1770
1771 HasValidControlBlock = true;
1772 break;
1773
1775 if (!HasValidControlBlock ||
1776 Implementation->readIdentifierBlock(Cursor, Scratch)) {
1777 Failed = true;
1778 return;
1779 }
1780 break;
1781
1783 if (!HasValidControlBlock ||
1784 Implementation->readContextBlock(Cursor, Scratch)) {
1785 Failed = true;
1786 return;
1787 }
1788
1789 break;
1790
1792 if (!HasValidControlBlock ||
1793 Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
1794 Failed = true;
1795 return;
1796 }
1797 break;
1798
1800 if (!HasValidControlBlock ||
1801 Implementation->readObjCMethodBlock(Cursor, Scratch)) {
1802 Failed = true;
1803 return;
1804 }
1805 break;
1806
1808 if (!HasValidControlBlock ||
1809 Implementation->readCXXMethodBlock(Cursor, Scratch)) {
1810 Failed = true;
1811 return;
1812 }
1813 break;
1814
1816 if (!HasValidControlBlock ||
1817 Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
1818 Failed = true;
1819 return;
1820 }
1821 break;
1822
1824 if (!HasValidControlBlock ||
1825 Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
1826 Failed = true;
1827 return;
1828 }
1829 break;
1830
1832 if (!HasValidControlBlock ||
1833 Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
1834 Failed = true;
1835 return;
1836 }
1837 break;
1838
1840 if (!HasValidControlBlock ||
1841 Implementation->readEnumConstantBlock(Cursor, Scratch)) {
1842 Failed = true;
1843 return;
1844 }
1845 break;
1846
1847 case TAG_BLOCK_ID:
1848 if (!HasValidControlBlock ||
1849 Implementation->readTagBlock(Cursor, Scratch)) {
1850 Failed = true;
1851 return;
1852 }
1853 break;
1854
1855 case TYPEDEF_BLOCK_ID:
1856 if (!HasValidControlBlock ||
1857 Implementation->readTypedefBlock(Cursor, Scratch)) {
1858 Failed = true;
1859 return;
1860 }
1861 break;
1862
1863 default:
1864 // Unknown top-level block, possibly for use by a future version of the
1865 // module format.
1866 if (Cursor.SkipBlock()) {
1867 Failed = true;
1868 return;
1869 }
1870 break;
1871 }
1872 }
1873
1874 if (!Cursor.AtEndOfStream()) {
1875 Failed = true;
1876 return;
1877 }
1878}
1879
1881
1882std::unique_ptr<APINotesReader>
1883APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
1884 llvm::VersionTuple SwiftVersion) {
1885 bool Failed = false;
1886 std::unique_ptr<APINotesReader> Reader(
1887 new APINotesReader(InputBuffer.release(), SwiftVersion, Failed));
1888 if (Failed)
1889 return nullptr;
1890
1891 return Reader;
1892}
1893
1894template <typename T>
1896 llvm::VersionTuple Version,
1897 llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)
1898 : Results(std::move(R)) {
1899
1900 assert(!Results.empty());
1901 assert(std::is_sorted(
1902 Results.begin(), Results.end(),
1903 [](const std::pair<llvm::VersionTuple, T> &left,
1904 const std::pair<llvm::VersionTuple, T> &right) -> bool {
1905 assert(left.first != right.first && "two entries for the same version");
1906 return left.first < right.first;
1907 }));
1908
1909 Selected = std::nullopt;
1910 for (unsigned i = 0, n = Results.size(); i != n; ++i) {
1911 if (!Version.empty() && Results[i].first >= Version) {
1912 // If the current version is "4", then entries for 4 are better than
1913 // entries for 5, but both are valid. Because entries are sorted, we get
1914 // that behavior by picking the first match.
1915 Selected = i;
1916 break;
1917 }
1918 }
1919
1920 // If we didn't find a match but we have an unversioned result, use the
1921 // unversioned result. This will always be the first entry because we encode
1922 // it as version 0.
1923 if (!Selected && Results[0].first.empty())
1924 Selected = 0;
1925}
1926
1927auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
1928 -> std::optional<ContextID> {
1930 return std::nullopt;
1931
1932 std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
1933 if (!ClassID)
1934 return std::nullopt;
1935
1936 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
1937 // context.
1938 auto KnownID = Implementation->ContextIDTable->find(
1939 ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
1940 if (KnownID == Implementation->ContextIDTable->end())
1941 return std::nullopt;
1942
1943 return ContextID(*KnownID);
1944}
1945
1946auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
1949 return std::nullopt;
1950
1951 std::optional<ContextID> CtxID = lookupObjCClassID(Name);
1952 if (!CtxID)
1953 return std::nullopt;
1954
1955 auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
1956 if (KnownInfo == Implementation->ContextInfoTable->end())
1957 return std::nullopt;
1958
1959 return {Implementation->SwiftVersion, *KnownInfo};
1960}
1961
1963 -> std::optional<ContextID> {
1965 return std::nullopt;
1966
1967 std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
1968 if (!classID)
1969 return std::nullopt;
1970
1971 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
1972 // context.
1973 auto KnownID = Implementation->ContextIDTable->find(
1974 ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
1975 if (KnownID == Implementation->ContextIDTable->end())
1976 return std::nullopt;
1977
1978 return ContextID(*KnownID);
1979}
1980
1984 return std::nullopt;
1985
1986 std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
1987 if (!CtxID)
1988 return std::nullopt;
1989
1990 auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
1991 if (KnownInfo == Implementation->ContextInfoTable->end())
1992 return std::nullopt;
1993
1994 return {Implementation->SwiftVersion, *KnownInfo};
1995}
1996
1997auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,
1998 bool IsInstance)
2001 return std::nullopt;
2002
2003 std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name);
2004 if (!PropertyID)
2005 return std::nullopt;
2006
2007 auto Known = Implementation->ObjCPropertyTable->find(
2008 std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance));
2009 if (Known == Implementation->ObjCPropertyTable->end())
2010 return std::nullopt;
2011
2012 return {Implementation->SwiftVersion, *Known};
2013}
2014
2016 bool IsInstanceMethod)
2019 return std::nullopt;
2020
2021 std::optional<SelectorID> SelID = Implementation->getSelector(Selector);
2022 if (!SelID)
2023 return std::nullopt;
2024
2025 auto Known = Implementation->ObjCMethodTable->find(
2026 ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
2027 IsInstanceMethod});
2028 if (Known == Implementation->ObjCMethodTable->end())
2029 return std::nullopt;
2030
2031 return {Implementation->SwiftVersion, *Known};
2032}
2033
2034auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
2037 return std::nullopt;
2038
2039 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2040 if (!NameID)
2041 return std::nullopt;
2042
2043 auto Known = Implementation->CXXMethodTable->find(
2044 SingleDeclTableKey(CtxID.Value, *NameID));
2045 if (Known == Implementation->CXXMethodTable->end())
2046 return std::nullopt;
2047
2048 return {Implementation->SwiftVersion, *Known};
2049}
2050
2052 std::optional<Context> Ctx)
2055 return std::nullopt;
2056
2057 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2058 if (!NameID)
2059 return std::nullopt;
2060
2061 SingleDeclTableKey Key(Ctx, *NameID);
2062
2063 auto Known = Implementation->GlobalVariableTable->find(Key);
2064 if (Known == Implementation->GlobalVariableTable->end())
2065 return std::nullopt;
2066
2067 return {Implementation->SwiftVersion, *Known};
2068}
2069
2071 std::optional<Context> Ctx)
2074 return std::nullopt;
2075
2076 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2077 if (!NameID)
2078 return std::nullopt;
2079
2080 SingleDeclTableKey Key(Ctx, *NameID);
2081
2082 auto Known = Implementation->GlobalFunctionTable->find(Key);
2083 if (Known == Implementation->GlobalFunctionTable->end())
2084 return std::nullopt;
2085
2086 return {Implementation->SwiftVersion, *Known};
2087}
2088
2089auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
2092 return std::nullopt;
2093
2094 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2095 if (!NameID)
2096 return std::nullopt;
2097
2098 auto Known = Implementation->EnumConstantTable->find(*NameID);
2099 if (Known == Implementation->EnumConstantTable->end())
2100 return std::nullopt;
2101
2102 return {Implementation->SwiftVersion, *Known};
2103}
2104
2105auto APINotesReader::lookupTagID(llvm::StringRef Name,
2106 std::optional<Context> ParentCtx)
2107 -> std::optional<ContextID> {
2109 return std::nullopt;
2110
2111 std::optional<IdentifierID> TagID = Implementation->getIdentifier(Name);
2112 if (!TagID)
2113 return std::nullopt;
2114
2115 auto KnownID = Implementation->ContextIDTable->find(
2116 ContextTableKey(ParentCtx, ContextKind::Tag, *TagID));
2117 if (KnownID == Implementation->ContextIDTable->end())
2118 return std::nullopt;
2119
2120 return ContextID(*KnownID);
2121}
2122
2123auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
2126 return std::nullopt;
2127
2128 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2129 if (!NameID)
2130 return std::nullopt;
2131
2132 SingleDeclTableKey Key(Ctx, *NameID);
2133
2134 auto Known = Implementation->TagTable->find(Key);
2135 if (Known == Implementation->TagTable->end())
2136 return std::nullopt;
2137
2138 return {Implementation->SwiftVersion, *Known};
2139}
2140
2141auto APINotesReader::lookupTypedef(llvm::StringRef Name,
2142 std::optional<Context> Ctx)
2145 return std::nullopt;
2146
2147 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2148 if (!NameID)
2149 return std::nullopt;
2150
2151 SingleDeclTableKey Key(Ctx, *NameID);
2152
2153 auto Known = Implementation->TypedefTable->find(Key);
2154 if (Known == Implementation->TypedefTable->end())
2155 return std::nullopt;
2156
2157 return {Implementation->SwiftVersion, *Known};
2158}
2159
2161 llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
2162 -> std::optional<ContextID> {
2164 return std::nullopt;
2165
2166 std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
2167 if (!NamespaceID)
2168 return std::nullopt;
2169
2170 uint32_t RawParentNamespaceID =
2171 ParentNamespaceID ? ParentNamespaceID->Value : -1;
2172 auto KnownID = Implementation->ContextIDTable->find(
2173 {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
2174 if (KnownID == Implementation->ContextIDTable->end())
2175 return std::nullopt;
2176
2177 return ContextID(*KnownID);
2178}
2179
2180} // namespace api_notes
2181} // 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< GlobalVariableTableInfo > SerializedGlobalVariableTable
std::unique_ptr< SerializedContextIDTable > ContextIDTable
The Objective-C / C++ context ID table.
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)
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)
std::unique_ptr< SerializedCXXMethodTable > CXXMethodTable
The C++ method table.
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 readGlobalVariableBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< ObjCPropertyTableInfo > SerializedObjCPropertyTable
std::unique_ptr< SerializedTagTable > TagTable
The tag table.
llvm::OnDiskIterableChainedHashTable< CXXMethodTableInfo > SerializedCXXMethodTable
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 readCXXMethodBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readIdentifierBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::VersionTuple SwiftVersion
The Swift version to use for filtering.
bool readContextBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< EnumConstantTableInfo > SerializedEnumConstantTable
std::unique_ptr< SerializedObjCMethodTable > ObjCMethodTable
The Objective-C method table.
std::unique_ptr< SerializedContextInfoTable > ContextInfoTable
The Objective-C context info table.
llvm::OnDiskIterableChainedHashTable< TypedefTableInfo > SerializedTypedefTable
llvm::OnDiskIterableChainedHashTable< GlobalFunctionTableInfo > SerializedGlobalFunctionTable
llvm::OnDiskIterableChainedHashTable< ContextInfoTableInfo > SerializedContextInfoTable
llvm::OnDiskIterableChainedHashTable< ContextIDTableInfo > SerializedContextIDTable
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< ContextInfo > lookupObjCClassInfo(llvm::StringRef Name)
Look for information regarding the given Objective-C class.
VersionedInfo< CXXMethodInfo > lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
Look for information regarding the given C++ method in the given C++ tag context.
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.
std::optional< ContextID > lookupTagID(llvm::StringRef Name, std::optional< Context > ParentCtx=std::nullopt)
Look for the context ID of the given C++ tag.
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< ContextInfo > 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:794
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,...
@ CXX_METHOD_BLOCK_ID
The C++ method data block, which maps C++ (context id, method name) pairs to information about the me...
@ 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:294
The JSON file list parser is used to communicate input to InstallAPI.
NullabilityKind
Describes the nullability of a particular type.
Definition: Specifiers.h:336
@ Result
The result type of a method or function.
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
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:821
A stored Objective-C or C++ declaration, represented by the ID of its parent context,...
A stored Objective-C selector.
llvm::SmallVector< IdentifierID, 2 > Identifiers