Coverage Report

Created: 2024-01-17 10:31

/src/llvm-project/clang/lib/APINotes/APINotesWriter.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- APINotesWriter.cpp - API Notes Writer -------------------*- 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/APINotesWriter.h"
10
#include "APINotesFormat.h"
11
#include "clang/APINotes/Types.h"
12
#include "clang/Basic/FileManager.h"
13
#include "llvm/ADT/DenseMap.h"
14
#include "llvm/ADT/StringMap.h"
15
#include "llvm/Bitstream/BitstreamWriter.h"
16
#include "llvm/Support/DJB.h"
17
#include "llvm/Support/OnDiskHashTable.h"
18
#include "llvm/Support/VersionTuple.h"
19
20
namespace clang {
21
namespace api_notes {
22
class APINotesWriter::Implementation {
23
  friend class APINotesWriter;
24
25
  template <typename T>
26
  using VersionedSmallVector =
27
      llvm::SmallVector<std::pair<llvm::VersionTuple, T>, 1>;
28
29
  std::string ModuleName;
30
  const FileEntry *SourceFile;
31
32
  /// Scratch space for bitstream writing.
33
  llvm::SmallVector<uint64_t, 64> Scratch;
34
35
  /// Mapping from strings to identifier IDs.
36
  llvm::StringMap<IdentifierID> IdentifierIDs;
37
38
  /// Information about contexts (Objective-C classes or protocols or C++
39
  /// namespaces).
40
  ///
41
  /// Indexed by the parent context ID, context kind and the identifier ID of
42
  /// this context and provides both the context ID and information describing
43
  /// the context within that module.
44
  llvm::DenseMap<ContextTableKey,
45
                 std::pair<unsigned, VersionedSmallVector<ObjCContextInfo>>>
46
      ObjCContexts;
47
48
  /// Information about parent contexts for each context.
49
  ///
50
  /// Indexed by context ID, provides the parent context ID.
51
  llvm::DenseMap<uint32_t, uint32_t> ParentContexts;
52
53
  /// Mapping from context IDs to the identifier ID holding the name.
54
  llvm::DenseMap<unsigned, unsigned> ObjCContextNames;
55
56
  /// Information about Objective-C properties.
57
  ///
58
  /// Indexed by the context ID, property name, and whether this is an
59
  /// instance property.
60
  llvm::DenseMap<
61
      std::tuple<unsigned, unsigned, char>,
62
      llvm::SmallVector<std::pair<VersionTuple, ObjCPropertyInfo>, 1>>
63
      ObjCProperties;
64
65
  /// Information about Objective-C methods.
66
  ///
67
  /// Indexed by the context ID, selector ID, and Boolean (stored as a char)
68
  /// indicating whether this is a class or instance method.
69
  llvm::DenseMap<std::tuple<unsigned, unsigned, char>,
70
                 llvm::SmallVector<std::pair<VersionTuple, ObjCMethodInfo>, 1>>
71
      ObjCMethods;
72
73
  /// Mapping from selectors to selector ID.
74
  llvm::DenseMap<StoredObjCSelector, SelectorID> SelectorIDs;
75
76
  /// Information about global variables.
77
  ///
78
  /// Indexed by the context ID, contextKind, identifier ID.
79
  llvm::DenseMap<
80
      ContextTableKey,
81
      llvm::SmallVector<std::pair<VersionTuple, GlobalVariableInfo>, 1>>
82
      GlobalVariables;
83
84
  /// Information about global functions.
85
  ///
86
  /// Indexed by the context ID, contextKind, identifier ID.
87
  llvm::DenseMap<
88
      ContextTableKey,
89
      llvm::SmallVector<std::pair<VersionTuple, GlobalFunctionInfo>, 1>>
90
      GlobalFunctions;
91
92
  /// Information about enumerators.
93
  ///
94
  /// Indexed by the identifier ID.
95
  llvm::DenseMap<
96
      unsigned, llvm::SmallVector<std::pair<VersionTuple, EnumConstantInfo>, 1>>
97
      EnumConstants;
98
99
  /// Information about tags.
100
  ///
101
  /// Indexed by the context ID, contextKind, identifier ID.
102
  llvm::DenseMap<ContextTableKey,
103
                 llvm::SmallVector<std::pair<VersionTuple, TagInfo>, 1>>
104
      Tags;
105
106
  /// Information about typedefs.
107
  ///
108
  /// Indexed by the context ID, contextKind, identifier ID.
109
  llvm::DenseMap<ContextTableKey,
110
                 llvm::SmallVector<std::pair<VersionTuple, TypedefInfo>, 1>>
111
      Typedefs;
112
113
  /// Retrieve the ID for the given identifier.
114
0
  IdentifierID getIdentifier(StringRef Identifier) {
115
0
    if (Identifier.empty())
116
0
      return 0;
117
118
0
    auto Known = IdentifierIDs.find(Identifier);
119
0
    if (Known != IdentifierIDs.end())
120
0
      return Known->second;
121
122
    // Add to the identifier table.
123
0
    Known = IdentifierIDs.insert({Identifier, IdentifierIDs.size() + 1}).first;
124
0
    return Known->second;
125
0
  }
126
127
  /// Retrieve the ID for the given selector.
128
0
  SelectorID getSelector(ObjCSelectorRef SelectorRef) {
129
    // Translate the selector reference into a stored selector.
130
0
    StoredObjCSelector Selector;
131
0
    Selector.Identifiers.reserve(SelectorRef.Identifiers.size());
132
0
    for (auto piece : SelectorRef.Identifiers)
133
0
      Selector.Identifiers.push_back(getIdentifier(piece));
134
135
    // Look for the stored selector.
136
0
    auto Known = SelectorIDs.find(Selector);
137
0
    if (Known != SelectorIDs.end())
138
0
      return Known->second;
139
140
    // Add to the selector table.
141
0
    Known = SelectorIDs.insert({Selector, SelectorIDs.size()}).first;
142
0
    return Known->second;
143
0
  }
144
145
private:
146
  void writeBlockInfoBlock(llvm::BitstreamWriter &Stream);
147
  void writeControlBlock(llvm::BitstreamWriter &Stream);
148
  void writeIdentifierBlock(llvm::BitstreamWriter &Stream);
149
  void writeObjCContextBlock(llvm::BitstreamWriter &Stream);
150
  void writeObjCPropertyBlock(llvm::BitstreamWriter &Stream);
151
  void writeObjCMethodBlock(llvm::BitstreamWriter &Stream);
152
  void writeObjCSelectorBlock(llvm::BitstreamWriter &Stream);
153
  void writeGlobalVariableBlock(llvm::BitstreamWriter &Stream);
154
  void writeGlobalFunctionBlock(llvm::BitstreamWriter &Stream);
155
  void writeEnumConstantBlock(llvm::BitstreamWriter &Stream);
156
  void writeTagBlock(llvm::BitstreamWriter &Stream);
157
  void writeTypedefBlock(llvm::BitstreamWriter &Stream);
158
159
public:
160
  Implementation(llvm::StringRef ModuleName, const FileEntry *SF)
161
0
      : ModuleName(std::string(ModuleName)), SourceFile(SF) {}
162
163
  void writeToStream(llvm::raw_ostream &OS);
164
};
165
166
0
void APINotesWriter::Implementation::writeToStream(llvm::raw_ostream &OS) {
167
0
  llvm::SmallVector<char, 0> Buffer;
168
169
0
  {
170
0
    llvm::BitstreamWriter Stream(Buffer);
171
172
    // Emit the signature.
173
0
    for (unsigned char Byte : API_NOTES_SIGNATURE)
174
0
      Stream.Emit(Byte, 8);
175
176
    // Emit the blocks.
177
0
    writeBlockInfoBlock(Stream);
178
0
    writeControlBlock(Stream);
179
0
    writeIdentifierBlock(Stream);
180
0
    writeObjCContextBlock(Stream);
181
0
    writeObjCPropertyBlock(Stream);
182
0
    writeObjCMethodBlock(Stream);
183
0
    writeObjCSelectorBlock(Stream);
184
0
    writeGlobalVariableBlock(Stream);
185
0
    writeGlobalFunctionBlock(Stream);
186
0
    writeEnumConstantBlock(Stream);
187
0
    writeTagBlock(Stream);
188
0
    writeTypedefBlock(Stream);
189
0
  }
190
191
0
  OS.write(Buffer.data(), Buffer.size());
192
0
  OS.flush();
193
0
}
194
195
namespace {
196
/// Record the name of a block.
197
void emitBlockID(llvm::BitstreamWriter &Stream, unsigned ID,
198
0
                 llvm::StringRef Name) {
199
0
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETBID,
200
0
                    llvm::ArrayRef<unsigned>{ID});
201
202
  // Emit the block name if present.
203
0
  if (Name.empty())
204
0
    return;
205
0
  Stream.EmitRecord(
206
0
      llvm::bitc::BLOCKINFO_CODE_BLOCKNAME,
207
0
      llvm::ArrayRef<unsigned char>(
208
0
          const_cast<unsigned char *>(
209
0
              reinterpret_cast<const unsigned char *>(Name.data())),
210
0
          Name.size()));
211
0
}
212
213
/// Record the name of a record within a block.
214
void emitRecordID(llvm::BitstreamWriter &Stream, unsigned ID,
215
0
                  llvm::StringRef Name) {
216
0
  assert(ID < 256 && "can't fit record ID in next to name");
217
218
0
  llvm::SmallVector<unsigned char, 64> Buffer;
219
0
  Buffer.resize(Name.size() + 1);
220
0
  Buffer[0] = ID;
221
0
  memcpy(Buffer.data() + 1, Name.data(), Name.size());
222
223
0
  Stream.EmitRecord(llvm::bitc::BLOCKINFO_CODE_SETRECORDNAME, Buffer);
224
0
}
225
} // namespace
226
227
void APINotesWriter::Implementation::writeBlockInfoBlock(
228
0
    llvm::BitstreamWriter &Stream) {
229
0
  llvm::BCBlockRAII Scope(Stream, llvm::bitc::BLOCKINFO_BLOCK_ID, 2);
230
231
0
#define BLOCK(Block) emitBlockID(Stream, Block##_ID, #Block)
232
0
#define BLOCK_RECORD(NameSpace, Block)                                         \
233
0
  emitRecordID(Stream, NameSpace::Block, #Block)
234
0
  BLOCK(CONTROL_BLOCK);
235
0
  BLOCK_RECORD(control_block, METADATA);
236
0
  BLOCK_RECORD(control_block, MODULE_NAME);
237
238
0
  BLOCK(IDENTIFIER_BLOCK);
239
0
  BLOCK_RECORD(identifier_block, IDENTIFIER_DATA);
240
241
0
  BLOCK(OBJC_CONTEXT_BLOCK);
242
0
  BLOCK_RECORD(objc_context_block, OBJC_CONTEXT_ID_DATA);
243
244
0
  BLOCK(OBJC_PROPERTY_BLOCK);
245
0
  BLOCK_RECORD(objc_property_block, OBJC_PROPERTY_DATA);
246
247
0
  BLOCK(OBJC_METHOD_BLOCK);
248
0
  BLOCK_RECORD(objc_method_block, OBJC_METHOD_DATA);
249
250
0
  BLOCK(OBJC_SELECTOR_BLOCK);
251
0
  BLOCK_RECORD(objc_selector_block, OBJC_SELECTOR_DATA);
252
253
0
  BLOCK(GLOBAL_VARIABLE_BLOCK);
254
0
  BLOCK_RECORD(global_variable_block, GLOBAL_VARIABLE_DATA);
255
256
0
  BLOCK(GLOBAL_FUNCTION_BLOCK);
257
0
  BLOCK_RECORD(global_function_block, GLOBAL_FUNCTION_DATA);
258
0
#undef BLOCK_RECORD
259
0
#undef BLOCK
260
0
}
261
262
void APINotesWriter::Implementation::writeControlBlock(
263
0
    llvm::BitstreamWriter &Stream) {
264
0
  llvm::BCBlockRAII Scope(Stream, CONTROL_BLOCK_ID, 3);
265
266
0
  control_block::MetadataLayout Metadata(Stream);
267
0
  Metadata.emit(Scratch, VERSION_MAJOR, VERSION_MINOR);
268
269
0
  control_block::ModuleNameLayout ModuleName(Stream);
270
0
  ModuleName.emit(Scratch, this->ModuleName);
271
272
0
  if (SourceFile) {
273
0
    control_block::SourceFileLayout SourceFile(Stream);
274
0
    SourceFile.emit(Scratch, this->SourceFile->getSize(),
275
0
                    this->SourceFile->getModificationTime());
276
0
  }
277
0
}
278
279
namespace {
280
/// Used to serialize the on-disk identifier table.
281
class IdentifierTableInfo {
282
public:
283
  using key_type = StringRef;
284
  using key_type_ref = key_type;
285
  using data_type = IdentifierID;
286
  using data_type_ref = const data_type &;
287
  using hash_value_type = uint32_t;
288
  using offset_type = unsigned;
289
290
0
  hash_value_type ComputeHash(key_type_ref Key) { return llvm::djbHash(Key); }
291
292
  std::pair<unsigned, unsigned>
293
0
  EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
294
0
    uint32_t KeyLength = Key.size();
295
0
    uint32_t DataLength = sizeof(uint32_t);
296
297
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
298
0
    writer.write<uint16_t>(KeyLength);
299
0
    writer.write<uint16_t>(DataLength);
300
0
    return {KeyLength, DataLength};
301
0
  }
302
303
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) { OS << Key; }
304
305
0
  void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
306
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
307
0
    writer.write<uint32_t>(Data);
308
0
  }
309
};
310
} // namespace
311
312
void APINotesWriter::Implementation::writeIdentifierBlock(
313
0
    llvm::BitstreamWriter &Stream) {
314
0
  llvm::BCBlockRAII restoreBlock(Stream, IDENTIFIER_BLOCK_ID, 3);
315
316
0
  if (IdentifierIDs.empty())
317
0
    return;
318
319
0
  llvm::SmallString<4096> HashTableBlob;
320
0
  uint32_t Offset;
321
0
  {
322
0
    llvm::OnDiskChainedHashTableGenerator<IdentifierTableInfo> Generator;
323
0
    for (auto &II : IdentifierIDs)
324
0
      Generator.insert(II.first(), II.second);
325
326
0
    llvm::raw_svector_ostream BlobStream(HashTableBlob);
327
    // Make sure that no bucket is at offset 0
328
0
    llvm::support::endian::write<uint32_t>(BlobStream, 0,
329
0
                                           llvm::endianness::little);
330
0
    Offset = Generator.Emit(BlobStream);
331
0
  }
332
333
0
  identifier_block::IdentifierDataLayout IdentifierData(Stream);
334
0
  IdentifierData.emit(Scratch, Offset, HashTableBlob);
335
0
}
336
337
namespace {
338
/// Used to serialize the on-disk Objective-C context table.
339
class ObjCContextIDTableInfo {
340
public:
341
  using key_type = ContextTableKey;
342
  using key_type_ref = key_type;
343
  using data_type = unsigned;
344
  using data_type_ref = const data_type &;
345
  using hash_value_type = size_t;
346
  using offset_type = unsigned;
347
348
0
  hash_value_type ComputeHash(key_type_ref Key) {
349
0
    return static_cast<size_t>(Key.hashValue());
350
0
  }
351
352
  std::pair<unsigned, unsigned> EmitKeyDataLength(raw_ostream &OS, key_type_ref,
353
0
                                                  data_type_ref) {
354
0
    uint32_t KeyLength = sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
355
0
    uint32_t DataLength = sizeof(uint32_t);
356
357
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
358
0
    writer.write<uint16_t>(KeyLength);
359
0
    writer.write<uint16_t>(DataLength);
360
0
    return {KeyLength, DataLength};
361
0
  }
362
363
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
364
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
365
0
    writer.write<uint32_t>(Key.parentContextID);
366
0
    writer.write<uint8_t>(Key.contextKind);
367
0
    writer.write<uint32_t>(Key.contextID);
368
0
  }
369
370
0
  void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
371
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
372
0
    writer.write<uint32_t>(Data);
373
0
  }
