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