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