374
};
375
376
/// Localized helper to make a type dependent, thwarting template argument
377
/// deduction.
378
template <typename T> struct MakeDependent { typedef T Type; };
379
380
/// Retrieve the serialized size of the given VersionTuple, for use in
381
/// on-disk hash tables.
382
0
unsigned getVersionTupleSize(const VersionTuple &VT) {
383
0
  unsigned size = sizeof(uint8_t) + /*major*/ sizeof(uint32_t);
384
0
  if (VT.getMinor())
385
0
    size += sizeof(uint32_t);
386
0
  if (VT.getSubminor())
387
0
    size += sizeof(uint32_t);
388
0
  if (VT.getBuild())
389
0
    size += sizeof(uint32_t);
390
0
  return size;
391
0
}
392
393
/// Determine the size of an array of versioned information,
394
template <typename T>
395
unsigned getVersionedInfoSize(
396
    const llvm::SmallVectorImpl<std::pair<llvm::VersionTuple, T>> &VI,
397
    llvm::function_ref<unsigned(const typename MakeDependent<T>::Type &)>
398
0
        getInfoSize) {
399
0
  unsigned result = sizeof(uint16_t); // # of elements
400
0
  for (const auto &E : VI) {
401
0
    result += getVersionTupleSize(E.first);
402
0
    result += getInfoSize(E.second);
403
0
  }
404
0
  return result;
405
0
}
Unexecuted instantiation: APINotesWriter.cpp:unsigned int clang::api_notes::(anonymous namespace)::getVersionedInfoSize<clang::api_notes::ObjCContextInfo>(llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo> > const&, llvm::function_ref<unsigned int (clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCContextInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:unsigned int clang::api_notes::(anonymous namespace)::getVersionedInfoSize<clang::api_notes::ObjCPropertyInfo>(llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo> > const&, llvm::function_ref<unsigned int (clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCPropertyInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:unsigned int clang::api_notes::(anonymous namespace)::getVersionedInfoSize<clang::api_notes::ObjCMethodInfo>(llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo> > const&, llvm::function_ref<unsigned int (clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCMethodInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:unsigned int clang::api_notes::(anonymous namespace)::getVersionedInfoSize<clang::api_notes::GlobalVariableInfo>(llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo> > const&, llvm::function_ref<unsigned int (clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::GlobalVariableInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:unsigned int clang::api_notes::(anonymous namespace)::getVersionedInfoSize<clang::api_notes::GlobalFunctionInfo>(llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo> > const&, llvm::function_ref<unsigned int (clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::GlobalFunctionInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:unsigned int clang::api_notes::(anonymous namespace)::getVersionedInfoSize<clang::api_notes::EnumConstantInfo>(llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo> > const&, llvm::function_ref<unsigned int (clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::EnumConstantInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:unsigned int clang::api_notes::(anonymous namespace)::getVersionedInfoSize<clang::api_notes::TagInfo>(llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo> > const&, llvm::function_ref<unsigned int (clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::TagInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:unsigned int clang::api_notes::(anonymous namespace)::getVersionedInfoSize<clang::api_notes::TypedefInfo>(llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo> > const&, llvm::function_ref<unsigned int (clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::TypedefInfo>::Type const&)>)
406
407
/// Emit a serialized representation of a version tuple.
408
0
void emitVersionTuple(raw_ostream &OS, const VersionTuple &VT) {
409
0
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
410
411
  // First byte contains the number of components beyond the 'major' component.
412
0
  uint8_t descriptor;
413
0
  if (VT.getBuild())
414
0
    descriptor = 3;
415
0
  else if (VT.getSubminor())
416
0
    descriptor = 2;
417
0
  else if (VT.getMinor())
418
0
    descriptor = 1;
419
0
  else
420
0
    descriptor = 0;
421
0
  writer.write<uint8_t>(descriptor);
422
423
  // Write the components.
424
0
  writer.write<uint32_t>(VT.getMajor());
425
0
  if (auto minor = VT.getMinor())
426
0
    writer.write<uint32_t>(*minor);
427
0
  if (auto subminor = VT.getSubminor())
428
0
    writer.write<uint32_t>(*subminor);
429
0
  if (auto build = VT.getBuild())
430
0
    writer.write<uint32_t>(*build);
431
0
}
432
433
/// Emit versioned information.
434
template <typename T>
435
void emitVersionedInfo(
436
    raw_ostream &OS, llvm::SmallVectorImpl<std::pair<VersionTuple, T>> &VI,
437
    llvm::function_ref<void(raw_ostream &,
438
                            const typename MakeDependent<T>::Type &)>
439
0
        emitInfo) {
440
0
  std::sort(VI.begin(), VI.end(),
441
0
            [](const std::pair<VersionTuple, T> &LHS,
442
0
               const std::pair<VersionTuple, T> &RHS) -> bool {
443
0
              assert(LHS.first != RHS.first &&
444
0
                     "two entries for the same version");
445
0
              return LHS.first < RHS.first;
446
0
            });
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::ObjCContextInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCContextInfo>::Type const&)>)::{lambda(std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo> const&)#1}::operator()(std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo> const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::ObjCPropertyInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCPropertyInfo>::Type const&)>)::{lambda(std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo> const&)#1}::operator()(std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo> const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::ObjCMethodInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCMethodInfo>::Type const&)>)::{lambda(std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo> const&)#1}::operator()(std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo> const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::GlobalVariableInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::GlobalVariableInfo>::Type const&)>)::{lambda(std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo> const&)#1}::operator()(std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo> const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::GlobalFunctionInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::GlobalFunctionInfo>::Type const&)>)::{lambda(std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo> const&)#1}::operator()(std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo> const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::EnumConstantInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::EnumConstantInfo>::Type const&)>)::{lambda(std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo> const&)#1}::operator()(std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo> const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::TagInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::TagInfo>::Type const&)>)::{lambda(std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo> const&)#1}::operator()(std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo> const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::TypedefInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::TypedefInfo>::Type const&)>)::{lambda(std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo> const&)#1}::operator()(std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo> const&, std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo> const&) const
447
448
0
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
449
0
  writer.write<uint16_t>(VI.size());
450
0
  for (const auto &E : VI) {
451
0
    emitVersionTuple(OS, E.first);
452
0
    emitInfo(OS, E.second);
453
0
  }
454
0
}
Unexecuted instantiation: APINotesWriter.cpp:void clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::ObjCContextInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCContextInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:void clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::ObjCPropertyInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCPropertyInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:void clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::ObjCMethodInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::ObjCMethodInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:void clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::GlobalVariableInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::GlobalVariableInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:void clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::GlobalFunctionInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::GlobalFunctionInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:void clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::EnumConstantInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::EnumConstantInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:void clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::TagInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::TagInfo>::Type const&)>)
Unexecuted instantiation: APINotesWriter.cpp:void clang::api_notes::(anonymous namespace)::emitVersionedInfo<clang::api_notes::TypedefInfo>(llvm::raw_ostream&, llvm::SmallVectorImpl<std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo> >&, llvm::function_ref<void (llvm::raw_ostream&, clang::api_notes::(anonymous namespace)::MakeDependent<clang::api_notes::TypedefInfo>::Type const&)>)
455
456
/// On-disk hash table info key base for handling versioned data.
457
template <typename Derived, typename KeyType, typename UnversionedDataType>
458
class VersionedTableInfo {
459
0
  Derived &asDerived() { return *static_cast<Derived *>(this); }
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCContextInfoTableInfo, unsigned int, clang::api_notes::ObjCContextInfo>::asDerived()
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCPropertyTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCPropertyInfo>::asDerived()
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCMethodTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCMethodInfo>::asDerived()
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalVariableTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalVariableInfo>::asDerived()
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalFunctionTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalFunctionInfo>::asDerived()
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::EnumConstantTableInfo, unsigned int, clang::api_notes::EnumConstantInfo>::asDerived()
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TagTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TagInfo>::asDerived()
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TypedefTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TypedefInfo>::asDerived()
460
461
  const Derived &asDerived() const {
462
    return *static_cast<const Derived *>(this);
463
  }
464
465
public:
466
  using key_type = KeyType;
467
  using key_type_ref = key_type;
468
  using data_type =
469
      llvm::SmallVector<std::pair<llvm::VersionTuple, UnversionedDataType>, 1>;
470
  using data_type_ref = data_type &;
471
  using hash_value_type = size_t;
472
  using offset_type = unsigned;
473
474
  std::pair<unsigned, unsigned>
475
0
  EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref Data) {
476
0
    uint32_t KeyLength = asDerived().getKeyLength(Key);
477
0
    uint32_t DataLength =
478
0
        getVersionedInfoSize(Data, [this](const UnversionedDataType &UI) {
479
0
          return asDerived().getUnversionedInfoSize(UI);
480
0
        });
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCContextInfoTableInfo, unsigned int, clang::api_notes::ObjCContextInfo>::EmitKeyDataLength(llvm::raw_ostream&, unsigned int, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo>, 1u>&)::{lambda(clang::api_notes::ObjCContextInfo const&)#1}::operator()(clang::api_notes::ObjCContextInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCPropertyTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCPropertyInfo>::EmitKeyDataLength(llvm::raw_ostream&, std::__1::tuple<unsigned int, unsigned int, char>, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo>, 1u>&)::{lambda(clang::api_notes::ObjCPropertyInfo const&)#1}::operator()(clang::api_notes::ObjCPropertyInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCMethodTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCMethodInfo>::EmitKeyDataLength(llvm::raw_ostream&, std::__1::tuple<unsigned int, unsigned int, char>, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo>, 1u>&)::{lambda(clang::api_notes::ObjCMethodInfo const&)#1}::operator()(clang::api_notes::ObjCMethodInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalVariableTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalVariableInfo>::EmitKeyDataLength(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo>, 1u>&)::{lambda(clang::api_notes::GlobalVariableInfo const&)#1}::operator()(clang::api_notes::GlobalVariableInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalFunctionTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalFunctionInfo>::EmitKeyDataLength(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo>, 1u>&)::{lambda(clang::api_notes::GlobalFunctionInfo const&)#1}::operator()(clang::api_notes::GlobalFunctionInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::EnumConstantTableInfo, unsigned int, clang::api_notes::EnumConstantInfo>::EmitKeyDataLength(llvm::raw_ostream&, unsigned int, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo>, 1u>&)::{lambda(clang::api_notes::EnumConstantInfo const&)#1}::operator()(clang::api_notes::EnumConstantInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TagTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TagInfo>::EmitKeyDataLength(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo>, 1u>&)::{lambda(clang::api_notes::TagInfo const&)#1}::operator()(clang::api_notes::TagInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TypedefTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TypedefInfo>::EmitKeyDataLength(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo>, 1u>&)::{lambda(clang::api_notes::TypedefInfo const&)#1}::operator()(clang::api_notes::TypedefInfo const&) const
481
482
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
483
0
    writer.write<uint16_t>(KeyLength);
484
0
    writer.write<uint16_t>(DataLength);
485
0
    return {KeyLength, DataLength};
486
0
  }
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCContextInfoTableInfo, unsigned int, clang::api_notes::ObjCContextInfo>::EmitKeyDataLength(llvm::raw_ostream&, unsigned int, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo>, 1u>&)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCPropertyTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCPropertyInfo>::EmitKeyDataLength(llvm::raw_ostream&, std::__1::tuple<unsigned int, unsigned int, char>, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo>, 1u>&)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCMethodTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCMethodInfo>::EmitKeyDataLength(llvm::raw_ostream&, std::__1::tuple<unsigned int, unsigned int, char>, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo>, 1u>&)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalVariableTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalVariableInfo>::EmitKeyDataLength(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo>, 1u>&)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalFunctionTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalFunctionInfo>::EmitKeyDataLength(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo>, 1u>&)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::EnumConstantTableInfo, unsigned int, clang::api_notes::EnumConstantInfo>::EmitKeyDataLength(llvm::raw_ostream&, unsigned int, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo>, 1u>&)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TagTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TagInfo>::EmitKeyDataLength(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo>, 1u>&)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TypedefTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TypedefInfo>::EmitKeyDataLength(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo>, 1u>&)
487
488
0
  void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
489
0
    emitVersionedInfo(
490
0
        OS, Data, [this](llvm::raw_ostream &OS, const UnversionedDataType &UI) {
491
0
          asDerived().emitUnversionedInfo(OS, UI);
492
0
        });
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCContextInfoTableInfo, unsigned int, clang::api_notes::ObjCContextInfo>::EmitData(llvm::raw_ostream&, unsigned int, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo>, 1u>&, unsigned int)::{lambda(llvm::raw_ostream&, clang::api_notes::ObjCContextInfo const&)#1}::operator()(llvm::raw_ostream&, clang::api_notes::ObjCContextInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCPropertyTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCPropertyInfo>::EmitData(llvm::raw_ostream&, std::__1::tuple<unsigned int, unsigned int, char>, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo>, 1u>&, unsigned int)::{lambda(llvm::raw_ostream&, clang::api_notes::ObjCPropertyInfo const&)#1}::operator()(llvm::raw_ostream&, clang::api_notes::ObjCPropertyInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCMethodTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCMethodInfo>::EmitData(llvm::raw_ostream&, std::__1::tuple<unsigned int, unsigned int, char>, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo>, 1u>&, unsigned int)::{lambda(llvm::raw_ostream&, clang::api_notes::ObjCMethodInfo const&)#1}::operator()(llvm::raw_ostream&, clang::api_notes::ObjCMethodInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalVariableTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalVariableInfo>::EmitData(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo>, 1u>&, unsigned int)::{lambda(llvm::raw_ostream&, clang::api_notes::GlobalVariableInfo const&)#1}::operator()(llvm::raw_ostream&, clang::api_notes::GlobalVariableInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalFunctionTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalFunctionInfo>::EmitData(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo>, 1u>&, unsigned int)::{lambda(llvm::raw_ostream&, clang::api_notes::GlobalFunctionInfo const&)#1}::operator()(llvm::raw_ostream&, clang::api_notes::GlobalFunctionInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::EnumConstantTableInfo, unsigned int, clang::api_notes::EnumConstantInfo>::EmitData(llvm::raw_ostream&, unsigned int, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo>, 1u>&, unsigned int)::{lambda(llvm::raw_ostream&, clang::api_notes::EnumConstantInfo const&)#1}::operator()(llvm::raw_ostream&, clang::api_notes::EnumConstantInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TagTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TagInfo>::EmitData(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo>, 1u>&, unsigned int)::{lambda(llvm::raw_ostream&, clang::api_notes::TagInfo const&)#1}::operator()(llvm::raw_ostream&, clang::api_notes::TagInfo const&) const
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TypedefTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TypedefInfo>::EmitData(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo>, 1u>&, unsigned int)::{lambda(llvm::raw_ostream&, clang::api_notes::TypedefInfo const&)#1}::operator()(llvm::raw_ostream&, clang::api_notes::TypedefInfo const&) const
493
0
  }
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCContextInfoTableInfo, unsigned int, clang::api_notes::ObjCContextInfo>::EmitData(llvm::raw_ostream&, unsigned int, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCContextInfo>, 1u>&, unsigned int)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCPropertyTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCPropertyInfo>::EmitData(llvm::raw_ostream&, std::__1::tuple<unsigned int, unsigned int, char>, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCPropertyInfo>, 1u>&, unsigned int)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::ObjCMethodTableInfo, std::__1::tuple<unsigned int, unsigned int, char>, clang::api_notes::ObjCMethodInfo>::EmitData(llvm::raw_ostream&, std::__1::tuple<unsigned int, unsigned int, char>, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::ObjCMethodInfo>, 1u>&, unsigned int)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalVariableTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalVariableInfo>::EmitData(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalVariableInfo>, 1u>&, unsigned int)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::GlobalFunctionTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::GlobalFunctionInfo>::EmitData(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::GlobalFunctionInfo>, 1u>&, unsigned int)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::EnumConstantTableInfo, unsigned int, clang::api_notes::EnumConstantInfo>::EmitData(llvm::raw_ostream&, unsigned int, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::EnumConstantInfo>, 1u>&, unsigned int)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TagTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TagInfo>::EmitData(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::TagInfo>, 1u>&, unsigned int)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::VersionedTableInfo<clang::api_notes::(anonymous namespace)::TypedefTableInfo, clang::api_notes::ContextTableKey, clang::api_notes::TypedefInfo>::EmitData(llvm::raw_ostream&, clang::api_notes::ContextTableKey, llvm::SmallVector<std::__1::pair<llvm::VersionTuple, clang::api_notes::TypedefInfo>, 1u>&, unsigned int)
494
};
495
496
/// Emit a serialized representation of the common entity information.
497
0
void emitCommonEntityInfo(raw_ostream &OS, const CommonEntityInfo &CEI) {
498
0
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
499
500
0
  uint8_t payload = 0;
501
0
  if (auto swiftPrivate = CEI.isSwiftPrivate()) {
502
0
    payload |= 0x01;
503
0
    if (*swiftPrivate)
504
0
      payload |= 0x02;
505
0
  }
506
0
  payload <<= 1;
507
0
  payload |= CEI.Unavailable;
508
0
  payload <<= 1;
509
0
  payload |= CEI.UnavailableInSwift;
510
511
0
  writer.write<uint8_t>(payload);
512
513
0
  writer.write<uint16_t>(CEI.UnavailableMsg.size());
514
0
  OS.write(CEI.UnavailableMsg.c_str(), CEI.UnavailableMsg.size());
515
516
0
  writer.write<uint16_t>(CEI.SwiftName.size());
517
0
  OS.write(CEI.SwiftName.c_str(), CEI.SwiftName.size());
518
0
}
519
520
/// Retrieve the serialized size of the given CommonEntityInfo, for use in
521
/// on-disk hash tables.
522
0
unsigned getCommonEntityInfoSize(const CommonEntityInfo &CEI) {
523
0
  return 5 + CEI.UnavailableMsg.size() + CEI.SwiftName.size();
524
0
}
525
526
// Retrieve the serialized size of the given CommonTypeInfo, for use
527
// in on-disk hash tables.
528
0
unsigned getCommonTypeInfoSize(const CommonTypeInfo &CTI) {
529
0
  return 2 + (CTI.getSwiftBridge() ? CTI.getSwiftBridge()->size() : 0) + 2 +
530
0
         (CTI.getNSErrorDomain() ? CTI.getNSErrorDomain()->size() : 0) +
531
0
         getCommonEntityInfoSize(CTI);
532
0
}
533
534
/// Emit a serialized representation of the common type information.
535
0
void emitCommonTypeInfo(raw_ostream &OS, const CommonTypeInfo &CTI) {
536
0
  emitCommonEntityInfo(OS, CTI);
537
538
0
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
539
0
  if (auto swiftBridge = CTI.getSwiftBridge()) {
540
0
    writer.write<uint16_t>(swiftBridge->size() + 1);
541
0
    OS.write(swiftBridge->c_str(), swiftBridge->size());
542
0
  } else {
543
0
    writer.write<uint16_t>(0);
544
0
  }
545
0
  if (auto nsErrorDomain = CTI.getNSErrorDomain()) {
546
0
    writer.write<uint16_t>(nsErrorDomain->size() + 1);
547
0
    OS.write(nsErrorDomain->c_str(), CTI.getNSErrorDomain()->size());
548
0
  } else {
549
0
    writer.write<uint16_t>(0);
550
0
  }
551
0
}
552
553
/// Used to serialize the on-disk Objective-C property table.
554
class ObjCContextInfoTableInfo
555
    : public VersionedTableInfo<ObjCContextInfoTableInfo, unsigned,
556
                                ObjCContextInfo> {
557
public:
558
0
  unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }
559
560
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
561
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
562
0
    writer.write<uint32_t>(Key);
563
0
  }
564
565
0
  hash_value_type ComputeHash(key_type_ref Key) {
566
0
    return static_cast<size_t>(llvm::hash_value(Key));
567
0
  }
568
569
0
  unsigned getUnversionedInfoSize(const ObjCContextInfo &OCI) {
570
0
    return getCommonTypeInfoSize(OCI) + 1;
571
0
  }
572
573
0
  void emitUnversionedInfo(raw_ostream &OS, const ObjCContextInfo &OCI) {
574
0
    emitCommonTypeInfo(OS, OCI);
575
576
0
    uint8_t payload = 0;
577
0
    if (auto swiftImportAsNonGeneric = OCI.getSwiftImportAsNonGeneric())
578
0
      payload |= (0x01 << 1) | (uint8_t)swiftImportAsNonGeneric.value();
579
0
    payload <<= 2;
580
0
    if (auto swiftObjCMembers = OCI.getSwiftObjCMembers())
581
0
      payload |= (0x01 << 1) | (uint8_t)swiftObjCMembers.value();
582
0
    payload <<= 3;
583
0
    if (auto nullable = OCI.getDefaultNullability())
584
0
      payload |= (0x01 << 2) | static_cast<uint8_t>(*nullable);
585
0
    payload = (payload << 1) | (OCI.hasDesignatedInits() ? 1 : 0);
586
587
0
    OS << payload;
588
0
  }
589
};
590
} // namespace
591
592
void APINotesWriter::Implementation::writeObjCContextBlock(
593
0
    llvm::BitstreamWriter &Stream) {
594
0
  llvm::BCBlockRAII restoreBlock(Stream, OBJC_CONTEXT_BLOCK_ID, 3);
595
596
0
  if (ObjCContexts.empty())
597
0
    return;
598
599
0
  {
600
0
    llvm::SmallString<4096> HashTableBlob;
601
0
    uint32_t Offset;
602
0
    {
603
0
      llvm::OnDiskChainedHashTableGenerator<ObjCContextIDTableInfo> Generator;
604
0
      for (auto &OC : ObjCContexts)
605
0
        Generator.insert(OC.first, OC.second.first);
606
607
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
608
      // Make sure that no bucket is at offset 0
609
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
610
0
                                             llvm::endianness::little);
611
0
      Offset = Generator.Emit(BlobStream);
612
0
    }
613
614
0
    objc_context_block::ObjCContextIDLayout ObjCContextID(Stream);
615
0
    ObjCContextID.emit(Scratch, Offset, HashTableBlob);
616
0
  }
617
618
0
  {
619
0
    llvm::SmallString<4096> HashTableBlob;
620
0
    uint32_t Offset;
621
0
    {
622
0
      llvm::OnDiskChainedHashTableGenerator<ObjCContextInfoTableInfo> Generator;
623
0
      for (auto &OC : ObjCContexts)
624
0
        Generator.insert(OC.second.first, OC.second.second);
625
626
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
627
      // Make sure that no bucket is at offset 0
628
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
629
0
                                             llvm::endianness::little);
630
0
      Offset = Generator.Emit(BlobStream);
631
0
    }
632
633
0
    objc_context_block::ObjCContextInfoLayout ObjCContextInfo(Stream);
634
0
    ObjCContextInfo.emit(Scratch, Offset, HashTableBlob);
635
0
  }
636
0
}
637
638
namespace {
639
/// Retrieve the serialized size of the given VariableInfo, for use in
640
/// on-disk hash tables.
641
0
unsigned getVariableInfoSize(const VariableInfo &VI) {
642
0
  return 2 + getCommonEntityInfoSize(VI) + 2 + VI.getType().size();
643
0
}
644
645
/// Emit a serialized representation of the variable information.
646
0
void emitVariableInfo(raw_ostream &OS, const VariableInfo &VI) {
647
0
  emitCommonEntityInfo(OS, VI);
648
649
0
  uint8_t bytes[2] = {0, 0};
650
0
  if (auto nullable = VI.getNullability()) {
651
0
    bytes[0] = 1;
652
0
    bytes[1] = static_cast<uint8_t>(*nullable);
653
0
  } else {
654
    // Nothing to do.
655
0
  }
656
657
0
  OS.write(reinterpret_cast<const char *>(bytes), 2);
658
659
0
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
660
0
  writer.write<uint16_t>(VI.getType().size());
661
0
  OS.write(VI.getType().data(), VI.getType().size());
662
0
}
663
664
/// Used to serialize the on-disk Objective-C property table.
665
class ObjCPropertyTableInfo
666
    : public VersionedTableInfo<ObjCPropertyTableInfo,
667
                                std::tuple<unsigned, unsigned, char>,
668
                                ObjCPropertyInfo> {
669
public:
670
0
  unsigned getKeyLength(key_type_ref) {
671
0
    return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t);
672
0
  }
673
674
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
675
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
676
0
    writer.write<uint32_t>(std::get<0>(Key));
677
0
    writer.write<uint32_t>(std::get<1>(Key));
678
0
    writer.write<uint8_t>(std::get<2>(Key));
679
0
  }
680
681
0
  hash_value_type ComputeHash(key_type_ref Key) {
682
0
    return static_cast<size_t>(llvm::hash_value(Key));
683
0
  }
684
685
0
  unsigned getUnversionedInfoSize(const ObjCPropertyInfo &OPI) {
686
0
    return getVariableInfoSize(OPI) + 1;
687
0
  }
688
689
0
  void emitUnversionedInfo(raw_ostream &OS, const ObjCPropertyInfo &OPI) {
690
0
    emitVariableInfo(OS, OPI);
691
692
0
    uint8_t flags = 0;
693
0
    if (auto value = OPI.getSwiftImportAsAccessors()) {
694
0
      flags |= 1 << 0;
695
0
      flags |= value.value() << 1;
696
0
    }
697
0
    OS << flags;
698
0
  }
699
};
700
} // namespace
701
702
void APINotesWriter::Implementation::writeObjCPropertyBlock(
703
0
    llvm::BitstreamWriter &Stream) {
704
0
  llvm::BCBlockRAII Scope(Stream, OBJC_PROPERTY_BLOCK_ID, 3);
705
706
0
  if (ObjCProperties.empty())
707
0
    return;
708
709
0
  {
710
0
    llvm::SmallString<4096> HashTableBlob;
711
0
    uint32_t Offset;
712
0
    {
713
0
      llvm::OnDiskChainedHashTableGenerator<ObjCPropertyTableInfo> Generator;
714
0
      for (auto &OP : ObjCProperties)
715
0
        Generator.insert(OP.first, OP.second);
716
717
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
718
      // Make sure that no bucket is at offset 0
719
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
720
0
                                             llvm::endianness::little);
721
0
      Offset = Generator.Emit(BlobStream);
722
0
    }
723
724
0
    objc_property_block::ObjCPropertyDataLayout ObjCPropertyData(Stream);
725
0
    ObjCPropertyData.emit(Scratch, Offset, HashTableBlob);
726
0
  }
727
0
}
728
729
namespace {
730
unsigned getFunctionInfoSize(const FunctionInfo &);
731
void emitFunctionInfo(llvm::raw_ostream &, const FunctionInfo &);
732
733
/// Used to serialize the on-disk Objective-C method table.
734
class ObjCMethodTableInfo
735
    : public VersionedTableInfo<ObjCMethodTableInfo,
736
                                std::tuple<unsigned, unsigned, char>,
737
                                ObjCMethodInfo> {
738
public:
739
0
  unsigned getKeyLength(key_type_ref) {
740
0
    return sizeof(uint32_t) + sizeof(uint32_t) + sizeof(uint8_t);
741
0
  }
742
743
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
744
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
745
0
    writer.write<uint32_t>(std::get<0>(Key));
746
0
    writer.write<uint32_t>(std::get<1>(Key));
747
0
    writer.write<uint8_t>(std::get<2>(Key));
748
0
  }
749
750
0
  hash_value_type ComputeHash(key_type_ref key) {
751
0
    return static_cast<size_t>(llvm::hash_value(key));
752
0
  }
753
754
0
  unsigned getUnversionedInfoSize(const ObjCMethodInfo &OMI) {
755
0
    return getFunctionInfoSize(OMI) + 1;
756
0
  }
757
758
0
  void emitUnversionedInfo(raw_ostream &OS, const ObjCMethodInfo &OMI) {
759
0
    uint8_t flags = 0;
760
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
761
0
    flags = (flags << 1) | OMI.DesignatedInit;
762
0
    flags = (flags << 1) | OMI.RequiredInit;
763
0
    writer.write<uint8_t>(flags);
764
765
0
    emitFunctionInfo(OS, OMI);
766
0
  }
767
};
768
} // namespace
769
770
void APINotesWriter::Implementation::writeObjCMethodBlock(
771
0
    llvm::BitstreamWriter &Stream) {
772
0
  llvm::BCBlockRAII Scope(Stream, OBJC_METHOD_BLOCK_ID, 3);
773
774
0
  if (ObjCMethods.empty())
775
0
    return;
776
777
0
  {
778
0
    llvm::SmallString<4096> HashTableBlob;
779
0
    uint32_t Offset;
780
0
    {
781
0
      llvm::OnDiskChainedHashTableGenerator<ObjCMethodTableInfo> Generator;
782
0
      for (auto &OM : ObjCMethods)
783
0
        Generator.insert(OM.first, OM.second);
784
785
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
786
      // Make sure that no bucket is at offset 0
787
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
788
0
                                             llvm::endianness::little);
789
0
      Offset = Generator.Emit(BlobStream);
790
0
    }
791
792
0
    objc_method_block::ObjCMethodDataLayout ObjCMethodData(Stream);
793
0
    ObjCMethodData.emit(Scratch, Offset, HashTableBlob);
794
0
  }
795
0
}
796
797
namespace {
798
/// Used to serialize the on-disk Objective-C selector table.
799
class ObjCSelectorTableInfo {
800
public:
801
  using key_type = StoredObjCSelector;
802
  using key_type_ref = const key_type &;
803
  using data_type = SelectorID;
804
  using data_type_ref = data_type;
805
  using hash_value_type = unsigned;
806
  using offset_type = unsigned;
807
808
0
  hash_value_type ComputeHash(key_type_ref Key) {
809
0
    return llvm::DenseMapInfo<StoredObjCSelector>::getHashValue(Key);
810
0
  }
811
812
  std::pair<unsigned, unsigned>
813
0
  EmitKeyDataLength(raw_ostream &OS, key_type_ref Key, data_type_ref) {
814
0
    uint32_t KeyLength =
815
0
        sizeof(uint16_t) + sizeof(uint32_t) * Key.Identifiers.size();
816
0
    uint32_t DataLength = sizeof(uint32_t);
817
818
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
819
0
    writer.write<uint16_t>(KeyLength);
820
0
    writer.write<uint16_t>(DataLength);
821
0
    return {KeyLength, DataLength};
822
0
  }
823
824
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
825
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
826
0
    writer.write<uint16_t>(Key.NumArgs);
827
0
    for (auto Identifier : Key.Identifiers)
828
0
      writer.write<uint32_t>(Identifier);
829
0
  }
830
831
0
  void EmitData(raw_ostream &OS, key_type_ref, data_type_ref Data, unsigned) {
832
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
833
0
    writer.write<uint32_t>(Data);
834
0
  }
835
};
836
} // namespace
837
838
void APINotesWriter::Implementation::writeObjCSelectorBlock(
839
0
    llvm::BitstreamWriter &Stream) {
840
0
  llvm::BCBlockRAII Scope(Stream, OBJC_SELECTOR_BLOCK_ID, 3);
841
842
0
  if (SelectorIDs.empty())
843
0
    return;
844
845
0
  {
846
0
    llvm::SmallString<4096> HashTableBlob;
847
0
    uint32_t Offset;
848
0
    {
849
0
      llvm::OnDiskChainedHashTableGenerator<ObjCSelectorTableInfo> Generator;
850
0
      for (auto &S : SelectorIDs)
851
0
        Generator.insert(S.first, S.second);
852
853
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
854
      // Make sure that no bucket is at offset 0
855
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
856
0
                                             llvm::endianness::little);
857
0
      Offset = Generator.Emit(BlobStream);
858
0
    }
859
860
0
    objc_selector_block::ObjCSelectorDataLayout ObjCSelectorData(Stream);
861
0
    ObjCSelectorData.emit(Scratch, Offset, HashTableBlob);
862
0
  }
863
0
}
864
865
namespace {
866
/// Used to serialize the on-disk global variable table.
867
class GlobalVariableTableInfo
868
    : public VersionedTableInfo<GlobalVariableTableInfo, ContextTableKey,
869
                                GlobalVariableInfo> {
870
public:
871
0
  unsigned getKeyLength(key_type_ref) {
872
0
    return sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
873
0
  }
874
875
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
876
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
877
0
    writer.write<uint32_t>(Key.parentContextID);
878
0
    writer.write<uint8_t>(Key.contextKind);
879
0
    writer.write<uint32_t>(Key.contextID);
880
0
  }
881
882
0
  hash_value_type ComputeHash(key_type_ref Key) {
883
0
    return static_cast<size_t>(Key.hashValue());
884
0
  }
885
886
0
  unsigned getUnversionedInfoSize(const GlobalVariableInfo &GVI) {
887
0
    return getVariableInfoSize(GVI);
888
0
  }
889
890
0
  void emitUnversionedInfo(raw_ostream &OS, const GlobalVariableInfo &GVI) {
891
0
    emitVariableInfo(OS, GVI);
892
0
  }
893
};
894
} // namespace
895
896
void APINotesWriter::Implementation::writeGlobalVariableBlock(
897
0
    llvm::BitstreamWriter &Stream) {
898
0
  llvm::BCBlockRAII Scope(Stream, GLOBAL_VARIABLE_BLOCK_ID, 3);
899
900
0
  if (GlobalVariables.empty())
901
0
    return;
902
903
0
  {
904
0
    llvm::SmallString<4096> HashTableBlob;
905
0
    uint32_t Offset;
906
0
    {
907
0
      llvm::OnDiskChainedHashTableGenerator<GlobalVariableTableInfo> Generator;
908
0
      for (auto &GV : GlobalVariables)
909
0
        Generator.insert(GV.first, GV.second);
910
911
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
912
      // Make sure that no bucket is at offset 0
913
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
914
0
                                             llvm::endianness::little);
915
0
      Offset = Generator.Emit(BlobStream);
916
0
    }
917
918
0
    global_variable_block::GlobalVariableDataLayout GlobalVariableData(Stream);
919
0
    GlobalVariableData.emit(Scratch, Offset, HashTableBlob);
920
0
  }
