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