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