921
0
}
922
923
namespace {
924
0
unsigned getParamInfoSize(const ParamInfo &PI) {
925
0
  return getVariableInfoSize(PI) + 1;
926
0
}
927
928
0
void emitParamInfo(raw_ostream &OS, const ParamInfo &PI) {
929
0
  emitVariableInfo(OS, PI);
930
931
0
  uint8_t flags = 0;
932
0
  if (auto noescape = PI.isNoEscape()) {
933
0
    flags |= 0x01;
934
0
    if (*noescape)
935
0
      flags |= 0x02;
936
0
  }
937
0
  flags <<= 3;
938
0
  if (auto RCC = PI.getRetainCountConvention())
939
0
    flags |= static_cast<uint8_t>(RCC.value()) + 1;
940
941
0
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
942
0
  writer.write<uint8_t>(flags);
943
0
}
944
945
/// Retrieve the serialized size of the given FunctionInfo, for use in on-disk
946
/// hash tables.
947
0
unsigned getFunctionInfoSize(const FunctionInfo &FI) {
948
0
  unsigned size = getCommonEntityInfoSize(FI) + 2 + sizeof(uint64_t);
949
0
  size += sizeof(uint16_t);
950
0
  for (const auto &P : FI.Params)
951
0
    size += getParamInfoSize(P);
952
0
  size += sizeof(uint16_t) + FI.ResultType.size();
953
0
  return size;
954
0
}
955
956
/// Emit a serialized representation of the function information.
957
0
void emitFunctionInfo(raw_ostream &OS, const FunctionInfo &FI) {
958
0
  emitCommonEntityInfo(OS, FI);
959
960
0
  uint8_t flags = 0;
961
0
  flags |= FI.NullabilityAudited;
962
0
  flags <<= 3;
963
0
  if (auto RCC = FI.getRetainCountConvention())
964
0
    flags |= static_cast<uint8_t>(RCC.value()) + 1;
965
966
0
  llvm::support::endian::Writer writer(OS, llvm::endianness::little);
967
968
0
  writer.write<uint8_t>(flags);
969
0
  writer.write<uint8_t>(FI.NumAdjustedNullable);
970
0
  writer.write<uint64_t>(FI.NullabilityPayload);
971
972
0
  writer.write<uint16_t>(FI.Params.size());
973
0
  for (const auto &PI : FI.Params)
974
0
    emitParamInfo(OS, PI);
975
976
0
  writer.write<uint16_t>(FI.ResultType.size());
977
0
  writer.write(ArrayRef<char>{FI.ResultType.data(), FI.ResultType.size()});
978
0
}
979
980
/// Used to serialize the on-disk global function table.
981
class GlobalFunctionTableInfo
982
    : public VersionedTableInfo<GlobalFunctionTableInfo, ContextTableKey,
983
                                GlobalFunctionInfo> {
984
public:
985
0
  unsigned getKeyLength(key_type_ref) {
986
0
    return sizeof(uint32_t) + sizeof(uint8_t) + sizeof(uint32_t);
987
0
  }
988
989
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
990
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
991
0
    writer.write<uint32_t>(Key.parentContextID);
992
0
    writer.write<uint8_t>(Key.contextKind);
993
0
    writer.write<uint32_t>(Key.contextID);
994
0
  }
995
996
0
  hash_value_type ComputeHash(key_type_ref Key) {
997
0
    return static_cast<size_t>(Key.hashValue());
998
0
  }
999
1000
0
  unsigned getUnversionedInfoSize(const GlobalFunctionInfo &GFI) {
1001
0
    return getFunctionInfoSize(GFI);
1002
0
  }
1003
1004
0
  void emitUnversionedInfo(raw_ostream &OS, const GlobalFunctionInfo &GFI) {
1005
0
    emitFunctionInfo(OS, GFI);
1006
0
  }
1007
};
1008
} // namespace
1009
1010
void APINotesWriter::Implementation::writeGlobalFunctionBlock(
1011
0
    llvm::BitstreamWriter &Stream) {
1012
0
  llvm::BCBlockRAII Scope(Stream, GLOBAL_FUNCTION_BLOCK_ID, 3);
1013
1014
0
  if (GlobalFunctions.empty())
1015
0
    return;
1016
1017
0
  {
1018
0
    llvm::SmallString<4096> HashTableBlob;
1019
0
    uint32_t Offset;
1020
0
    {
1021
0
      llvm::OnDiskChainedHashTableGenerator<GlobalFunctionTableInfo> Generator;
1022
0
      for (auto &F : GlobalFunctions)
1023
0
        Generator.insert(F.first, F.second);
1024
1025
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
1026
      // Make sure that no bucket is at offset 0
1027
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
1028
0
                                             llvm::endianness::little);
1029
0
      Offset = Generator.Emit(BlobStream);
1030
0
    }
1031
1032
0
    global_function_block::GlobalFunctionDataLayout GlobalFunctionData(Stream);
1033
0
    GlobalFunctionData.emit(Scratch, Offset, HashTableBlob);
1034
0
  }
