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