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