1035
0
}
1036
1037
namespace {
1038
/// Used to serialize the on-disk global enum constant.
1039
class EnumConstantTableInfo
1040
    : public VersionedTableInfo<EnumConstantTableInfo, unsigned,
1041
                                EnumConstantInfo> {
1042
public:
1043
0
  unsigned getKeyLength(key_type_ref) { return sizeof(uint32_t); }
1044
1045
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
1046
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1047
0
    writer.write<uint32_t>(Key);
1048
0
  }
1049
1050
0
  hash_value_type ComputeHash(key_type_ref Key) {
1051
0
    return static_cast<size_t>(llvm::hash_value(Key));
1052
0
  }
1053
1054
0
  unsigned getUnversionedInfoSize(const EnumConstantInfo &ECI) {
1055
0
    return getCommonEntityInfoSize(ECI);
1056
0
  }
1057
1058
0
  void emitUnversionedInfo(raw_ostream &OS, const EnumConstantInfo &ECI) {
1059
0
    emitCommonEntityInfo(OS, ECI);
1060
0
  }
1061
};
1062
} // namespace
1063
1064
void APINotesWriter::Implementation::writeEnumConstantBlock(
1065
0
    llvm::BitstreamWriter &Stream) {
1066
0
  llvm::BCBlockRAII Scope(Stream, ENUM_CONSTANT_BLOCK_ID, 3);
1067
1068
0
  if (EnumConstants.empty())
1069
0
    return;
1070
1071
0
  {
1072
0
    llvm::SmallString<4096> HashTableBlob;
1073
0
    uint32_t Offset;
1074
0
    {
1075
0
      llvm::OnDiskChainedHashTableGenerator<EnumConstantTableInfo> Generator;
1076
0
      for (auto &EC : EnumConstants)
1077
0
        Generator.insert(EC.first, EC.second);
1078
1079
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
1080
      // Make sure that no bucket is at offset 0
1081
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
1082
0
                                             llvm::endianness::little);
1083
0
      Offset = Generator.Emit(BlobStream);
1084
0
    }
1085
1086
0
    enum_constant_block::EnumConstantDataLayout EnumConstantData(Stream);
1087
0
    EnumConstantData.emit(Scratch, Offset, HashTableBlob);
1088
0
  }
