Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/APINotes/APINotesReader.cpp
35259 views
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
//===----------------------------------------------------------------------===//
15
#include "clang/APINotes/APINotesReader.h"
16
#include "APINotesFormat.h"
17
#include "llvm/ADT/Hashing.h"
18
#include "llvm/ADT/StringExtras.h"
19
#include "llvm/Bitstream/BitstreamReader.h"
20
#include "llvm/Support/DJB.h"
21
#include "llvm/Support/EndianStream.h"
22
#include "llvm/Support/OnDiskHashTable.h"
23
24
namespace clang {
25
namespace api_notes {
26
using namespace llvm::support;
27
28
namespace {
29
/// Deserialize a version tuple.
30
llvm::VersionTuple ReadVersionTuple(const uint8_t *&Data) {
31
uint8_t NumVersions = (*Data++) & 0x03;
32
33
unsigned Major = endian::readNext<uint32_t, llvm::endianness::little>(Data);
34
if (NumVersions == 0)
35
return llvm::VersionTuple(Major);
36
37
unsigned Minor = endian::readNext<uint32_t, llvm::endianness::little>(Data);
38
if (NumVersions == 1)
39
return llvm::VersionTuple(Major, Minor);
40
41
unsigned Subminor =
42
endian::readNext<uint32_t, llvm::endianness::little>(Data);
43
if (NumVersions == 2)
44
return llvm::VersionTuple(Major, Minor, Subminor);
45
46
unsigned Build = endian::readNext<uint32_t, llvm::endianness::little>(Data);
47
return llvm::VersionTuple(Major, Minor, Subminor, Build);
48
}
49
50
/// An on-disk hash table whose data is versioned based on the Swift version.
51
template <typename Derived, typename KeyType, typename UnversionedDataType>
52
class VersionedTableInfo {
53
public:
54
using internal_key_type = KeyType;
55
using external_key_type = KeyType;
56
using data_type =
57
llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
58
using hash_value_type = size_t;
59
using offset_type = unsigned;
60
61
internal_key_type GetInternalKey(external_key_type Key) { return Key; }
62
63
external_key_type GetExternalKey(internal_key_type Key) { return Key; }
64
65
static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
66
return LHS == RHS;
67
}
68
69
static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
70
unsigned KeyLength =
71
endian::readNext<uint16_t, llvm::endianness::little>(Data);
72
unsigned DataLength =
73
endian::readNext<uint16_t, llvm::endianness::little>(Data);
74
return {KeyLength, DataLength};
75
}
76
77
static data_type ReadData(internal_key_type Key, const uint8_t *Data,
78
unsigned Length) {
79
unsigned NumElements =
80
endian::readNext<uint16_t, llvm::endianness::little>(Data);
81
data_type Result;
82
Result.reserve(NumElements);
83
for (unsigned i = 0; i != NumElements; ++i) {
84
auto version = ReadVersionTuple(Data);
85
const auto *DataBefore = Data;
86
(void)DataBefore;
87
auto UnversionedData = Derived::readUnversioned(Key, Data);
88
assert(Data != DataBefore &&
89
"Unversioned data reader didn't move pointer");
90
Result.push_back({version, UnversionedData});
91
}
92
return Result;
93
}
94
};
95
96
/// Read serialized CommonEntityInfo.
97
void ReadCommonEntityInfo(const uint8_t *&Data, CommonEntityInfo &Info) {
98
uint8_t UnavailableBits = *Data++;
99
Info.Unavailable = (UnavailableBits >> 1) & 0x01;
100
Info.UnavailableInSwift = UnavailableBits & 0x01;
101
if ((UnavailableBits >> 2) & 0x01)
102
Info.setSwiftPrivate(static_cast<bool>((UnavailableBits >> 3) & 0x01));
103
104
unsigned MsgLength =
105
endian::readNext<uint16_t, llvm::endianness::little>(Data);
106
Info.UnavailableMsg =
107
std::string(reinterpret_cast<const char *>(Data),
108
reinterpret_cast<const char *>(Data) + MsgLength);
109
Data += MsgLength;
110
111
unsigned SwiftNameLength =
112
endian::readNext<uint16_t, llvm::endianness::little>(Data);
113
Info.SwiftName =
114
std::string(reinterpret_cast<const char *>(Data),
115
reinterpret_cast<const char *>(Data) + SwiftNameLength);
116
Data += SwiftNameLength;
117
}
118
119
/// Read serialized CommonTypeInfo.
120
void ReadCommonTypeInfo(const uint8_t *&Data, CommonTypeInfo &Info) {
121
ReadCommonEntityInfo(Data, Info);
122
123
unsigned SwiftBridgeLength =
124
endian::readNext<uint16_t, llvm::endianness::little>(Data);
125
if (SwiftBridgeLength > 0) {
126
Info.setSwiftBridge(std::string(reinterpret_cast<const char *>(Data),
127
SwiftBridgeLength - 1));
128
Data += SwiftBridgeLength - 1;
129
}
130
131
unsigned ErrorDomainLength =
132
endian::readNext<uint16_t, llvm::endianness::little>(Data);
133
if (ErrorDomainLength > 0) {
134
Info.setNSErrorDomain(std::optional<std::string>(std::string(
135
reinterpret_cast<const char *>(Data), ErrorDomainLength - 1)));
136
Data += ErrorDomainLength - 1;
137
}
138
}
139
140
/// Used to deserialize the on-disk identifier table.
141
class IdentifierTableInfo {
142
public:
143
using internal_key_type = llvm::StringRef;
144
using external_key_type = llvm::StringRef;
145
using data_type = IdentifierID;
146
using hash_value_type = uint32_t;
147
using offset_type = unsigned;
148
149
internal_key_type GetInternalKey(external_key_type Key) { return Key; }
150
151
external_key_type GetExternalKey(internal_key_type Key) { return Key; }
152
153
hash_value_type ComputeHash(internal_key_type Key) {
154
return llvm::djbHash(Key);
155
}
156
157
static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
158
return LHS == RHS;
159
}
160
161
static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
162
unsigned KeyLength =
163
endian::readNext<uint16_t, llvm::endianness::little>(Data);
164
unsigned DataLength =
165
endian::readNext<uint16_t, llvm::endianness::little>(Data);
166
return {KeyLength, DataLength};
167
}
168
169
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
170
return llvm::StringRef(reinterpret_cast<const char *>(Data), Length);
171
}
172
173
static data_type ReadData(internal_key_type key, const uint8_t *Data,
174
unsigned Length) {
175
return endian::readNext<uint32_t, llvm::endianness::little>(Data);
176
}
177
};
178
179
/// Used to deserialize the on-disk table of Objective-C classes and C++
180
/// namespaces.
181
class ContextIDTableInfo {
182
public:
183
using internal_key_type = ContextTableKey;
184
using external_key_type = internal_key_type;
185
using data_type = unsigned;
186
using hash_value_type = size_t;
187
using offset_type = unsigned;
188
189
internal_key_type GetInternalKey(external_key_type Key) { return Key; }
190
191
external_key_type GetExternalKey(internal_key_type Key) { return Key; }
192
193
hash_value_type ComputeHash(internal_key_type Key) {
194
return static_cast<size_t>(Key.hashValue());
195
}
196
197
static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
198
return LHS == RHS;
199
}
200
201
static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
202
unsigned KeyLength =
203
endian::readNext<uint16_t, llvm::endianness::little>(Data);
204
unsigned DataLength =
205
endian::readNext<uint16_t, llvm::endianness::little>(Data);
206
return {KeyLength, DataLength};
207
}
208
209
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
210
auto ParentCtxID =
211
endian::readNext<uint32_t, llvm::endianness::little>(Data);
212
auto ContextKind =
213
endian::readNext<uint8_t, llvm::endianness::little>(Data);
214
auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
215
return {ParentCtxID, ContextKind, NameID};
216
}
217
218
static data_type ReadData(internal_key_type Key, const uint8_t *Data,
219
unsigned Length) {
220
return endian::readNext<uint32_t, llvm::endianness::little>(Data);
221
}
222
};
223
224
/// Used to deserialize the on-disk Objective-C property table.
225
class ContextInfoTableInfo
226
: public VersionedTableInfo<ContextInfoTableInfo, unsigned, ContextInfo> {
227
public:
228
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
229
return endian::readNext<uint32_t, llvm::endianness::little>(Data);
230
}
231
232
hash_value_type ComputeHash(internal_key_type Key) {
233
return static_cast<size_t>(llvm::hash_value(Key));
234
}
235
236
static ContextInfo readUnversioned(internal_key_type Key,
237
const uint8_t *&Data) {
238
ContextInfo Info;
239
ReadCommonTypeInfo(Data, Info);
240
uint8_t Payload = *Data++;
241
242
if (Payload & 0x01)
243
Info.setHasDesignatedInits(true);
244
Payload = Payload >> 1;
245
246
if (Payload & 0x4)
247
Info.setDefaultNullability(static_cast<NullabilityKind>(Payload & 0x03));
248
Payload >>= 3;
249
250
if (Payload & (1 << 1))
251
Info.setSwiftObjCMembers(Payload & 1);
252
Payload >>= 2;
253
254
if (Payload & (1 << 1))
255
Info.setSwiftImportAsNonGeneric(Payload & 1);
256
257
return Info;
258
}
259
};
260
261
/// Read serialized VariableInfo.
262
void ReadVariableInfo(const uint8_t *&Data, VariableInfo &Info) {
263
ReadCommonEntityInfo(Data, Info);
264
if (*Data++) {
265
Info.setNullabilityAudited(static_cast<NullabilityKind>(*Data));
266
}
267
++Data;
268
269
auto TypeLen = endian::readNext<uint16_t, llvm::endianness::little>(Data);
270
Info.setType(std::string(Data, Data + TypeLen));
271
Data += TypeLen;
272
}
273
274
/// Used to deserialize the on-disk Objective-C property table.
275
class ObjCPropertyTableInfo
276
: public VersionedTableInfo<ObjCPropertyTableInfo,
277
std::tuple<uint32_t, uint32_t, uint8_t>,
278
ObjCPropertyInfo> {
279
public:
280
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
281
auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
282
auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
283
char IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);
284
return {ClassID, NameID, IsInstance};
285
}
286
287
hash_value_type ComputeHash(internal_key_type Key) {
288
return static_cast<size_t>(llvm::hash_value(Key));
289
}
290
291
static ObjCPropertyInfo readUnversioned(internal_key_type Key,
292
const uint8_t *&Data) {
293
ObjCPropertyInfo Info;
294
ReadVariableInfo(Data, Info);
295
uint8_t Flags = *Data++;
296
if (Flags & (1 << 0))
297
Info.setSwiftImportAsAccessors(Flags & (1 << 1));
298
return Info;
299
}
300
};
301
302
/// Read serialized ParamInfo.
303
void ReadParamInfo(const uint8_t *&Data, ParamInfo &Info) {
304
ReadVariableInfo(Data, Info);
305
306
uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);
307
if (auto RawConvention = Payload & 0x7) {
308
auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
309
Info.setRetainCountConvention(Convention);
310
}
311
Payload >>= 3;
312
if (Payload & 0x01)
313
Info.setNoEscape(Payload & 0x02);
314
Payload >>= 2;
315
assert(Payload == 0 && "Bad API notes");
316
}
317
318
/// Read serialized FunctionInfo.
319
void ReadFunctionInfo(const uint8_t *&Data, FunctionInfo &Info) {
320
ReadCommonEntityInfo(Data, Info);
321
322
uint8_t Payload = endian::readNext<uint8_t, llvm::endianness::little>(Data);
323
if (auto RawConvention = Payload & 0x7) {
324
auto Convention = static_cast<RetainCountConventionKind>(RawConvention - 1);
325
Info.setRetainCountConvention(Convention);
326
}
327
Payload >>= 3;
328
Info.NullabilityAudited = Payload & 0x1;
329
Payload >>= 1;
330
assert(Payload == 0 && "Bad API notes");
331
332
Info.NumAdjustedNullable =
333
endian::readNext<uint8_t, llvm::endianness::little>(Data);
334
Info.NullabilityPayload =
335
endian::readNext<uint64_t, llvm::endianness::little>(Data);
336
337
unsigned NumParams =
338
endian::readNext<uint16_t, llvm::endianness::little>(Data);
339
while (NumParams > 0) {
340
ParamInfo pi;
341
ReadParamInfo(Data, pi);
342
Info.Params.push_back(pi);
343
--NumParams;
344
}
345
346
unsigned ResultTypeLen =
347
endian::readNext<uint16_t, llvm::endianness::little>(Data);
348
Info.ResultType = std::string(Data, Data + ResultTypeLen);
349
Data += ResultTypeLen;
350
}
351
352
/// Used to deserialize the on-disk Objective-C method table.
353
class ObjCMethodTableInfo
354
: public VersionedTableInfo<ObjCMethodTableInfo,
355
std::tuple<uint32_t, uint32_t, uint8_t>,
356
ObjCMethodInfo> {
357
public:
358
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
359
auto ClassID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
360
auto SelectorID =
361
endian::readNext<uint32_t, llvm::endianness::little>(Data);
362
auto IsInstance = endian::readNext<uint8_t, llvm::endianness::little>(Data);
363
return {ClassID, SelectorID, IsInstance};
364
}
365
366
hash_value_type ComputeHash(internal_key_type Key) {
367
return static_cast<size_t>(llvm::hash_value(Key));
368
}
369
370
static ObjCMethodInfo readUnversioned(internal_key_type Key,
371
const uint8_t *&Data) {
372
ObjCMethodInfo Info;
373
uint8_t Payload = *Data++;
374
Info.RequiredInit = Payload & 0x01;
375
Payload >>= 1;
376
Info.DesignatedInit = Payload & 0x01;
377
Payload >>= 1;
378
379
ReadFunctionInfo(Data, Info);
380
return Info;
381
}
382
};
383
384
/// Used to deserialize the on-disk Objective-C selector table.
385
class ObjCSelectorTableInfo {
386
public:
387
using internal_key_type = StoredObjCSelector;
388
using external_key_type = internal_key_type;
389
using data_type = SelectorID;
390
using hash_value_type = unsigned;
391
using offset_type = unsigned;
392
393
internal_key_type GetInternalKey(external_key_type Key) { return Key; }
394
395
external_key_type GetExternalKey(internal_key_type Key) { return Key; }
396
397
hash_value_type ComputeHash(internal_key_type Key) {
398
return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
399
}
400
401
static bool EqualKey(internal_key_type LHS, internal_key_type RHS) {
402
return llvm::DenseMapInfo<StoredObjCSelector>::isEqual(LHS, RHS);
403
}
404
405
static std::pair<unsigned, unsigned> ReadKeyDataLength(const uint8_t *&Data) {
406
unsigned KeyLength =
407
endian::readNext<uint16_t, llvm::endianness::little>(Data);
408
unsigned DataLength =
409
endian::readNext<uint16_t, llvm::endianness::little>(Data);
410
return {KeyLength, DataLength};
411
}
412
413
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
414
internal_key_type Key;
415
Key.NumArgs = endian::readNext<uint16_t, llvm::endianness::little>(Data);
416
unsigned NumIdents = (Length - sizeof(uint16_t)) / sizeof(uint32_t);
417
for (unsigned i = 0; i != NumIdents; ++i) {
418
Key.Identifiers.push_back(
419
endian::readNext<uint32_t, llvm::endianness::little>(Data));
420
}
421
return Key;
422
}
423
424
static data_type ReadData(internal_key_type Key, const uint8_t *Data,
425
unsigned Length) {
426
return endian::readNext<uint32_t, llvm::endianness::little>(Data);
427
}
428
};
429
430
/// Used to deserialize the on-disk global variable table.
431
class GlobalVariableTableInfo
432
: public VersionedTableInfo<GlobalVariableTableInfo, SingleDeclTableKey,
433
GlobalVariableInfo> {
434
public:
435
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
436
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
437
auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
438
return {CtxID, NameID};
439
}
440
441
hash_value_type ComputeHash(internal_key_type Key) {
442
return static_cast<size_t>(Key.hashValue());
443
}
444
445
static GlobalVariableInfo readUnversioned(internal_key_type Key,
446
const uint8_t *&Data) {
447
GlobalVariableInfo Info;
448
ReadVariableInfo(Data, Info);
449
return Info;
450
}
451
};
452
453
/// Used to deserialize the on-disk global function table.
454
class GlobalFunctionTableInfo
455
: public VersionedTableInfo<GlobalFunctionTableInfo, SingleDeclTableKey,
456
GlobalFunctionInfo> {
457
public:
458
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
459
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
460
auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
461
return {CtxID, NameID};
462
}
463
464
hash_value_type ComputeHash(internal_key_type Key) {
465
return static_cast<size_t>(Key.hashValue());
466
}
467
468
static GlobalFunctionInfo readUnversioned(internal_key_type Key,
469
const uint8_t *&Data) {
470
GlobalFunctionInfo Info;
471
ReadFunctionInfo(Data, Info);
472
return Info;
473
}
474
};
475
476
/// Used to deserialize the on-disk C++ method table.
477
class CXXMethodTableInfo
478
: public VersionedTableInfo<CXXMethodTableInfo, SingleDeclTableKey,
479
CXXMethodInfo> {
480
public:
481
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
482
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
483
auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
484
return {CtxID, NameID};
485
}
486
487
hash_value_type ComputeHash(internal_key_type Key) {
488
return static_cast<size_t>(Key.hashValue());
489
}
490
491
static CXXMethodInfo readUnversioned(internal_key_type Key,
492
const uint8_t *&Data) {
493
CXXMethodInfo Info;
494
ReadFunctionInfo(Data, Info);
495
return Info;
496
}
497
};
498
499
/// Used to deserialize the on-disk enumerator table.
500
class EnumConstantTableInfo
501
: public VersionedTableInfo<EnumConstantTableInfo, uint32_t,
502
EnumConstantInfo> {
503
public:
504
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
505
auto NameID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
506
return NameID;
507
}
508
509
hash_value_type ComputeHash(internal_key_type Key) {
510
return static_cast<size_t>(llvm::hash_value(Key));
511
}
512
513
static EnumConstantInfo readUnversioned(internal_key_type Key,
514
const uint8_t *&Data) {
515
EnumConstantInfo Info;
516
ReadCommonEntityInfo(Data, Info);
517
return Info;
518
}
519
};
520
521
/// Used to deserialize the on-disk tag table.
522
class TagTableInfo
523
: public VersionedTableInfo<TagTableInfo, SingleDeclTableKey, TagInfo> {
524
public:
525
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
526
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
527
auto NameID =
528
endian::readNext<IdentifierID, llvm::endianness::little>(Data);
529
return {CtxID, NameID};
530
}
531
532
hash_value_type ComputeHash(internal_key_type Key) {
533
return static_cast<size_t>(Key.hashValue());
534
}
535
536
static TagInfo readUnversioned(internal_key_type Key, const uint8_t *&Data) {
537
TagInfo Info;
538
539
uint8_t Payload = *Data++;
540
if (Payload & 1)
541
Info.setFlagEnum(Payload & 2);
542
Payload >>= 2;
543
if (Payload > 0)
544
Info.EnumExtensibility =
545
static_cast<EnumExtensibilityKind>((Payload & 0x3) - 1);
546
547
uint8_t Copyable =
548
endian::readNext<uint8_t, llvm::endianness::little>(Data);
549
if (Copyable == kSwiftNonCopyable)
550
Info.setSwiftCopyable(std::optional(false));
551
else if (Copyable == kSwiftCopyable)
552
Info.setSwiftCopyable(std::optional(true));
553
554
unsigned ImportAsLength =
555
endian::readNext<uint16_t, llvm::endianness::little>(Data);
556
if (ImportAsLength > 0) {
557
Info.SwiftImportAs =
558
std::string(reinterpret_cast<const char *>(Data), ImportAsLength - 1);
559
Data += ImportAsLength - 1;
560
}
561
unsigned RetainOpLength =
562
endian::readNext<uint16_t, llvm::endianness::little>(Data);
563
if (RetainOpLength > 0) {
564
Info.SwiftRetainOp =
565
std::string(reinterpret_cast<const char *>(Data), RetainOpLength - 1);
566
Data += RetainOpLength - 1;
567
}
568
unsigned ReleaseOpLength =
569
endian::readNext<uint16_t, llvm::endianness::little>(Data);
570
if (ReleaseOpLength > 0) {
571
Info.SwiftReleaseOp = std::string(reinterpret_cast<const char *>(Data),
572
ReleaseOpLength - 1);
573
Data += ReleaseOpLength - 1;
574
}
575
576
ReadCommonTypeInfo(Data, Info);
577
return Info;
578
}
579
};
580
581
/// Used to deserialize the on-disk typedef table.
582
class TypedefTableInfo
583
: public VersionedTableInfo<TypedefTableInfo, SingleDeclTableKey,
584
TypedefInfo> {
585
public:
586
static internal_key_type ReadKey(const uint8_t *Data, unsigned Length) {
587
auto CtxID = endian::readNext<uint32_t, llvm::endianness::little>(Data);
588
auto nameID =
589
endian::readNext<IdentifierID, llvm::endianness::little>(Data);
590
return {CtxID, nameID};
591
}
592
593
hash_value_type ComputeHash(internal_key_type Key) {
594
return static_cast<size_t>(Key.hashValue());
595
}
596
597
static TypedefInfo readUnversioned(internal_key_type Key,
598
const uint8_t *&Data) {
599
TypedefInfo Info;
600
601
uint8_t Payload = *Data++;
602
if (Payload > 0)
603
Info.SwiftWrapper = static_cast<SwiftNewTypeKind>((Payload & 0x3) - 1);
604
605
ReadCommonTypeInfo(Data, Info);
606
return Info;
607
}
608
};
609
} // end anonymous namespace
610
611
class APINotesReader::Implementation {
612
public:
613
/// The input buffer for the API notes data.
614
llvm::MemoryBuffer *InputBuffer;
615
616
/// The Swift version to use for filtering.
617
llvm::VersionTuple SwiftVersion;
618
619
/// The name of the module that we read from the control block.
620
std::string ModuleName;
621
622
// The size and modification time of the source file from
623
// which this API notes file was created, if known.
624
std::optional<std::pair<off_t, time_t>> SourceFileSizeAndModTime;
625
626
using SerializedIdentifierTable =
627
llvm::OnDiskIterableChainedHashTable<IdentifierTableInfo>;
628
629
/// The identifier table.
630
std::unique_ptr<SerializedIdentifierTable> IdentifierTable;
631
632
using SerializedContextIDTable =
633
llvm::OnDiskIterableChainedHashTable<ContextIDTableInfo>;
634
635
/// The Objective-C / C++ context ID table.
636
std::unique_ptr<SerializedContextIDTable> ContextIDTable;
637
638
using SerializedContextInfoTable =
639
llvm::OnDiskIterableChainedHashTable<ContextInfoTableInfo>;
640
641
/// The Objective-C context info table.
642
std::unique_ptr<SerializedContextInfoTable> ContextInfoTable;
643
644
using SerializedObjCPropertyTable =
645
llvm::OnDiskIterableChainedHashTable<ObjCPropertyTableInfo>;
646
647
/// The Objective-C property table.
648
std::unique_ptr<SerializedObjCPropertyTable> ObjCPropertyTable;
649
650
using SerializedObjCMethodTable =
651
llvm::OnDiskIterableChainedHashTable<ObjCMethodTableInfo>;
652
653
/// The Objective-C method table.
654
std::unique_ptr<SerializedObjCMethodTable> ObjCMethodTable;
655
656
using SerializedCXXMethodTable =
657
llvm::OnDiskIterableChainedHashTable<CXXMethodTableInfo>;
658
659
/// The C++ method table.
660
std::unique_ptr<SerializedCXXMethodTable> CXXMethodTable;
661
662
using SerializedObjCSelectorTable =
663
llvm::OnDiskIterableChainedHashTable<ObjCSelectorTableInfo>;
664
665
/// The Objective-C selector table.
666
std::unique_ptr<SerializedObjCSelectorTable> ObjCSelectorTable;
667
668
using SerializedGlobalVariableTable =
669
llvm::OnDiskIterableChainedHashTable<GlobalVariableTableInfo>;
670
671
/// The global variable table.
672
std::unique_ptr<SerializedGlobalVariableTable> GlobalVariableTable;
673
674
using SerializedGlobalFunctionTable =
675
llvm::OnDiskIterableChainedHashTable<GlobalFunctionTableInfo>;
676
677
/// The global function table.
678
std::unique_ptr<SerializedGlobalFunctionTable> GlobalFunctionTable;
679
680
using SerializedEnumConstantTable =
681
llvm::OnDiskIterableChainedHashTable<EnumConstantTableInfo>;
682
683
/// The enumerator table.
684
std::unique_ptr<SerializedEnumConstantTable> EnumConstantTable;
685
686
using SerializedTagTable = llvm::OnDiskIterableChainedHashTable<TagTableInfo>;
687
688
/// The tag table.
689
std::unique_ptr<SerializedTagTable> TagTable;
690
691
using SerializedTypedefTable =
692
llvm::OnDiskIterableChainedHashTable<TypedefTableInfo>;
693
694
/// The typedef table.
695
std::unique_ptr<SerializedTypedefTable> TypedefTable;
696
697
/// Retrieve the identifier ID for the given string, or an empty
698
/// optional if the string is unknown.
699
std::optional<IdentifierID> getIdentifier(llvm::StringRef Str);
700
701
/// Retrieve the selector ID for the given selector, or an empty
702
/// optional if the string is unknown.
703
std::optional<SelectorID> getSelector(ObjCSelectorRef Selector);
704
705
bool readControlBlock(llvm::BitstreamCursor &Cursor,
706
llvm::SmallVectorImpl<uint64_t> &Scratch);
707
bool readIdentifierBlock(llvm::BitstreamCursor &Cursor,
708
llvm::SmallVectorImpl<uint64_t> &Scratch);
709
bool readContextBlock(llvm::BitstreamCursor &Cursor,
710
llvm::SmallVectorImpl<uint64_t> &Scratch);
711
bool readObjCPropertyBlock(llvm::BitstreamCursor &Cursor,
712
llvm::SmallVectorImpl<uint64_t> &Scratch);
713
bool readObjCMethodBlock(llvm::BitstreamCursor &Cursor,
714
llvm::SmallVectorImpl<uint64_t> &Scratch);
715
bool readCXXMethodBlock(llvm::BitstreamCursor &Cursor,
716
llvm::SmallVectorImpl<uint64_t> &Scratch);
717
bool readObjCSelectorBlock(llvm::BitstreamCursor &Cursor,
718
llvm::SmallVectorImpl<uint64_t> &Scratch);
719
bool readGlobalVariableBlock(llvm::BitstreamCursor &Cursor,
720
llvm::SmallVectorImpl<uint64_t> &Scratch);
721
bool readGlobalFunctionBlock(llvm::BitstreamCursor &Cursor,
722
llvm::SmallVectorImpl<uint64_t> &Scratch);
723
bool readEnumConstantBlock(llvm::BitstreamCursor &Cursor,
724
llvm::SmallVectorImpl<uint64_t> &Scratch);
725
bool readTagBlock(llvm::BitstreamCursor &Cursor,
726
llvm::SmallVectorImpl<uint64_t> &Scratch);
727
bool readTypedefBlock(llvm::BitstreamCursor &Cursor,
728
llvm::SmallVectorImpl<uint64_t> &Scratch);
729
};
730
731
std::optional<IdentifierID>
732
APINotesReader::Implementation::getIdentifier(llvm::StringRef Str) {
733
if (!IdentifierTable)
734
return std::nullopt;
735
736
if (Str.empty())
737
return IdentifierID(0);
738
739
auto Known = IdentifierTable->find(Str);
740
if (Known == IdentifierTable->end())
741
return std::nullopt;
742
743
return *Known;
744
}
745
746
std::optional<SelectorID>
747
APINotesReader::Implementation::getSelector(ObjCSelectorRef Selector) {
748
if (!ObjCSelectorTable || !IdentifierTable)
749
return std::nullopt;
750
751
// Translate the identifiers.
752
StoredObjCSelector Key;
753
Key.NumArgs = Selector.NumArgs;
754
for (auto Ident : Selector.Identifiers) {
755
if (auto IdentID = getIdentifier(Ident)) {
756
Key.Identifiers.push_back(*IdentID);
757
} else {
758
return std::nullopt;
759
}
760
}
761
762
auto Known = ObjCSelectorTable->find(Key);
763
if (Known == ObjCSelectorTable->end())
764
return std::nullopt;
765
766
return *Known;
767
}
768
769
bool APINotesReader::Implementation::readControlBlock(
770
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
771
if (Cursor.EnterSubBlock(CONTROL_BLOCK_ID))
772
return true;
773
774
bool SawMetadata = false;
775
776
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
777
if (!MaybeNext) {
778
// FIXME this drops the error on the floor.
779
consumeError(MaybeNext.takeError());
780
return false;
781
}
782
llvm::BitstreamEntry Next = MaybeNext.get();
783
784
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
785
if (Next.Kind == llvm::BitstreamEntry::Error)
786
return true;
787
788
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
789
// Unknown metadata sub-block, possibly for use by a future version of the
790
// API notes format.
791
if (Cursor.SkipBlock())
792
return true;
793
794
MaybeNext = Cursor.advance();
795
if (!MaybeNext) {
796
// FIXME this drops the error on the floor.
797
consumeError(MaybeNext.takeError());
798
return false;
799
}
800
Next = MaybeNext.get();
801
continue;
802
}
803
804
Scratch.clear();
805
llvm::StringRef BlobData;
806
llvm::Expected<unsigned> MaybeKind =
807
Cursor.readRecord(Next.ID, Scratch, &BlobData);
808
if (!MaybeKind) {
809
// FIXME this drops the error on the floor.
810
consumeError(MaybeKind.takeError());
811
return false;
812
}
813
unsigned Kind = MaybeKind.get();
814
815
switch (Kind) {
816
case control_block::METADATA:
817
// Already saw metadata.
818
if (SawMetadata)
819
return true;
820
821
if (Scratch[0] != VERSION_MAJOR || Scratch[1] != VERSION_MINOR)
822
return true;
823
824
SawMetadata = true;
825
break;
826
827
case control_block::MODULE_NAME:
828
ModuleName = BlobData.str();
829
break;
830
831
case control_block::MODULE_OPTIONS:
832
break;
833
834
case control_block::SOURCE_FILE:
835
SourceFileSizeAndModTime = {Scratch[0], Scratch[1]};
836
break;
837
838
default:
839
// Unknown metadata record, possibly for use by a future version of the
840
// module format.
841
break;
842
}
843
844
MaybeNext = Cursor.advance();
845
if (!MaybeNext) {
846
// FIXME this drops the error on the floor.
847
consumeError(MaybeNext.takeError());
848
return false;
849
}
850
Next = MaybeNext.get();
851
}
852
853
return !SawMetadata;
854
}
855
856
bool APINotesReader::Implementation::readIdentifierBlock(
857
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
858
if (Cursor.EnterSubBlock(IDENTIFIER_BLOCK_ID))
859
return true;
860
861
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
862
if (!MaybeNext) {
863
// FIXME this drops the error on the floor.
864
consumeError(MaybeNext.takeError());
865
return false;
866
}
867
llvm::BitstreamEntry Next = MaybeNext.get();
868
869
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
870
if (Next.Kind == llvm::BitstreamEntry::Error)
871
return true;
872
873
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
874
// Unknown sub-block, possibly for use by a future version of the
875
// API notes format.
876
if (Cursor.SkipBlock())
877
return true;
878
879
MaybeNext = Cursor.advance();
880
if (!MaybeNext) {
881
// FIXME this drops the error on the floor.
882
consumeError(MaybeNext.takeError());
883
return false;
884
}
885
Next = MaybeNext.get();
886
continue;
887
}
888
889
Scratch.clear();
890
llvm::StringRef BlobData;
891
llvm::Expected<unsigned> MaybeKind =
892
Cursor.readRecord(Next.ID, Scratch, &BlobData);
893
if (!MaybeKind) {
894
// FIXME this drops the error on the floor.
895
consumeError(MaybeKind.takeError());
896
return false;
897
}
898
unsigned Kind = MaybeKind.get();
899
switch (Kind) {
900
case identifier_block::IDENTIFIER_DATA: {
901
// Already saw identifier table.
902
if (IdentifierTable)
903
return true;
904
905
uint32_t tableOffset;
906
identifier_block::IdentifierDataLayout::readRecord(Scratch, tableOffset);
907
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
908
909
IdentifierTable.reset(SerializedIdentifierTable::Create(
910
base + tableOffset, base + sizeof(uint32_t), base));
911
break;
912
}
913
914
default:
915
// Unknown record, possibly for use by a future version of the
916
// module format.
917
break;
918
}
919
920
MaybeNext = Cursor.advance();
921
if (!MaybeNext) {
922
// FIXME this drops the error on the floor.
923
consumeError(MaybeNext.takeError());
924
return false;
925
}
926
Next = MaybeNext.get();
927
}
928
929
return false;
930
}
931
932
bool APINotesReader::Implementation::readContextBlock(
933
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
934
if (Cursor.EnterSubBlock(OBJC_CONTEXT_BLOCK_ID))
935
return true;
936
937
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
938
if (!MaybeNext) {
939
// FIXME this drops the error on the floor.
940
consumeError(MaybeNext.takeError());
941
return false;
942
}
943
llvm::BitstreamEntry Next = MaybeNext.get();
944
945
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
946
if (Next.Kind == llvm::BitstreamEntry::Error)
947
return true;
948
949
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
950
// Unknown sub-block, possibly for use by a future version of the
951
// API notes format.
952
if (Cursor.SkipBlock())
953
return true;
954
955
MaybeNext = Cursor.advance();
956
if (!MaybeNext) {
957
// FIXME this drops the error on the floor.
958
consumeError(MaybeNext.takeError());
959
return false;
960
}
961
Next = MaybeNext.get();
962
continue;
963
}
964
965
Scratch.clear();
966
llvm::StringRef BlobData;
967
llvm::Expected<unsigned> MaybeKind =
968
Cursor.readRecord(Next.ID, Scratch, &BlobData);
969
if (!MaybeKind) {
970
// FIXME this drops the error on the floor.
971
consumeError(MaybeKind.takeError());
972
return false;
973
}
974
unsigned Kind = MaybeKind.get();
975
switch (Kind) {
976
case context_block::CONTEXT_ID_DATA: {
977
// Already saw Objective-C / C++ context ID table.
978
if (ContextIDTable)
979
return true;
980
981
uint32_t tableOffset;
982
context_block::ContextIDLayout::readRecord(Scratch, tableOffset);
983
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
984
985
ContextIDTable.reset(SerializedContextIDTable::Create(
986
base + tableOffset, base + sizeof(uint32_t), base));
987
break;
988
}
989
990
case context_block::CONTEXT_INFO_DATA: {
991
// Already saw Objective-C / C++ context info table.
992
if (ContextInfoTable)
993
return true;
994
995
uint32_t tableOffset;
996
context_block::ContextInfoLayout::readRecord(Scratch, tableOffset);
997
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
998
999
ContextInfoTable.reset(SerializedContextInfoTable::Create(
1000
base + tableOffset, base + sizeof(uint32_t), base));
1001
break;
1002
}
1003
1004
default:
1005
// Unknown record, possibly for use by a future version of the
1006
// module format.
1007
break;
1008
}
1009
1010
MaybeNext = Cursor.advance();
1011
if (!MaybeNext) {
1012
// FIXME this drops the error on the floor.
1013
consumeError(MaybeNext.takeError());
1014
return false;
1015
}
1016
Next = MaybeNext.get();
1017
}
1018
1019
return false;
1020
}
1021
1022
bool APINotesReader::Implementation::readObjCPropertyBlock(
1023
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1024
if (Cursor.EnterSubBlock(OBJC_PROPERTY_BLOCK_ID))
1025
return true;
1026
1027
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1028
if (!MaybeNext) {
1029
// FIXME this drops the error on the floor.
1030
consumeError(MaybeNext.takeError());
1031
return false;
1032
}
1033
llvm::BitstreamEntry Next = MaybeNext.get();
1034
1035
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1036
if (Next.Kind == llvm::BitstreamEntry::Error)
1037
return true;
1038
1039
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1040
// Unknown sub-block, possibly for use by a future version of the
1041
// API notes format.
1042
if (Cursor.SkipBlock())
1043
return true;
1044
1045
MaybeNext = Cursor.advance();
1046
if (!MaybeNext) {
1047
// FIXME this drops the error on the floor.
1048
consumeError(MaybeNext.takeError());
1049
return false;
1050
}
1051
Next = MaybeNext.get();
1052
continue;
1053
}
1054
1055
Scratch.clear();
1056
llvm::StringRef BlobData;
1057
llvm::Expected<unsigned> MaybeKind =
1058
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1059
if (!MaybeKind) {
1060
// FIXME this drops the error on the floor.
1061
consumeError(MaybeKind.takeError());
1062
return false;
1063
}
1064
unsigned Kind = MaybeKind.get();
1065
switch (Kind) {
1066
case objc_property_block::OBJC_PROPERTY_DATA: {
1067
// Already saw Objective-C property table.
1068
if (ObjCPropertyTable)
1069
return true;
1070
1071
uint32_t tableOffset;
1072
objc_property_block::ObjCPropertyDataLayout::readRecord(Scratch,
1073
tableOffset);
1074
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1075
1076
ObjCPropertyTable.reset(SerializedObjCPropertyTable::Create(
1077
base + tableOffset, base + sizeof(uint32_t), base));
1078
break;
1079
}
1080
1081
default:
1082
// Unknown record, possibly for use by a future version of the
1083
// module format.
1084
break;
1085
}
1086
1087
MaybeNext = Cursor.advance();
1088
if (!MaybeNext) {
1089
// FIXME this drops the error on the floor.
1090
consumeError(MaybeNext.takeError());
1091
return false;
1092
}
1093
Next = MaybeNext.get();
1094
}
1095
1096
return false;
1097
}
1098
1099
bool APINotesReader::Implementation::readObjCMethodBlock(
1100
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1101
if (Cursor.EnterSubBlock(OBJC_METHOD_BLOCK_ID))
1102
return true;
1103
1104
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1105
if (!MaybeNext) {
1106
// FIXME this drops the error on the floor.
1107
consumeError(MaybeNext.takeError());
1108
return false;
1109
}
1110
llvm::BitstreamEntry Next = MaybeNext.get();
1111
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1112
if (Next.Kind == llvm::BitstreamEntry::Error)
1113
return true;
1114
1115
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1116
// Unknown sub-block, possibly for use by a future version of the
1117
// API notes format.
1118
if (Cursor.SkipBlock())
1119
return true;
1120
1121
MaybeNext = Cursor.advance();
1122
if (!MaybeNext) {
1123
// FIXME this drops the error on the floor.
1124
consumeError(MaybeNext.takeError());
1125
return false;
1126
}
1127
Next = MaybeNext.get();
1128
continue;
1129
}
1130
1131
Scratch.clear();
1132
llvm::StringRef BlobData;
1133
llvm::Expected<unsigned> MaybeKind =
1134
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1135
if (!MaybeKind) {
1136
// FIXME this drops the error on the floor.
1137
consumeError(MaybeKind.takeError());
1138
return false;
1139
}
1140
unsigned Kind = MaybeKind.get();
1141
switch (Kind) {
1142
case objc_method_block::OBJC_METHOD_DATA: {
1143
// Already saw Objective-C method table.
1144
if (ObjCMethodTable)
1145
return true;
1146
1147
uint32_t tableOffset;
1148
objc_method_block::ObjCMethodDataLayout::readRecord(Scratch, tableOffset);
1149
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1150
1151
ObjCMethodTable.reset(SerializedObjCMethodTable::Create(
1152
base + tableOffset, base + sizeof(uint32_t), base));
1153
break;
1154
}
1155
1156
default:
1157
// Unknown record, possibly for use by a future version of the
1158
// module format.
1159
break;
1160
}
1161
1162
MaybeNext = Cursor.advance();
1163
if (!MaybeNext) {
1164
// FIXME this drops the error on the floor.
1165
consumeError(MaybeNext.takeError());
1166
return false;
1167
}
1168
Next = MaybeNext.get();
1169
}
1170
1171
return false;
1172
}
1173
1174
bool APINotesReader::Implementation::readCXXMethodBlock(
1175
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1176
if (Cursor.EnterSubBlock(CXX_METHOD_BLOCK_ID))
1177
return true;
1178
1179
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1180
if (!MaybeNext) {
1181
// FIXME this drops the error on the floor.
1182
consumeError(MaybeNext.takeError());
1183
return false;
1184
}
1185
llvm::BitstreamEntry Next = MaybeNext.get();
1186
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1187
if (Next.Kind == llvm::BitstreamEntry::Error)
1188
return true;
1189
1190
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1191
// Unknown sub-block, possibly for use by a future version of the
1192
// API notes format.
1193
if (Cursor.SkipBlock())
1194
return true;
1195
1196
MaybeNext = Cursor.advance();
1197
if (!MaybeNext) {
1198
// FIXME this drops the error on the floor.
1199
consumeError(MaybeNext.takeError());
1200
return false;
1201
}
1202
Next = MaybeNext.get();
1203
continue;
1204
}
1205
1206
Scratch.clear();
1207
llvm::StringRef BlobData;
1208
llvm::Expected<unsigned> MaybeKind =
1209
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1210
if (!MaybeKind) {
1211
// FIXME this drops the error on the floor.
1212
consumeError(MaybeKind.takeError());
1213
return false;
1214
}
1215
unsigned Kind = MaybeKind.get();
1216
switch (Kind) {
1217
case cxx_method_block::CXX_METHOD_DATA: {
1218
// Already saw C++ method table.
1219
if (CXXMethodTable)
1220
return true;
1221
1222
uint32_t tableOffset;
1223
cxx_method_block::CXXMethodDataLayout::readRecord(Scratch, tableOffset);
1224
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1225
1226
CXXMethodTable.reset(SerializedCXXMethodTable::Create(
1227
base + tableOffset, base + sizeof(uint32_t), base));
1228
break;
1229
}
1230
1231
default:
1232
// Unknown record, possibly for use by a future version of the
1233
// module format.
1234
break;
1235
}
1236
1237
MaybeNext = Cursor.advance();
1238
if (!MaybeNext) {
1239
// FIXME this drops the error on the floor.
1240
consumeError(MaybeNext.takeError());
1241
return false;
1242
}
1243
Next = MaybeNext.get();
1244
}
1245
1246
return false;
1247
}
1248
1249
bool APINotesReader::Implementation::readObjCSelectorBlock(
1250
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1251
if (Cursor.EnterSubBlock(OBJC_SELECTOR_BLOCK_ID))
1252
return true;
1253
1254
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1255
if (!MaybeNext) {
1256
// FIXME this drops the error on the floor.
1257
consumeError(MaybeNext.takeError());
1258
return false;
1259
}
1260
llvm::BitstreamEntry Next = MaybeNext.get();
1261
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1262
if (Next.Kind == llvm::BitstreamEntry::Error)
1263
return true;
1264
1265
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1266
// Unknown sub-block, possibly for use by a future version of the
1267
// API notes format.
1268
if (Cursor.SkipBlock())
1269
return true;
1270
1271
MaybeNext = Cursor.advance();
1272
if (!MaybeNext) {
1273
// FIXME this drops the error on the floor.
1274
consumeError(MaybeNext.takeError());
1275
return false;
1276
}
1277
Next = MaybeNext.get();
1278
continue;
1279
}
1280
1281
Scratch.clear();
1282
llvm::StringRef BlobData;
1283
llvm::Expected<unsigned> MaybeKind =
1284
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1285
if (!MaybeKind) {
1286
// FIXME this drops the error on the floor.
1287
consumeError(MaybeKind.takeError());
1288
return false;
1289
}
1290
unsigned Kind = MaybeKind.get();
1291
switch (Kind) {
1292
case objc_selector_block::OBJC_SELECTOR_DATA: {
1293
// Already saw Objective-C selector table.
1294
if (ObjCSelectorTable)
1295
return true;
1296
1297
uint32_t tableOffset;
1298
objc_selector_block::ObjCSelectorDataLayout::readRecord(Scratch,
1299
tableOffset);
1300
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1301
1302
ObjCSelectorTable.reset(SerializedObjCSelectorTable::Create(
1303
base + tableOffset, base + sizeof(uint32_t), base));
1304
break;
1305
}
1306
1307
default:
1308
// Unknown record, possibly for use by a future version of the
1309
// module format.
1310
break;
1311
}
1312
1313
MaybeNext = Cursor.advance();
1314
if (!MaybeNext) {
1315
// FIXME this drops the error on the floor.
1316
consumeError(MaybeNext.takeError());
1317
return false;
1318
}
1319
Next = MaybeNext.get();
1320
}
1321
1322
return false;
1323
}
1324
1325
bool APINotesReader::Implementation::readGlobalVariableBlock(
1326
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1327
if (Cursor.EnterSubBlock(GLOBAL_VARIABLE_BLOCK_ID))
1328
return true;
1329
1330
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1331
if (!MaybeNext) {
1332
// FIXME this drops the error on the floor.
1333
consumeError(MaybeNext.takeError());
1334
return false;
1335
}
1336
llvm::BitstreamEntry Next = MaybeNext.get();
1337
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1338
if (Next.Kind == llvm::BitstreamEntry::Error)
1339
return true;
1340
1341
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1342
// Unknown sub-block, possibly for use by a future version of the
1343
// API notes format.
1344
if (Cursor.SkipBlock())
1345
return true;
1346
1347
MaybeNext = Cursor.advance();
1348
if (!MaybeNext) {
1349
// FIXME this drops the error on the floor.
1350
consumeError(MaybeNext.takeError());
1351
return false;
1352
}
1353
Next = MaybeNext.get();
1354
continue;
1355
}
1356
1357
Scratch.clear();
1358
llvm::StringRef BlobData;
1359
llvm::Expected<unsigned> MaybeKind =
1360
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1361
if (!MaybeKind) {
1362
// FIXME this drops the error on the floor.
1363
consumeError(MaybeKind.takeError());
1364
return false;
1365
}
1366
unsigned Kind = MaybeKind.get();
1367
switch (Kind) {
1368
case global_variable_block::GLOBAL_VARIABLE_DATA: {
1369
// Already saw global variable table.
1370
if (GlobalVariableTable)
1371
return true;
1372
1373
uint32_t tableOffset;
1374
global_variable_block::GlobalVariableDataLayout::readRecord(Scratch,
1375
tableOffset);
1376
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1377
1378
GlobalVariableTable.reset(SerializedGlobalVariableTable::Create(
1379
base + tableOffset, base + sizeof(uint32_t), base));
1380
break;
1381
}
1382
1383
default:
1384
// Unknown record, possibly for use by a future version of the
1385
// module format.
1386
break;
1387
}
1388
1389
MaybeNext = Cursor.advance();
1390
if (!MaybeNext) {
1391
// FIXME this drops the error on the floor.
1392
consumeError(MaybeNext.takeError());
1393
return false;
1394
}
1395
Next = MaybeNext.get();
1396
}
1397
1398
return false;
1399
}
1400
1401
bool APINotesReader::Implementation::readGlobalFunctionBlock(
1402
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1403
if (Cursor.EnterSubBlock(GLOBAL_FUNCTION_BLOCK_ID))
1404
return true;
1405
1406
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1407
if (!MaybeNext) {
1408
// FIXME this drops the error on the floor.
1409
consumeError(MaybeNext.takeError());
1410
return false;
1411
}
1412
llvm::BitstreamEntry Next = MaybeNext.get();
1413
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1414
if (Next.Kind == llvm::BitstreamEntry::Error)
1415
return true;
1416
1417
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1418
// Unknown sub-block, possibly for use by a future version of the
1419
// API notes format.
1420
if (Cursor.SkipBlock())
1421
return true;
1422
1423
MaybeNext = Cursor.advance();
1424
if (!MaybeNext) {
1425
// FIXME this drops the error on the floor.
1426
consumeError(MaybeNext.takeError());
1427
return false;
1428
}
1429
Next = MaybeNext.get();
1430
continue;
1431
}
1432
1433
Scratch.clear();
1434
llvm::StringRef BlobData;
1435
llvm::Expected<unsigned> MaybeKind =
1436
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1437
if (!MaybeKind) {
1438
// FIXME this drops the error on the floor.
1439
consumeError(MaybeKind.takeError());
1440
return false;
1441
}
1442
unsigned Kind = MaybeKind.get();
1443
switch (Kind) {
1444
case global_function_block::GLOBAL_FUNCTION_DATA: {
1445
// Already saw global function table.
1446
if (GlobalFunctionTable)
1447
return true;
1448
1449
uint32_t tableOffset;
1450
global_function_block::GlobalFunctionDataLayout::readRecord(Scratch,
1451
tableOffset);
1452
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1453
1454
GlobalFunctionTable.reset(SerializedGlobalFunctionTable::Create(
1455
base + tableOffset, base + sizeof(uint32_t), base));
1456
break;
1457
}
1458
1459
default:
1460
// Unknown record, possibly for use by a future version of the
1461
// module format.
1462
break;
1463
}
1464
1465
MaybeNext = Cursor.advance();
1466
if (!MaybeNext) {
1467
// FIXME this drops the error on the floor.
1468
consumeError(MaybeNext.takeError());
1469
return false;
1470
}
1471
Next = MaybeNext.get();
1472
}
1473
1474
return false;
1475
}
1476
1477
bool APINotesReader::Implementation::readEnumConstantBlock(
1478
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1479
if (Cursor.EnterSubBlock(ENUM_CONSTANT_BLOCK_ID))
1480
return true;
1481
1482
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1483
if (!MaybeNext) {
1484
// FIXME this drops the error on the floor.
1485
consumeError(MaybeNext.takeError());
1486
return false;
1487
}
1488
llvm::BitstreamEntry Next = MaybeNext.get();
1489
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1490
if (Next.Kind == llvm::BitstreamEntry::Error)
1491
return true;
1492
1493
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1494
// Unknown sub-block, possibly for use by a future version of the
1495
// API notes format.
1496
if (Cursor.SkipBlock())
1497
return true;
1498
1499
MaybeNext = Cursor.advance();
1500
if (!MaybeNext) {
1501
// FIXME this drops the error on the floor.
1502
consumeError(MaybeNext.takeError());
1503
return false;
1504
}
1505
Next = MaybeNext.get();
1506
continue;
1507
}
1508
1509
Scratch.clear();
1510
llvm::StringRef BlobData;
1511
llvm::Expected<unsigned> MaybeKind =
1512
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1513
if (!MaybeKind) {
1514
// FIXME this drops the error on the floor.
1515
consumeError(MaybeKind.takeError());
1516
return false;
1517
}
1518
unsigned Kind = MaybeKind.get();
1519
switch (Kind) {
1520
case enum_constant_block::ENUM_CONSTANT_DATA: {
1521
// Already saw enumerator table.
1522
if (EnumConstantTable)
1523
return true;
1524
1525
uint32_t tableOffset;
1526
enum_constant_block::EnumConstantDataLayout::readRecord(Scratch,
1527
tableOffset);
1528
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1529
1530
EnumConstantTable.reset(SerializedEnumConstantTable::Create(
1531
base + tableOffset, base + sizeof(uint32_t), base));
1532
break;
1533
}
1534
1535
default:
1536
// Unknown record, possibly for use by a future version of the
1537
// module format.
1538
break;
1539
}
1540
1541
MaybeNext = Cursor.advance();
1542
if (!MaybeNext) {
1543
// FIXME this drops the error on the floor.
1544
consumeError(MaybeNext.takeError());
1545
return false;
1546
}
1547
Next = MaybeNext.get();
1548
}
1549
1550
return false;
1551
}
1552
1553
bool APINotesReader::Implementation::readTagBlock(
1554
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1555
if (Cursor.EnterSubBlock(TAG_BLOCK_ID))
1556
return true;
1557
1558
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1559
if (!MaybeNext) {
1560
// FIXME this drops the error on the floor.
1561
consumeError(MaybeNext.takeError());
1562
return false;
1563
}
1564
llvm::BitstreamEntry Next = MaybeNext.get();
1565
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1566
if (Next.Kind == llvm::BitstreamEntry::Error)
1567
return true;
1568
1569
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1570
// Unknown sub-block, possibly for use by a future version of the
1571
// API notes format.
1572
if (Cursor.SkipBlock())
1573
return true;
1574
1575
MaybeNext = Cursor.advance();
1576
if (!MaybeNext) {
1577
// FIXME this drops the error on the floor.
1578
consumeError(MaybeNext.takeError());
1579
return false;
1580
}
1581
Next = MaybeNext.get();
1582
continue;
1583
}
1584
1585
Scratch.clear();
1586
llvm::StringRef BlobData;
1587
llvm::Expected<unsigned> MaybeKind =
1588
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1589
if (!MaybeKind) {
1590
// FIXME this drops the error on the floor.
1591
consumeError(MaybeKind.takeError());
1592
return false;
1593
}
1594
unsigned Kind = MaybeKind.get();
1595
switch (Kind) {
1596
case tag_block::TAG_DATA: {
1597
// Already saw tag table.
1598
if (TagTable)
1599
return true;
1600
1601
uint32_t tableOffset;
1602
tag_block::TagDataLayout::readRecord(Scratch, tableOffset);
1603
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1604
1605
TagTable.reset(SerializedTagTable::Create(base + tableOffset,
1606
base + sizeof(uint32_t), base));
1607
break;
1608
}
1609
1610
default:
1611
// Unknown record, possibly for use by a future version of the
1612
// module format.
1613
break;
1614
}
1615
1616
MaybeNext = Cursor.advance();
1617
if (!MaybeNext) {
1618
// FIXME this drops the error on the floor.
1619
consumeError(MaybeNext.takeError());
1620
return false;
1621
}
1622
Next = MaybeNext.get();
1623
}
1624
1625
return false;
1626
}
1627
1628
bool APINotesReader::Implementation::readTypedefBlock(
1629
llvm::BitstreamCursor &Cursor, llvm::SmallVectorImpl<uint64_t> &Scratch) {
1630
if (Cursor.EnterSubBlock(TYPEDEF_BLOCK_ID))
1631
return true;
1632
1633
llvm::Expected<llvm::BitstreamEntry> MaybeNext = Cursor.advance();
1634
if (!MaybeNext) {
1635
// FIXME this drops the error on the floor.
1636
consumeError(MaybeNext.takeError());
1637
return false;
1638
}
1639
llvm::BitstreamEntry Next = MaybeNext.get();
1640
while (Next.Kind != llvm::BitstreamEntry::EndBlock) {
1641
if (Next.Kind == llvm::BitstreamEntry::Error)
1642
return true;
1643
1644
if (Next.Kind == llvm::BitstreamEntry::SubBlock) {
1645
// Unknown sub-block, possibly for use by a future version of the
1646
// API notes format.
1647
if (Cursor.SkipBlock())
1648
return true;
1649
1650
MaybeNext = Cursor.advance();
1651
if (!MaybeNext) {
1652
// FIXME this drops the error on the floor.
1653
consumeError(MaybeNext.takeError());
1654
return false;
1655
}
1656
Next = MaybeNext.get();
1657
continue;
1658
}
1659
1660
Scratch.clear();
1661
llvm::StringRef BlobData;
1662
llvm::Expected<unsigned> MaybeKind =
1663
Cursor.readRecord(Next.ID, Scratch, &BlobData);
1664
if (!MaybeKind) {
1665
// FIXME this drops the error on the floor.
1666
consumeError(MaybeKind.takeError());
1667
return false;
1668
}
1669
unsigned Kind = MaybeKind.get();
1670
switch (Kind) {
1671
case typedef_block::TYPEDEF_DATA: {
1672
// Already saw typedef table.
1673
if (TypedefTable)
1674
return true;
1675
1676
uint32_t tableOffset;
1677
typedef_block::TypedefDataLayout::readRecord(Scratch, tableOffset);
1678
auto base = reinterpret_cast<const uint8_t *>(BlobData.data());
1679
1680
TypedefTable.reset(SerializedTypedefTable::Create(
1681
base + tableOffset, base + sizeof(uint32_t), base));
1682
break;
1683
}
1684
1685
default:
1686
// Unknown record, possibly for use by a future version of the
1687
// module format.
1688
break;
1689
}
1690
1691
MaybeNext = Cursor.advance();
1692
if (!MaybeNext) {
1693
// FIXME this drops the error on the floor.
1694
consumeError(MaybeNext.takeError());
1695
return false;
1696
}
1697
Next = MaybeNext.get();
1698
}
1699
1700
return false;
1701
}
1702
1703
APINotesReader::APINotesReader(llvm::MemoryBuffer *InputBuffer,
1704
llvm::VersionTuple SwiftVersion, bool &Failed)
1705
: Implementation(new class Implementation) {
1706
Failed = false;
1707
1708
// Initialize the input buffer.
1709
Implementation->InputBuffer = InputBuffer;
1710
Implementation->SwiftVersion = SwiftVersion;
1711
llvm::BitstreamCursor Cursor(*Implementation->InputBuffer);
1712
1713
// Validate signature.
1714
for (auto byte : API_NOTES_SIGNATURE) {
1715
if (Cursor.AtEndOfStream()) {
1716
Failed = true;
1717
return;
1718
}
1719
if (llvm::Expected<llvm::SimpleBitstreamCursor::word_t> maybeRead =
1720
Cursor.Read(8)) {
1721
if (maybeRead.get() != byte) {
1722
Failed = true;
1723
return;
1724
}
1725
} else {
1726
// FIXME this drops the error on the floor.
1727
consumeError(maybeRead.takeError());
1728
Failed = true;
1729
return;
1730
}
1731
}
1732
1733
// Look at all of the blocks.
1734
bool HasValidControlBlock = false;
1735
llvm::SmallVector<uint64_t, 64> Scratch;
1736
while (!Cursor.AtEndOfStream()) {
1737
llvm::Expected<llvm::BitstreamEntry> MaybeTopLevelEntry = Cursor.advance();
1738
if (!MaybeTopLevelEntry) {
1739
// FIXME this drops the error on the floor.
1740
consumeError(MaybeTopLevelEntry.takeError());
1741
Failed = true;
1742
return;
1743
}
1744
llvm::BitstreamEntry TopLevelEntry = MaybeTopLevelEntry.get();
1745
1746
if (TopLevelEntry.Kind != llvm::BitstreamEntry::SubBlock)
1747
break;
1748
1749
switch (TopLevelEntry.ID) {
1750
case llvm::bitc::BLOCKINFO_BLOCK_ID:
1751
if (!Cursor.ReadBlockInfoBlock()) {
1752
Failed = true;
1753
break;
1754
}
1755
break;
1756
1757
case CONTROL_BLOCK_ID:
1758
// Only allow a single control block.
1759
if (HasValidControlBlock ||
1760
Implementation->readControlBlock(Cursor, Scratch)) {
1761
Failed = true;
1762
return;
1763
}
1764
1765
HasValidControlBlock = true;
1766
break;
1767
1768
case IDENTIFIER_BLOCK_ID:
1769
if (!HasValidControlBlock ||
1770
Implementation->readIdentifierBlock(Cursor, Scratch)) {
1771
Failed = true;
1772
return;
1773
}
1774
break;
1775
1776
case OBJC_CONTEXT_BLOCK_ID:
1777
if (!HasValidControlBlock ||
1778
Implementation->readContextBlock(Cursor, Scratch)) {
1779
Failed = true;
1780
return;
1781
}
1782
1783
break;
1784
1785
case OBJC_PROPERTY_BLOCK_ID:
1786
if (!HasValidControlBlock ||
1787
Implementation->readObjCPropertyBlock(Cursor, Scratch)) {
1788
Failed = true;
1789
return;
1790
}
1791
break;
1792
1793
case OBJC_METHOD_BLOCK_ID:
1794
if (!HasValidControlBlock ||
1795
Implementation->readObjCMethodBlock(Cursor, Scratch)) {
1796
Failed = true;
1797
return;
1798
}
1799
break;
1800
1801
case CXX_METHOD_BLOCK_ID:
1802
if (!HasValidControlBlock ||
1803
Implementation->readCXXMethodBlock(Cursor, Scratch)) {
1804
Failed = true;
1805
return;
1806
}
1807
break;
1808
1809
case OBJC_SELECTOR_BLOCK_ID:
1810
if (!HasValidControlBlock ||
1811
Implementation->readObjCSelectorBlock(Cursor, Scratch)) {
1812
Failed = true;
1813
return;
1814
}
1815
break;
1816
1817
case GLOBAL_VARIABLE_BLOCK_ID:
1818
if (!HasValidControlBlock ||
1819
Implementation->readGlobalVariableBlock(Cursor, Scratch)) {
1820
Failed = true;
1821
return;
1822
}
1823
break;
1824
1825
case GLOBAL_FUNCTION_BLOCK_ID:
1826
if (!HasValidControlBlock ||
1827
Implementation->readGlobalFunctionBlock(Cursor, Scratch)) {
1828
Failed = true;
1829
return;
1830
}
1831
break;
1832
1833
case ENUM_CONSTANT_BLOCK_ID:
1834
if (!HasValidControlBlock ||
1835
Implementation->readEnumConstantBlock(Cursor, Scratch)) {
1836
Failed = true;
1837
return;
1838
}
1839
break;
1840
1841
case TAG_BLOCK_ID:
1842
if (!HasValidControlBlock ||
1843
Implementation->readTagBlock(Cursor, Scratch)) {
1844
Failed = true;
1845
return;
1846
}
1847
break;
1848
1849
case TYPEDEF_BLOCK_ID:
1850
if (!HasValidControlBlock ||
1851
Implementation->readTypedefBlock(Cursor, Scratch)) {
1852
Failed = true;
1853
return;
1854
}
1855
break;
1856
1857
default:
1858
// Unknown top-level block, possibly for use by a future version of the
1859
// module format.
1860
if (Cursor.SkipBlock()) {
1861
Failed = true;
1862
return;
1863
}
1864
break;
1865
}
1866
}
1867
1868
if (!Cursor.AtEndOfStream()) {
1869
Failed = true;
1870
return;
1871
}
1872
}
1873
1874
APINotesReader::~APINotesReader() { delete Implementation->InputBuffer; }
1875
1876
std::unique_ptr<APINotesReader>
1877
APINotesReader::Create(std::unique_ptr<llvm::MemoryBuffer> InputBuffer,
1878
llvm::VersionTuple SwiftVersion) {
1879
bool Failed = false;
1880
std::unique_ptr<APINotesReader> Reader(
1881
new APINotesReader(InputBuffer.release(), SwiftVersion, Failed));
1882
if (Failed)
1883
return nullptr;
1884
1885
return Reader;
1886
}
1887
1888
template <typename T>
1889
APINotesReader::VersionedInfo<T>::VersionedInfo(
1890
llvm::VersionTuple Version,
1891
llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1> R)
1892
: Results(std::move(R)) {
1893
1894
assert(!Results.empty());
1895
assert(std::is_sorted(
1896
Results.begin(), Results.end(),
1897
[](const std::pair<llvm::VersionTuple, T> &left,
1898
const std::pair<llvm::VersionTuple, T> &right) -> bool {
1899
assert(left.first != right.first && "two entries for the same version");
1900
return left.first < right.first;
1901
}));
1902
1903
Selected = std::nullopt;
1904
for (unsigned i = 0, n = Results.size(); i != n; ++i) {
1905
if (!Version.empty() && Results[i].first >= Version) {
1906
// If the current version is "4", then entries for 4 are better than
1907
// entries for 5, but both are valid. Because entries are sorted, we get
1908
// that behavior by picking the first match.
1909
Selected = i;
1910
break;
1911
}
1912
}
1913
1914
// If we didn't find a match but we have an unversioned result, use the
1915
// unversioned result. This will always be the first entry because we encode
1916
// it as version 0.
1917
if (!Selected && Results[0].first.empty())
1918
Selected = 0;
1919
}
1920
1921
auto APINotesReader::lookupObjCClassID(llvm::StringRef Name)
1922
-> std::optional<ContextID> {
1923
if (!Implementation->ContextIDTable)
1924
return std::nullopt;
1925
1926
std::optional<IdentifierID> ClassID = Implementation->getIdentifier(Name);
1927
if (!ClassID)
1928
return std::nullopt;
1929
1930
// ObjC classes can't be declared in C++ namespaces, so use -1 as the global
1931
// context.
1932
auto KnownID = Implementation->ContextIDTable->find(
1933
ContextTableKey(-1, (uint8_t)ContextKind::ObjCClass, *ClassID));
1934
if (KnownID == Implementation->ContextIDTable->end())
1935
return std::nullopt;
1936
1937
return ContextID(*KnownID);
1938
}
1939
1940
auto APINotesReader::lookupObjCClassInfo(llvm::StringRef Name)
1941
-> VersionedInfo<ContextInfo> {
1942
if (!Implementation->ContextInfoTable)
1943
return std::nullopt;
1944
1945
std::optional<ContextID> CtxID = lookupObjCClassID(Name);
1946
if (!CtxID)
1947
return std::nullopt;
1948
1949
auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
1950
if (KnownInfo == Implementation->ContextInfoTable->end())
1951
return std::nullopt;
1952
1953
return {Implementation->SwiftVersion, *KnownInfo};
1954
}
1955
1956
auto APINotesReader::lookupObjCProtocolID(llvm::StringRef Name)
1957
-> std::optional<ContextID> {
1958
if (!Implementation->ContextIDTable)
1959
return std::nullopt;
1960
1961
std::optional<IdentifierID> classID = Implementation->getIdentifier(Name);
1962
if (!classID)
1963
return std::nullopt;
1964
1965
// ObjC classes can't be declared in C++ namespaces, so use -1 as the global
1966
// context.
1967
auto KnownID = Implementation->ContextIDTable->find(
1968
ContextTableKey(-1, (uint8_t)ContextKind::ObjCProtocol, *classID));
1969
if (KnownID == Implementation->ContextIDTable->end())
1970
return std::nullopt;
1971
1972
return ContextID(*KnownID);
1973
}
1974
1975
auto APINotesReader::lookupObjCProtocolInfo(llvm::StringRef Name)
1976
-> VersionedInfo<ContextInfo> {
1977
if (!Implementation->ContextInfoTable)
1978
return std::nullopt;
1979
1980
std::optional<ContextID> CtxID = lookupObjCProtocolID(Name);
1981
if (!CtxID)
1982
return std::nullopt;
1983
1984
auto KnownInfo = Implementation->ContextInfoTable->find(CtxID->Value);
1985
if (KnownInfo == Implementation->ContextInfoTable->end())
1986
return std::nullopt;
1987
1988
return {Implementation->SwiftVersion, *KnownInfo};
1989
}
1990
1991
auto APINotesReader::lookupObjCProperty(ContextID CtxID, llvm::StringRef Name,
1992
bool IsInstance)
1993
-> VersionedInfo<ObjCPropertyInfo> {
1994
if (!Implementation->ObjCPropertyTable)
1995
return std::nullopt;
1996
1997
std::optional<IdentifierID> PropertyID = Implementation->getIdentifier(Name);
1998
if (!PropertyID)
1999
return std::nullopt;
2000
2001
auto Known = Implementation->ObjCPropertyTable->find(
2002
std::make_tuple(CtxID.Value, *PropertyID, (char)IsInstance));
2003
if (Known == Implementation->ObjCPropertyTable->end())
2004
return std::nullopt;
2005
2006
return {Implementation->SwiftVersion, *Known};
2007
}
2008
2009
auto APINotesReader::lookupObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
2010
bool IsInstanceMethod)
2011
-> VersionedInfo<ObjCMethodInfo> {
2012
if (!Implementation->ObjCMethodTable)
2013
return std::nullopt;
2014
2015
std::optional<SelectorID> SelID = Implementation->getSelector(Selector);
2016
if (!SelID)
2017
return std::nullopt;
2018
2019
auto Known = Implementation->ObjCMethodTable->find(
2020
ObjCMethodTableInfo::internal_key_type{CtxID.Value, *SelID,
2021
IsInstanceMethod});
2022
if (Known == Implementation->ObjCMethodTable->end())
2023
return std::nullopt;
2024
2025
return {Implementation->SwiftVersion, *Known};
2026
}
2027
2028
auto APINotesReader::lookupCXXMethod(ContextID CtxID, llvm::StringRef Name)
2029
-> VersionedInfo<CXXMethodInfo> {
2030
if (!Implementation->CXXMethodTable)
2031
return std::nullopt;
2032
2033
std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2034
if (!NameID)
2035
return std::nullopt;
2036
2037
auto Known = Implementation->CXXMethodTable->find(
2038
SingleDeclTableKey(CtxID.Value, *NameID));
2039
if (Known == Implementation->CXXMethodTable->end())
2040
return std::nullopt;
2041
2042
return {Implementation->SwiftVersion, *Known};
2043
}
2044
2045
auto APINotesReader::lookupGlobalVariable(llvm::StringRef Name,
2046
std::optional<Context> Ctx)
2047
-> VersionedInfo<GlobalVariableInfo> {
2048
if (!Implementation->GlobalVariableTable)
2049
return std::nullopt;
2050
2051
std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2052
if (!NameID)
2053
return std::nullopt;
2054
2055
SingleDeclTableKey Key(Ctx, *NameID);
2056
2057
auto Known = Implementation->GlobalVariableTable->find(Key);
2058
if (Known == Implementation->GlobalVariableTable->end())
2059
return std::nullopt;
2060
2061
return {Implementation->SwiftVersion, *Known};
2062
}
2063
2064
auto APINotesReader::lookupGlobalFunction(llvm::StringRef Name,
2065
std::optional<Context> Ctx)
2066
-> VersionedInfo<GlobalFunctionInfo> {
2067
if (!Implementation->GlobalFunctionTable)
2068
return std::nullopt;
2069
2070
std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2071
if (!NameID)
2072
return std::nullopt;
2073
2074
SingleDeclTableKey Key(Ctx, *NameID);
2075
2076
auto Known = Implementation->GlobalFunctionTable->find(Key);
2077
if (Known == Implementation->GlobalFunctionTable->end())
2078
return std::nullopt;
2079
2080
return {Implementation->SwiftVersion, *Known};
2081
}
2082
2083
auto APINotesReader::lookupEnumConstant(llvm::StringRef Name)
2084
-> VersionedInfo<EnumConstantInfo> {
2085
if (!Implementation->EnumConstantTable)
2086
return std::nullopt;
2087
2088
std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2089
if (!NameID)
2090
return std::nullopt;
2091
2092
auto Known = Implementation->EnumConstantTable->find(*NameID);
2093
if (Known == Implementation->EnumConstantTable->end())
2094
return std::nullopt;
2095
2096
return {Implementation->SwiftVersion, *Known};
2097
}
2098
2099
auto APINotesReader::lookupTagID(llvm::StringRef Name,
2100
std::optional<Context> ParentCtx)
2101
-> std::optional<ContextID> {
2102
if (!Implementation->ContextIDTable)
2103
return std::nullopt;
2104
2105
std::optional<IdentifierID> TagID = Implementation->getIdentifier(Name);
2106
if (!TagID)
2107
return std::nullopt;
2108
2109
auto KnownID = Implementation->ContextIDTable->find(
2110
ContextTableKey(ParentCtx, ContextKind::Tag, *TagID));
2111
if (KnownID == Implementation->ContextIDTable->end())
2112
return std::nullopt;
2113
2114
return ContextID(*KnownID);
2115
}
2116
2117
auto APINotesReader::lookupTag(llvm::StringRef Name, std::optional<Context> Ctx)
2118
-> VersionedInfo<TagInfo> {
2119
if (!Implementation->TagTable)
2120
return std::nullopt;
2121
2122
std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2123
if (!NameID)
2124
return std::nullopt;
2125
2126
SingleDeclTableKey Key(Ctx, *NameID);
2127
2128
auto Known = Implementation->TagTable->find(Key);
2129
if (Known == Implementation->TagTable->end())
2130
return std::nullopt;
2131
2132
return {Implementation->SwiftVersion, *Known};
2133
}
2134
2135
auto APINotesReader::lookupTypedef(llvm::StringRef Name,
2136
std::optional<Context> Ctx)
2137
-> VersionedInfo<TypedefInfo> {
2138
if (!Implementation->TypedefTable)
2139
return std::nullopt;
2140
2141
std::optional<IdentifierID> NameID = Implementation->getIdentifier(Name);
2142
if (!NameID)
2143
return std::nullopt;
2144
2145
SingleDeclTableKey Key(Ctx, *NameID);
2146
2147
auto Known = Implementation->TypedefTable->find(Key);
2148
if (Known == Implementation->TypedefTable->end())
2149
return std::nullopt;
2150
2151
return {Implementation->SwiftVersion, *Known};
2152
}
2153
2154
auto APINotesReader::lookupNamespaceID(
2155
llvm::StringRef Name, std::optional<ContextID> ParentNamespaceID)
2156
-> std::optional<ContextID> {
2157
if (!Implementation->ContextIDTable)
2158
return std::nullopt;
2159
2160
std::optional<IdentifierID> NamespaceID = Implementation->getIdentifier(Name);
2161
if (!NamespaceID)
2162
return std::nullopt;
2163
2164
uint32_t RawParentNamespaceID =
2165
ParentNamespaceID ? ParentNamespaceID->Value : -1;
2166
auto KnownID = Implementation->ContextIDTable->find(
2167
{RawParentNamespaceID, (uint8_t)ContextKind::Namespace, *NamespaceID});
2168
if (KnownID == Implementation->ContextIDTable->end())
2169
return std::nullopt;
2170
2171
return ContextID(*KnownID);
2172
}
2173
2174
} // namespace api_notes
2175
} // namespace clang
2176
2177