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