1089
0
}
1090
1091
namespace {
1092
template <typename Derived, typename UnversionedDataType>
1093
class CommonTypeTableInfo
1094
    : public VersionedTableInfo<Derived, ContextTableKey, UnversionedDataType> {
1095
public:
1096
  using key_type_ref = typename CommonTypeTableInfo::key_type_ref;
1097
  using hash_value_type = typename CommonTypeTableInfo::hash_value_type;
1098
1099
0
  unsigned getKeyLength(key_type_ref) {
1100
0
    return sizeof(uint32_t) + sizeof(uint8_t) + sizeof(IdentifierID);
1101
0
  }
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::CommonTypeTableInfo<clang::api_notes::(anonymous namespace)::TagTableInfo, clang::api_notes::TagInfo>::getKeyLength(clang::api_notes::ContextTableKey)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::CommonTypeTableInfo<clang::api_notes::(anonymous namespace)::TypedefTableInfo, clang::api_notes::TypedefInfo>::getKeyLength(clang::api_notes::ContextTableKey)
1102
1103
0
  void EmitKey(raw_ostream &OS, key_type_ref Key, unsigned) {
1104
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1105
0
    writer.write<uint32_t>(Key.parentContextID);
1106
0
    writer.write<uint8_t>(Key.contextKind);
1107
0
    writer.write<IdentifierID>(Key.contextID);
1108
0
  }
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::CommonTypeTableInfo<clang::api_notes::(anonymous namespace)::TagTableInfo, clang::api_notes::TagInfo>::EmitKey(llvm::raw_ostream&, clang::api_notes::ContextTableKey, unsigned int)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::CommonTypeTableInfo<clang::api_notes::(anonymous namespace)::TypedefTableInfo, clang::api_notes::TypedefInfo>::EmitKey(llvm::raw_ostream&, clang::api_notes::ContextTableKey, unsigned int)
1109
1110
0
  hash_value_type ComputeHash(key_type_ref Key) {
1111
0
    return static_cast<size_t>(Key.hashValue());
1112
0
  }
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::CommonTypeTableInfo<clang::api_notes::(anonymous namespace)::TagTableInfo, clang::api_notes::TagInfo>::ComputeHash(clang::api_notes::ContextTableKey)
Unexecuted instantiation: APINotesWriter.cpp:clang::api_notes::(anonymous namespace)::CommonTypeTableInfo<clang::api_notes::(anonymous namespace)::TypedefTableInfo, clang::api_notes::TypedefInfo>::ComputeHash(clang::api_notes::ContextTableKey)
1113
1114
  unsigned getUnversionedInfoSize(const UnversionedDataType &UDT) {
1115
    return getCommonTypeInfoSize(UDT);
1116
  }
1117
1118
  void emitUnversionedInfo(raw_ostream &OS, const UnversionedDataType &UDT) {
1119
    emitCommonTypeInfo(OS, UDT);
1120
  }
1121
};
1122
1123
/// Used to serialize the on-disk tag table.
1124
class TagTableInfo : public CommonTypeTableInfo<TagTableInfo, TagInfo> {
1125
public:
1126
0
  unsigned getUnversionedInfoSize(const TagInfo &TI) {
1127
0
    return 2 + (TI.SwiftImportAs ? TI.SwiftImportAs->size() : 0) +
1128
0
           2 + (TI.SwiftRetainOp ? TI.SwiftRetainOp->size() : 0) +
1129
0
           2 + (TI.SwiftReleaseOp ? TI.SwiftReleaseOp->size() : 0) +
1130
0
           1 + getCommonTypeInfoSize(TI);
1131
0
  }
1132
1133
0
  void emitUnversionedInfo(raw_ostream &OS, const TagInfo &TI) {
1134
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1135
1136
0
    uint8_t Flags = 0;
1137
0
    if (auto extensibility = TI.EnumExtensibility) {
1138
0
      Flags |= static_cast<uint8_t>(extensibility.value()) + 1;
1139
0
      assert((Flags < (1 << 2)) && "must fit in two bits");
1140
0
    }
1141
1142
0
    Flags <<= 2;
1143
0
    if (auto value = TI.isFlagEnum())
1144
0
      Flags |= (value.value() << 1 | 1 << 0);
1145
1146
0
    writer.write<uint8_t>(Flags);
1147
1148
0
    if (auto ImportAs = TI.SwiftImportAs) {
1149
0
      writer.write<uint16_t>(ImportAs->size() + 1);
1150
0
      OS.write(ImportAs->c_str(), ImportAs->size());
1151
0
    } else {
1152
0
      writer.write<uint16_t>(0);
1153
0
    }
1154
0
    if (auto RetainOp = TI.SwiftRetainOp) {
1155
0
      writer.write<uint16_t>(RetainOp->size() + 1);
1156
0
      OS.write(RetainOp->c_str(), RetainOp->size());
1157
0
    } else {
1158
0
      writer.write<uint16_t>(0);
1159
0
    }
1160
0
    if (auto ReleaseOp = TI.SwiftReleaseOp) {
1161
0
      writer.write<uint16_t>(ReleaseOp->size() + 1);
1162
0
      OS.write(ReleaseOp->c_str(), ReleaseOp->size());
1163
0
    } else {
1164
0
      writer.write<uint16_t>(0);
1165
0
    }
1166
1167
0
    emitCommonTypeInfo(OS, TI);
1168
0
  }
1169
};
1170
} // namespace
1171
1172
void APINotesWriter::Implementation::writeTagBlock(
1173
0
    llvm::BitstreamWriter &Stream) {
1174
0
  llvm::BCBlockRAII Scope(Stream, TAG_BLOCK_ID, 3);
1175
1176
0
  if (Tags.empty())
1177
0
    return;
1178
1179
0
  {
1180
0
    llvm::SmallString<4096> HashTableBlob;
1181
0
    uint32_t Offset;
1182
0
    {
1183
0
      llvm::OnDiskChainedHashTableGenerator<TagTableInfo> Generator;
1184
0
      for (auto &T : Tags)
1185
0
        Generator.insert(T.first, T.second);
1186
1187
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
1188
      // Make sure that no bucket is at offset 0
1189
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
1190
0
                                             llvm::endianness::little);
1191
0
      Offset = Generator.Emit(BlobStream);
1192
0
    }
1193
1194
0
    tag_block::TagDataLayout TagData(Stream);
1195
0
    TagData.emit(Scratch, Offset, HashTableBlob);
1196
0
  }
