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