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