1197
0
}
1198
1199
namespace {
1200
/// Used to serialize the on-disk typedef table.
1201
class TypedefTableInfo
1202
    : public CommonTypeTableInfo<TypedefTableInfo, TypedefInfo> {
1203
public:
1204
0
  unsigned getUnversionedInfoSize(const TypedefInfo &TI) {
1205
0
    return 1 + getCommonTypeInfoSize(TI);
1206
0
  }
1207
1208
0
  void emitUnversionedInfo(raw_ostream &OS, const TypedefInfo &TI) {
1209
0
    llvm::support::endian::Writer writer(OS, llvm::endianness::little);
1210
1211
0
    uint8_t Flags = 0;
1212
0
    if (auto swiftWrapper = TI.SwiftWrapper)
1213
0
      Flags |= static_cast<uint8_t>(*swiftWrapper) + 1;
1214
1215
0
    writer.write<uint8_t>(Flags);
1216
1217
0
    emitCommonTypeInfo(OS, TI);
1218
0
  }
1219
};
1220
} // namespace
1221
1222
void APINotesWriter::Implementation::writeTypedefBlock(
1223
0
    llvm::BitstreamWriter &Stream) {
1224
0
  llvm::BCBlockRAII Scope(Stream, TYPEDEF_BLOCK_ID, 3);
1225
1226
0
  if (Typedefs.empty())
1227
0
    return;
1228
1229
0
  {
1230
0
    llvm::SmallString<4096> HashTableBlob;
1231
0
    uint32_t Offset;
1232
0
    {
1233
0
      llvm::OnDiskChainedHashTableGenerator<TypedefTableInfo> Generator;
1234
0
      for (auto &T : Typedefs)
1235
0
        Generator.insert(T.first, T.second);
1236
1237
0
      llvm::raw_svector_ostream BlobStream(HashTableBlob);
1238
      // Make sure that no bucket is at offset 0
1239
0
      llvm::support::endian::write<uint32_t>(BlobStream, 0,
1240
0
                                             llvm::endianness::little);
1241
0
      Offset = Generator.Emit(BlobStream);
1242
0
    }
1243
1244
0
    typedef_block::TypedefDataLayout TypedefData(Stream);
1245
0
    TypedefData.emit(Scratch, Offset, HashTableBlob);
1246
0
  }
1247
0
}
1248
1249
// APINotesWriter
1250
1251
APINotesWriter::APINotesWriter(llvm::StringRef ModuleName, const FileEntry *SF)
1252
0
    : Implementation(new class Implementation(ModuleName, SF)) {}
