xref: /llvm-project/clang/lib/ExtractAPI/API.cpp (revision 80b787e803292119f30da2e1e95acff5beea61db)
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 ObjCCategoryRecord *APISet::addObjCCategory(
315     StringRef Name, StringRef USR, PresumedLoc Loc,
316     AvailabilitySet Availabilities, const DocComment &Comment,
317     DeclarationFragments Declaration, DeclarationFragments SubHeading,
318     SymbolReference Interface, bool IsFromSystemHeader,
319     bool IsFromExternalModule) {
320   // Create the category record.
321   auto *Record =
322       addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc,
323                         std::move(Availabilities), Comment, Declaration,
324                         SubHeading, Interface, IsFromSystemHeader);
325 
326   Record->IsFromExternalModule = IsFromExternalModule;
327 
328   auto It = ObjCInterfaces.find(Interface.USR);
329   if (It != ObjCInterfaces.end())
330     It->second->Categories.push_back(Record);
331 
332   return Record;
333 }
334 
335 ObjCInterfaceRecord *
336 APISet::addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
337                          AvailabilitySet Availabilities, LinkageInfo Linkage,
338                          const DocComment &Comment,
339                          DeclarationFragments Declaration,
340                          DeclarationFragments SubHeading,
341                          SymbolReference SuperClass, bool IsFromSystemHeader) {
342   return addTopLevelRecord(USRBasedLookupTable, ObjCInterfaces, USR, Name, Loc,
343                            std::move(Availabilities), Linkage, Comment,
344                            Declaration, SubHeading, SuperClass,
345                            IsFromSystemHeader);
346 }
347 
348 ObjCMethodRecord *APISet::addObjCMethod(
349     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
350     PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment,
351     DeclarationFragments Declaration, DeclarationFragments SubHeading,
352     FunctionSignature Signature, bool IsInstanceMethod,
353     bool IsFromSystemHeader) {
354   std::unique_ptr<ObjCMethodRecord> Record;
355   if (IsInstanceMethod)
356     Record = std::make_unique<ObjCInstanceMethodRecord>(
357         USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
358         SubHeading, Signature, IsFromSystemHeader);
359   else
360     Record = std::make_unique<ObjCClassMethodRecord>(
361         USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
362         SubHeading, Signature, IsFromSystemHeader);
363 
364   Record->ParentInformation = APIRecord::HierarchyInformation(
365       Container->USR, Container->Name, Container->getKind(), Container);
366   USRBasedLookupTable.insert({USR, Record.get()});
367   return Container->Methods.emplace_back(std::move(Record)).get();
368 }
369 
370 ObjCPropertyRecord *APISet::addObjCProperty(
371     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
372     PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment,
373     DeclarationFragments Declaration, DeclarationFragments SubHeading,
374     ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
375     StringRef SetterName, bool IsOptional, bool IsInstanceProperty,
376     bool IsFromSystemHeader) {
377   std::unique_ptr<ObjCPropertyRecord> Record;
378   if (IsInstanceProperty)
379     Record = std::make_unique<ObjCInstancePropertyRecord>(
380         USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
381         SubHeading, Attributes, GetterName, SetterName, IsOptional,
382         IsFromSystemHeader);
383   else
384     Record = std::make_unique<ObjCClassPropertyRecord>(
385         USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
386         SubHeading, Attributes, GetterName, SetterName, IsOptional,
387         IsFromSystemHeader);
388   Record->ParentInformation = APIRecord::HierarchyInformation(
389       Container->USR, Container->Name, Container->getKind(), Container);
390   USRBasedLookupTable.insert({USR, Record.get()});
391   return Container->Properties.emplace_back(std::move(Record)).get();
392 }
393 
394 ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
395     ObjCContainerRecord *Container, StringRef Name, StringRef USR,
396     PresumedLoc Loc, AvailabilitySet Availabilities, const DocComment &Comment,
397     DeclarationFragments Declaration, DeclarationFragments SubHeading,
398     ObjCInstanceVariableRecord::AccessControl Access, bool IsFromSystemHeader) {
399   auto Record = std::make_unique<ObjCInstanceVariableRecord>(
400       USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
401       SubHeading, Access, IsFromSystemHeader);
402   Record->ParentInformation = APIRecord::HierarchyInformation(
403       Container->USR, Container->Name, Container->getKind(), Container);
404   USRBasedLookupTable.insert({USR, Record.get()});
405   return Container->Ivars.emplace_back(std::move(Record)).get();
406 }
407 
408 ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR,
409                                             PresumedLoc Loc,
410                                             AvailabilitySet Availabilities,
411                                             const DocComment &Comment,
412                                             DeclarationFragments Declaration,
413                                             DeclarationFragments SubHeading,
414                                             bool IsFromSystemHeader) {
415   return addTopLevelRecord(USRBasedLookupTable, ObjCProtocols, USR, Name, Loc,
416                            std::move(Availabilities), Comment, Declaration,
417                            SubHeading, IsFromSystemHeader);
418 }
419 
420 MacroDefinitionRecord *
421 APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
422                            DeclarationFragments Declaration,
423                            DeclarationFragments SubHeading,
424                            bool IsFromSystemHeader) {
425   return addTopLevelRecord(USRBasedLookupTable, Macros, USR, Name, Loc,
426                            Declaration, SubHeading, IsFromSystemHeader);
427 }
428 
429 TypedefRecord *
430 APISet::addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
431                    AvailabilitySet Availabilities, const DocComment &Comment,
432                    DeclarationFragments Declaration,
433                    DeclarationFragments SubHeading,
434                    SymbolReference UnderlyingType, bool IsFromSystemHeader) {
435   return addTopLevelRecord(USRBasedLookupTable, Typedefs, USR, Name, Loc,
436                            std::move(Availabilities), Comment, Declaration,
437                            SubHeading, UnderlyingType, IsFromSystemHeader);
438 }
439 
440 APIRecord *APISet::findRecordForUSR(StringRef USR) const {
441   if (USR.empty())
442     return nullptr;
443 
444   return USRBasedLookupTable.lookup(USR);
445 }
446 
447 StringRef APISet::recordUSR(const Decl *D) {
448   SmallString<128> USR;
449   index::generateUSRForDecl(D, USR);
450   return copyString(USR);
451 }
452 
453 StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
454                                     const SourceManager &SM) {
455   SmallString<128> USR;
456   index::generateUSRForMacro(Name, SL, SM, USR);
457   return copyString(USR);
458 }
459 
460 StringRef APISet::copyString(StringRef String) {
461   if (String.empty())
462     return {};
463 
464   // No need to allocate memory and copy if the string has already been stored.
465   if (StringAllocator.identifyObject(String.data()))
466     return String;
467 
468   void *Ptr = StringAllocator.Allocate(String.size(), 1);
469   memcpy(Ptr, String.data(), String.size());
470   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
471 }
472 
473 APIRecord::~APIRecord() {}
474 ObjCContainerRecord::~ObjCContainerRecord() {}
475 ObjCMethodRecord::~ObjCMethodRecord() {}
476 ObjCPropertyRecord::~ObjCPropertyRecord() {}
477 CXXMethodRecord::~CXXMethodRecord() {}
478 
479 void GlobalFunctionRecord::anchor() {}
480 void GlobalVariableRecord::anchor() {}
481 void EnumConstantRecord::anchor() {}
482 void EnumRecord::anchor() {}
483 void StructFieldRecord::anchor() {}
484 void StructRecord::anchor() {}
485 void CXXFieldRecord::anchor() {}
486 void CXXClassRecord::anchor() {}
487 void CXXConstructorRecord::anchor() {}
488 void CXXDestructorRecord::anchor() {}
489 void CXXInstanceMethodRecord::anchor() {}
490 void CXXStaticMethodRecord::anchor() {}
491 void ObjCInstancePropertyRecord::anchor() {}
492 void ObjCClassPropertyRecord::anchor() {}
493 void ObjCInstanceVariableRecord::anchor() {}
494 void ObjCInstanceMethodRecord::anchor() {}
495 void ObjCClassMethodRecord::anchor() {}
496 void ObjCCategoryRecord::anchor() {}
497 void ObjCInterfaceRecord::anchor() {}
498 void ObjCProtocolRecord::anchor() {}
499 void MacroDefinitionRecord::anchor() {}
500 void TypedefRecord::anchor() {}
501