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 =
56 llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
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>
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.
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.
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.
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.
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.
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;
1889 llvm::SmallVector<uint64_t, 64> Scratch;
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
FormatToken * Next
The next token in the unwrapped line.
static StringRef getIdentifier(const Token &Tok)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Smart pointer class that efficiently represents Objective-C method names.
llvm::OnDiskIterableChainedHashTable< FieldTableInfo > SerializedFieldTable
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
llvm::OnDiskIterableChainedHashTable< GlobalFunctionTableInfo > SerializedGlobalFunctionTable
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)
llvm::OnDiskIterableChainedHashTable< EnumConstantTableInfo > SerializedEnumConstantTable
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)
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.
llvm::OnDiskIterableChainedHashTable< ObjCMethodTableInfo > SerializedObjCMethodTable
bool readControlBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< CXXMethodTableInfo > SerializedCXXMethodTable
llvm::OnDiskIterableChainedHashTable< ContextInfoTableInfo > SerializedContextInfoTable
std::unique_ptr< SerializedCXXMethodTable > CXXMethodTable
The C++ method table.
llvm::OnDiskIterableChainedHashTable< ObjCSelectorTableInfo > SerializedObjCSelectorTable
llvm::OnDiskIterableChainedHashTable< IdentifierTableInfo > SerializedIdentifierTable
bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
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)
std::unique_ptr< SerializedTagTable > TagTable
The tag table.
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< TypedefTableInfo > SerializedTypedefTable
bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readIdentifierBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< GlobalVariableTableInfo > SerializedGlobalVariableTable
llvm::VersionTuple SwiftVersion
The Swift version to use for filtering.
llvm::OnDiskIterableChainedHashTable< ContextIDTableInfo > SerializedContextIDTable
bool readContextBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::unique_ptr< SerializedObjCMethodTable > ObjCMethodTable
The Objective-C method table.
std::unique_ptr< SerializedContextInfoTable > ContextInfoTable
The Objective-C context info table.
llvm::OnDiskIterableChainedHashTable< ObjCPropertyTableInfo > SerializedObjCPropertyTable
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.
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.
Describes API notes data for any entity.
Definition Types.h:52
Describes API notes for types.
Definition Types.h:135
Opaque context ID used to refer to an Objective-C class or protocol or a C++ namespace.
Definition Types.h:877
API notes for a function or method.
Definition Types.h:527
Describes a function or method parameter.
Definition Types.h:433
API notes for a variable/property.
Definition Types.h:318
RetainCountConventionKind
Definition Types.h:25
llvm::PointerEmbeddedInt< unsigned, 31 > IdentifierID
llvm::PointerEmbeddedInt< unsigned, 31 > SelectorID
const uint8_t kSwiftConforms
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)
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.
Definition TypeBase.h:905
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