1253
1254
0
APINotesWriter::~APINotesWriter() = default;
1255
1256
0
void APINotesWriter::writeToStream(llvm::raw_ostream &OS) {
1257
0
  Implementation->writeToStream(OS);
1258
0
}
1259
1260
ContextID APINotesWriter::addObjCContext(std::optional<ContextID> ParentCtxID,
1261
                                         StringRef Name, ContextKind Kind,
1262
                                         const ObjCContextInfo &Info,
1263
0
                                         VersionTuple SwiftVersion) {
1264
0
  IdentifierID NameID = Implementation->getIdentifier(Name);
1265
1266
0
  uint32_t RawParentCtxID = ParentCtxID ? ParentCtxID->Value : -1;
1267
0
  ContextTableKey Key(RawParentCtxID, static_cast<uint8_t>(Kind), NameID);
1268
0
  auto Known = Implementation->ObjCContexts.find(Key);
1269
0
  if (Known == Implementation->ObjCContexts.end()) {
1270
0
    unsigned NextID = Implementation->ObjCContexts.size() + 1;
1271
1272
0
    Implementation::VersionedSmallVector<ObjCContextInfo> EmptyVersionedInfo;
1273
0
    Known = Implementation->ObjCContexts
1274
0
                .insert(std::make_pair(
1275
0
                    Key, std::make_pair(NextID, EmptyVersionedInfo)))
1276
0
                .first;
1277
1278
0
    Implementation->ObjCContextNames[NextID] = NameID;
1279
0
    Implementation->ParentContexts[NextID] = RawParentCtxID;
1280
0
  }
1281
1282
  // Add this version information.
1283
0
  auto &VersionedVec = Known->second.second;
1284
0
  bool Found = false;
1285
0
  for (auto &Versioned : VersionedVec) {
1286
0
    if (Versioned.first == SwiftVersion) {
1287
0
      Versioned.second |= Info;
1288
0
      Found = true;
1289
0
      break;
1290
0
    }
1291
0
  }
1292
1293
0
  if (!Found)
1294
0
    VersionedVec.push_back({SwiftVersion, Info});
1295
1296
0
  return ContextID(Known->second.first);
1297
0
}
1298
1299
void APINotesWriter::addObjCProperty(ContextID CtxID, StringRef Name,
1300
                                     bool IsInstanceProperty,
1301
                                     const ObjCPropertyInfo &Info,
1302
0
                                     VersionTuple SwiftVersion) {
1303
0
  IdentifierID NameID = Implementation->getIdentifier(Name);
1304
0
  Implementation
1305
0
      ->ObjCProperties[std::make_tuple(CtxID.Value, NameID, IsInstanceProperty)]
1306
0
      .push_back({SwiftVersion, Info});
1307
0
}
1308
1309
void APINotesWriter::addObjCMethod(ContextID CtxID, ObjCSelectorRef Selector,
1310
                                   bool IsInstanceMethod,
1311
                                   const ObjCMethodInfo &Info,
1312
0
                                   VersionTuple SwiftVersion) {
1313
0
  SelectorID SelID = Implementation->getSelector(Selector);
1314
0
  auto Key = std::tuple<unsigned, unsigned, char>{CtxID.Value, SelID,
1315
0
                                                  IsInstanceMethod};
1316
0
  Implementation->ObjCMethods[Key].push_back({SwiftVersion, Info});
1317
1318
  // If this method is a designated initializer, update the class to note that
1319
  // it has designated initializers.
1320
0
  if (Info.DesignatedInit) {
1321
0
    assert(Implementation->ParentContexts.contains(CtxID.Value));
1322
0
    uint32_t ParentCtxID = Implementation->ParentContexts[CtxID.Value];
1323
0
    ContextTableKey CtxKey(ParentCtxID,
1324
0
                           static_cast<uint8_t>(ContextKind::ObjCClass),
1325
0
                           Implementation->ObjCContextNames[CtxID.Value]);
1326
0
    assert(Implementation->ObjCContexts.contains(CtxKey));
1327
0
    auto &VersionedVec = Implementation->ObjCContexts[CtxKey].second;
1328
0
    bool Found = false;
1329
0
    for (auto &Versioned : VersionedVec) {
1330
0
      if (Versioned.first == SwiftVersion) {
1331
0
        Versioned.second.setHasDesignatedInits(true);
1332
0
        Found = true;
1333
0
        break;
1334
0
      }
1335
0
    }
1336
1337
0
    if (!Found) {
1338
0
      VersionedVec.push_back({SwiftVersion, ObjCContextInfo()});
1339
0
      VersionedVec.back().second.setHasDesignatedInits(true);
1340
0
    }
1341
0
  }
1342
0
}
1343
1344
void APINotesWriter::addGlobalVariable(std::optional<Context> Ctx,
1345
                                       llvm::StringRef Name,
1346
                                       const GlobalVariableInfo &Info,
1347
0
                                       VersionTuple SwiftVersion) {
1348
0
  IdentifierID VariableID = Implementation->getIdentifier(Name);
1349
0
  ContextTableKey Key(Ctx, VariableID);
1350
0
  Implementation->GlobalVariables[Key].push_back({SwiftVersion, Info});
1351
0
}
1352
1353
void APINotesWriter::addGlobalFunction(std::optional<Context> Ctx,
1354
                                       llvm::StringRef Name,
1355
                                       const GlobalFunctionInfo &Info,
1356
0
                                       VersionTuple SwiftVersion) {
1357
0
  IdentifierID NameID = Implementation->getIdentifier(Name);
1358
0
  ContextTableKey Key(Ctx, NameID);
1359
0
  Implementation->GlobalFunctions[Key].push_back({SwiftVersion, Info});
1360
0
}
1361
1362
void APINotesWriter::addEnumConstant(llvm::StringRef Name,
1363
                                     const EnumConstantInfo &Info,
1364
0
                                     VersionTuple SwiftVersion) {
1365
0
  IdentifierID EnumConstantID = Implementation->getIdentifier(Name);
1366
0
  Implementation->EnumConstants[EnumConstantID].push_back({SwiftVersion, Info});
1367
0
}
1368
1369
void APINotesWriter::addTag(std::optional<Context> Ctx, llvm::StringRef Name,
1370
0
                            const TagInfo &Info, VersionTuple SwiftVersion) {
1371
0
  IdentifierID TagID = Implementation->getIdentifier(Name);
1372
0
  ContextTableKey Key(Ctx, TagID);
1373
0
  Implementation->Tags[Key].push_back({SwiftVersion, Info});
1374
0
}
1375
1376
void APINotesWriter::addTypedef(std::optional<Context> Ctx,
1377
                                llvm::StringRef Name, const TypedefInfo &Info,
1378
0
                                VersionTuple SwiftVersion) {
1379
0
  IdentifierID TypedefID = Implementation->getIdentifier(Name);
1380
0
  ContextTableKey Key(Ctx, TypedefID);
1381
0
  Implementation->Typedefs[Key].push_back({SwiftVersion, Info});
1382
0
}
1383
} // namespace api_notes
1384
} // namespace clang