1 //===- ExtractAPI/API.cpp ---------------------------------------*- 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 /// \file
10 /// This file implements the APIRecord and derived record structs,
11 /// and the APISet class.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #include "clang/ExtractAPI/API.h"
16 #include "clang/AST/CommentCommandTraits.h"
17 #include "clang/AST/CommentLexer.h"
18 #include "clang/AST/RawCommentList.h"
19 #include "clang/Index/USRGeneration.h"
20 #include "llvm/ADT/StringRef.h"
21 #include <memory>
22 
23 using namespace clang::extractapi;
24 using namespace llvm;
25 
26 namespace {
27 
28 template <typename RecordTy, typename... CtorArgsTy>
29 RecordTy *addTopLevelRecord(DenseMap<StringRef, APIRecord *> &USRLookupTable,
30                             APISet::RecordMap<RecordTy> &RecordMap,
31                             StringRef USR, CtorArgsTy &&...CtorArgs) {
32   auto Result = RecordMap.insert({USR, nullptr});
33 
34   // Create the record if it does not already exist
35   if (Result.second)
36     Result.first->second =
37         std::make_unique<RecordTy>(USR, std::forward<CtorArgsTy>(CtorArgs)...);
38 
39   auto *Record = Result.first->second.get();
40   USRLookupTable.insert({USR, Record});
41   return Record;
42 }
43 
44 } // namespace
45 
46 NamespaceRecord *
47 APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR,
48                      PresumedLoc Loc, AvailabilityInfo Availability,
49                      LinkageInfo Linkage, const DocComment &Comment,
50                      DeclarationFragments Declaration,
51                      DeclarationFragments SubHeading, bool IsFromSystemHeader) {
52   auto *Record = addTopLevelRecord(
53       USRBasedLookupTable, Namespaces, USR, Name, Loc, std::move(Availability),
54       Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader);
55 
56   if (Parent)
57     Record->ParentInformation = APIRecord::HierarchyInformation(
58         Parent->USR, Parent->Name, Parent->getKind(), Parent);
59   return Record;
60 }
61 
62 GlobalVariableRecord *
63 APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
64                      AvailabilityInfo Availability, LinkageInfo Linkage,
65                      const DocComment &Comment, DeclarationFragments Fragments,
66                      DeclarationFragments SubHeading, bool IsFromSystemHeader) {
67   return addTopLevelRecord(USRBasedLookupTable, GlobalVariables, USR, Name, Loc,
68                            std::move(Availability), Linkage, Comment, Fragments,
69                            SubHeading, IsFromSystemHeader);
70 }
71 
72 GlobalVariableTemplateRecord *APISet::addGlobalVariableTemplate(
73     StringRef Name, StringRef USR, PresumedLoc Loc,
74     AvailabilityInfo Availability, LinkageInfo Linkage,
75     const DocComment &Comment, DeclarationFragments Declaration,
76     DeclarationFragments SubHeading, Template Template,
77     bool IsFromSystemHeader) {
78   return addTopLevelRecord(USRBasedLookupTable, GlobalVariableTemplates, USR,
79                            Name, Loc, std::move(Availability), Linkage, Comment,
80                            Declaration, SubHeading, Template,
81                            IsFromSystemHeader);
82 }
83 
84 GlobalFunctionRecord *APISet::addGlobalFunction(
85     StringRef Name, StringRef USR, PresumedLoc Loc,
86     AvailabilityInfo Availability, LinkageInfo Linkage,
87     const DocComment &Comment, DeclarationFragments Fragments,
88     DeclarationFragments SubHeading, FunctionSignature Signature,
89     bool IsFromSystemHeader) {
90   return addTopLevelRecord(USRBasedLookupTable, GlobalFunctions, USR, Name, Loc,
91                            std::move(Availability), Linkage, Comment, Fragments,
92                            SubHeading, Signature, IsFromSystemHeader);
93 }
94 
95 GlobalFunctionTemplateRecord *APISet::addGlobalFunctionTemplate(
96     StringRef Name, StringRef USR, PresumedLoc Loc,
97     AvailabilityInfo Availability, LinkageInfo Linkage,
98     const DocComment &Comment, DeclarationFragments Declaration,
99     DeclarationFragments SubHeading, FunctionSignature Signature,
100     Template Template, bool IsFromSystemHeader) {
101   return addTopLevelRecord(USRBasedLookupTable, GlobalFunctionTemplates, USR,
102                            Name, Loc, std::move(Availability), Linkage, Comment,
103                            Declaration, SubHeading, Signature, Template,
104                            IsFromSystemHeader);
105 }
106 
107 GlobalFunctionTemplateSpecializationRecord *
108 APISet::addGlobalFunctionTemplateSpecialization(
109     StringRef Name, StringRef USR, PresumedLoc Loc,
110     AvailabilityInfo Availability, LinkageInfo Linkage,
111     const DocComment &Comment, DeclarationFragments Declaration,
112     DeclarationFragments SubHeading, FunctionSignature Signature,
113     bool IsFromSystemHeader) {
114   return addTopLevelRecord(
115       USRBasedLookupTable, GlobalFunctionTemplateSpecializations, USR, Name,
116       Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading,
117       Signature, IsFromSystemHeader);
118 }
119 
120 EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name,
121                                             StringRef USR, PresumedLoc Loc,
122                                             AvailabilityInfo Availability,
123                                             const DocComment &Comment,
124                                             DeclarationFragments Declaration,
125                                             DeclarationFragments SubHeading,
126                                             bool IsFromSystemHeader) {
127   auto Record = std::make_unique<EnumConstantRecord>(
128       USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
129       IsFromSystemHeader);
130   Record->ParentInformation = APIRecord::HierarchyInformation(
131       Enum->USR, Enum->Name, Enum->getKind(), Enum);
132   USRBasedLookupTable.insert({USR, Record.get()});
133   return Enum->Constants.emplace_back(std::move(Record)).get();
134 }
135 
136 EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
137                             AvailabilityInfo Availability,
138                             const DocComment &Comment,
139                             DeclarationFragments Declaration,
140                             DeclarationFragments SubHeading,
141                             bool IsFromSystemHeader) {
142   return addTopLevelRecord(USRBasedLookupTable, Enums, USR, Name, Loc,
143                            std::move(Availability), Comment, Declaration,
144                            SubHeading, IsFromSystemHeader);
145 }
146 
147 RecordFieldRecord *APISet::addRecordField(
148     RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc,
149     AvailabilityInfo Availability, const DocComment &Comment,
150     DeclarationFragments Declaration, DeclarationFragments SubHeading,
151     APIRecord::RecordKind Kind, bool IsFromSystemHeader) {
152   auto RecordField = std::make_unique<RecordFieldRecord>(
153       USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
154       Kind, IsFromSystemHeader);
155   RecordField->ParentInformation = APIRecord::HierarchyInformation(
156       Record->USR, Record->Name, Record->getKind(), Record);
157   USRBasedLookupTable.insert({USR, RecordField.get()});
158   return Record->Fields.emplace_back(std::move(RecordField)).get();
159 }
160 
161 RecordRecord *APISet::addRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
162                                 AvailabilityInfo Availability,
163                                 const DocComment &Comment,
164                                 DeclarationFragments Declaration,
165                                 DeclarationFragments SubHeading,
166                                 APIRecord::RecordKind Kind,
167                                 bool IsFromSystemHeader) {
168   return addTopLevelRecord(USRBasedLookupTable, Records, USR, Name, Loc,
169                            std::move(Availability), Comment, Declaration,
170                            SubHeading, Kind, IsFromSystemHeader);
171 }
172 
173 StaticFieldRecord *
174 APISet::addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
175                        AvailabilityInfo Availability, LinkageInfo Linkage,
176                        const DocComment &Comment,
177                        DeclarationFragments Declaration,
178                        DeclarationFragments SubHeading, SymbolReference Context,
179                        AccessControl Access, bool IsFromSystemHeader) {
180   return addTopLevelRecord(USRBasedLookupTable, StaticFields, USR, Name, Loc,
181                            std::move(Availability), Linkage, Comment,
182                            Declaration, SubHeading, Context, Access,
183                            IsFromSystemHeader);
184 }
185 
186 CXXFieldRecord *
187 APISet::addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR,
188                     PresumedLoc Loc, AvailabilityInfo Availability,
189                     const DocComment &Comment, DeclarationFragments Declaration,
190                     DeclarationFragments SubHeading, AccessControl Access,
191                     bool IsFromSystemHeader) {
192   auto *Record = addTopLevelRecord(
193       USRBasedLookupTable, CXXFields, USR, Name, Loc, std::move(Availability),
194       Comment, Declaration, SubHeading, Access, IsFromSystemHeader);
195   Record->ParentInformation = APIRecord::HierarchyInformation(
196       CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass);
197   return Record;
198 }
199 
200 CXXFieldTemplateRecord *APISet::addCXXFieldTemplate(
201     APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
202     AvailabilityInfo Availability, const DocComment &Comment,
203     DeclarationFragments Declaration, DeclarationFragments SubHeading,
204     AccessControl Access, Template Template, bool IsFromSystemHeader) {
205   auto *Record =
206       addTopLevelRecord(USRBasedLookupTable, CXXFieldTemplates, USR, Name, Loc,
207                         std::move(Availability), Comment, Declaration,
208                         SubHeading, Access, Template, IsFromSystemHeader);
209   Record->ParentInformation = APIRecord::HierarchyInformation(
210       Parent->USR, Parent->Name, Parent->getKind(), Parent);
211 
212   return Record;
213 }
214 
215 CXXClassRecord *
216 APISet::addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
217                     PresumedLoc Loc, AvailabilityInfo Availability,
218                     const DocComment &Comment, DeclarationFragments Declaration,
219                     DeclarationFragments SubHeading, APIRecord::RecordKind Kind,
220                     AccessControl Access, bool IsFromSystemHeader) {
221   auto *Record = addTopLevelRecord(
222       USRBasedLookupTable, CXXClasses, USR, Name, Loc, std::move(Availability),
223       Comment, Declaration, SubHeading, Kind, Access, IsFromSystemHeader);
224   if (Parent)
225     Record->ParentInformation = APIRecord::HierarchyInformation(
226         Parent->USR, Parent->Name, Parent->getKind(), Parent);
227   return Record;
228 }
229 
230 ClassTemplateRecord *APISet::addClassTemplate(
231     APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
232     AvailabilityInfo Availability, const DocComment &Comment,
233     DeclarationFragments Declaration, DeclarationFragments SubHeading,
234     Template Template, AccessControl Access, bool IsFromSystemHeader) {
235   auto *Record =
236       addTopLevelRecord(USRBasedLookupTable, ClassTemplates, USR, Name, Loc,
237                         std::move(Availability), Comment, Declaration,
238                         SubHeading, Template, Access, IsFromSystemHeader);
239   if (Parent)
240     Record->ParentInformation = APIRecord::HierarchyInformation(
241         Parent->USR, Parent->Name, Parent->getKind(), Parent);
242   return Record;
243 }
244 
245 ClassTemplateSpecializationRecord *APISet::addClassTemplateSpecialization(
246     APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
247     AvailabilityInfo Availability, const DocComment &Comment,
248     DeclarationFragments Declaration, DeclarationFragments SubHeading,
249     AccessControl Access, bool IsFromSystemHeader) {
250   auto *Record =
251       addTopLevelRecord(USRBasedLookupTable, ClassTemplateSpecializations, USR,
252                         Name, Loc, std::move(Availability), Comment,
253                         Declaration, SubHeading, Access, IsFromSystemHeader);
254   if (Parent)
255     Record->ParentInformation = APIRecord::HierarchyInformation(
256         Parent->USR, Parent->Name, Parent->getKind(), Parent);
257   return Record;
258 }
259 
260 ClassTemplatePartialSpecializationRecord *
261 APISet::addClassTemplatePartialSpecialization(
262     APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
263     AvailabilityInfo Availability, const DocComment &Comment,
264     DeclarationFragments Declaration, DeclarationFragments SubHeading,
265     Template Template, AccessControl Access, bool IsFromSystemHeader) {
266   auto *Record = addTopLevelRecord(
267       USRBasedLookupTable, ClassTemplatePartialSpecializations, USR, Name, Loc,
268       std::move(Availability), Comment, Declaration, SubHeading, Template,
269       Access, IsFromSystemHeader);
270   if (Parent)
271     Record->ParentInformation = APIRecord::HierarchyInformation(
272         Parent->USR, Parent->Name, Parent->getKind(), Parent);
273   return Record;
274 }
275 
276 GlobalVariableTemplateSpecializationRecord *
277 APISet::addGlobalVariableTemplateSpecialization(
278     StringRef Name, StringRef USR, PresumedLoc Loc,
279     AvailabilityInfo Availability, LinkageInfo Linkage,
280     const DocComment &Comment, DeclarationFragments Declaration,
281     DeclarationFragments SubHeading, bool IsFromSystemHeader) {
282   return addTopLevelRecord(USRBasedLookupTable,
283                            GlobalVariableTemplateSpecializations, USR, Name,
284                            Loc, std::move(Availability), Linkage, Comment,
285                            Declaration, SubHeading, IsFromSystemHeader);
286 }
287 
288 GlobalVariableTemplatePartialSpecializationRecord *
289 APISet::addGlobalVariableTemplatePartialSpecialization(
290     StringRef Name, StringRef USR, PresumedLoc Loc,
291     AvailabilityInfo Availability, LinkageInfo Linkage,
292     const DocComment &Comment, DeclarationFragments Declaration,
293     DeclarationFragments SubHeading, Template Template,
294     bool IsFromSystemHeader) {
295   return addTopLevelRecord(
296       USRBasedLookupTable, GlobalVariableTemplatePartialSpecializations, USR,
297       Name, Loc, std::move(Availability), Linkage, Comment, Declaration,
298       SubHeading, Template, IsFromSystemHeader);
299 }
300 
301 ConceptRecord *APISet::addConcept(StringRef Name, StringRef USR,
302                                   PresumedLoc Loc,
303                                   AvailabilityInfo Availability,
304                                   const DocComment &Comment,
305                                   DeclarationFragments Declaration,
306                                   DeclarationFragments SubHeading,
307                                   Template Template, bool IsFromSystemHeader) {
308   return addTopLevelRecord(USRBasedLookupTable, Concepts, USR, Name, Loc,
309                            std::move(Availability), Comment, Declaration,
310                            SubHeading, Template, IsFromSystemHeader);
311 }
312 
313 CXXMethodRecord *APISet::addCXXInstanceMethod(
314     APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
315     AvailabilityInfo Availability, const DocComment &Comment,
316     DeclarationFragments Declaration, DeclarationFragments SubHeading,
317     FunctionSignature Signature, AccessControl Access,
318     bool IsFromSystemHeader) {
319   CXXMethodRecord *Record =
320       addTopLevelRecord(USRBasedLookupTable, CXXInstanceMethods, USR, Name, Loc,
321                         std::move(Availability), Comment, Declaration,
322                         SubHeading, Signature, Access, IsFromSystemHeader);
323 
324   Record->ParentInformation = APIRecord::HierarchyInformation(
325       CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
326       CXXClassRecord);
327   return Record;
328 }
329 
330 CXXMethodRecord *APISet::addCXXStaticMethod(
331     APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
332     AvailabilityInfo Availability, const DocComment &Comment,
333     DeclarationFragments Declaration, DeclarationFragments SubHeading,
334     FunctionSignature Signature, AccessControl Access,
335     bool IsFromSystemHeader) {
336   CXXMethodRecord *Record =
337       addTopLevelRecord(USRBasedLookupTable, CXXStaticMethods, USR, Name, Loc,
338                         std::move(Availability), Comment, Declaration,
339                         SubHeading, Signature, Access, IsFromSystemHeader);
340 
341   Record->ParentInformation = APIRecord::HierarchyInformation(
342       CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
343       CXXClassRecord);
344   return Record;
345 }
346 
347 CXXMethodTemplateRecord *APISet::addCXXMethodTemplate(
348     APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
349     AvailabilityInfo Availability, const DocComment &Comment,
350     DeclarationFragments Declaration, DeclarationFragments SubHeading,
351     FunctionSignature Signature, AccessControl Access, Template Template,
352     bool IsFromSystemHeader) {
353   auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR,
354                                    Name, Loc, std::move(Availability), Comment,
355                                    Declaration, SubHeading, Signature, Access,
356                                    Template, IsFromSystemHeader);
357   Record->ParentInformation = APIRecord::HierarchyInformation(
358       Parent->USR, Parent->Name, Parent->getKind(), Parent);
359 
360   return Record;
361 }
362 
363 CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec(
364     APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
365     AvailabilityInfo Availability, const DocComment &Comment,
366     DeclarationFragments Declaration, DeclarationFragments SubHeading,
367     FunctionSignature Signature, AccessControl Access,
368     bool IsFromSystemHeader) {
369 
370   auto *Record = addTopLevelRecord(
371       USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc,
372       std::move(Availability), Comment, Declaration, SubHeading, Signature,
373       Access, IsFromSystemHeader);
374   Record->ParentInformation = APIRecord::HierarchyInformation(
375       Parent->USR, Parent->Name, Parent->getKind(), Parent);
376 
377   return Record;
378 }
379 
380 ObjCCategoryRecord *APISet::addObjCCategory(
381     StringRef Name, StringRef USR, PresumedLoc Loc,
382     AvailabilityInfo Availability, const DocComment &Comment,
383     DeclarationFragments Declaration, DeclarationFragments SubHeading,
384     SymbolReference Interface, bool IsFromSystemHeader,
385     bool IsFromExternalModule) {
386   // Create the category record.
387   auto *Record =
388       addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc,
389                         std::move(Availability), Comment, Declaration,
390                         SubHeading, Interface, IsFromSystemHeader);
391 
392   Record->IsFromExternalModule = IsFromExternalModule;
393 
394   auto It = ObjCInterfaces.find(Interface.USR);
395   if (It != ObjCInterfaces.end())
396     It->second->Categories.push_back(Record);
397 
398   return Record;
399 }
400 
401 ObjCInterfaceRecord *
402 APISet::addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
403                          AvailabilityInfo Availability, LinkageInfo Linkage,
404                          const DocComment &Comment,
405                          DeclarationFragments Declaration,
406                          DeclarationFragments SubHeading,
407                          SymbolReference SuperClass, bool IsFromSystemHeader) {
408   return addTopLevelRecord(USRBasedLookupTable, ObjCInterfaces, USR, Name, Loc,
409                            std::move(Availability), Linkage, Comment,
410                            Declaration, SubHeading, SuperClass,
411                            IsFromSystemHeader);
412 }
413 
414 ObjCMethodRecord *APISet::addObjCMethod(
415     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
416     PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
417     DeclarationFragments Declaration, DeclarationFragments SubHeading,
418     FunctionSignature Signature, bool IsInstanceMethod,
419     bool IsFromSystemHeader) {
420   std::unique_ptr<ObjCMethodRecord> Record;
421   if (IsInstanceMethod)
422     Record = std::make_unique<ObjCInstanceMethodRecord>(
423         USR, Name, Loc, std::move(Availability), Comment, Declaration,
424         SubHeading, Signature, IsFromSystemHeader);
425   else
426     Record = std::make_unique<ObjCClassMethodRecord>(
427         USR, Name, Loc, std::move(Availability), Comment, Declaration,
428         SubHeading, Signature, IsFromSystemHeader);
429 
430   Record->ParentInformation = APIRecord::HierarchyInformation(
431       Container->USR, Container->Name, Container->getKind(), Container);
432   USRBasedLookupTable.insert({USR, Record.get()});
433   return Container->Methods.emplace_back(std::move(Record)).get();
434 }
435 
436 ObjCPropertyRecord *APISet::addObjCProperty(
437     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
438     PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
439     DeclarationFragments Declaration, DeclarationFragments SubHeading,
440     ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
441     StringRef SetterName, bool IsOptional, bool IsInstanceProperty,
442     bool IsFromSystemHeader) {
443   std::unique_ptr<ObjCPropertyRecord> Record;
444   if (IsInstanceProperty)
445     Record = std::make_unique<ObjCInstancePropertyRecord>(
446         USR, Name, Loc, std::move(Availability), Comment, Declaration,
447         SubHeading, Attributes, GetterName, SetterName, IsOptional,
448         IsFromSystemHeader);
449   else
450     Record = std::make_unique<ObjCClassPropertyRecord>(
451         USR, Name, Loc, std::move(Availability), Comment, Declaration,
452         SubHeading, Attributes, GetterName, SetterName, IsOptional,
453         IsFromSystemHeader);
454   Record->ParentInformation = APIRecord::HierarchyInformation(
455       Container->USR, Container->Name, Container->getKind(), Container);
456   USRBasedLookupTable.insert({USR, Record.get()});
457   return Container->Properties.emplace_back(std::move(Record)).get();
458 }
459 
460 ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
461     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
462     PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
463     DeclarationFragments Declaration, DeclarationFragments SubHeading,
464     ObjCInstanceVariableRecord::AccessControl Access, bool IsFromSystemHeader) {
465   auto Record = std::make_unique<ObjCInstanceVariableRecord>(
466       USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
467       Access, IsFromSystemHeader);
468   Record->ParentInformation = APIRecord::HierarchyInformation(
469       Container->USR, Container->Name, Container->getKind(), Container);
470   USRBasedLookupTable.insert({USR, Record.get()});
471   return Container->Ivars.emplace_back(std::move(Record)).get();
472 }
473 
474 ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR,
475                                             PresumedLoc Loc,
476                                             AvailabilityInfo Availability,
477                                             const DocComment &Comment,
478                                             DeclarationFragments Declaration,
479                                             DeclarationFragments SubHeading,
480                                             bool IsFromSystemHeader) {
481   return addTopLevelRecord(USRBasedLookupTable, ObjCProtocols, USR, Name, Loc,
482                            std::move(Availability), Comment, Declaration,
483                            SubHeading, IsFromSystemHeader);
484 }
485 
486 MacroDefinitionRecord *
487 APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
488                            DeclarationFragments Declaration,
489                            DeclarationFragments SubHeading,
490                            bool IsFromSystemHeader) {
491   return addTopLevelRecord(USRBasedLookupTable, Macros, USR, Name, Loc,
492                            Declaration, SubHeading, IsFromSystemHeader);
493 }
494 
495 TypedefRecord *
496 APISet::addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
497                    AvailabilityInfo Availability, const DocComment &Comment,
498                    DeclarationFragments Declaration,
499                    DeclarationFragments SubHeading,
500                    SymbolReference UnderlyingType, bool IsFromSystemHeader) {
501   return addTopLevelRecord(USRBasedLookupTable, Typedefs, USR, Name, Loc,
502                            std::move(Availability), Comment, Declaration,
503                            SubHeading, UnderlyingType, IsFromSystemHeader);
504 }
505 
506 APIRecord *APISet::findRecordForUSR(StringRef USR) const {
507   if (USR.empty())
508     return nullptr;
509 
510   return USRBasedLookupTable.lookup(USR);
511 }
512 
513 StringRef APISet::recordUSR(const Decl *D) {
514   SmallString<128> USR;
515   index::generateUSRForDecl(D, USR);
516   return copyString(USR);
517 }
518 
519 StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
520                                     const SourceManager &SM) {
521   SmallString<128> USR;
522   index::generateUSRForMacro(Name, SL, SM, USR);
523   return copyString(USR);
524 }
525 
526 StringRef APISet::copyString(StringRef String) {
527   if (String.empty())
528     return {};
529 
530   // No need to allocate memory and copy if the string has already been stored.
531   if (StringAllocator.identifyObject(String.data()))
532     return String;
533 
534   void *Ptr = StringAllocator.Allocate(String.size(), 1);
535   memcpy(Ptr, String.data(), String.size());
536   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
537 }
538 
539 APIRecord::~APIRecord() {}
540 ObjCContainerRecord::~ObjCContainerRecord() {}
541 ObjCMethodRecord::~ObjCMethodRecord() {}
542 ObjCPropertyRecord::~ObjCPropertyRecord() {}
543 CXXMethodRecord::~CXXMethodRecord() {}
544 
545 void GlobalFunctionRecord::anchor() {}
546 void GlobalVariableRecord::anchor() {}
547 void EnumConstantRecord::anchor() {}
548 void EnumRecord::anchor() {}
549 void RecordFieldRecord::anchor() {}
550 void RecordRecord::anchor() {}
551 void CXXFieldRecord::anchor() {}
552 void CXXClassRecord::anchor() {}
553 void CXXConstructorRecord::anchor() {}
554 void CXXDestructorRecord::anchor() {}
555 void CXXInstanceMethodRecord::anchor() {}
556 void CXXStaticMethodRecord::anchor() {}
557 void ObjCInstancePropertyRecord::anchor() {}
558 void ObjCClassPropertyRecord::anchor() {}
559 void ObjCInstanceVariableRecord::anchor() {}
560 void ObjCInstanceMethodRecord::anchor() {}
561 void ObjCClassMethodRecord::anchor() {}
562 void ObjCCategoryRecord::anchor() {}
563 void ObjCInterfaceRecord::anchor() {}
564 void ObjCProtocolRecord::anchor() {}
565 void MacroDefinitionRecord::anchor() {}
566 void TypedefRecord::anchor() {}
567