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

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