Coverage Report

Created: 2024-01-17 10:31

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