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 (Payload & 0x1)
382 Info.UnsafeBufferUsage = 1;
383 Payload >>= 0x1;
384 if (auto RawConvention = Payload & 0x7) {
385 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
386 Info.setRetainCountConvention(Convention);
387 }
388 Payload >>= 3;
389 Info.NullabilityAudited = Payload & 0x1;
390 Payload >>= 1;
391 assert(Payload == 0 && "Bad API notes");
392
393 Info.NumAdjustedNullable =
394 endian::readNext<uint8_t, llvm::endianness::little>(Data);
395 Info.NullabilityPayload =
396 endian::readNext<uint64_t, llvm::endianness::little>(Data);
397
398 unsigned NumParams =
399 endian::readNext<uint16_t, llvm::endianness::little>(Data);
400 while (NumParams > 0) {
401 ParamInfo pi;
402 ReadParamInfo(Data, pi);
403 Info.Params.push_back(pi);
404 --NumParams;
405 }
406
407 unsigned ResultTypeLen =
408 endian::readNext<uint16_t, llvm::endianness::little>(Data);
409 Info.ResultType = std::string(Data, Data + ResultTypeLen);
410 Data += ResultTypeLen;
411
412 unsigned SwiftReturnOwnershipLength =
413 endian::readNext<uint16_t, llvm::endianness::little>(Data);
414 Info.SwiftReturnOwnership = std::string(reinterpret_cast<const char *>(Data),
415 reinterpret_cast<const char *>(Data) +
416 SwiftReturnOwnershipLength);
417 Data += SwiftReturnOwnershipLength;
418}
419
420/// Used to deserialize the on-disk Objective-C method table.
421class ObjCMethodTableInfo
422 : public VersionedTableInfo<ObjCMethodTableInfo,
423 std::tuple<uint32_t, uint32_t, uint8_t>,
424 ObjCMethodInfo> {
425public:
426 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
427 auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
428 auto SelectorID =
429 endian::readNext<uint32_t, llvm::endianness::little>(Data);
430 auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);
431 return {ClassID, SelectorID, IsInstance};
432 }
433
434 hash_value_type ComputeHash(internal_key_type Key) {
435 return static_cast<size_t>(llvm::hash_value(Key));
436 }
437
438 static ObjCMethodInfo readUnversioned(internal_key_type Key,
439 const uint8_t *&Data) {
440 ObjCMethodInfo Info;
441 uint8_t Payload = *Data++;
442 bool HasSelf = Payload & 0x01;
443 Payload >>= 1;
444 Info.RequiredInit = Payload & 0x01;
445 Payload >>= 1;
446 Info.DesignatedInit = Payload & 0x01;
447 Payload >>= 1;
448 assert(Payload == 0 && "Unable to fully decode 'Payload'.");
449
450 ReadFunctionInfo(Data, Info);
451 if (HasSelf) {
452 Info.Self = ParamInfo{};
453 ReadParamInfo(Data, *Info.Self);
454 }
455 return Info;
456 }
457};
458
459/// Used to deserialize the on-disk Objective-C selector table.
460class ObjCSelectorTableInfo {
461public:
462 using internal_key_type = StoredObjCSelector;
463 using external_key_type = internal_key_type;
464 using data_type = SelectorID;
465 using hash_value_type = unsigned;
466 using offset_type = unsigned;
467
468 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
469
470 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
471
472 hash_value_type ComputeHash(internal_key_type Key) {
473 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
474 }
475
476 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
477 return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);
478 }
479
480 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
481 unsigned KeyLength =
482 endian::readNext<uint16_t, llvm::endianness::little>(Data);
483 unsigned DataLength =
484 endian::readNext<uint16_t, llvm::endianness::little>(Data);
485 return {KeyLength, DataLength};
486 }
487
488 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
489 internal_key_type Key;
490 Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(Data);
491 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
492 for (unsigned i = 0; i != NumIdents; ++i) {
493 Key.Identifiers.push_back(
494 endian::readNext<uint32_t, llvm::endianness::little>(Data));
495 }
496 return Key;
497 }
498
499 static data_type ReadData(internal_key_type Key, const uint8_t *Data,
500 unsigned Length) {
501 return endian::readNext<uint32_t, llvm::endianness::little>(Data);
502 }
503};
504
505/// Used to deserialize the on-disk global variable table.
506class GlobalVariableTableInfo
507 : public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
508 GlobalVariableInfo> {
509public:
510 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
511 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
512 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
513 return {CtxID, NameID};
514 }
515
516 hash_value_type ComputeHash(internal_key_type Key) {
517 return static_cast<size_t>(Key.hashValue());
518 }
519
520 static GlobalVariableInfo readUnversioned(internal_key_type Key,
521 const uint8_t *&Data) {
522 GlobalVariableInfo Info;
523 ReadVariableInfo(Data, Info);
524 return Info;
525 }
526};
527
528/// Used to deserialize the on-disk global function table.
529class GlobalFunctionTableInfo
530 : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
531 GlobalFunctionInfo> {
532public:
533 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
534 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
535 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
536 return {CtxID, NameID};
537 }
538
539 hash_value_type ComputeHash(internal_key_type Key) {
540 return static_cast<size_t>(Key.hashValue());
541 }
542
543 static GlobalFunctionInfo readUnversioned(internal_key_type Key,
544 const uint8_t *&Data) {
545 GlobalFunctionInfo Info;
546 ReadFunctionInfo(Data, Info);
547 return Info;
548 }
549};
550
551/// Used to deserialize the on-disk C++ method table.
552class CXXMethodTableInfo
553 : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
554 CXXMethodInfo> {
555public:
556 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
557 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
558 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
559 return {CtxID, NameID};
560 }
561
562 hash_value_type ComputeHash(internal_key_type Key) {
563 return static_cast<size_t>(Key.hashValue());
564 }
565
566 static CXXMethodInfo readUnversioned(internal_key_type Key,
567 const uint8_t *&Data) {
568 CXXMethodInfo Info;
569
570 uint8_t Payload = *Data++;
571 bool HasThis = Payload & 0x01;
572 Payload >>= 1;
573 assert(Payload == 0 && "Unable to fully decode 'Payload'.");
574
575 ReadFunctionInfo(Data, Info);
576 if (HasThis) {
577 Info.This = ParamInfo{};
578 ReadParamInfo(Data, *Info.This);
579 }
580 return Info;
581 }
582};
583
584/// Used to deserialize the on-disk enumerator table.
585class EnumConstantTableInfo
586 : public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
587 EnumConstantInfo> {
588public:
589 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
590 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
591 return NameID;
592 }
593
594 hash_value_type ComputeHash(internal_key_type Key) {
595 return static_cast<size_t>(llvm::hash_value(Key));
596 }
597
598 static EnumConstantInfo readUnversioned(internal_key_type Key,
599 const uint8_t *&Data) {
600 EnumConstantInfo Info;
601 ReadCommonEntityInfo(Data, Info);
602 return Info;
603 }
604};
605
606/// Used to deserialize the on-disk tag table.
607class TagTableInfo
608 : public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> {
609public:
610 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
611 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
612 auto NameID =
613 endian::readNext<IdentifierID, llvm::endianness::little>(Data);
614 return {CtxID, NameID};
615 }
616
617 hash_value_type ComputeHash(internal_key_type Key) {
618 return static_cast<size_t>(Key.hashValue());
619 }
620
621 static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {
622 TagInfo Info;
623
624 uint8_t Payload = *Data++;
625 if (Payload & 1)
626 Info.setFlagEnum(Payload & 2);
627 Payload >>= 2;
628 if (Payload > 0)
629 Info.EnumExtensibility =
630 static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);
631
632 uint8_t Copyable =
633 endian::readNext<uint8_t, llvm::endianness::little>(Data);
634 if (Copyable == kSwiftConforms || Copyable == kSwiftDoesNotConform)
635 Info.setSwiftCopyable(std::optional(Copyable == kSwiftConforms));
636 uint8_t Escapable =
637 endian::readNext<uint8_t, llvm::endianness::little>(Data);
638 if (Escapable == kSwiftConforms || Escapable == kSwiftDoesNotConform)
639 Info.setSwiftEscapable(std::optional(Escapable == kSwiftConforms));
640
641 unsigned ImportAsLength =
642 endian::readNext<uint16_t, llvm::endianness::little>(Data);
643 if (ImportAsLength > 0) {
644 Info.SwiftImportAs =
645 std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1);
646 Data += ImportAsLength - 1;
647 }
648 unsigned RetainOpLength =
649 endian::readNext<uint16_t, llvm::endianness::little>(Data);
650 if (RetainOpLength > 0) {
651 Info.SwiftRetainOp =
652 std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1);
653 Data += RetainOpLength - 1;
654 }
655 unsigned ReleaseOpLength =
656 endian::readNext<uint16_t, llvm::endianness::little>(Data);
657 if (ReleaseOpLength > 0) {
658 Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data),
659 ReleaseOpLength - 1);
660 Data += ReleaseOpLength - 1;
661 }
662 unsigned DefaultOwnershipLength =
663 endian::readNext<uint16_t, llvm::endianness::little>(Data);
664 if (DefaultOwnershipLength > 0) {
665 Info.SwiftDefaultOwnership = std::string(
666 reinterpret_cast<const char *>(Data), DefaultOwnershipLength - 1);
667 Data += DefaultOwnershipLength - 1;
668 }
669 unsigned DestroyOpLength =
670 endian::readNext<uint16_t, llvm::endianness::little>(Data);
671 if (DestroyOpLength > 0) {
672 Info.SwiftDestroyOp = std::string(reinterpret_cast<const char *>(Data),
673 DestroyOpLength - 1);
674 Data += DestroyOpLength - 1;
675 }
676
677 ReadCommonTypeInfo(Data, Info);
678 return Info;
679 }
680};
681
682/// Used to deserialize the on-disk typedef table.
683class TypedefTableInfo
684 : public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey,
685 TypedefInfo> {
686public:
687 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
688 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
689 auto nameID =
690 endian::readNext<IdentifierID, llvm::endianness::little>(Data);
691 return {CtxID, nameID};
692 }
693
694 hash_value_type ComputeHash(internal_key_type Key) {
695 return static_cast<size_t>(Key.hashValue());
696 }
697
698 static TypedefInfo readUnversioned(internal_key_type Key,
699 const uint8_t *&Data) {
700 TypedefInfo Info;
701
702 uint8_t Payload = *Data++;
703 if (Payload > 0)
704 Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);
705
706 ReadCommonTypeInfo(Data, Info);
707 return Info;
708 }
709};
710} // end anonymous namespace
711
713public:
714 /// The input buffer for the API notes data.
715 llvm::MemoryBuffer *InputBuffer;
716
717 /// The Swift version to use for filtering.
718 llvm::VersionTuple SwiftVersion;
719
720 /// The name of the module that we read from the control block.
721 std::string ModuleName;
722
723 // The size and modification time of the source file from
724 // which this API notes file was created, if known.
725 std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime;
726
728 llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;
729
730 /// The identifier table.
731 std::unique_ptr<SerializedIdentifierTable> IdentifierTable;
732
734 llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;
735
736 /// The Objective-C / C++ context ID table.
737 std::unique_ptr<SerializedContextIDTable> ContextIDTable;
738
740 llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;
741
742 /// The Objective-C context info table.
743 std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;
744
746 llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
747
748 /// The Objective-C property table.
749 std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;
750
752 llvm::OnDiskIterableChainedHashTable<FieldTableInfo>;
753
754 /// The C record field table.
755 std::unique_ptr<SerializedFieldTable> FieldTable;
756
758 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
759
760 /// The Objective-C method table.
761 std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
762
764 llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
765
766 /// The C++ method table.
767 std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
768
770 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
771
772 /// The Objective-C selector table.
773 std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;
774
776 llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;
777
778 /// The global variable table.
779 std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;
780
782 llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;
783
784 /// The global function table.
785 std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;
786
788 llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
789
790 /// The enumerator table.
791 std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;
792
793 using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;
794
795 /// The tag table.
796 std::unique_ptr<SerializedTagTable> TagTable;
797
799 llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;
800
801 /// The typedef table.
802 std::unique_ptr<SerializedTypedefTable> TypedefTable;
803
804 /// Retrieve the identifier ID for the given string, or an empty
805 /// optional if the string is unknown.
806 std::optional<IdentifierID> getIdentifier(llvm::StringRef Str);
807
808 /// Retrieve the selector ID for the given selector, or an empty
809 /// optional if the string is unknown.
810 std::optional<SelectorID> getSelector(ObjCSelectorRef Selector);
811
812 llvm::Error readControlBlock(llvm::BitstreamCursor &Cursor,
814 llvm::Error readIdentifierBlock(llvm::BitstreamCursor &Cursor,
816 llvm::Error readContextBlock(llvm::BitstreamCursor &Cursor,
818 llvm::Error readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
820 llvm::Error readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
822 llvm::Error readCXXMethodBlock(llvm::BitstreamCursor &Cursor,
824 llvm::Error readFieldBlock(llvm::BitstreamCursor &Cursor,
826 llvm::Error readObjCSelectorBlock(llvm::BitstreamCursor &Cursor,
828 llvm::Error readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,
830 llvm::Error readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
832 llvm::Error readEnumConstantBlock(llvm::BitstreamCursor &Cursor,
834 llvm::Error readTagBlock(llvm::BitstreamCursor &Cursor,
836 llvm::Error readTypedefBlock(llvm::BitstreamCursor &Cursor,
838};
839
840std::optional<IdentifierID>
842 if (!IdentifierTable)
843 return std::nullopt;
844
845 if (Str.empty())
846 return IdentifierID(0);
847
848 auto Known = IdentifierTable->find(Str);
849 if (Known == IdentifierTable->end())
850 return std::nullopt;
851
852 return *Known;
853}
854
855std::optional<SelectorID>
858 return std::nullopt;
859
860 // Translate the identifiers.
862 Key.NumArgs = Selector.NumArgs;
863 for (auto Ident : Selector.Identifiers) {
864 if (auto IdentID = getIdentifier(Ident)) {
865 Key.Identifiers.push_back(*IdentID);
866 } else {
867 return std::nullopt;
868 }
869 }
870
871 auto Known = ObjCSelectorTable->find(Key);
872 if (Known == ObjCSelectorTable->end())
873 return std::nullopt;
874
875 return *Known;
876}
877
879 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
880 if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID))
881 return llvm::createStringError(llvm::inconvertibleErrorCode(),
882 "Failed to enter control block");
883
884 bool SawMetadata = false;
885
886 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
887 if (!MaybeNext)
888 return MaybeNext.takeError();
889
890 llvm::BitstreamEntry Next = MaybeNext.get();
891
892 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
893 if (Next.Kind == llvm::BitstreamEntry::Error)
894 return llvm::createStringError(llvm::inconvertibleErrorCode(),
895 "Malformed bitstream entry");
896
897 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
898 // Unknown metadata sub-block, possibly for use by a future version of the
899 // API notes format.
900 if (Cursor.SkipBlock())
901 return llvm::createStringError(llvm::inconvertibleErrorCode(),
902 "Failed to skip sub-block");
903
904 MaybeNext = Cursor.advance();
905 if (!MaybeNext)
906 return MaybeNext.takeError();
907
908 Next = MaybeNext.get();
909 continue;
910 }
911
912 Scratch.clear();
913 llvm::StringRef BlobData;
914 llvm::Expected<unsigned> MaybeKind =
915 Cursor.readRecord(Next.ID, Scratch, &BlobData);
916 if (!MaybeKind) {
917 return MaybeKind.takeError();
918 }
919 unsigned Kind = MaybeKind.get();
920
921 switch (Kind) {
923 // Already saw metadata.
924 if (SawMetadata)
925 return llvm::createStringError(llvm::inconvertibleErrorCode(),
926 "Multiple metadata records found");
927
928 if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)
929 return llvm::createStringError(llvm::inconvertibleErrorCode(),
930 "Version mismatch in API Notes");
931
932 SawMetadata = true;
933 break;
934
936 ModuleName = BlobData.str();
937 break;
938
940 break;
941
943 SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
944 break;
945
946 default:
947 // Unknown metadata record, possibly for use by a future version of the
948 // module format.
949 break;
950 }
951
952 MaybeNext = Cursor.advance();
953 if (!MaybeNext)
954 return MaybeNext.takeError();
955
956 Next = MaybeNext.get();
957 }
958
959 if (!SawMetadata)
960 return llvm::createStringError(llvm::inconvertibleErrorCode(),
961 "Missing metadata record");
962
963 return llvm::Error::success();
964}
965
967 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
968 if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID))
969 return llvm::createStringError(llvm::inconvertibleErrorCode(),
970 "Failed to enter identifier block");
971
972 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
973 if (!MaybeNext)
974 return MaybeNext.takeError();
975
976 llvm::BitstreamEntry Next = MaybeNext.get();
977
978 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
979 if (Next.Kind == llvm::BitstreamEntry::Error)
980 return llvm::createStringError(llvm::inconvertibleErrorCode(),
981 "Malformed bitstream entry");
982
983 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
984 // Unknown sub-block, possibly for use by a future version of the
985 // API notes format.
986 if (Cursor.SkipBlock())
987 return llvm::createStringError(llvm::inconvertibleErrorCode(),
988 "Failed to skip sub-block");
989
990 MaybeNext = Cursor.advance();
991 if (!MaybeNext)
992 return MaybeNext.takeError();
993
994 Next = MaybeNext.get();
995 continue;
996 }
997
998 Scratch.clear();
999 llvm::StringRef BlobData;
1000 llvm::Expected<unsigned> MaybeKind =
1001 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1002 if (!MaybeKind) {
1003 return MaybeKind.takeError();
1004 }
1005 unsigned Kind = MaybeKind.get();
1006 switch (Kind) {
1008 // Already saw identifier table.
1009 if (IdentifierTable)
1010 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1011 "Multiple identifier records found");
1012
1013 uint32_t tableOffset;
1014 identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);
1015 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1016
1017 IdentifierTable.reset(SerializedIdentifierTable::Create(
1018 base + tableOffset, base + sizeof(uint32_t), base));
1019 break;
1020 }
1021
1022 default:
1023 // Unknown record, possibly for use by a future version of the
1024 // module format.
1025 break;
1026 }
1027
1028 MaybeNext = Cursor.advance();
1029 if (!MaybeNext)
1030 return MaybeNext.takeError();
1031
1032 Next = MaybeNext.get();
1033 }
1034
1035 return llvm::Error::success();
1036}
1037
1039 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1040 if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
1041 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1042 "Failed to enter Objective-C context block");
1043
1044 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1045 if (!MaybeNext)
1046 return MaybeNext.takeError();
1047
1048 llvm::BitstreamEntry Next = MaybeNext.get();
1049
1050 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1051 if (Next.Kind == llvm::BitstreamEntry::Error)
1052 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1053 "Malformed bitstream entry");
1054
1055 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1056 // Unknown sub-block, possibly for use by a future version of the
1057 // API notes format.
1058 if (Cursor.SkipBlock())
1059 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1060 "Failed to skip sub-block");
1061
1062 MaybeNext = Cursor.advance();
1063 if (!MaybeNext)
1064 return MaybeNext.takeError();
1065
1066 Next = MaybeNext.get();
1067 continue;
1068 }
1069
1070 Scratch.clear();
1071 llvm::StringRef BlobData;
1072 llvm::Expected<unsigned> MaybeKind =
1073 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1074 if (!MaybeKind) {
1075 return MaybeKind.takeError();
1076 }
1077 unsigned Kind = MaybeKind.get();
1078 switch (Kind) {
1080 // Already saw Objective-C / C++ context ID table.
1081 if (ContextIDTable)
1082 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1083 "Multiple context ID records found");
1084
1085 uint32_t tableOffset;
1086 context_block::ContextIDLayout::readRecord(Scratch, tableOffset);
1087 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1088
1089 ContextIDTable.reset(SerializedContextIDTable::Create(
1090 base + tableOffset, base + sizeof(uint32_t), base));
1091 break;
1092 }
1093
1095 // Already saw Objective-C / C++ context info table.
1096 if (ContextInfoTable)
1097 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1098 "Multiple context info records found");
1099
1100 uint32_t tableOffset;
1101 context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);
1102 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1103
1104 ContextInfoTable.reset(SerializedContextInfoTable::Create(
1105 base + tableOffset, base + sizeof(uint32_t), base));
1106 break;
1107 }
1108
1109 default:
1110 // Unknown record, possibly for use by a future version of the
1111 // module format.
1112 break;
1113 }
1114
1115 MaybeNext = Cursor.advance();
1116 if (!MaybeNext)
1117 return MaybeNext.takeError();
1118
1119 Next = MaybeNext.get();
1120 }
1121
1122 return llvm::Error::success();
1123}
1124
1126 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1127 if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID))
1128 return llvm::createStringError(
1129 llvm::inconvertibleErrorCode(),
1130 "Failed to enter Objective-C property block");
1131
1132 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1133 if (!MaybeNext)
1134 return MaybeNext.takeError();
1135
1136 llvm::BitstreamEntry Next = MaybeNext.get();
1137
1138 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1139 if (Next.Kind == llvm::BitstreamEntry::Error)
1140 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1141 "Malformed bitstream entry");
1142
1143 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1144 // Unknown sub-block, possibly for use by a future version of the
1145 // API notes format.
1146 if (Cursor.SkipBlock())
1147 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1148 "Failed to skip sub-block");
1149
1150 MaybeNext = Cursor.advance();
1151 if (!MaybeNext)
1152 return MaybeNext.takeError();
1153
1154 Next = MaybeNext.get();
1155 continue;
1156 }
1157
1158 Scratch.clear();
1159 llvm::StringRef BlobData;
1160 llvm::Expected<unsigned> MaybeKind =
1161 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1162 if (!MaybeKind) {
1163 return MaybeKind.takeError();
1164 }
1165 unsigned Kind = MaybeKind.get();
1166 switch (Kind) {
1168 // Already saw Objective-C property table.
1170 return llvm::createStringError(
1171 llvm::inconvertibleErrorCode(),
1172 "Multiple Objective-C property records found");
1173
1174 uint32_t tableOffset;
1175 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,
1176 tableOffset);
1177 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1178
1179 ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(
1180 base + tableOffset, base + sizeof(uint32_t), base));
1181 break;
1182 }
1183
1184 default:
1185 // Unknown record, possibly for use by a future version of the
1186 // module format.
1187 break;
1188 }
1189
1190 MaybeNext = Cursor.advance();
1191 if (!MaybeNext)
1192 return MaybeNext.takeError();
1193
1194 Next = MaybeNext.get();
1195 }
1196
1197 return llvm::Error::success();
1198}
1199
1201 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1202 if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID))
1203 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1204 "Failed to enter Objective-C method block");
1205
1206 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1207 if (!MaybeNext)
1208 return MaybeNext.takeError();
1209
1210 llvm::BitstreamEntry Next = MaybeNext.get();
1211 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1212 if (Next.Kind == llvm::BitstreamEntry::Error)
1213 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1214 "Malformed bitstream entry");
1215
1216 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1217 // Unknown sub-block, possibly for use by a future version of the
1218 // API notes format.
1219 if (Cursor.SkipBlock())
1220 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1221 "Failed to skip sub-block");
1222
1223 MaybeNext = Cursor.advance();
1224 if (!MaybeNext)
1225 return MaybeNext.takeError();
1226
1227 Next = MaybeNext.get();
1228 continue;
1229 }
1230
1231 Scratch.clear();
1232 llvm::StringRef BlobData;
1233 llvm::Expected<unsigned> MaybeKind =
1234 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1235 if (!MaybeKind) {
1236 return MaybeKind.takeError();
1237 }
1238 unsigned Kind = MaybeKind.get();
1239 switch (Kind) {
1241 // Already saw Objective-C method table.
1242 if (ObjCMethodTable)
1243 return llvm::createStringError(
1244 llvm::inconvertibleErrorCode(),
1245 "Multiple Objective-C method records found");
1246
1247 uint32_t tableOffset;
1248 objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);
1249 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1250
1251 ObjCMethodTable.reset(SerializedObjCMethodTable::Create(
1252 base + tableOffset, base + sizeof(uint32_t), base));
1253 break;
1254 }
1255
1256 default:
1257 // Unknown record, possibly for use by a future version of the
1258 // module format.
1259 break;
1260 }
1261
1262 MaybeNext = Cursor.advance();
1263 if (!MaybeNext)
1264 return MaybeNext.takeError();
1265
1266 Next = MaybeNext.get();
1267 }
1268
1269 return llvm::Error::success();
1270}
1271
1273 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1274 if (Cursor.EnterSubBlock(CXX_METHOD_BLOCK_ID))
1275 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1276 "Failed to enter C++ method block");
1277
1278 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1279 if (!MaybeNext)
1280 return MaybeNext.takeError();
1281
1282 llvm::BitstreamEntry Next = MaybeNext.get();
1283 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1284 if (Next.Kind == llvm::BitstreamEntry::Error)
1285 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1286 "Malformed bitstream entry");
1287
1288 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1289 // Unknown sub-block, possibly for use by a future version of the
1290 // API notes format.
1291 if (Cursor.SkipBlock())
1292 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1293 "Failed to skip sub-block");
1294
1295 MaybeNext = Cursor.advance();
1296 if (!MaybeNext)
1297 return MaybeNext.takeError();
1298
1299 Next = MaybeNext.get();
1300 continue;
1301 }
1302
1303 Scratch.clear();
1304 llvm::StringRef BlobData;
1305 llvm::Expected<unsigned> MaybeKind =
1306 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1307 if (!MaybeKind) {
1308 return MaybeKind.takeError();
1309 }
1310 unsigned Kind = MaybeKind.get();
1311 switch (Kind) {
1313 // Already saw C++ method table.
1314 if (CXXMethodTable)
1315 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1316 "Multiple C++ method records found");
1317
1318 uint32_t tableOffset;
1319 cxx_method_block::CXXMethodDataLayout::readRecord(Scratch, tableOffset);
1320 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1321
1322 CXXMethodTable.reset(SerializedCXXMethodTable::Create(
1323 base + tableOffset, base + sizeof(uint32_t), base));
1324 break;
1325 }
1326
1327 default:
1328 // Unknown record, possibly for use by a future version of the
1329 // module format.
1330 break;
1331 }
1332
1333 MaybeNext = Cursor.advance();
1334 if (!MaybeNext)
1335 return MaybeNext.takeError();
1336
1337 Next = MaybeNext.get();
1338 }
1339
1340 return llvm::Error::success();
1341}
1342
1344 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1345 if (Cursor.EnterSubBlock(FIELD_BLOCK_ID))
1346 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1347 "Failed to enter field block");
1348
1349 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1350 if (!MaybeNext)
1351 return MaybeNext.takeError();
1352
1353 llvm::BitstreamEntry Next = MaybeNext.get();
1354 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1355 if (Next.Kind == llvm::BitstreamEntry::Error)
1356 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1357 "Malformed bitstream entry");
1358
1359 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1360 // Unknown sub-block, possibly for use by a future version of the
1361 // API notes format.
1362 if (Cursor.SkipBlock())
1363 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1364 "Failed to skip sub-block");
1365
1366 MaybeNext = Cursor.advance();
1367 if (!MaybeNext)
1368 return MaybeNext.takeError();
1369
1370 Next = MaybeNext.get();
1371 continue;
1372 }
1373
1374 Scratch.clear();
1375 llvm::StringRef BlobData;
1376 llvm::Expected<unsigned> MaybeKind =
1377 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1378 if (!MaybeKind) {
1379 return MaybeKind.takeError();
1380 }
1381 unsigned Kind = MaybeKind.get();
1382 switch (Kind) {
1384 // Already saw field table.
1385 if (FieldTable)
1386 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1387 "Multiple field records found");
1388
1389 uint32_t tableOffset;
1390 field_block::FieldDataLayout::readRecord(Scratch, tableOffset);
1391 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1392
1393 FieldTable.reset(SerializedFieldTable::Create(
1394 base + tableOffset, base + sizeof(uint32_t), base));
1395 break;
1396 }
1397
1398 default:
1399 // Unknown record, possibly for use by a future version of the
1400 // module format.
1401 break;
1402 }
1403
1404 MaybeNext = Cursor.advance();
1405 if (!MaybeNext)
1406 return MaybeNext.takeError();
1407
1408 Next = MaybeNext.get();
1409 }
1410
1411 return llvm::Error::success();
1412}
1413
1415 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1416 if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID))
1417 return llvm::createStringError(
1418 llvm::inconvertibleErrorCode(),
1419 "Failed to enter Objective-C selector block");
1420
1421 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1422 if (!MaybeNext)
1423 return MaybeNext.takeError();
1424
1425 llvm::BitstreamEntry Next = MaybeNext.get();
1426 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1427 if (Next.Kind == llvm::BitstreamEntry::Error)
1428 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1429 "Malformed bitstream entry");
1430
1431 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1432 // Unknown sub-block, possibly for use by a future version of the
1433 // API notes format.
1434 if (Cursor.SkipBlock())
1435 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1436 "Failed to skip sub-block");
1437
1438 MaybeNext = Cursor.advance();
1439 if (!MaybeNext)
1440 return MaybeNext.takeError();
1441
1442 Next = MaybeNext.get();
1443 continue;
1444 }
1445
1446 Scratch.clear();
1447 llvm::StringRef BlobData;
1448 llvm::Expected<unsigned> MaybeKind =
1449 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1450 if (!MaybeKind) {
1451 return MaybeKind.takeError();
1452 }
1453 unsigned Kind = MaybeKind.get();
1454 switch (Kind) {
1456 // Already saw Objective-C selector table.
1458 return llvm::createStringError(
1459 llvm::inconvertibleErrorCode(),
1460 "Multiple Objective-C selector records found");
1461
1462 uint32_t tableOffset;
1463 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,
1464 tableOffset);
1465 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1466
1467 ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(
1468 base + tableOffset, base + sizeof(uint32_t), base));
1469 break;
1470 }
1471
1472 default:
1473 // Unknown record, possibly for use by a future version of the
1474 // module format.
1475 break;
1476 }
1477
1478 MaybeNext = Cursor.advance();
1479 if (!MaybeNext)
1480 return MaybeNext.takeError();
1481
1482 Next = MaybeNext.get();
1483 }
1484
1485 return llvm::Error::success();
1486}
1487
1489 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1490 if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID))
1491 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1492 "Failed to enter global variable block");
1493
1494 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1495 if (!MaybeNext)
1496 return MaybeNext.takeError();
1497
1498 llvm::BitstreamEntry Next = MaybeNext.get();
1499 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1500 if (Next.Kind == llvm::BitstreamEntry::Error)
1501 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1502 "Malformed bitstream entry");
1503
1504 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1505 // Unknown sub-block, possibly for use by a future version of the
1506 // API notes format.
1507 if (Cursor.SkipBlock())
1508 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1509 "Failed to skip sub-block");
1510
1511 MaybeNext = Cursor.advance();
1512 if (!MaybeNext)
1513 return MaybeNext.takeError();
1514
1515 Next = MaybeNext.get();
1516 continue;
1517 }
1518
1519 Scratch.clear();
1520 llvm::StringRef BlobData;
1521 llvm::Expected<unsigned> MaybeKind =
1522 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1523 if (!MaybeKind) {
1524 return MaybeKind.takeError();
1525 }
1526 unsigned Kind = MaybeKind.get();
1527 switch (Kind) {
1529 // Already saw global variable table.
1531 return llvm::createStringError(
1532 llvm::inconvertibleErrorCode(),
1533 "Multiple global variable records found");
1534
1535 uint32_t tableOffset;
1536 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,
1537 tableOffset);
1538 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1539
1540 GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(
1541 base + tableOffset, base + sizeof(uint32_t), base));
1542 break;
1543 }
1544
1545 default:
1546 // Unknown record, possibly for use by a future version of the
1547 // module format.
1548 break;
1549 }
1550
1551 MaybeNext = Cursor.advance();
1552 if (!MaybeNext)
1553 return MaybeNext.takeError();
1554
1555 Next = MaybeNext.get();
1556 }
1557
1558 return llvm::Error::success();
1559}
1560
1562 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1563 if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID))
1564 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1565 "Failed to enter global function block");
1566
1567 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1568 if (!MaybeNext)
1569 return MaybeNext.takeError();
1570
1571 llvm::BitstreamEntry Next = MaybeNext.get();
1572 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1573 if (Next.Kind == llvm::BitstreamEntry::Error)
1574 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1575 "Malformed bitstream entry");
1576
1577 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1578 // Unknown sub-block, possibly for use by a future version of the
1579 // API notes format.
1580 if (Cursor.SkipBlock())
1581 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1582 "Failed to skip sub-block");
1583
1584 MaybeNext = Cursor.advance();
1585 if (!MaybeNext)
1586 return MaybeNext.takeError();
1587
1588 Next = MaybeNext.get();
1589 continue;
1590 }
1591
1592 Scratch.clear();
1593 llvm::StringRef BlobData;
1594 llvm::Expected<unsigned> MaybeKind =
1595 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1596 if (!MaybeKind) {
1597 return MaybeKind.takeError();
1598 }
1599 unsigned Kind = MaybeKind.get();
1600 switch (Kind) {
1602 // Already saw global function table.
1604 return llvm::createStringError(
1605 llvm::inconvertibleErrorCode(),
1606 "Multiple global function records found");
1607
1608 uint32_t tableOffset;
1609 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,
1610 tableOffset);
1611 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1612
1613 GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(
1614 base + tableOffset, base + sizeof(uint32_t), base));
1615 break;
1616 }
1617
1618 default:
1619 // Unknown record, possibly for use by a future version of the
1620 // module format.
1621 break;
1622 }
1623
1624 MaybeNext = Cursor.advance();
1625 if (!MaybeNext)
1626 return MaybeNext.takeError();
1627
1628 Next = MaybeNext.get();
1629 }
1630
1631 return llvm::Error::success();
1632}
1633
1635 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1636 if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID))
1637 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1638 "Failed to enter enum constant block");
1639
1640 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1641 if (!MaybeNext)
1642 return MaybeNext.takeError();
1643
1644 llvm::BitstreamEntry Next = MaybeNext.get();
1645 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1646 if (Next.Kind == llvm::BitstreamEntry::Error)
1647 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1648 "Malformed bitstream entry");
1649
1650 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1651 // Unknown sub-block, possibly for use by a future version of the
1652 // API notes format.
1653 if (Cursor.SkipBlock())
1654 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1655 "Failed to skip sub-block");
1656
1657 MaybeNext = Cursor.advance();
1658 if (!MaybeNext)
1659 return MaybeNext.takeError();
1660
1661 Next = MaybeNext.get();
1662 continue;
1663 }
1664
1665 Scratch.clear();
1666 llvm::StringRef BlobData;
1667 llvm::Expected<unsigned> MaybeKind =
1668 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1669 if (!MaybeKind) {
1670 return MaybeKind.takeError();
1671 }
1672 unsigned Kind = MaybeKind.get();
1673 switch (Kind) {
1675 // Already saw enumerator table.
1677 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1678 "Multiple enum constant records found");
1679
1680 uint32_t tableOffset;
1681 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,
1682 tableOffset);
1683 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1684
1685 EnumConstantTable.reset(SerializedEnumConstantTable::Create(
1686 base + tableOffset, base + sizeof(uint32_t), base));
1687 break;
1688 }
1689
1690 default:
1691 // Unknown record, possibly for use by a future version of the
1692 // module format.
1693 break;
1694 }
1695
1696 MaybeNext = Cursor.advance();
1697 if (!MaybeNext)
1698 return MaybeNext.takeError();
1699
1700 Next = MaybeNext.get();
1701 }
1702
1703 return llvm::Error::success();
1704}
1705
1707 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1708 if (Cursor.EnterSubBlock(TAG_BLOCK_ID))
1709 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1710 "Failed to enter tag block");
1711
1712 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1713 if (!MaybeNext)
1714 return MaybeNext.takeError();
1715
1716 llvm::BitstreamEntry Next = MaybeNext.get();
1717 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1718 if (Next.Kind == llvm::BitstreamEntry::Error)
1719 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1720 "Malformed bitstream entry");
1721
1722 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1723 // Unknown sub-block, possibly for use by a future version of the
1724 // API notes format.
1725 if (Cursor.SkipBlock())
1726 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1727 "Failed to skip sub-block");
1728
1729 MaybeNext = Cursor.advance();
1730 if (!MaybeNext)
1731 return MaybeNext.takeError();
1732
1733 Next = MaybeNext.get();
1734 continue;
1735 }
1736
1737 Scratch.clear();
1738 llvm::StringRef BlobData;
1739 llvm::Expected<unsigned> MaybeKind =
1740 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1741 if (!MaybeKind) {
1742 return MaybeKind.takeError();
1743 }
1744 unsigned Kind = MaybeKind.get();
1745 switch (Kind) {
1746 case tag_block::TAG_DATA: {
1747 // Already saw tag table.
1748 if (TagTable)
1749 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1750 "Multiple tag records found");
1751
1752 uint32_t tableOffset;
1753 tag_block::TagDataLayout::readRecord(Scratch, tableOffset);
1754 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1755
1756 TagTable.reset(SerializedTagTable::Create(base + tableOffset,
1757 base + sizeof(uint32_t), base));
1758 break;
1759 }
1760
1761 default:
1762 // Unknown record, possibly for use by a future version of the
1763 // module format.
1764 break;
1765 }
1766
1767 MaybeNext = Cursor.advance();
1768 if (!MaybeNext)
1769 return MaybeNext.takeError();
1770
1771 Next = MaybeNext.get();
1772 }
1773
1774 return llvm::Error::success();
1775}
1776
1778 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1779 if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID))
1780 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1781 "Failed to enter typedef block");
1782
1783 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1784 if (!MaybeNext)
1785 return MaybeNext.takeError();
1786
1787 llvm::BitstreamEntry Next = MaybeNext.get();
1788 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1789 if (Next.Kind == llvm::BitstreamEntry::Error)
1790 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1791 "Malformed bitstream entry");
1792
1793 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1794 // Unknown sub-block, possibly for use by a future version of the
1795 // API notes format.
1796 if (Cursor.SkipBlock())
1797 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1798 "Failed to skip sub-block");
1799
1800 MaybeNext = Cursor.advance();
1801 if (!MaybeNext)
1802 return MaybeNext.takeError();
1803
1804 Next = MaybeNext.get();
1805 continue;
1806 }
1807
1808 Scratch.clear();
1809 llvm::StringRef BlobData;
1810 llvm::Expected<unsigned> MaybeKind =
1811 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1812 if (!MaybeKind) {
1813 return MaybeKind.takeError();
1814 }
1815 unsigned Kind = MaybeKind.get();
1816 switch (Kind) {
1818 // Already saw typedef table.
1819 if (TypedefTable)
1820 return llvm::createStringError(llvm::inconvertibleErrorCode(),
1821 "Multiple typedef records found");
1822
1823 uint32_t tableOffset;
1824 typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);
1825 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1826
1827 TypedefTable.reset(SerializedTypedefTable::Create(
1828 base + tableOffset, base + sizeof(uint32_t), base));
1829 break;
1830 }
1831
1832 default:
1833 // Unknown record, possibly for use by a future version of the
1834 // module format.
1835 break;
1836 }
1837
1838 MaybeNext = Cursor.advance();
1839 if (!MaybeNext)
1840 return MaybeNext.takeError();
1841
1842 Next = MaybeNext.get();
1843 }
1844
1845 return llvm::Error::success();
1846}
1847
1848APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1849 llvm::VersionTuple SwiftVersion,
1850 llvm::Error &Err)
1851 : Implementation(new class Implementation) {
1852
1853 // Initialize the input buffer.
1856 llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);
1857
1858 // Validate signature.
1859 for (auto byte : API_NOTES_SIGNATURE) {
1860 if (Cursor.AtEndOfStream()) {
1861 Err = llvm::createStringError(
1862 llvm::inconvertibleErrorCode(),
1863 "Unexpected end of stream while reading signature");
1864 return;
1865 }
1867 Cursor.Read(8);
1868 if (!maybeRead) {
1869 Err = maybeRead.takeError();
1870 return;
1871 }
1872 if (maybeRead.get() != byte) {
1873 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1874 "Invalid signature in API notes file");
1875 return;
1876 }
1877 }
1878
1879 // Look at all of the blocks.
1880 bool HasValidControlBlock = false;
1881 llvm::SmallVector<uint64_t, 64> Scratch;
1882 while (!Cursor.AtEndOfStream()) {
1883 llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();
1884 if (!MaybeTopLevelEntry) {
1885 Err = MaybeTopLevelEntry.takeError();
1886 return;
1887 }
1888 llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();
1889
1890 if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
1891 break;
1892
1893 switch (TopLevelEntry.ID) {
1894 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1895 if (!Cursor.ReadBlockInfoBlock()) {
1896 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1897 "Failed to read block info");
1898 return;
1899 }
1900 break;
1901
1902 case CONTROL_BLOCK_ID:
1903 // Only allow a single control block.
1904 if (HasValidControlBlock) {
1905 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1906 "Multiple control blocks found");
1907 return;
1908 }
1909 if (llvm::Error BlockErr =
1910 Implementation->readControlBlock(Cursor, Scratch)) {
1911 Err = std::move(BlockErr);
1912 return;
1913 }
1914 HasValidControlBlock = true;
1915 break;
1916
1918 if (!HasValidControlBlock) {
1919 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1920 "Missing control block");
1921 return;
1922 }
1923 if (llvm::Error BlockErr =
1924 Implementation->readIdentifierBlock(Cursor, Scratch)) {
1925 Err = std::move(BlockErr);
1926 return;
1927 }
1928 break;
1929
1931 if (!HasValidControlBlock) {
1932 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1933 "Missing control block");
1934 return;
1935 }
1936 if (llvm::Error BlockErr =
1937 Implementation->readContextBlock(Cursor, Scratch)) {
1938 Err = std::move(BlockErr);
1939 return;
1940 }
1941 break;
1942
1944 if (!HasValidControlBlock) {
1945 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1946 "Missing control block");
1947 return;
1948 }
1949 if (llvm::Error BlockErr =
1950 Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
1951 Err = std::move(BlockErr);
1952 return;
1953 }
1954 break;
1955
1957 if (!HasValidControlBlock) {
1958 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1959 "Missing control block");
1960 return;
1961 }
1962 if (llvm::Error BlockErr =
1963 Implementation->readObjCMethodBlock(Cursor, Scratch)) {
1964 Err = std::move(BlockErr);
1965 return;
1966 }
1967 break;
1968
1970 if (!HasValidControlBlock) {
1971 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1972 "Missing control block");
1973 return;
1974 }
1975 if (llvm::Error BlockErr =
1976 Implementation->readCXXMethodBlock(Cursor, Scratch)) {
1977 Err = std::move(BlockErr);
1978 return;
1979 }
1980 break;
1981
1982 case FIELD_BLOCK_ID:
1983 if (!HasValidControlBlock) {
1984 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1985 "Missing control block");
1986 return;
1987 }
1988 if (llvm::Error BlockErr =
1989 Implementation->readFieldBlock(Cursor, Scratch)) {
1990 Err = std::move(BlockErr);
1991 return;
1992 }
1993 break;
1994
1996 if (!HasValidControlBlock) {
1997 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
1998 "Missing control block");
1999 return;
2000 }
2001 if (llvm::Error BlockErr =
2002 Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
2003 Err = std::move(BlockErr);
2004 return;
2005 }
2006 break;
2007
2009 if (!HasValidControlBlock) {
2010 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
2011 "Missing control block");
2012 return;
2013 }
2014 if (llvm::Error BlockErr =
2015 Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
2016 Err = std::move(BlockErr);
2017 return;
2018 }
2019 break;
2020
2022 if (!HasValidControlBlock) {
2023 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
2024 "Missing control block");
2025 return;
2026 }
2027 if (llvm::Error BlockErr =
2028 Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
2029 Err = std::move(BlockErr);
2030 return;
2031 }
2032 break;
2033
2035 if (!HasValidControlBlock) {
2036 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
2037 "Missing control block");
2038 return;
2039 }
2040 if (llvm::Error BlockErr =
2041 Implementation->readEnumConstantBlock(Cursor, Scratch)) {
2042 Err = std::move(BlockErr);
2043 return;
2044 }
2045 break;
2046
2047 case TAG_BLOCK_ID:
2048 if (!HasValidControlBlock) {
2049 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
2050 "Missing control block");
2051 return;
2052 }
2053 if (llvm::Error BlockErr =
2054 Implementation->readTagBlock(Cursor, Scratch)) {
2055 Err = std::move(BlockErr);
2056 return;
2057 }
2058 break;
2059
2060 case TYPEDEF_BLOCK_ID:
2061 if (!HasValidControlBlock) {
2062 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
2063 "Missing control block");
2064 return;
2065 }
2066 if (llvm::Error BlockErr =
2067 Implementation->readTypedefBlock(Cursor, Scratch)) {
2068 Err = std::move(BlockErr);
2069 return;
2070 }
2071 break;
2072
2073 default:
2074 // Unknown top-level block, possibly for use by a future version of the
2075 // module format.
2076 if (Cursor.SkipBlock()) {
2077 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
2078 "Failed to skip unknown top-level block");
2079 return;
2080 }
2081 break;
2082 }
2083 }
2084
2085 if (!Cursor.AtEndOfStream()) {
2086 Err = llvm::createStringError(llvm::inconvertibleErrorCode(),
2087 "Bitstream has unread data after all blocks");
2088 return;
2089 }
2090}
2091
2093
2095APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
2096 llvm::VersionTuple SwiftVersion) {
2097 llvm::Error Err = llvm::Error::success();
2098 std::unique_ptr<APINotesReader> Reader(
2099 new APINotesReader(InputBuffer.release(), SwiftVersion, Err));
2100
2101 if (Err)
2102 return Err;
2103
2104 return std::move(Reader);
2105}
2106
2107template <typename T>
2109 llvm::VersionTuple Version,
2110 llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)
2111 : Results(std::move(R)) {
2112
2113 assert(!Results.empty());
2114 assert(llvm::is_sorted(
2115 Results,
2116 [](const std::pair<llvm::VersionTuple, T> &left,
2117 const std::pair<llvm::VersionTuple, T> &right) -> bool {
2118 // The comparison function should be reflective, and with expensive
2119 // checks we can get callbacks basically checking that lambda(a,a) is
2120 // false. We could still check that we do not find equal elements when
2121 // left!=right.
2122 assert((&left == &right || left.first != right.first) &&
2123 "two entries for the same version");
2124 return left.first < right.first;
2125 }));
2126
2127 Selected = std::nullopt;
2128 for (unsigned i = 0, n = Results.size(); i != n; ++i) {
2129 if (!Version.empty() && Results[i].first >= Version) {
2130 // If the current version is "4", then entries for 4 are better than
2131 // entries for 5, but both are valid. Because entries are sorted, we get
2132 // that behavior by picking the first match.
2133 Selected = i;
2134 break;
2135 }
2136 }
2137
2138 // If we didn't find a match but we have an unversioned result, use the
2139 // unversioned result. This will always be the first entry because we encode
2140 // it as version 0.
2141 if (!Selected && Results[0].first.empty())
2142 Selected = 0;
2143}
2144
2145auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
2146 -> std::optional<ContextID> {
2148 return std::nullopt;
2149
2150 std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
2151 if (!ClassID)
2152 return std::nullopt;
2153
2154 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
2155 // context.
2156 auto KnownID = Implementation->ContextIDTable->find(
2157 ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
2158 if (KnownID == Implementation->ContextIDTable->end())
2159 return std::nullopt;
2160
2161 return ContextID(*KnownID);
2162}
2163
2164auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
2167 return std::nullopt;
2168
2169 std::optional<ContextID> CtxID = lookupObjCClassID(Name);
2170 if (!CtxID)
2171 return std::nullopt;
2172
2173 auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
2174 if (KnownInfo == Implementation->ContextInfoTable->end())
2175 return std::nullopt;
2176
2177 return {Implementation->SwiftVersion, *KnownInfo};
2178}
2179
2181 -> std::optional<ContextID> {
2183 return std::nullopt;
2184
2185 std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
2186 if (!classID)
2187 return std::nullopt;
2188
2189 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
2190 // context.
2191 auto KnownID = Implementation->ContextIDTable->find(
2192 ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
2193 if (KnownID == Implementation->ContextIDTable->end())
2194 return std::nullopt;
2195
2196 return ContextID(*KnownID);
2197}
2198
2202 return std::nullopt;
2203
2204 std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
2205 if (!CtxID)
2206 return std::nullopt;
2207
2208 auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
2209 if (KnownInfo == Implementation->ContextInfoTable->end())
2210 return std::nullopt;
2211
2212 return {Implementation->SwiftVersion, *KnownInfo};
2213}
2214
2215auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,
2216 bool IsInstance)
2219 return std::nullopt;
2220
2221 std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name);
2222 if (!PropertyID)
2223 return std::nullopt;
2224
2225 auto Known = Implementation->ObjCPropertyTable->find(
2226 std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance));
2227 if (Known == Implementation->ObjCPropertyTable->end())
2228 return std::nullopt;
2229
2230 return {Implementation->SwiftVersion, *Known};
2231}
2232
2234 bool IsInstanceMethod)
2237 return std::nullopt;
2238
2239 std::optional<SelectorID> SelID = Implementation->getSelector(Selector);
2240 if (!SelID)
2241 return std::nullopt;
2242
2243 auto Known = Implementation->ObjCMethodTable->find(
2244 ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
2245 IsInstanceMethod});
2246 if (Known == Implementation->ObjCMethodTable->end())
2247 return std::nullopt;
2248
2249 return {Implementation->SwiftVersion, *Known};
2250}
2251
2252auto APINotesReader::lookupField(ContextID CtxID, llvm::StringRef Name)
2255 return std::nullopt;
2256
2257 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2258 if (!NameID)
2259 return std::nullopt;
2260
2261 auto Known = Implementation->FieldTable->find(
2262 SingleDeclTableKey(CtxID.Value, *NameID));
2263 if (Known == Implementation->FieldTable->end())
2264 return std::nullopt;
2265
2266 return {Implementation->SwiftVersion, *Known};
2267}
2268
2269auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
2272 return std::nullopt;
2273
2274 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2275 if (!NameID)
2276 return std::nullopt;
2277
2278 auto Known = Implementation->CXXMethodTable->find(
2279 SingleDeclTableKey(CtxID.Value, *NameID));
2280 if (Known == Implementation->CXXMethodTable->end())
2281 return std::nullopt;
2282
2283 return {Implementation->SwiftVersion, *Known};
2284}
2285
2287 std::optional<Context> Ctx)
2290 return std::nullopt;
2291
2292 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2293 if (!NameID)
2294 return std::nullopt;
2295
2296 SingleDeclTableKey Key(Ctx, *NameID);
2297
2298 auto Known = Implementation->GlobalVariableTable->find(Key);
2299 if (Known == Implementation->GlobalVariableTable->end())
2300 return std::nullopt;
2301
2302 return {Implementation->SwiftVersion, *Known};
2303}
2304
2306 std::optional<Context> Ctx)
2309 return std::nullopt;
2310
2311 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2312 if (!NameID)
2313 return std::nullopt;
2314
2315 SingleDeclTableKey Key(Ctx, *NameID);
2316
2317 auto Known = Implementation->GlobalFunctionTable->find(Key);
2318 if (Known == Implementation->GlobalFunctionTable->end())
2319 return std::nullopt;
2320
2321 return {Implementation->SwiftVersion, *Known};
2322}
2323
2324auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
2327 return std::nullopt;
2328
2329 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2330 if (!NameID)
2331 return std::nullopt;
2332
2333 auto Known = Implementation->EnumConstantTable->find(*NameID);
2334 if (Known == Implementation->EnumConstantTable->end())
2335 return std::nullopt;
2336
2337 return {Implementation->SwiftVersion, *Known};
2338}
2339
2340auto APINotesReader::lookupTagID(llvm::StringRef Name,
2341 std::optional<Context> ParentCtx)
2342 -> std::optional<ContextID> {
2344 return std::nullopt;
2345
2346 std::optional<IdentifierID> TagID = Implementation->getIdentifier(Name);
2347 if (!TagID)
2348 return std::nullopt;
2349
2350 auto KnownID = Implementation->ContextIDTable->find(
2351 ContextTableKey(ParentCtx, ContextKind::Tag, *TagID));
2352 if (KnownID == Implementation->ContextIDTable->end())
2353 return std::nullopt;
2354
2355 return ContextID(*KnownID);
2356}
2357
2358auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
2361 return std::nullopt;
2362
2363 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2364 if (!NameID)
2365 return std::nullopt;
2366
2367 SingleDeclTableKey Key(Ctx, *NameID);
2368
2369 auto Known = Implementation->TagTable->find(Key);
2370 if (Known == Implementation->TagTable->end())
2371 return std::nullopt;
2372
2373 return {Implementation->SwiftVersion, *Known};
2374}
2375
2376auto APINotesReader::lookupTypedef(llvm::StringRef Name,
2377 std::optional<Context> Ctx)
2380 return std::nullopt;
2381
2382 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2383 if (!NameID)
2384 return std::nullopt;
2385
2386 SingleDeclTableKey Key(Ctx, *NameID);
2387
2388 auto Known = Implementation->TypedefTable->find(Key);
2389 if (Known == Implementation->TypedefTable->end())
2390 return std::nullopt;
2391
2392 return {Implementation->SwiftVersion, *Known};
2393}
2394
2396 llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
2397 -> std::optional<ContextID> {
2399 return std::nullopt;
2400
2401 std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
2402 if (!NamespaceID)
2403 return std::nullopt;
2404
2405 uint32_t RawParentNamespaceID =
2406 ParentNamespaceID ? ParentNamespaceID->Value : -1;
2407 auto KnownID = Implementation->ContextIDTable->find(
2408 {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
2409 if (KnownID == Implementation->ContextIDTable->end())
2410 return std::nullopt;
2411
2412 return ContextID(*KnownID);
2413}
2414
2415} // namespace api_notes
2416} // 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:970
API notes for a function or method.
Definition Types.h:615
Describes a function or method parameter.
Definition Types.h:515
API notes for a variable/property.
Definition Types.h:408
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:997
A stored Objective-C or C++ declaration, represented by the ID of its parent context,...
A stored Objective-C selector.
llvm::SmallVector< IdentifierID, 2 > Identifiers