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