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

source code of clang/lib/APINotes/APINotesReader.cpp