clang 22.0.0git
APINotesReader.cpp
Go to the documentation of this file.
1//===--- APINotesReader.cpp - API Notes Reader ------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the \c APINotesReader class that reads source
10// API notes data providing additional information about source code as
11// a separate input, such as the non-nil/nilable annotations for
12// method parameters.
13//
14//===----------------------------------------------------------------------===//
16#include "APINotesFormat.h"
18#include "llvm/ADT/Hashing.h"
19#include "llvm/Bitstream/BitstreamReader.h"
20#include "llvm/Support/DJB.h"
21#include "llvm/Support/OnDiskHashTable.h"
22
23namespace clang {
24namespace api_notes {
25using namespace llvm::support;
26
27namespace {
28/// Deserialize a version tuple.
29llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {
30 uint8_t NumVersions = (*Data++) & 0x03;
31
32 unsigned Major = endian::readNext<uint32_t, llvm::endianness::little>(Data);
33 if (NumVersions == 0)
34 return llvm::VersionTuple(Major);
35
36 unsigned Minor = endian::readNext<uint32_t, llvm::endianness::little>(Data);
37 if (NumVersions == 1)
38 return llvm::VersionTuple(Major, Minor);
39
40 unsigned Subminor =
41 endian::readNext<uint32_t, llvm::endianness::little>(Data);
42 if (NumVersions == 2)
43 return llvm::VersionTuple(Major, Minor, Subminor);
44
45 unsigned Build = endian::readNext<uint32_t, llvm::endianness::little>(Data);
46 return llvm::VersionTuple(Major, Minor, Subminor, Build);
47}
48
49/// An on-disk hash table whose data is versioned based on the Swift version.
50template <typename Derived, typename KeyType, typename UnversionedDataType>
51class VersionedTableInfo {
52public:
53 using internal_key_type = KeyType;
54 using external_key_type = KeyType;
55 using data_type =
56 llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
57 using hash_value_type = size_t;
58 using offset_type = unsigned;
59
60 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
61
62 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
63
64 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
65 return LHS == RHS;
66 }
67
68 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
69 unsigned KeyLength =
70 endian::readNext<uint16_t, llvm::endianness::little>(Data);
71 unsigned DataLength =
72 endian::readNext<uint16_t, llvm::endianness::little>(Data);
73 return {KeyLength, DataLength};
74 }
75
76 static data_type ReadData(internal_key_type Key, const uint8_t *Data,
77 unsigned Length) {
78 unsigned NumElements =
79 endian::readNext<uint16_t, llvm::endianness::little>(Data);
80 data_type Result;
81 Result.reserve(NumElements);
82 for (unsigned i = 0; i != NumElements; ++i) {
83 auto version = ReadVersionTuple(Data);
84 const auto *DataBefore = Data;
85 (void)DataBefore;
86 auto UnversionedData = Derived::readUnversioned(Key, Data);
87 assert(Data != DataBefore &&
88 "Unversioned data reader didn't move pointer");
89 Result.push_back({version, UnversionedData});
90 }
91 return Result;
92 }
93};
94
95/// Read serialized CommonEntityInfo.
96void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) {
97 uint8_t 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 ParamInfo.
334void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) {
335 ReadVariableInfo(Data, Info);
336
337 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);
338 if (auto RawConvention = Payload & 0x7) {
339 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
340 Info.setRetainCountConvention(Convention);
341 }
342 Payload >>= 3;
343 if (Payload & 0x01)
344 Info.setLifetimebound(Payload & 0x02);
345 Payload >>= 2;
346 if (Payload & 0x01)
347 Info.setNoEscape(Payload & 0x02);
348 Payload >>= 2;
349 assert(Payload == 0 && "Bad API notes");
350}
351
352/// Read serialized FunctionInfo.
353void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) {
354 ReadCommonEntityInfo(Data, Info);
355
356 uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);
357 if (auto RawConvention = Payload & 0x7) {
358 auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
359 Info.setRetainCountConvention(Convention);
360 }
361 Payload >>= 3;
362 Info.NullabilityAudited = Payload & 0x1;
363 Payload >>= 1;
364 assert(Payload == 0 && "Bad API notes");
365
366 Info.NumAdjustedNullable =
367 endian::readNext<uint8_t, llvm::endianness::little>(Data);
368 Info.NullabilityPayload =
369 endian::readNext<uint64_t, llvm::endianness::little>(Data);
370
371 unsigned NumParams =
372 endian::readNext<uint16_t, llvm::endianness::little>(Data);
373 while (NumParams > 0) {
374 ParamInfo pi;
375 ReadParamInfo(Data, pi);
376 Info.Params.push_back(pi);
377 --NumParams;
378 }
379
380 unsigned ResultTypeLen =
381 endian::readNext<uint16_t, llvm::endianness::little>(Data);
382 Info.ResultType = std::string(Data, Data + ResultTypeLen);
383 Data += ResultTypeLen;
384
385 unsigned SwiftReturnOwnershipLength =
386 endian::readNext<uint16_t, llvm::endianness::little>(Data);
387 Info.SwiftReturnOwnership = std::string(reinterpret_cast<const char *>(Data),
388 reinterpret_cast<const char *>(Data) +
389 SwiftReturnOwnershipLength);
390 Data += SwiftReturnOwnershipLength;
391}
392
393/// Used to deserialize the on-disk Objective-C method table.
394class ObjCMethodTableInfo
395 : public VersionedTableInfo<ObjCMethodTableInfo,
396 std::tuple<uint32_t, uint32_t, uint8_t>,
397 ObjCMethodInfo> {
398public:
399 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
400 auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
401 auto SelectorID =
402 endian::readNext<uint32_t, llvm::endianness::little>(Data);
403 auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);
404 return {ClassID, SelectorID, IsInstance};
405 }
406
407 hash_value_type ComputeHash(internal_key_type Key) {
408 return static_cast<size_t>(llvm::hash_value(Key));
409 }
410
411 static ObjCMethodInfo readUnversioned(internal_key_type Key,
412 const uint8_t *&Data) {
413 ObjCMethodInfo Info;
414 uint8_t Payload = *Data++;
415 bool HasSelf = Payload & 0x01;
416 Payload >>= 1;
417 Info.RequiredInit = Payload & 0x01;
418 Payload >>= 1;
419 Info.DesignatedInit = Payload & 0x01;
420 Payload >>= 1;
421 assert(Payload == 0 && "Unable to fully decode 'Payload'.");
422
423 ReadFunctionInfo(Data, Info);
424 if (HasSelf) {
425 Info.Self = ParamInfo{};
426 ReadParamInfo(Data, *Info.Self);
427 }
428 return Info;
429 }
430};
431
432/// Used to deserialize the on-disk Objective-C selector table.
433class ObjCSelectorTableInfo {
434public:
435 using internal_key_type = StoredObjCSelector;
436 using external_key_type = internal_key_type;
437 using data_type = SelectorID;
438 using hash_value_type = unsigned;
439 using offset_type = unsigned;
440
441 internal_key_type GetInternalKey(external_key_type Key) { return Key; }
442
443 external_key_type GetExternalKey(internal_key_type Key) { return Key; }
444
445 hash_value_type ComputeHash(internal_key_type Key) {
446 return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
447 }
448
449 static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
450 return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);
451 }
452
453 static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
454 unsigned KeyLength =
455 endian::readNext<uint16_t, llvm::endianness::little>(Data);
456 unsigned DataLength =
457 endian::readNext<uint16_t, llvm::endianness::little>(Data);
458 return {KeyLength, DataLength};
459 }
460
461 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
462 internal_key_type Key;
463 Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(Data);
464 unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
465 for (unsigned i = 0; i != NumIdents; ++i) {
466 Key.Identifiers.push_back(
467 endian::readNext<uint32_t, llvm::endianness::little>(Data));
468 }
469 return Key;
470 }
471
472 static data_type ReadData(internal_key_type Key, const uint8_t *Data,
473 unsigned Length) {
474 return endian::readNext<uint32_t, llvm::endianness::little>(Data);
475 }
476};
477
478/// Used to deserialize the on-disk global variable table.
479class GlobalVariableTableInfo
480 : public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
481 GlobalVariableInfo> {
482public:
483 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
484 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
485 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
486 return {CtxID, NameID};
487 }
488
489 hash_value_type ComputeHash(internal_key_type Key) {
490 return static_cast<size_t>(Key.hashValue());
491 }
492
493 static GlobalVariableInfo readUnversioned(internal_key_type Key,
494 const uint8_t *&Data) {
495 GlobalVariableInfo Info;
496 ReadVariableInfo(Data, Info);
497 return Info;
498 }
499};
500
501/// Used to deserialize the on-disk global function table.
502class GlobalFunctionTableInfo
503 : public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
504 GlobalFunctionInfo> {
505public:
506 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
507 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
508 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
509 return {CtxID, NameID};
510 }
511
512 hash_value_type ComputeHash(internal_key_type Key) {
513 return static_cast<size_t>(Key.hashValue());
514 }
515
516 static GlobalFunctionInfo readUnversioned(internal_key_type Key,
517 const uint8_t *&Data) {
518 GlobalFunctionInfo Info;
519 ReadFunctionInfo(Data, Info);
520 return Info;
521 }
522};
523
524/// Used to deserialize the on-disk C++ method table.
525class CXXMethodTableInfo
526 : public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
527 CXXMethodInfo> {
528public:
529 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
530 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
531 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
532 return {CtxID, NameID};
533 }
534
535 hash_value_type ComputeHash(internal_key_type Key) {
536 return static_cast<size_t>(Key.hashValue());
537 }
538
539 static CXXMethodInfo readUnversioned(internal_key_type Key,
540 const uint8_t *&Data) {
541 CXXMethodInfo Info;
542
543 uint8_t Payload = *Data++;
544 bool HasThis = Payload & 0x01;
545 Payload >>= 1;
546 assert(Payload == 0 && "Unable to fully decode 'Payload'.");
547
548 ReadFunctionInfo(Data, Info);
549 if (HasThis) {
550 Info.This = ParamInfo{};
551 ReadParamInfo(Data, *Info.This);
552 }
553 return Info;
554 }
555};
556
557/// Used to deserialize the on-disk enumerator table.
558class EnumConstantTableInfo
559 : public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
560 EnumConstantInfo> {
561public:
562 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
563 auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
564 return NameID;
565 }
566
567 hash_value_type ComputeHash(internal_key_type Key) {
568 return static_cast<size_t>(llvm::hash_value(Key));
569 }
570
571 static EnumConstantInfo readUnversioned(internal_key_type Key,
572 const uint8_t *&Data) {
573 EnumConstantInfo Info;
574 ReadCommonEntityInfo(Data, Info);
575 return Info;
576 }
577};
578
579/// Used to deserialize the on-disk tag table.
580class TagTableInfo
581 : public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> {
582public:
583 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
584 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
585 auto NameID =
586 endian::readNext<IdentifierID, llvm::endianness::little>(Data);
587 return {CtxID, NameID};
588 }
589
590 hash_value_type ComputeHash(internal_key_type Key) {
591 return static_cast<size_t>(Key.hashValue());
592 }
593
594 static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {
595 TagInfo Info;
596
597 uint8_t Payload = *Data++;
598 if (Payload & 1)
599 Info.setFlagEnum(Payload & 2);
600 Payload >>= 2;
601 if (Payload > 0)
602 Info.EnumExtensibility =
603 static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);
604
605 uint8_t Copyable =
606 endian::readNext<uint8_t, llvm::endianness::little>(Data);
607 if (Copyable == kSwiftConforms || Copyable == kSwiftDoesNotConform)
608 Info.setSwiftCopyable(std::optional(Copyable == kSwiftConforms));
609 uint8_t Escapable =
610 endian::readNext<uint8_t, llvm::endianness::little>(Data);
611 if (Escapable == kSwiftConforms || Escapable == kSwiftDoesNotConform)
612 Info.setSwiftEscapable(std::optional(Escapable == kSwiftConforms));
613
614 unsigned ImportAsLength =
615 endian::readNext<uint16_t, llvm::endianness::little>(Data);
616 if (ImportAsLength > 0) {
617 Info.SwiftImportAs =
618 std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1);
619 Data += ImportAsLength - 1;
620 }
621 unsigned RetainOpLength =
622 endian::readNext<uint16_t, llvm::endianness::little>(Data);
623 if (RetainOpLength > 0) {
624 Info.SwiftRetainOp =
625 std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1);
626 Data += RetainOpLength - 1;
627 }
628 unsigned ReleaseOpLength =
629 endian::readNext<uint16_t, llvm::endianness::little>(Data);
630 if (ReleaseOpLength > 0) {
631 Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data),
632 ReleaseOpLength - 1);
633 Data += ReleaseOpLength - 1;
634 }
635 unsigned DefaultOwnershipLength =
636 endian::readNext<uint16_t, llvm::endianness::little>(Data);
637 if (DefaultOwnershipLength > 0) {
638 Info.SwiftDefaultOwnership = std::string(
639 reinterpret_cast<const char *>(Data), DefaultOwnershipLength - 1);
640 Data += DefaultOwnershipLength - 1;
641 }
642 unsigned DestroyOpLength =
643 endian::readNext<uint16_t, llvm::endianness::little>(Data);
644 if (DestroyOpLength > 0) {
645 Info.SwiftDestroyOp = std::string(reinterpret_cast<const char *>(Data),
646 DestroyOpLength - 1);
647 Data += DestroyOpLength - 1;
648 }
649
650 ReadCommonTypeInfo(Data, Info);
651 return Info;
652 }
653};
654
655/// Used to deserialize the on-disk typedef table.
656class TypedefTableInfo
657 : public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey,
658 TypedefInfo> {
659public:
660 static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
661 auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
662 auto nameID =
663 endian::readNext<IdentifierID, llvm::endianness::little>(Data);
664 return {CtxID, nameID};
665 }
666
667 hash_value_type ComputeHash(internal_key_type Key) {
668 return static_cast<size_t>(Key.hashValue());
669 }
670
671 static TypedefInfo readUnversioned(internal_key_type Key,
672 const uint8_t *&Data) {
673 TypedefInfo Info;
674
675 uint8_t Payload = *Data++;
676 if (Payload > 0)
677 Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);
678
679 ReadCommonTypeInfo(Data, Info);
680 return Info;
681 }
682};
683} // end anonymous namespace
684
686public:
687 /// The input buffer for the API notes data.
688 llvm::MemoryBuffer *InputBuffer;
689
690 /// The Swift version to use for filtering.
691 llvm::VersionTuple SwiftVersion;
692
693 /// The name of the module that we read from the control block.
694 std::string ModuleName;
695
696 // The size and modification time of the source file from
697 // which this API notes file was created, if known.
698 std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime;
699
701 llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;
702
703 /// The identifier table.
704 std::unique_ptr<SerializedIdentifierTable> IdentifierTable;
705
707 llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;
708
709 /// The Objective-C / C++ context ID table.
710 std::unique_ptr<SerializedContextIDTable> ContextIDTable;
711
713 llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;
714
715 /// The Objective-C context info table.
716 std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;
717
719 llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
720
721 /// The Objective-C property table.
722 std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;
723
725 llvm::OnDiskIterableChainedHashTable<FieldTableInfo>;
726
727 /// The C record field table.
728 std::unique_ptr<SerializedFieldTable> FieldTable;
729
731 llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
732
733 /// The Objective-C method table.
734 std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
735
737 llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
738
739 /// The C++ method table.
740 std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
741
743 llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
744
745 /// The Objective-C selector table.
746 std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;
747
749 llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;
750
751 /// The global variable table.
752 std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;
753
755 llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;
756
757 /// The global function table.
758 std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;
759
761 llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
762
763 /// The enumerator table.
764 std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;
765
766 using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;
767
768 /// The tag table.
769 std::unique_ptr<SerializedTagTable> TagTable;
770
772 llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;
773
774 /// The typedef table.
775 std::unique_ptr<SerializedTypedefTable> TypedefTable;
776
777 /// Retrieve the identifier ID for the given string, or an empty
778 /// optional if the string is unknown.
779 std::optional<IdentifierID> getIdentifier(llvm::StringRef Str);
780
781 /// Retrieve the selector ID for the given selector, or an empty
782 /// optional if the string is unknown.
783 std::optional<SelectorID> getSelector(ObjCSelectorRef Selector);
784
785 bool readControlBlock(llvm::BitstreamCursor &Cursor,
787 bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,
789 bool readContextBlock(llvm::BitstreamCursor &Cursor,
791 bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
793 bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
795 bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor,
797 bool readFieldBlock(llvm::BitstreamCursor &Cursor,
799 bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor,
801 bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,
803 bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
805 bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor,
807 bool readTagBlock(llvm::BitstreamCursor &Cursor,
809 bool readTypedefBlock(llvm::BitstreamCursor &Cursor,
811};
812
813std::optional<IdentifierID>
815 if (!IdentifierTable)
816 return std::nullopt;
817
818 if (Str.empty())
819 return IdentifierID(0);
820
821 auto Known = IdentifierTable->find(Str);
822 if (Known == IdentifierTable->end())
823 return std::nullopt;
824
825 return *Known;
826}
827
828std::optional<SelectorID>
831 return std::nullopt;
832
833 // Translate the identifiers.
835 Key.NumArgs = Selector.NumArgs;
836 for (auto Ident : Selector.Identifiers) {
837 if (auto IdentID = getIdentifier(Ident)) {
838 Key.Identifiers.push_back(*IdentID);
839 } else {
840 return std::nullopt;
841 }
842 }
843
844 auto Known = ObjCSelectorTable->find(Key);
845 if (Known == ObjCSelectorTable->end())
846 return std::nullopt;
847
848 return *Known;
849}
850
852 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
853 if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID))
854 return true;
855
856 bool SawMetadata = false;
857
858 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
859 if (!MaybeNext) {
860 // FIXME this drops the error on the floor.
861 consumeError(MaybeNext.takeError());
862 return false;
863 }
864 llvm::BitstreamEntry Next = MaybeNext.get();
865
866 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
867 if (Next.Kind == llvm::BitstreamEntry::Error)
868 return true;
869
870 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
871 // Unknown metadata sub-block, possibly for use by a future version of the
872 // API notes format.
873 if (Cursor.SkipBlock())
874 return true;
875
876 MaybeNext = Cursor.advance();
877 if (!MaybeNext) {
878 // FIXME this drops the error on the floor.
879 consumeError(MaybeNext.takeError());
880 return false;
881 }
882 Next = MaybeNext.get();
883 continue;
884 }
885
886 Scratch.clear();
887 llvm::StringRef BlobData;
888 llvm::Expected<unsigned> MaybeKind =
889 Cursor.readRecord(Next.ID, Scratch, &BlobData);
890 if (!MaybeKind) {
891 // FIXME this drops the error on the floor.
892 consumeError(MaybeKind.takeError());
893 return false;
894 }
895 unsigned Kind = MaybeKind.get();
896
897 switch (Kind) {
899 // Already saw metadata.
900 if (SawMetadata)
901 return true;
902
903 if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)
904 return true;
905
906 SawMetadata = true;
907 break;
908
910 ModuleName = BlobData.str();
911 break;
912
914 break;
915
917 SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
918 break;
919
920 default:
921 // Unknown metadata record, possibly for use by a future version of the
922 // module format.
923 break;
924 }
925
926 MaybeNext = Cursor.advance();
927 if (!MaybeNext) {
928 // FIXME this drops the error on the floor.
929 consumeError(MaybeNext.takeError());
930 return false;
931 }
932 Next = MaybeNext.get();
933 }
934
935 return !SawMetadata;
936}
937
939 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
940 if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID))
941 return true;
942
943 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
944 if (!MaybeNext) {
945 // FIXME this drops the error on the floor.
946 consumeError(MaybeNext.takeError());
947 return false;
948 }
949 llvm::BitstreamEntry Next = MaybeNext.get();
950
951 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
952 if (Next.Kind == llvm::BitstreamEntry::Error)
953 return true;
954
955 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
956 // Unknown sub-block, possibly for use by a future version of the
957 // API notes format.
958 if (Cursor.SkipBlock())
959 return true;
960
961 MaybeNext = Cursor.advance();
962 if (!MaybeNext) {
963 // FIXME this drops the error on the floor.
964 consumeError(MaybeNext.takeError());
965 return false;
966 }
967 Next = MaybeNext.get();
968 continue;
969 }
970
971 Scratch.clear();
972 llvm::StringRef BlobData;
973 llvm::Expected<unsigned> MaybeKind =
974 Cursor.readRecord(Next.ID, Scratch, &BlobData);
975 if (!MaybeKind) {
976 // FIXME this drops the error on the floor.
977 consumeError(MaybeKind.takeError());
978 return false;
979 }
980 unsigned Kind = MaybeKind.get();
981 switch (Kind) {
983 // Already saw identifier table.
984 if (IdentifierTable)
985 return true;
986
987 uint32_t tableOffset;
988 identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);
989 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
990
991 IdentifierTable.reset(SerializedIdentifierTable::Create(
992 base + tableOffset, base + sizeof(uint32_t), base));
993 break;
994 }
995
996 default:
997 // Unknown record, possibly for use by a future version of the
998 // module format.
999 break;
1000 }
1001
1002 MaybeNext = Cursor.advance();
1003 if (!MaybeNext) {
1004 // FIXME this drops the error on the floor.
1005 consumeError(MaybeNext.takeError());
1006 return false;
1007 }
1008 Next = MaybeNext.get();
1009 }
1010
1011 return false;
1012}
1013
1015 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1016 if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
1017 return true;
1018
1019 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1020 if (!MaybeNext) {
1021 // FIXME this drops the error on the floor.
1022 consumeError(MaybeNext.takeError());
1023 return false;
1024 }
1025 llvm::BitstreamEntry Next = MaybeNext.get();
1026
1027 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1028 if (Next.Kind == llvm::BitstreamEntry::Error)
1029 return true;
1030
1031 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1032 // Unknown sub-block, possibly for use by a future version of the
1033 // API notes format.
1034 if (Cursor.SkipBlock())
1035 return true;
1036
1037 MaybeNext = Cursor.advance();
1038 if (!MaybeNext) {
1039 // FIXME this drops the error on the floor.
1040 consumeError(MaybeNext.takeError());
1041 return false;
1042 }
1043 Next = MaybeNext.get();
1044 continue;
1045 }
1046
1047 Scratch.clear();
1048 llvm::StringRef BlobData;
1049 llvm::Expected<unsigned> MaybeKind =
1050 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1051 if (!MaybeKind) {
1052 // FIXME this drops the error on the floor.
1053 consumeError(MaybeKind.takeError());
1054 return false;
1055 }
1056 unsigned Kind = MaybeKind.get();
1057 switch (Kind) {
1059 // Already saw Objective-C / C++ context ID table.
1060 if (ContextIDTable)
1061 return true;
1062
1063 uint32_t tableOffset;
1064 context_block::ContextIDLayout::readRecord(Scratch, tableOffset);
1065 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1066
1067 ContextIDTable.reset(SerializedContextIDTable::Create(
1068 base + tableOffset, base + sizeof(uint32_t), base));
1069 break;
1070 }
1071
1073 // Already saw Objective-C / C++ context info table.
1074 if (ContextInfoTable)
1075 return true;
1076
1077 uint32_t tableOffset;
1078 context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);
1079 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1080
1081 ContextInfoTable.reset(SerializedContextInfoTable::Create(
1082 base + tableOffset, base + sizeof(uint32_t), base));
1083 break;
1084 }
1085
1086 default:
1087 // Unknown record, possibly for use by a future version of the
1088 // module format.
1089 break;
1090 }
1091
1092 MaybeNext = Cursor.advance();
1093 if (!MaybeNext) {
1094 // FIXME this drops the error on the floor.
1095 consumeError(MaybeNext.takeError());
1096 return false;
1097 }
1098 Next = MaybeNext.get();
1099 }
1100
1101 return false;
1102}
1103
1105 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1106 if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID))
1107 return true;
1108
1109 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1110 if (!MaybeNext) {
1111 // FIXME this drops the error on the floor.
1112 consumeError(MaybeNext.takeError());
1113 return false;
1114 }
1115 llvm::BitstreamEntry Next = MaybeNext.get();
1116
1117 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1118 if (Next.Kind == llvm::BitstreamEntry::Error)
1119 return true;
1120
1121 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1122 // Unknown sub-block, possibly for use by a future version of the
1123 // API notes format.
1124 if (Cursor.SkipBlock())
1125 return true;
1126
1127 MaybeNext = Cursor.advance();
1128 if (!MaybeNext) {
1129 // FIXME this drops the error on the floor.
1130 consumeError(MaybeNext.takeError());
1131 return false;
1132 }
1133 Next = MaybeNext.get();
1134 continue;
1135 }
1136
1137 Scratch.clear();
1138 llvm::StringRef BlobData;
1139 llvm::Expected<unsigned> MaybeKind =
1140 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1141 if (!MaybeKind) {
1142 // FIXME this drops the error on the floor.
1143 consumeError(MaybeKind.takeError());
1144 return false;
1145 }
1146 unsigned Kind = MaybeKind.get();
1147 switch (Kind) {
1149 // Already saw Objective-C property table.
1151 return true;
1152
1153 uint32_t tableOffset;
1154 objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,
1155 tableOffset);
1156 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1157
1158 ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(
1159 base + tableOffset, base + sizeof(uint32_t), base));
1160 break;
1161 }
1162
1163 default:
1164 // Unknown record, possibly for use by a future version of the
1165 // module format.
1166 break;
1167 }
1168
1169 MaybeNext = Cursor.advance();
1170 if (!MaybeNext) {
1171 // FIXME this drops the error on the floor.
1172 consumeError(MaybeNext.takeError());
1173 return false;
1174 }
1175 Next = MaybeNext.get();
1176 }
1177
1178 return false;
1179}
1180
1182 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1183 if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID))
1184 return true;
1185
1186 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1187 if (!MaybeNext) {
1188 // FIXME this drops the error on the floor.
1189 consumeError(MaybeNext.takeError());
1190 return false;
1191 }
1192 llvm::BitstreamEntry Next = MaybeNext.get();
1193 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1194 if (Next.Kind == llvm::BitstreamEntry::Error)
1195 return true;
1196
1197 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1198 // Unknown sub-block, possibly for use by a future version of the
1199 // API notes format.
1200 if (Cursor.SkipBlock())
1201 return true;
1202
1203 MaybeNext = Cursor.advance();
1204 if (!MaybeNext) {
1205 // FIXME this drops the error on the floor.
1206 consumeError(MaybeNext.takeError());
1207 return false;
1208 }
1209 Next = MaybeNext.get();
1210 continue;
1211 }
1212
1213 Scratch.clear();
1214 llvm::StringRef BlobData;
1215 llvm::Expected<unsigned> MaybeKind =
1216 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1217 if (!MaybeKind) {
1218 // FIXME this drops the error on the floor.
1219 consumeError(MaybeKind.takeError());
1220 return false;
1221 }
1222 unsigned Kind = MaybeKind.get();
1223 switch (Kind) {
1225 // Already saw Objective-C method table.
1226 if (ObjCMethodTable)
1227 return true;
1228
1229 uint32_t tableOffset;
1230 objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);
1231 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1232
1233 ObjCMethodTable.reset(SerializedObjCMethodTable::Create(
1234 base + tableOffset, base + sizeof(uint32_t), base));
1235 break;
1236 }
1237
1238 default:
1239 // Unknown record, possibly for use by a future version of the
1240 // module format.
1241 break;
1242 }
1243
1244 MaybeNext = Cursor.advance();
1245 if (!MaybeNext) {
1246 // FIXME this drops the error on the floor.
1247 consumeError(MaybeNext.takeError());
1248 return false;
1249 }
1250 Next = MaybeNext.get();
1251 }
1252
1253 return false;
1254}
1255
1257 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1258 if (Cursor.EnterSubBlock(CXX_METHOD_BLOCK_ID))
1259 return true;
1260
1261 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1262 if (!MaybeNext) {
1263 // FIXME this drops the error on the floor.
1264 consumeError(MaybeNext.takeError());
1265 return false;
1266 }
1267 llvm::BitstreamEntry Next = MaybeNext.get();
1268 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1269 if (Next.Kind == llvm::BitstreamEntry::Error)
1270 return true;
1271
1272 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1273 // Unknown sub-block, possibly for use by a future version of the
1274 // API notes format.
1275 if (Cursor.SkipBlock())
1276 return true;
1277
1278 MaybeNext = Cursor.advance();
1279 if (!MaybeNext) {
1280 // FIXME this drops the error on the floor.
1281 consumeError(MaybeNext.takeError());
1282 return false;
1283 }
1284 Next = MaybeNext.get();
1285 continue;
1286 }
1287
1288 Scratch.clear();
1289 llvm::StringRef BlobData;
1290 llvm::Expected<unsigned> MaybeKind =
1291 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1292 if (!MaybeKind) {
1293 // FIXME this drops the error on the floor.
1294 consumeError(MaybeKind.takeError());
1295 return false;
1296 }
1297 unsigned Kind = MaybeKind.get();
1298 switch (Kind) {
1300 // Already saw C++ method table.
1301 if (CXXMethodTable)
1302 return true;
1303
1304 uint32_t tableOffset;
1305 cxx_method_block::CXXMethodDataLayout::readRecord(Scratch, tableOffset);
1306 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1307
1308 CXXMethodTable.reset(SerializedCXXMethodTable::Create(
1309 base + tableOffset, base + sizeof(uint32_t), base));
1310 break;
1311 }
1312
1313 default:
1314 // Unknown record, possibly for use by a future version of the
1315 // module format.
1316 break;
1317 }
1318
1319 MaybeNext = Cursor.advance();
1320 if (!MaybeNext) {
1321 // FIXME this drops the error on the floor.
1322 consumeError(MaybeNext.takeError());
1323 return false;
1324 }
1325 Next = MaybeNext.get();
1326 }
1327
1328 return false;
1329}
1330
1332 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1333 if (Cursor.EnterSubBlock(FIELD_BLOCK_ID))
1334 return true;
1335
1336 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1337 if (!MaybeNext) {
1338 // FIXME this drops the error on the floor.
1339 consumeError(MaybeNext.takeError());
1340 return false;
1341 }
1342 llvm::BitstreamEntry Next = MaybeNext.get();
1343 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1344 if (Next.Kind == llvm::BitstreamEntry::Error)
1345 return true;
1346
1347 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1348 // Unknown sub-block, possibly for use by a future version of the
1349 // API notes format.
1350 if (Cursor.SkipBlock())
1351 return true;
1352
1353 MaybeNext = Cursor.advance();
1354 if (!MaybeNext) {
1355 // FIXME this drops the error on the floor.
1356 consumeError(MaybeNext.takeError());
1357 return false;
1358 }
1359 Next = MaybeNext.get();
1360 continue;
1361 }
1362
1363 Scratch.clear();
1364 llvm::StringRef BlobData;
1365 llvm::Expected<unsigned> MaybeKind =
1366 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1367 if (!MaybeKind) {
1368 // FIXME this drops the error on the floor.
1369 consumeError(MaybeKind.takeError());
1370 return false;
1371 }
1372 unsigned Kind = MaybeKind.get();
1373 switch (Kind) {
1375 // Already saw field table.
1376 if (FieldTable)
1377 return true;
1378
1379 uint32_t tableOffset;
1380 field_block::FieldDataLayout::readRecord(Scratch, tableOffset);
1381 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1382
1383 FieldTable.reset(SerializedFieldTable::Create(
1384 base + tableOffset, base + sizeof(uint32_t), base));
1385 break;
1386 }
1387
1388 default:
1389 // Unknown record, possibly for use by a future version of the
1390 // module format.
1391 break;
1392 }
1393
1394 MaybeNext = Cursor.advance();
1395 if (!MaybeNext) {
1396 // FIXME this drops the error on the floor.
1397 consumeError(MaybeNext.takeError());
1398 return false;
1399 }
1400 Next = MaybeNext.get();
1401 }
1402
1403 return false;
1404}
1405
1407 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1408 if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID))
1409 return true;
1410
1411 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1412 if (!MaybeNext) {
1413 // FIXME this drops the error on the floor.
1414 consumeError(MaybeNext.takeError());
1415 return false;
1416 }
1417 llvm::BitstreamEntry Next = MaybeNext.get();
1418 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1419 if (Next.Kind == llvm::BitstreamEntry::Error)
1420 return true;
1421
1422 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1423 // Unknown sub-block, possibly for use by a future version of the
1424 // API notes format.
1425 if (Cursor.SkipBlock())
1426 return true;
1427
1428 MaybeNext = Cursor.advance();
1429 if (!MaybeNext) {
1430 // FIXME this drops the error on the floor.
1431 consumeError(MaybeNext.takeError());
1432 return false;
1433 }
1434 Next = MaybeNext.get();
1435 continue;
1436 }
1437
1438 Scratch.clear();
1439 llvm::StringRef BlobData;
1440 llvm::Expected<unsigned> MaybeKind =
1441 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1442 if (!MaybeKind) {
1443 // FIXME this drops the error on the floor.
1444 consumeError(MaybeKind.takeError());
1445 return false;
1446 }
1447 unsigned Kind = MaybeKind.get();
1448 switch (Kind) {
1450 // Already saw Objective-C selector table.
1452 return true;
1453
1454 uint32_t tableOffset;
1455 objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,
1456 tableOffset);
1457 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1458
1459 ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(
1460 base + tableOffset, base + sizeof(uint32_t), base));
1461 break;
1462 }
1463
1464 default:
1465 // Unknown record, possibly for use by a future version of the
1466 // module format.
1467 break;
1468 }
1469
1470 MaybeNext = Cursor.advance();
1471 if (!MaybeNext) {
1472 // FIXME this drops the error on the floor.
1473 consumeError(MaybeNext.takeError());
1474 return false;
1475 }
1476 Next = MaybeNext.get();
1477 }
1478
1479 return false;
1480}
1481
1483 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1484 if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID))
1485 return true;
1486
1487 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1488 if (!MaybeNext) {
1489 // FIXME this drops the error on the floor.
1490 consumeError(MaybeNext.takeError());
1491 return false;
1492 }
1493 llvm::BitstreamEntry Next = MaybeNext.get();
1494 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1495 if (Next.Kind == llvm::BitstreamEntry::Error)
1496 return true;
1497
1498 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1499 // Unknown sub-block, possibly for use by a future version of the
1500 // API notes format.
1501 if (Cursor.SkipBlock())
1502 return true;
1503
1504 MaybeNext = Cursor.advance();
1505 if (!MaybeNext) {
1506 // FIXME this drops the error on the floor.
1507 consumeError(MaybeNext.takeError());
1508 return false;
1509 }
1510 Next = MaybeNext.get();
1511 continue;
1512 }
1513
1514 Scratch.clear();
1515 llvm::StringRef BlobData;
1516 llvm::Expected<unsigned> MaybeKind =
1517 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1518 if (!MaybeKind) {
1519 // FIXME this drops the error on the floor.
1520 consumeError(MaybeKind.takeError());
1521 return false;
1522 }
1523 unsigned Kind = MaybeKind.get();
1524 switch (Kind) {
1526 // Already saw global variable table.
1528 return true;
1529
1530 uint32_t tableOffset;
1531 global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,
1532 tableOffset);
1533 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1534
1535 GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(
1536 base + tableOffset, base + sizeof(uint32_t), base));
1537 break;
1538 }
1539
1540 default:
1541 // Unknown record, possibly for use by a future version of the
1542 // module format.
1543 break;
1544 }
1545
1546 MaybeNext = Cursor.advance();
1547 if (!MaybeNext) {
1548 // FIXME this drops the error on the floor.
1549 consumeError(MaybeNext.takeError());
1550 return false;
1551 }
1552 Next = MaybeNext.get();
1553 }
1554
1555 return false;
1556}
1557
1559 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1560 if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID))
1561 return true;
1562
1563 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1564 if (!MaybeNext) {
1565 // FIXME this drops the error on the floor.
1566 consumeError(MaybeNext.takeError());
1567 return false;
1568 }
1569 llvm::BitstreamEntry Next = MaybeNext.get();
1570 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1571 if (Next.Kind == llvm::BitstreamEntry::Error)
1572 return true;
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 true;
1579
1580 MaybeNext = Cursor.advance();
1581 if (!MaybeNext) {
1582 // FIXME this drops the error on the floor.
1583 consumeError(MaybeNext.takeError());
1584 return false;
1585 }
1586 Next = MaybeNext.get();
1587 continue;
1588 }
1589
1590 Scratch.clear();
1591 llvm::StringRef BlobData;
1592 llvm::Expected<unsigned> MaybeKind =
1593 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1594 if (!MaybeKind) {
1595 // FIXME this drops the error on the floor.
1596 consumeError(MaybeKind.takeError());
1597 return false;
1598 }
1599 unsigned Kind = MaybeKind.get();
1600 switch (Kind) {
1602 // Already saw global function table.
1604 return true;
1605
1606 uint32_t tableOffset;
1607 global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,
1608 tableOffset);
1609 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1610
1611 GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(
1612 base + tableOffset, base + sizeof(uint32_t), base));
1613 break;
1614 }
1615
1616 default:
1617 // Unknown record, possibly for use by a future version of the
1618 // module format.
1619 break;
1620 }
1621
1622 MaybeNext = Cursor.advance();
1623 if (!MaybeNext) {
1624 // FIXME this drops the error on the floor.
1625 consumeError(MaybeNext.takeError());
1626 return false;
1627 }
1628 Next = MaybeNext.get();
1629 }
1630
1631 return false;
1632}
1633
1635 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1636 if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID))
1637 return true;
1638
1639 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1640 if (!MaybeNext) {
1641 // FIXME this drops the error on the floor.
1642 consumeError(MaybeNext.takeError());
1643 return false;
1644 }
1645 llvm::BitstreamEntry Next = MaybeNext.get();
1646 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1647 if (Next.Kind == llvm::BitstreamEntry::Error)
1648 return true;
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 true;
1655
1656 MaybeNext = Cursor.advance();
1657 if (!MaybeNext) {
1658 // FIXME this drops the error on the floor.
1659 consumeError(MaybeNext.takeError());
1660 return false;
1661 }
1662 Next = MaybeNext.get();
1663 continue;
1664 }
1665
1666 Scratch.clear();
1667 llvm::StringRef BlobData;
1668 llvm::Expected<unsigned> MaybeKind =
1669 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1670 if (!MaybeKind) {
1671 // FIXME this drops the error on the floor.
1672 consumeError(MaybeKind.takeError());
1673 return false;
1674 }
1675 unsigned Kind = MaybeKind.get();
1676 switch (Kind) {
1678 // Already saw enumerator table.
1680 return true;
1681
1682 uint32_t tableOffset;
1683 enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,
1684 tableOffset);
1685 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1686
1687 EnumConstantTable.reset(SerializedEnumConstantTable::Create(
1688 base + tableOffset, base + sizeof(uint32_t), base));
1689 break;
1690 }
1691
1692 default:
1693 // Unknown record, possibly for use by a future version of the
1694 // module format.
1695 break;
1696 }
1697
1698 MaybeNext = Cursor.advance();
1699 if (!MaybeNext) {
1700 // FIXME this drops the error on the floor.
1701 consumeError(MaybeNext.takeError());
1702 return false;
1703 }
1704 Next = MaybeNext.get();
1705 }
1706
1707 return false;
1708}
1709
1711 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1712 if (Cursor.EnterSubBlock(TAG_BLOCK_ID))
1713 return true;
1714
1715 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1716 if (!MaybeNext) {
1717 // FIXME this drops the error on the floor.
1718 consumeError(MaybeNext.takeError());
1719 return false;
1720 }
1721 llvm::BitstreamEntry Next = MaybeNext.get();
1722 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1723 if (Next.Kind == llvm::BitstreamEntry::Error)
1724 return true;
1725
1726 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1727 // Unknown sub-block, possibly for use by a future version of the
1728 // API notes format.
1729 if (Cursor.SkipBlock())
1730 return true;
1731
1732 MaybeNext = Cursor.advance();
1733 if (!MaybeNext) {
1734 // FIXME this drops the error on the floor.
1735 consumeError(MaybeNext.takeError());
1736 return false;
1737 }
1738 Next = MaybeNext.get();
1739 continue;
1740 }
1741
1742 Scratch.clear();
1743 llvm::StringRef BlobData;
1744 llvm::Expected<unsigned> MaybeKind =
1745 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1746 if (!MaybeKind) {
1747 // FIXME this drops the error on the floor.
1748 consumeError(MaybeKind.takeError());
1749 return false;
1750 }
1751 unsigned Kind = MaybeKind.get();
1752 switch (Kind) {
1753 case tag_block::TAG_DATA: {
1754 // Already saw tag table.
1755 if (TagTable)
1756 return true;
1757
1758 uint32_t tableOffset;
1759 tag_block::TagDataLayout::readRecord(Scratch, tableOffset);
1760 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1761
1762 TagTable.reset(SerializedTagTable::Create(base + tableOffset,
1763 base + sizeof(uint32_t), base));
1764 break;
1765 }
1766
1767 default:
1768 // Unknown record, possibly for use by a future version of the
1769 // module format.
1770 break;
1771 }
1772
1773 MaybeNext = Cursor.advance();
1774 if (!MaybeNext) {
1775 // FIXME this drops the error on the floor.
1776 consumeError(MaybeNext.takeError());
1777 return false;
1778 }
1779 Next = MaybeNext.get();
1780 }
1781
1782 return false;
1783}
1784
1786 llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1787 if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID))
1788 return true;
1789
1790 llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1791 if (!MaybeNext) {
1792 // FIXME this drops the error on the floor.
1793 consumeError(MaybeNext.takeError());
1794 return false;
1795 }
1796 llvm::BitstreamEntry Next = MaybeNext.get();
1797 while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1798 if (Next.Kind == llvm::BitstreamEntry::Error)
1799 return true;
1800
1801 if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1802 // Unknown sub-block, possibly for use by a future version of the
1803 // API notes format.
1804 if (Cursor.SkipBlock())
1805 return true;
1806
1807 MaybeNext = Cursor.advance();
1808 if (!MaybeNext) {
1809 // FIXME this drops the error on the floor.
1810 consumeError(MaybeNext.takeError());
1811 return false;
1812 }
1813 Next = MaybeNext.get();
1814 continue;
1815 }
1816
1817 Scratch.clear();
1818 llvm::StringRef BlobData;
1819 llvm::Expected<unsigned> MaybeKind =
1820 Cursor.readRecord(Next.ID, Scratch, &BlobData);
1821 if (!MaybeKind) {
1822 // FIXME this drops the error on the floor.
1823 consumeError(MaybeKind.takeError());
1824 return false;
1825 }
1826 unsigned Kind = MaybeKind.get();
1827 switch (Kind) {
1829 // Already saw typedef table.
1830 if (TypedefTable)
1831 return true;
1832
1833 uint32_t tableOffset;
1834 typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);
1835 auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1836
1837 TypedefTable.reset(SerializedTypedefTable::Create(
1838 base + tableOffset, base + sizeof(uint32_t), base));
1839 break;
1840 }
1841
1842 default:
1843 // Unknown record, possibly for use by a future version of the
1844 // module format.
1845 break;
1846 }
1847
1848 MaybeNext = Cursor.advance();
1849 if (!MaybeNext) {
1850 // FIXME this drops the error on the floor.
1851 consumeError(MaybeNext.takeError());
1852 return false;
1853 }
1854 Next = MaybeNext.get();
1855 }
1856
1857 return false;
1858}
1859
1860APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1861 llvm::VersionTuple SwiftVersion, bool &Failed)
1862 : Implementation(new class Implementation) {
1863 Failed = false;
1864
1865 // Initialize the input buffer.
1868 llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);
1869
1870 // Validate signature.
1871 for (auto byte : API_NOTES_SIGNATURE) {
1872 if (Cursor.AtEndOfStream()) {
1873 Failed = true;
1874 return;
1875 }
1877 Cursor.Read(8)) {
1878 if (maybeRead.get() != byte) {
1879 Failed = true;
1880 return;
1881 }
1882 } else {
1883 // FIXME this drops the error on the floor.
1884 consumeError(maybeRead.takeError());
1885 Failed = true;
1886 return;
1887 }
1888 }
1889
1890 // Look at all of the blocks.
1891 bool HasValidControlBlock = false;
1892 llvm::SmallVector<uint64_t, 64> Scratch;
1893 while (!Cursor.AtEndOfStream()) {
1894 llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();
1895 if (!MaybeTopLevelEntry) {
1896 // FIXME this drops the error on the floor.
1897 consumeError(MaybeTopLevelEntry.takeError());
1898 Failed = true;
1899 return;
1900 }
1901 llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();
1902
1903 if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
1904 break;
1905
1906 switch (TopLevelEntry.ID) {
1907 case llvm::bitc::BLOCKINFO_BLOCK_ID:
1908 if (!Cursor.ReadBlockInfoBlock()) {
1909 Failed = true;
1910 break;
1911 }
1912 break;
1913
1914 case CONTROL_BLOCK_ID:
1915 // Only allow a single control block.
1916 if (HasValidControlBlock ||
1917 Implementation->readControlBlock(Cursor, Scratch)) {
1918 Failed = true;
1919 return;
1920 }
1921
1922 HasValidControlBlock = true;
1923 break;
1924
1926 if (!HasValidControlBlock ||
1927 Implementation->readIdentifierBlock(Cursor, Scratch)) {
1928 Failed = true;
1929 return;
1930 }
1931 break;
1932
1934 if (!HasValidControlBlock ||
1935 Implementation->readContextBlock(Cursor, Scratch)) {
1936 Failed = true;
1937 return;
1938 }
1939
1940 break;
1941
1943 if (!HasValidControlBlock ||
1944 Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
1945 Failed = true;
1946 return;
1947 }
1948 break;
1949
1951 if (!HasValidControlBlock ||
1952 Implementation->readObjCMethodBlock(Cursor, Scratch)) {
1953 Failed = true;
1954 return;
1955 }
1956 break;
1957
1959 if (!HasValidControlBlock ||
1960 Implementation->readCXXMethodBlock(Cursor, Scratch)) {
1961 Failed = true;
1962 return;
1963 }
1964 break;
1965
1966 case FIELD_BLOCK_ID:
1967 if (!HasValidControlBlock ||
1968 Implementation->readFieldBlock(Cursor, Scratch)) {
1969 Failed = true;
1970 return;
1971 }
1972 break;
1973
1975 if (!HasValidControlBlock ||
1976 Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
1977 Failed = true;
1978 return;
1979 }
1980 break;
1981
1983 if (!HasValidControlBlock ||
1984 Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
1985 Failed = true;
1986 return;
1987 }
1988 break;
1989
1991 if (!HasValidControlBlock ||
1992 Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
1993 Failed = true;
1994 return;
1995 }
1996 break;
1997
1999 if (!HasValidControlBlock ||
2000 Implementation->readEnumConstantBlock(Cursor, Scratch)) {
2001 Failed = true;
2002 return;
2003 }
2004 break;
2005
2006 case TAG_BLOCK_ID:
2007 if (!HasValidControlBlock ||
2008 Implementation->readTagBlock(Cursor, Scratch)) {
2009 Failed = true;
2010 return;
2011 }
2012 break;
2013
2014 case TYPEDEF_BLOCK_ID:
2015 if (!HasValidControlBlock ||
2016 Implementation->readTypedefBlock(Cursor, Scratch)) {
2017 Failed = true;
2018 return;
2019 }
2020 break;
2021
2022 default:
2023 // Unknown top-level block, possibly for use by a future version of the
2024 // module format.
2025 if (Cursor.SkipBlock()) {
2026 Failed = true;
2027 return;
2028 }
2029 break;
2030 }
2031 }
2032
2033 if (!Cursor.AtEndOfStream()) {
2034 Failed = true;
2035 return;
2036 }
2037}
2038
2040
2041std::unique_ptr<APINotesReader>
2042APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
2043 llvm::VersionTuple SwiftVersion) {
2044 bool Failed = false;
2045 std::unique_ptr<APINotesReader> Reader(
2046 new APINotesReader(InputBuffer.release(), SwiftVersion, Failed));
2047 if (Failed)
2048 return nullptr;
2049
2050 return Reader;
2051}
2052
2053template <typename T>
2055 llvm::VersionTuple Version,
2056 llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)
2057 : Results(std::move(R)) {
2058
2059 assert(!Results.empty());
2060 assert(llvm::is_sorted(
2061 Results,
2062 [](const std::pair<llvm::VersionTuple, T> &left,
2063 const std::pair<llvm::VersionTuple, T> &right) -> bool {
2064 // The comparison function should be reflective, and with expensive
2065 // checks we can get callbacks basically checking that lambda(a,a) is
2066 // false. We could still check that we do not find equal elements when
2067 // left!=right.
2068 assert((&left == &right || left.first != right.first) &&
2069 "two entries for the same version");
2070 return left.first < right.first;
2071 }));
2072
2073 Selected = std::nullopt;
2074 for (unsigned i = 0, n = Results.size(); i != n; ++i) {
2075 if (!Version.empty() && Results[i].first >= Version) {
2076 // If the current version is "4", then entries for 4 are better than
2077 // entries for 5, but both are valid. Because entries are sorted, we get
2078 // that behavior by picking the first match.
2079 Selected = i;
2080 break;
2081 }
2082 }
2083
2084 // If we didn't find a match but we have an unversioned result, use the
2085 // unversioned result. This will always be the first entry because we encode
2086 // it as version 0.
2087 if (!Selected && Results[0].first.empty())
2088 Selected = 0;
2089}
2090
2091auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
2092 -> std::optional<ContextID> {
2094 return std::nullopt;
2095
2096 std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
2097 if (!ClassID)
2098 return std::nullopt;
2099
2100 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
2101 // context.
2102 auto KnownID = Implementation->ContextIDTable->find(
2103 ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
2104 if (KnownID == Implementation->ContextIDTable->end())
2105 return std::nullopt;
2106
2107 return ContextID(*KnownID);
2108}
2109
2110auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
2113 return std::nullopt;
2114
2115 std::optional<ContextID> CtxID = lookupObjCClassID(Name);
2116 if (!CtxID)
2117 return std::nullopt;
2118
2119 auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
2120 if (KnownInfo == Implementation->ContextInfoTable->end())
2121 return std::nullopt;
2122
2123 return {Implementation->SwiftVersion, *KnownInfo};
2124}
2125
2127 -> std::optional<ContextID> {
2129 return std::nullopt;
2130
2131 std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
2132 if (!classID)
2133 return std::nullopt;
2134
2135 // ObjC classes can't be declared in C++ namespaces, so use -1 as the global
2136 // context.
2137 auto KnownID = Implementation->ContextIDTable->find(
2138 ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
2139 if (KnownID == Implementation->ContextIDTable->end())
2140 return std::nullopt;
2141
2142 return ContextID(*KnownID);
2143}
2144
2148 return std::nullopt;
2149
2150 std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
2151 if (!CtxID)
2152 return std::nullopt;
2153
2154 auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
2155 if (KnownInfo == Implementation->ContextInfoTable->end())
2156 return std::nullopt;
2157
2158 return {Implementation->SwiftVersion, *KnownInfo};
2159}
2160
2161auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,
2162 bool IsInstance)
2165 return std::nullopt;
2166
2167 std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name);
2168 if (!PropertyID)
2169 return std::nullopt;
2170
2171 auto Known = Implementation->ObjCPropertyTable->find(
2172 std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance));
2173 if (Known == Implementation->ObjCPropertyTable->end())
2174 return std::nullopt;
2175
2176 return {Implementation->SwiftVersion, *Known};
2177}
2178
2180 bool IsInstanceMethod)
2183 return std::nullopt;
2184
2185 std::optional<SelectorID> SelID = Implementation->getSelector(Selector);
2186 if (!SelID)
2187 return std::nullopt;
2188
2189 auto Known = Implementation->ObjCMethodTable->find(
2190 ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
2191 IsInstanceMethod});
2192 if (Known == Implementation->ObjCMethodTable->end())
2193 return std::nullopt;
2194
2195 return {Implementation->SwiftVersion, *Known};
2196}
2197
2198auto APINotesReader::lookupField(ContextID CtxID, llvm::StringRef Name)
2201 return std::nullopt;
2202
2203 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2204 if (!NameID)
2205 return std::nullopt;
2206
2207 auto Known = Implementation->FieldTable->find(
2208 SingleDeclTableKey(CtxID.Value, *NameID));
2209 if (Known == Implementation->FieldTable->end())
2210 return std::nullopt;
2211
2212 return {Implementation->SwiftVersion, *Known};
2213}
2214
2215auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
2218 return std::nullopt;
2219
2220 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2221 if (!NameID)
2222 return std::nullopt;
2223
2224 auto Known = Implementation->CXXMethodTable->find(
2225 SingleDeclTableKey(CtxID.Value, *NameID));
2226 if (Known == Implementation->CXXMethodTable->end())
2227 return std::nullopt;
2228
2229 return {Implementation->SwiftVersion, *Known};
2230}
2231
2233 std::optional<Context> Ctx)
2236 return std::nullopt;
2237
2238 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2239 if (!NameID)
2240 return std::nullopt;
2241
2242 SingleDeclTableKey Key(Ctx, *NameID);
2243
2244 auto Known = Implementation->GlobalVariableTable->find(Key);
2245 if (Known == Implementation->GlobalVariableTable->end())
2246 return std::nullopt;
2247
2248 return {Implementation->SwiftVersion, *Known};
2249}
2250
2252 std::optional<Context> Ctx)
2255 return std::nullopt;
2256
2257 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2258 if (!NameID)
2259 return std::nullopt;
2260
2261 SingleDeclTableKey Key(Ctx, *NameID);
2262
2263 auto Known = Implementation->GlobalFunctionTable->find(Key);
2264 if (Known == Implementation->GlobalFunctionTable->end())
2265 return std::nullopt;
2266
2267 return {Implementation->SwiftVersion, *Known};
2268}
2269
2270auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
2273 return std::nullopt;
2274
2275 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2276 if (!NameID)
2277 return std::nullopt;
2278
2279 auto Known = Implementation->EnumConstantTable->find(*NameID);
2280 if (Known == Implementation->EnumConstantTable->end())
2281 return std::nullopt;
2282
2283 return {Implementation->SwiftVersion, *Known};
2284}
2285
2286auto APINotesReader::lookupTagID(llvm::StringRef Name,
2287 std::optional<Context> ParentCtx)
2288 -> std::optional<ContextID> {
2290 return std::nullopt;
2291
2292 std::optional<IdentifierID> TagID = Implementation->getIdentifier(Name);
2293 if (!TagID)
2294 return std::nullopt;
2295
2296 auto KnownID = Implementation->ContextIDTable->find(
2297 ContextTableKey(ParentCtx, ContextKind::Tag, *TagID));
2298 if (KnownID == Implementation->ContextIDTable->end())
2299 return std::nullopt;
2300
2301 return ContextID(*KnownID);
2302}
2303
2304auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
2307 return std::nullopt;
2308
2309 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2310 if (!NameID)
2311 return std::nullopt;
2312
2313 SingleDeclTableKey Key(Ctx, *NameID);
2314
2315 auto Known = Implementation->TagTable->find(Key);
2316 if (Known == Implementation->TagTable->end())
2317 return std::nullopt;
2318
2319 return {Implementation->SwiftVersion, *Known};
2320}
2321
2322auto APINotesReader::lookupTypedef(llvm::StringRef Name,
2323 std::optional<Context> Ctx)
2326 return std::nullopt;
2327
2328 std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2329 if (!NameID)
2330 return std::nullopt;
2331
2332 SingleDeclTableKey Key(Ctx, *NameID);
2333
2334 auto Known = Implementation->TypedefTable->find(Key);
2335 if (Known == Implementation->TypedefTable->end())
2336 return std::nullopt;
2337
2338 return {Implementation->SwiftVersion, *Known};
2339}
2340
2342 llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
2343 -> std::optional<ContextID> {
2345 return std::nullopt;
2346
2347 std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
2348 if (!NamespaceID)
2349 return std::nullopt;
2350
2351 uint32_t RawParentNamespaceID =
2352 ParentNamespaceID ? ParentNamespaceID->Value : -1;
2353 auto KnownID = Implementation->ContextIDTable->find(
2354 {RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
2355 if (KnownID == Implementation->ContextIDTable->end())
2356 return std::nullopt;
2357
2358 return ContextID(*KnownID);
2359}
2360
2361} // namespace api_notes
2362} // namespace clang
FormatToken * Next
The next token in the unwrapped line.
static StringRef getIdentifier(const Token &Tok)
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Smart pointer class that efficiently represents Objective-C method names.
llvm::OnDiskIterableChainedHashTable< FieldTableInfo > SerializedFieldTable
std::unique_ptr< SerializedContextIDTable > ContextIDTable
The Objective-C / C++ context ID table.
bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::string ModuleName
The name of the module that we read from the control block.
std::optional< std::pair< off_t, time_t > > SourceFileSizeAndModTime
std::unique_ptr< SerializedIdentifierTable > IdentifierTable
The identifier table.
llvm::OnDiskIterableChainedHashTable< TagTableInfo > SerializedTagTable
llvm::OnDiskIterableChainedHashTable< GlobalFunctionTableInfo > SerializedGlobalFunctionTable
std::unique_ptr< SerializedGlobalFunctionTable > GlobalFunctionTable
The global function table.
std::unique_ptr< SerializedObjCPropertyTable > ObjCPropertyTable
The Objective-C property table.
bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< EnumConstantTableInfo > SerializedEnumConstantTable
std::unique_ptr< SerializedGlobalVariableTable > GlobalVariableTable
The global variable table.
bool readTagBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::unique_ptr< SerializedTypedefTable > TypedefTable
The typedef table.
bool readFieldBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readTypedefBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::MemoryBuffer * InputBuffer
The input buffer for the API notes data.
std::unique_ptr< SerializedObjCSelectorTable > ObjCSelectorTable
The Objective-C selector table.
llvm::OnDiskIterableChainedHashTable< ObjCMethodTableInfo > SerializedObjCMethodTable
bool readControlBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< CXXMethodTableInfo > SerializedCXXMethodTable
llvm::OnDiskIterableChainedHashTable< ContextInfoTableInfo > SerializedContextInfoTable
std::unique_ptr< SerializedCXXMethodTable > CXXMethodTable
The C++ method table.
llvm::OnDiskIterableChainedHashTable< ObjCSelectorTableInfo > SerializedObjCSelectorTable
llvm::OnDiskIterableChainedHashTable< IdentifierTableInfo > SerializedIdentifierTable
bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::unique_ptr< SerializedEnumConstantTable > EnumConstantTable
The enumerator table.
std::optional< IdentifierID > getIdentifier(llvm::StringRef Str)
Retrieve the identifier ID for the given string, or an empty optional if the string is unknown.
bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::unique_ptr< SerializedTagTable > TagTable
The tag table.
std::unique_ptr< SerializedFieldTable > FieldTable
The C record field table.
std::optional< SelectorID > getSelector(ObjCSelectorRef Selector)
Retrieve the selector ID for the given selector, or an empty optional if the string is unknown.
llvm::OnDiskIterableChainedHashTable< TypedefTableInfo > SerializedTypedefTable
bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
bool readIdentifierBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
llvm::OnDiskIterableChainedHashTable< GlobalVariableTableInfo > SerializedGlobalVariableTable
llvm::VersionTuple SwiftVersion
The Swift version to use for filtering.
llvm::OnDiskIterableChainedHashTable< ContextIDTableInfo > SerializedContextIDTable
bool readContextBlock(llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl< uint64_t > &Scratch)
std::unique_ptr< SerializedObjCMethodTable > ObjCMethodTable
The Objective-C method table.
std::unique_ptr< SerializedContextInfoTable > ContextInfoTable
The Objective-C context info table.
llvm::OnDiskIterableChainedHashTable< ObjCPropertyTableInfo > SerializedObjCPropertyTable
Captures the completed versioned information for a particular part of API notes, including both unver...
VersionedInfo(std::nullopt_t)
Form an empty set of versioned information.
VersionedInfo< ContextInfo > lookupObjCClassInfo(llvm::StringRef Name)
Look for information regarding the given Objective-C class.
VersionedInfo< FieldInfo > lookupField(ContextID CtxID, llvm::StringRef Name)
Look for information regarding the given field of a C struct.
VersionedInfo< CXXMethodInfo > lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
Look for information regarding the given C++ method in the given C++ tag context.
VersionedInfo< TagInfo > lookupTag(llvm::StringRef Name, std::optional< Context > Ctx=std::nullopt)
Look for information regarding the given tag (struct/union/enum/C++ class).
VersionedInfo< GlobalFunctionInfo > lookupGlobalFunction(llvm::StringRef Name, std::optional< Context > Ctx=std::nullopt)
Look for information regarding the given global function.
VersionedInfo< ObjCPropertyInfo > lookupObjCProperty(ContextID CtxID, llvm::StringRef Name, bool IsInstance)
Look for information regarding the given Objective-C property in the given context.
VersionedInfo< ObjCMethodInfo > lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector, bool IsInstanceMethod)
Look for information regarding the given Objective-C method in the given context.
VersionedInfo< GlobalVariableInfo > lookupGlobalVariable(llvm::StringRef Name, std::optional< Context > Ctx=std::nullopt)
Look for information regarding the given global variable.
std::optional< ContextID > lookupNamespaceID(llvm::StringRef Name, std::optional< ContextID > ParentNamespaceID=std::nullopt)
Look for the context ID of the given C++ namespace.
std::optional< ContextID > lookupTagID(llvm::StringRef Name, std::optional< Context > ParentCtx=std::nullopt)
Look for the context ID of the given C++ tag.
VersionedInfo< TypedefInfo > lookupTypedef(llvm::StringRef Name, std::optional< Context > Ctx=std::nullopt)
Look for information regarding the given typedef.
std::optional< ContextID > lookupObjCClassID(llvm::StringRef Name)
Look for the context ID of the given Objective-C class.
static std::unique_ptr< APINotesReader > Create(std::unique_ptr< llvm::MemoryBuffer > InputBuffer, llvm::VersionTuple SwiftVersion)
Create a new API notes reader from the given member buffer, which contains the contents of a binary A...
VersionedInfo< ContextInfo > lookupObjCProtocolInfo(llvm::StringRef Name)
Look for information regarding the given Objective-C protocol.
std::optional< ContextID > lookupObjCProtocolID(llvm::StringRef Name)
Look for the context ID of the given Objective-C protocol.
VersionedInfo< EnumConstantInfo > lookupEnumConstant(llvm::StringRef Name)
Look for information regarding the given enumerator.
Describes API notes data for any entity.
Definition Types.h: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:901
API notes for a function or method.
Definition Types.h:551
Describes a function or method parameter.
Definition Types.h:457
API notes for a variable/property.
Definition Types.h:342
RetainCountConventionKind
Definition Types.h:25
llvm::PointerEmbeddedInt< unsigned, 31 > IdentifierID
llvm::PointerEmbeddedInt< unsigned, 31 > SelectorID
const uint8_t kSwiftConforms
SwiftNewTypeKind
The kind of a swift_wrapper/swift_newtype.
Definition Types.h:43
EnumExtensibilityKind
The payload for an enum_extensibility attribute.
Definition Types.h:36
const uint8_t kSwiftDoesNotConform
const uint16_t VERSION_MAJOR
API notes file major version number.
const unsigned char API_NOTES_SIGNATURE[]
Magic number for API notes files.
const uint16_t VERSION_MINOR
API notes file minor version number.
@ OBJC_CONTEXT_BLOCK_ID
The Objective-C context data block, which contains information about Objective-C classes and protocol...
@ TYPEDEF_BLOCK_ID
The typedef data block, which maps typedef names to information about the typedefs.
@ OBJC_PROPERTY_BLOCK_ID
The Objective-C property data block, which maps Objective-C (class name, property name) pairs to info...
@ ENUM_CONSTANT_BLOCK_ID
The enum constant data block, which maps enumerator names to information about the enumerators.
@ TAG_BLOCK_ID
The tag data block, which maps tag names to information about the tags.
@ OBJC_METHOD_BLOCK_ID
The Objective-C property data block, which maps Objective-C (class name, selector,...
@ FIELD_BLOCK_ID
The fields data block, which maps names fields of C records to information about the field.
@ OBJC_SELECTOR_BLOCK_ID
The Objective-C selector data block, which maps Objective-C selector names (# of pieces,...
@ CXX_METHOD_BLOCK_ID
The C++ method data block, which maps C++ (context id, method name) pairs to information about the me...
@ GLOBAL_FUNCTION_BLOCK_ID
The (global) functions data block, which maps global function names to information about the global f...
@ CONTROL_BLOCK_ID
The control block, which contains all of the information that needs to be validated prior to committi...
@ IDENTIFIER_BLOCK_ID
The identifier data block, which maps identifier strings to IDs.
@ GLOBAL_VARIABLE_BLOCK_ID
The global variables data block, which maps global variable names to information about the global var...
unsigned ComputeHash(Selector Sel)
The JSON file list parser is used to communicate input to InstallAPI.
NullabilityKind
Describes the nullability of a particular type.
Definition Specifiers.h:348
@ Result
The result type of a method or function.
Definition TypeBase.h:905
unsigned int uint32_t
hash_code hash_value(const clang::tooling::dependencies::ModuleID &ID)
A stored Objective-C or C++ context, represented by the ID of its parent context, the kind of this co...
A temporary reference to an Objective-C selector, suitable for referencing selector data on the stack...
Definition Types.h:928
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