1 //===- ExtractAPI/API.h -----------------------------------------*- 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 defines the APIRecord-based structs and the APISet class.
11 ///
12 /// Clang ExtractAPI is a tool to collect API information from a given set of
13 /// header files. The structures in this file describe data representations of
14 /// the API information collected for various kinds of symbols.
15 ///
16 //===----------------------------------------------------------------------===//
17 
18 #ifndef LLVM_CLANG_EXTRACTAPI_API_H
19 #define LLVM_CLANG_EXTRACTAPI_API_H
20 
21 #include "clang/AST/Availability.h"
22 #include "clang/AST/Decl.h"
23 #include "clang/AST/DeclBase.h"
24 #include "clang/AST/DeclObjC.h"
25 #include "clang/AST/RawCommentList.h"
26 #include "clang/Basic/SourceLocation.h"
27 #include "clang/Basic/Specifiers.h"
28 #include "clang/ExtractAPI/DeclarationFragments.h"
29 #include "llvm/ADT/ArrayRef.h"
30 #include "llvm/ADT/MapVector.h"
31 #include "llvm/ADT/StringRef.h"
32 #include "llvm/Support/Allocator.h"
33 #include "llvm/Support/Casting.h"
34 #include "llvm/Support/Compiler.h"
35 #include "llvm/Support/ErrorHandling.h"
36 #include "llvm/Support/raw_ostream.h"
37 #include "llvm/TargetParser/Triple.h"
38 #include <cstddef>
39 #include <iterator>
40 #include <memory>
41 #include <optional>
42 #include <type_traits>
43 
44 namespace clang {
45 namespace extractapi {
46 
47 class Template {
48   struct TemplateParameter {
49     // "class", "typename", or concept name
50     std::string Type;
51     std::string Name;
52     unsigned int Index;
53     unsigned int Depth;
54     bool IsParameterPack;
55 
TemplateParameterTemplateParameter56     TemplateParameter(std::string Type, std::string Name, unsigned int Index,
57                       unsigned int Depth, bool IsParameterPack)
58         : Type(Type), Name(Name), Index(Index), Depth(Depth),
59           IsParameterPack(IsParameterPack) {}
60   };
61 
62   struct TemplateConstraint {
63     // type name of the constraint, if it has one
64     std::string Type;
65     std::string Kind;
66     std::string LHS, RHS;
67   };
68   llvm::SmallVector<TemplateParameter> Parameters;
69   llvm::SmallVector<TemplateConstraint> Constraints;
70 
71 public:
72   Template() = default;
73 
Template(const TemplateDecl * Decl)74   Template(const TemplateDecl *Decl) {
75     for (auto *const Parameter : *Decl->getTemplateParameters()) {
76       const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
77       if (!Param) // some params are null
78         continue;
79       std::string Type;
80       if (Param->hasTypeConstraint())
81         Type = Param->getTypeConstraint()->getNamedConcept()->getName().str();
82       else if (Param->wasDeclaredWithTypename())
83         Type = "typename";
84       else
85         Type = "class";
86 
87       addTemplateParameter(Type, Param->getName().str(), Param->getIndex(),
88                            Param->getDepth(), Param->isParameterPack());
89     }
90   }
91 
Template(const ClassTemplatePartialSpecializationDecl * Decl)92   Template(const ClassTemplatePartialSpecializationDecl *Decl) {
93     for (auto *const Parameter : *Decl->getTemplateParameters()) {
94       const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
95       if (!Param) // some params are null
96         continue;
97       std::string Type;
98       if (Param->hasTypeConstraint())
99         Type = Param->getTypeConstraint()->getNamedConcept()->getName().str();
100       else if (Param->wasDeclaredWithTypename())
101         Type = "typename";
102       else
103         Type = "class";
104 
105       addTemplateParameter(Type, Param->getName().str(), Param->getIndex(),
106                            Param->getDepth(), Param->isParameterPack());
107     }
108   }
109 
Template(const VarTemplatePartialSpecializationDecl * Decl)110   Template(const VarTemplatePartialSpecializationDecl *Decl) {
111     for (auto *const Parameter : *Decl->getTemplateParameters()) {
112       const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
113       if (!Param) // some params are null
114         continue;
115       std::string Type;
116       if (Param->hasTypeConstraint())
117         Type = Param->getTypeConstraint()->getNamedConcept()->getName().str();
118       else if (Param->wasDeclaredWithTypename())
119         Type = "typename";
120       else
121         Type = "class";
122 
123       addTemplateParameter(Type, Param->getName().str(), Param->getIndex(),
124                            Param->getDepth(), Param->isParameterPack());
125     }
126   }
127 
getParameters()128   const llvm::SmallVector<TemplateParameter> &getParameters() const {
129     return Parameters;
130   }
131 
getConstraints()132   const llvm::SmallVector<TemplateConstraint> &getConstraints() const {
133     return Constraints;
134   }
135 
addTemplateParameter(std::string Type,std::string Name,unsigned int Index,unsigned int Depth,bool IsParameterPack)136   void addTemplateParameter(std::string Type, std::string Name,
137                             unsigned int Index, unsigned int Depth,
138                             bool IsParameterPack) {
139     Parameters.emplace_back(Type, Name, Index, Depth, IsParameterPack);
140   }
141 
empty()142   bool empty() const { return Parameters.empty() && Constraints.empty(); }
143 };
144 
145 /// DocComment is a vector of RawComment::CommentLine.
146 ///
147 /// Each line represents one line of striped documentation comment,
148 /// with source range information. This simplifies calculating the source
149 /// location of a character in the doc comment for pointing back to the source
150 /// file.
151 /// e.g.
152 /// \code
153 ///   /// This is a documentation comment
154 ///       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'  First line.
155 ///   ///     with multiple lines.
156 ///       ^~~~~~~~~~~~~~~~~~~~~~~'         Second line.
157 /// \endcode
158 using DocComment = std::vector<RawComment::CommentLine>;
159 
160 struct APIRecord;
161 
162 // This represents a reference to another symbol that might come from external
163 /// sources.
164 struct SymbolReference {
165   StringRef Name;
166   StringRef USR;
167 
168   /// The source project/module/product of the referred symbol.
169   StringRef Source;
170 
171   // A Pointer to the APIRecord for this reference if known
172   const APIRecord *Record = nullptr;
173 
174   SymbolReference() = default;
175   SymbolReference(StringRef Name, StringRef USR, StringRef Source = "")
NameSymbolReference176       : Name(Name), USR(USR), Source(Source) {}
177   SymbolReference(const APIRecord *R);
178 
179   /// Determine if this SymbolReference is empty.
180   ///
181   /// \returns true if and only if all \c Name, \c USR, and \c Source is empty.
emptySymbolReference182   bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
183 };
184 
185 class RecordContext;
186 
187 // Concrete classes deriving from APIRecord need to have a construct with first
188 // arguments USR, and Name, in that order. This is so that they
189 // are compatible with `APISet::createRecord`.
190 // When adding a new kind of record don't forget to update APIRecords.inc!
191 /// The base representation of an API record. Holds common symbol information.
192 struct APIRecord {
193   /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
194   enum RecordKind {
195     RK_Unknown,
196     // If adding a record context record kind here make sure to update
197     // RecordContext::classof if needed and add a RECORD_CONTEXT entry to
198     // APIRecords.inc
199     RK_FirstRecordContext,
200     RK_Namespace,
201     RK_Enum,
202     RK_Struct,
203     RK_Union,
204     RK_ObjCInterface,
205     RK_ObjCCategory,
206     RK_ObjCProtocol,
207     RK_CXXClass,
208     RK_ClassTemplate,
209     RK_ClassTemplateSpecialization,
210     RK_ClassTemplatePartialSpecialization,
211     RK_StructField,
212     RK_UnionField,
213     RK_CXXField,
214     RK_StaticField,
215     RK_CXXFieldTemplate,
216     RK_GlobalVariable,
217     RK_GlobalVariableTemplate,
218     RK_GlobalVariableTemplateSpecialization,
219     RK_GlobalVariableTemplatePartialSpecialization,
220     RK_LastRecordContext,
221     RK_GlobalFunction,
222     RK_GlobalFunctionTemplate,
223     RK_GlobalFunctionTemplateSpecialization,
224     RK_EnumConstant,
225     RK_Concept,
226     RK_CXXStaticMethod,
227     RK_CXXInstanceMethod,
228     RK_CXXConstructorMethod,
229     RK_CXXDestructorMethod,
230     RK_CXXMethodTemplate,
231     RK_CXXMethodTemplateSpecialization,
232     RK_ObjCInstanceProperty,
233     RK_ObjCClassProperty,
234     RK_ObjCIvar,
235     RK_ObjCClassMethod,
236     RK_ObjCInstanceMethod,
237     RK_MacroDefinition,
238     RK_Typedef,
239   };
240 
241   StringRef USR;
242   StringRef Name;
243 
244   SymbolReference Parent;
245 
246   PresumedLoc Location;
247   AvailabilityInfo Availability;
248   LinkageInfo Linkage;
249 
250   /// Documentation comment lines attached to this symbol declaration.
251   DocComment Comment;
252 
253   /// Declaration fragments of this symbol declaration.
254   DeclarationFragments Declaration;
255 
256   /// SubHeading provides a more detailed representation than the plain
257   /// declaration name.
258   ///
259   /// SubHeading is an array of declaration fragments of tagged declaration
260   /// name, with potentially more tokens (for example the \c +/- symbol for
261   /// Objective-C class/instance methods).
262   DeclarationFragments SubHeading;
263 
264   /// Whether the symbol was defined in a system header.
265   bool IsFromSystemHeader;
266 
267   AccessControl Access;
268 
269 private:
270   const RecordKind Kind;
271   friend class RecordContext;
272   // Used to store the next child record in RecordContext. This works because
273   // APIRecords semantically only have one parent.
274   mutable APIRecord *NextInContext = nullptr;
275 
276 public:
getNextInContextAPIRecord277   APIRecord *getNextInContext() const { return NextInContext; }
278 
getKindAPIRecord279   RecordKind getKind() const { return Kind; }
280 
281   static APIRecord *castFromRecordContext(const RecordContext *Ctx);
282   static RecordContext *castToRecordContext(const APIRecord *Record);
283 
284   APIRecord() = delete;
285 
286   APIRecord(RecordKind Kind, StringRef USR, StringRef Name,
287             SymbolReference Parent, PresumedLoc Location,
288             AvailabilityInfo Availability, LinkageInfo Linkage,
289             const DocComment &Comment, DeclarationFragments Declaration,
290             DeclarationFragments SubHeading, bool IsFromSystemHeader,
291             AccessControl Access = AccessControl())
USRAPIRecord292       : USR(USR), Name(Name), Parent(std::move(Parent)), Location(Location),
293         Availability(std::move(Availability)), Linkage(Linkage),
294         Comment(Comment), Declaration(Declaration), SubHeading(SubHeading),
295         IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)),
296         Kind(Kind) {}
297 
APIRecordAPIRecord298   APIRecord(RecordKind Kind, StringRef USR, StringRef Name)
299       : USR(USR), Name(Name), Kind(Kind) {}
300 
301   // Pure virtual destructor to make APIRecord abstract
302   virtual ~APIRecord() = 0;
classofAPIRecord303   static bool classof(const APIRecord *Record) { return true; }
classofKindAPIRecord304   static bool classofKind(RecordKind K) { return true; }
classofAPIRecord305   static bool classof(const RecordContext *Ctx) { return true; }
306 };
307 
308 /// Base class used for specific record types that have children records this is
309 /// analogous to the DeclContext for the AST
310 class RecordContext {
311 public:
classof(const APIRecord * Record)312   static bool classof(const APIRecord *Record) {
313     return classofKind(Record->getKind());
314   }
classofKind(APIRecord::RecordKind K)315   static bool classofKind(APIRecord::RecordKind K) {
316     return K > APIRecord::RK_FirstRecordContext &&
317            K < APIRecord::RK_LastRecordContext;
318   }
319 
classof(const RecordContext * Context)320   static bool classof(const RecordContext *Context) { return true; }
321 
RecordContext(APIRecord::RecordKind Kind)322   RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}
323 
324   /// Append \p Other children chain into ours and empty out Other's record
325   /// chain.
326   void stealRecordChain(RecordContext &Other);
327 
getKind()328   APIRecord::RecordKind getKind() const { return Kind; }
329 
330   struct record_iterator {
331   private:
332     APIRecord *Current = nullptr;
333 
334   public:
335     using value_type = APIRecord *;
336     using reference = const value_type &;
337     using pointer = const value_type *;
338     using iterator_category = std::forward_iterator_tag;
339     using difference_type = std::ptrdiff_t;
340 
341     record_iterator() = default;
record_iteratorrecord_iterator342     explicit record_iterator(value_type R) : Current(R) {}
343     reference operator*() const { return Current; }
344     // This doesn't strictly meet the iterator requirements, but it's the
345     // behavior we want here.
346     value_type operator->() const { return Current; }
347     record_iterator &operator++() {
348       Current = Current->getNextInContext();
349       return *this;
350     }
351     record_iterator operator++(int) {
352       record_iterator tmp(*this);
353       ++(*this);
354       return tmp;
355     }
356 
357     friend bool operator==(record_iterator x, record_iterator y) {
358       return x.Current == y.Current;
359     }
360     friend bool operator!=(record_iterator x, record_iterator y) {
361       return x.Current != y.Current;
362     }
363   };
364 
365   using record_range = llvm::iterator_range<record_iterator>;
records()366   record_range records() const {
367     return record_range(records_begin(), records_end());
368   }
records_begin()369   record_iterator records_begin() const { return record_iterator(First); };
records_end()370   record_iterator records_end() const { return record_iterator(); }
records_empty()371   bool records_empty() const { return First == nullptr; };
372 
373 private:
374   APIRecord::RecordKind Kind;
375   mutable APIRecord *First = nullptr;
376   mutable APIRecord *Last = nullptr;
377   bool IsWellFormed() const;
378 
379 protected:
380   friend class APISet;
381   void addToRecordChain(APIRecord *) const;
382 };
383 
384 struct NamespaceRecord : APIRecord, RecordContext {
NamespaceRecordNamespaceRecord385   NamespaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
386                   PresumedLoc Loc, AvailabilityInfo Availability,
387                   LinkageInfo Linkage, const DocComment &Comment,
388                   DeclarationFragments Declaration,
389                   DeclarationFragments SubHeading, bool IsFromSystemHeader)
390       : APIRecord(RK_Namespace, USR, Name, Parent, Loc, std::move(Availability),
391                   Linkage, Comment, Declaration, SubHeading,
392                   IsFromSystemHeader),
393         RecordContext(RK_Namespace) {}
394 
classofNamespaceRecord395   static bool classof(const APIRecord *Record) {
396     return classofKind(Record->getKind());
397   }
classofKindNamespaceRecord398   static bool classofKind(RecordKind K) { return K == RK_Namespace; }
399 };
400 
401 /// This holds information associated with global functions.
402 struct GlobalFunctionRecord : APIRecord {
403   FunctionSignature Signature;
404 
GlobalFunctionRecordGlobalFunctionRecord405   GlobalFunctionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
406                        PresumedLoc Loc, AvailabilityInfo Availability,
407                        LinkageInfo Linkage, const DocComment &Comment,
408                        DeclarationFragments Declaration,
409                        DeclarationFragments SubHeading,
410                        FunctionSignature Signature, bool IsFromSystemHeader)
411       : APIRecord(RK_GlobalFunction, USR, Name, Parent, Loc,
412                   std::move(Availability), Linkage, Comment, Declaration,
413                   SubHeading, IsFromSystemHeader),
414         Signature(Signature) {}
415 
GlobalFunctionRecordGlobalFunctionRecord416   GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
417                        SymbolReference Parent, PresumedLoc Loc,
418                        AvailabilityInfo Availability, LinkageInfo Linkage,
419                        const DocComment &Comment,
420                        DeclarationFragments Declaration,
421                        DeclarationFragments SubHeading,
422                        FunctionSignature Signature, bool IsFromSystemHeader)
423       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
424                   Linkage, Comment, Declaration, SubHeading,
425                   IsFromSystemHeader),
426         Signature(Signature) {}
427 
classofGlobalFunctionRecord428   static bool classof(const APIRecord *Record) {
429     return classofKind(Record->getKind());
430   }
classofKindGlobalFunctionRecord431   static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; }
432 
433 private:
434   virtual void anchor();
435 };
436 
437 struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
438   Template Templ;
439 
GlobalFunctionTemplateRecordGlobalFunctionTemplateRecord440   GlobalFunctionTemplateRecord(StringRef USR, StringRef Name,
441                                SymbolReference Parent, PresumedLoc Loc,
442                                AvailabilityInfo Availability,
443                                LinkageInfo Linkage, const DocComment &Comment,
444                                DeclarationFragments Declaration,
445                                DeclarationFragments SubHeading,
446                                FunctionSignature Signature, Template Template,
447                                bool IsFromSystemHeader)
448       : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Parent, Loc,
449                              std::move(Availability), Linkage, Comment,
450                              Declaration, SubHeading, Signature,
451                              IsFromSystemHeader),
452         Templ(Template) {}
453 
classofGlobalFunctionTemplateRecord454   static bool classof(const APIRecord *Record) {
455     return classofKind(Record->getKind());
456   }
classofKindGlobalFunctionTemplateRecord457   static bool classofKind(RecordKind K) {
458     return K == RK_GlobalFunctionTemplate;
459   }
460 };
461 
462 struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
GlobalFunctionTemplateSpecializationRecordGlobalFunctionTemplateSpecializationRecord463   GlobalFunctionTemplateSpecializationRecord(
464       StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
465       AvailabilityInfo Availability, LinkageInfo Linkage,
466       const DocComment &Comment, DeclarationFragments Declaration,
467       DeclarationFragments SubHeading, FunctionSignature Signature,
468       bool IsFromSystemHeader)
469       : GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
470                              Parent, Loc, std::move(Availability), Linkage,
471                              Comment, Declaration, SubHeading, Signature,
472                              IsFromSystemHeader) {}
473 
classofGlobalFunctionTemplateSpecializationRecord474   static bool classof(const APIRecord *Record) {
475     return classofKind(Record->getKind());
476   }
classofKindGlobalFunctionTemplateSpecializationRecord477   static bool classofKind(RecordKind K) {
478     return K == RK_GlobalFunctionTemplateSpecialization;
479   }
480 };
481 
482 /// This holds information associated with global functions.
483 struct GlobalVariableRecord : APIRecord, RecordContext {
GlobalVariableRecordGlobalVariableRecord484   GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
485                        PresumedLoc Loc, AvailabilityInfo Availability,
486                        LinkageInfo Linkage, const DocComment &Comment,
487                        DeclarationFragments Declaration,
488                        DeclarationFragments SubHeading, bool IsFromSystemHeader)
489       : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
490                   std::move(Availability), Linkage, Comment, Declaration,
491                   SubHeading, IsFromSystemHeader),
492         RecordContext(RK_GlobalVariable) {}
493 
GlobalVariableRecordGlobalVariableRecord494   GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
495                        SymbolReference Parent, PresumedLoc Loc,
496                        AvailabilityInfo Availability, LinkageInfo Linkage,
497                        const DocComment &Comment,
498                        DeclarationFragments Declaration,
499                        DeclarationFragments SubHeading, bool IsFromSystemHeader)
500       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
501                   Linkage, Comment, Declaration, SubHeading,
502                   IsFromSystemHeader),
503         RecordContext(Kind) {}
504 
classofGlobalVariableRecord505   static bool classof(const APIRecord *Record) {
506     return classofKind(Record->getKind());
507   }
classofKindGlobalVariableRecord508   static bool classofKind(RecordKind K) {
509     return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate ||
510            K == RK_GlobalVariableTemplateSpecialization ||
511            K == RK_GlobalVariableTemplatePartialSpecialization;
512   }
513 
514 private:
515   virtual void anchor();
516 };
517 
518 struct GlobalVariableTemplateRecord : GlobalVariableRecord {
519   Template Templ;
520 
GlobalVariableTemplateRecordGlobalVariableTemplateRecord521   GlobalVariableTemplateRecord(StringRef USR, StringRef Name,
522                                SymbolReference Parent, PresumedLoc Loc,
523                                AvailabilityInfo Availability,
524                                LinkageInfo Linkage, const DocComment &Comment,
525                                DeclarationFragments Declaration,
526                                DeclarationFragments SubHeading,
527                                class Template Template, bool IsFromSystemHeader)
528       : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Parent, Loc,
529                              std::move(Availability), Linkage, Comment,
530                              Declaration, SubHeading, IsFromSystemHeader),
531         Templ(Template) {}
532 
classofGlobalVariableTemplateRecord533   static bool classof(const APIRecord *Record) {
534     return classofKind(Record->getKind());
535   }
classofKindGlobalVariableTemplateRecord536   static bool classofKind(RecordKind K) {
537     return K == RK_GlobalVariableTemplate;
538   }
539 };
540 
541 struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord {
GlobalVariableTemplateSpecializationRecordGlobalVariableTemplateSpecializationRecord542   GlobalVariableTemplateSpecializationRecord(
543       StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
544       AvailabilityInfo Availability, LinkageInfo Linkage,
545       const DocComment &Comment, DeclarationFragments Declaration,
546       DeclarationFragments SubHeading, bool IsFromSystemHeader)
547       : GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name,
548                              Parent, Loc, std::move(Availability), Linkage,
549                              Comment, Declaration, SubHeading,
550                              IsFromSystemHeader) {}
551 
classofGlobalVariableTemplateSpecializationRecord552   static bool classof(const APIRecord *Record) {
553     return classofKind(Record->getKind());
554   }
classofKindGlobalVariableTemplateSpecializationRecord555   static bool classofKind(RecordKind K) {
556     return K == RK_GlobalVariableTemplateSpecialization;
557   }
558 };
559 
560 struct GlobalVariableTemplatePartialSpecializationRecord
561     : GlobalVariableRecord {
562   Template Templ;
563 
GlobalVariableTemplatePartialSpecializationRecordGlobalVariableTemplatePartialSpecializationRecord564   GlobalVariableTemplatePartialSpecializationRecord(
565       StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
566       AvailabilityInfo Availability, LinkageInfo Linkage,
567       const DocComment &Comment, DeclarationFragments Declaration,
568       DeclarationFragments SubHeading, class Template Template,
569       bool IsFromSystemHeader)
570       : GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization,
571                              USR, Name, Parent, Loc, std::move(Availability),
572                              Linkage, Comment, Declaration, SubHeading,
573                              IsFromSystemHeader),
574         Templ(Template) {}
575 
classofGlobalVariableTemplatePartialSpecializationRecord576   static bool classof(const APIRecord *Record) {
577     return classofKind(Record->getKind());
578   }
classofKindGlobalVariableTemplatePartialSpecializationRecord579   static bool classofKind(RecordKind K) {
580     return K == RK_GlobalVariableTemplatePartialSpecialization;
581   }
582 };
583 
584 /// This holds information associated with enum constants.
585 struct EnumConstantRecord : APIRecord {
EnumConstantRecordEnumConstantRecord586   EnumConstantRecord(StringRef USR, StringRef Name, SymbolReference Parent,
587                      PresumedLoc Loc, AvailabilityInfo Availability,
588                      const DocComment &Comment,
589                      DeclarationFragments Declaration,
590                      DeclarationFragments SubHeading, bool IsFromSystemHeader)
591       : APIRecord(RK_EnumConstant, USR, Name, Parent, Loc,
592                   std::move(Availability), LinkageInfo::none(), Comment,
593                   Declaration, SubHeading, IsFromSystemHeader) {}
594 
classofEnumConstantRecord595   static bool classof(const APIRecord *Record) {
596     return classofKind(Record->getKind());
597   }
classofKindEnumConstantRecord598   static bool classofKind(RecordKind K) { return K == RK_EnumConstant; }
599 
600 private:
601   virtual void anchor();
602 };
603 
604 struct TagRecord : APIRecord, RecordContext {
605   TagRecord(RecordKind Kind, StringRef USR, StringRef Name,
606             SymbolReference Parent, PresumedLoc Loc,
607             AvailabilityInfo Availability, const DocComment &Comment,
608             DeclarationFragments Declaration, DeclarationFragments SubHeading,
609             bool IsFromSystemHeader, bool IsEmbeddedInVarDeclarator,
610             AccessControl Access = AccessControl())
APIRecordTagRecord611       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
612                   LinkageInfo::none(), Comment, Declaration, SubHeading,
613                   IsFromSystemHeader, std::move(Access)),
614         RecordContext(Kind),
615         IsEmbeddedInVarDeclarator(IsEmbeddedInVarDeclarator){};
616 
classofTagRecord617   static bool classof(const APIRecord *Record) {
618     return classofKind(Record->getKind());
619   }
classofKindTagRecord620   static bool classofKind(RecordKind K) {
621     return K == RK_Struct || K == RK_Union || K == RK_Enum;
622   }
623 
624   bool IsEmbeddedInVarDeclarator;
625 
626   virtual ~TagRecord() = 0;
627 };
628 
629 /// This holds information associated with enums.
630 struct EnumRecord : TagRecord {
631   EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
632              PresumedLoc Loc, AvailabilityInfo Availability,
633              const DocComment &Comment, DeclarationFragments Declaration,
634              DeclarationFragments SubHeading, bool IsFromSystemHeader,
635              bool IsEmbeddedInVarDeclarator,
636              AccessControl Access = AccessControl())
TagRecordEnumRecord637       : TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
638                   Comment, Declaration, SubHeading, IsFromSystemHeader,
639                   IsEmbeddedInVarDeclarator, std::move(Access)) {}
640 
classofEnumRecord641   static bool classof(const APIRecord *Record) {
642     return classofKind(Record->getKind());
643   }
644 
classofKindEnumRecord645   static bool classofKind(RecordKind K) { return K == RK_Enum; }
646 
647 private:
648   virtual void anchor();
649 };
650 
651 /// This holds information associated with struct or union fields fields.
652 struct RecordFieldRecord : APIRecord, RecordContext {
RecordFieldRecordRecordFieldRecord653   RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
654                     SymbolReference Parent, PresumedLoc Loc,
655                     AvailabilityInfo Availability, const DocComment &Comment,
656                     DeclarationFragments Declaration,
657                     DeclarationFragments SubHeading, bool IsFromSystemHeader)
658       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
659                   LinkageInfo::none(), Comment, Declaration, SubHeading,
660                   IsFromSystemHeader),
661         RecordContext(Kind) {}
662 
classofRecordFieldRecord663   static bool classof(const APIRecord *Record) {
664     return classofKind(Record->getKind());
665   }
classofKindRecordFieldRecord666   static bool classofKind(RecordKind K) {
667     return K == RK_StructField || K == RK_UnionField;
668   }
669 
670   virtual ~RecordFieldRecord() = 0;
671 };
672 
673 /// This holds information associated with structs and unions.
674 struct RecordRecord : TagRecord {
675   RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
676                SymbolReference Parent, PresumedLoc Loc,
677                AvailabilityInfo Availability, const DocComment &Comment,
678                DeclarationFragments Declaration,
679                DeclarationFragments SubHeading, bool IsFromSystemHeader,
680                bool IsEmbeddedInVarDeclarator,
681                AccessControl Access = AccessControl())
TagRecordRecordRecord682       : TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
683                   Comment, Declaration, SubHeading, IsFromSystemHeader,
684                   IsEmbeddedInVarDeclarator, std::move(Access)) {}
685 
classofRecordRecord686   static bool classof(const APIRecord *Record) {
687     return classofKind(Record->getKind());
688   }
classofKindRecordRecord689   static bool classofKind(RecordKind K) {
690     return K == RK_Struct || K == RK_Union;
691   }
692 
isAnonymousWithNoTypedefRecordRecord693   bool isAnonymousWithNoTypedef() { return Name.empty(); }
694 
695   virtual ~RecordRecord() = 0;
696 };
697 
698 struct StructFieldRecord : RecordFieldRecord {
StructFieldRecordStructFieldRecord699   StructFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
700                     PresumedLoc Loc, AvailabilityInfo Availability,
701                     const DocComment &Comment, DeclarationFragments Declaration,
702                     DeclarationFragments SubHeading, bool IsFromSystemHeader)
703       : RecordFieldRecord(RK_StructField, USR, Name, Parent, Loc,
704                           std::move(Availability), Comment, Declaration,
705                           SubHeading, IsFromSystemHeader) {}
706 
classofStructFieldRecord707   static bool classof(const APIRecord *Record) {
708     return classofKind(Record->getKind());
709   }
classofKindStructFieldRecord710   static bool classofKind(RecordKind K) { return K == RK_StructField; }
711 
712 private:
713   virtual void anchor();
714 };
715 
716 struct StructRecord : RecordRecord {
StructRecordStructRecord717   StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
718                PresumedLoc Loc, AvailabilityInfo Availability,
719                const DocComment &Comment, DeclarationFragments Declaration,
720                DeclarationFragments SubHeading, bool IsFromSystemHeader,
721                bool IsEmbeddedInVarDeclarator)
722       : RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
723                      Comment, Declaration, SubHeading, IsFromSystemHeader,
724                      IsEmbeddedInVarDeclarator) {}
725 
classofStructRecord726   static bool classof(const APIRecord *Record) {
727     return classofKind(Record->getKind());
728   }
classofKindStructRecord729   static bool classofKind(RecordKind K) { return K == RK_Struct; }
730 
731 private:
732   virtual void anchor();
733 };
734 
735 struct UnionFieldRecord : RecordFieldRecord {
UnionFieldRecordUnionFieldRecord736   UnionFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
737                    PresumedLoc Loc, AvailabilityInfo Availability,
738                    const DocComment &Comment, DeclarationFragments Declaration,
739                    DeclarationFragments SubHeading, bool IsFromSystemHeader)
740       : RecordFieldRecord(RK_UnionField, USR, Name, Parent, Loc,
741                           std::move(Availability), Comment, Declaration,
742                           SubHeading, IsFromSystemHeader) {}
743 
classofUnionFieldRecord744   static bool classof(const APIRecord *Record) {
745     return classofKind(Record->getKind());
746   }
classofKindUnionFieldRecord747   static bool classofKind(RecordKind K) { return K == RK_UnionField; }
748 
749 private:
750   virtual void anchor();
751 };
752 
753 struct UnionRecord : RecordRecord {
UnionRecordUnionRecord754   UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
755               PresumedLoc Loc, AvailabilityInfo Availability,
756               const DocComment &Comment, DeclarationFragments Declaration,
757               DeclarationFragments SubHeading, bool IsFromSystemHeader,
758               bool IsEmbeddedInVarDeclarator)
759       : RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
760                      Comment, Declaration, SubHeading, IsFromSystemHeader,
761                      IsEmbeddedInVarDeclarator) {}
762 
classofUnionRecord763   static bool classof(const APIRecord *Record) {
764     return classofKind(Record->getKind());
765   }
classofKindUnionRecord766   static bool classofKind(RecordKind K) { return K == RK_Union; }
767 
768 private:
769   virtual void anchor();
770 };
771 
772 struct CXXFieldRecord : APIRecord, RecordContext {
CXXFieldRecordCXXFieldRecord773   CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
774                  PresumedLoc Loc, AvailabilityInfo Availability,
775                  const DocComment &Comment, DeclarationFragments Declaration,
776                  DeclarationFragments SubHeading, AccessControl Access,
777                  bool IsFromSystemHeader)
778       : APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
779                   LinkageInfo::none(), Comment, Declaration, SubHeading,
780                   IsFromSystemHeader, std::move(Access)),
781         RecordContext(RK_CXXField) {}
782 
CXXFieldRecordCXXFieldRecord783   CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
784                  SymbolReference Parent, PresumedLoc Loc,
785                  AvailabilityInfo Availability, const DocComment &Comment,
786                  DeclarationFragments Declaration,
787                  DeclarationFragments SubHeading, AccessControl Access,
788                  bool IsFromSystemHeader)
789       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
790                   LinkageInfo::none(), Comment, Declaration, SubHeading,
791                   IsFromSystemHeader, std::move(Access)),
792         RecordContext(Kind) {}
793 
classofCXXFieldRecord794   static bool classof(const APIRecord *Record) {
795     return classofKind(Record->getKind());
796   }
classofKindCXXFieldRecord797   static bool classofKind(RecordKind K) {
798     return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField;
799   }
800 
801 private:
802   virtual void anchor();
803 };
804 
805 struct CXXFieldTemplateRecord : CXXFieldRecord {
806   Template Templ;
807 
CXXFieldTemplateRecordCXXFieldTemplateRecord808   CXXFieldTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
809                          PresumedLoc Loc, AvailabilityInfo Availability,
810                          const DocComment &Comment,
811                          DeclarationFragments Declaration,
812                          DeclarationFragments SubHeading, AccessControl Access,
813                          Template Template, bool IsFromSystemHeader)
814       : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Parent, Loc,
815                        std::move(Availability), Comment, Declaration,
816                        SubHeading, std::move(Access), IsFromSystemHeader),
817         Templ(Template) {}
818 
classofCXXFieldTemplateRecord819   static bool classof(const APIRecord *Record) {
820     return classofKind(Record->getKind());
821   }
classofKindCXXFieldTemplateRecord822   static bool classofKind(RecordKind K) { return K == RK_CXXFieldTemplate; }
823 };
824 
825 struct CXXMethodRecord : APIRecord {
826   FunctionSignature Signature;
827 
828   CXXMethodRecord() = delete;
829 
CXXMethodRecordCXXMethodRecord830   CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
831                   SymbolReference Parent, PresumedLoc Loc,
832                   AvailabilityInfo Availability, const DocComment &Comment,
833                   DeclarationFragments Declaration,
834                   DeclarationFragments SubHeading, FunctionSignature Signature,
835                   AccessControl Access, bool IsFromSystemHeader)
836       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
837                   LinkageInfo::none(), Comment, Declaration, SubHeading,
838                   IsFromSystemHeader, std::move(Access)),
839         Signature(Signature) {}
840 
841   virtual ~CXXMethodRecord() = 0;
842 };
843 
844 struct CXXConstructorRecord : CXXMethodRecord {
CXXConstructorRecordCXXConstructorRecord845   CXXConstructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
846                        PresumedLoc Loc, AvailabilityInfo Availability,
847                        const DocComment &Comment,
848                        DeclarationFragments Declaration,
849                        DeclarationFragments SubHeading,
850                        FunctionSignature Signature, AccessControl Access,
851                        bool IsFromSystemHeader)
852       : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Parent, Loc,
853                         std::move(Availability), Comment, Declaration,
854                         SubHeading, Signature, std::move(Access),
855                         IsFromSystemHeader) {}
classofCXXConstructorRecord856   static bool classof(const APIRecord *Record) {
857     return classofKind(Record->getKind());
858   }
classofKindCXXConstructorRecord859   static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; }
860 
861 private:
862   virtual void anchor();
863 };
864 
865 struct CXXDestructorRecord : CXXMethodRecord {
CXXDestructorRecordCXXDestructorRecord866   CXXDestructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
867                       PresumedLoc Loc, AvailabilityInfo Availability,
868                       const DocComment &Comment,
869                       DeclarationFragments Declaration,
870                       DeclarationFragments SubHeading,
871                       FunctionSignature Signature, AccessControl Access,
872                       bool IsFromSystemHeader)
873       : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Parent, Loc,
874                         std::move(Availability), Comment, Declaration,
875                         SubHeading, Signature, std::move(Access),
876                         IsFromSystemHeader) {}
classofCXXDestructorRecord877   static bool classof(const APIRecord *Record) {
878     return classofKind(Record->getKind());
879   }
classofKindCXXDestructorRecord880   static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; }
881 
882 private:
883   virtual void anchor();
884 };
885 
886 struct CXXStaticMethodRecord : CXXMethodRecord {
CXXStaticMethodRecordCXXStaticMethodRecord887   CXXStaticMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
888                         PresumedLoc Loc, AvailabilityInfo Availability,
889                         const DocComment &Comment,
890                         DeclarationFragments Declaration,
891                         DeclarationFragments SubHeading,
892                         FunctionSignature Signature, AccessControl Access,
893                         bool IsFromSystemHeader)
894       : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Parent, Loc,
895                         std::move(Availability), Comment, Declaration,
896                         SubHeading, Signature, std::move(Access),
897                         IsFromSystemHeader) {}
classofCXXStaticMethodRecord898   static bool classof(const APIRecord *Record) {
899     return classofKind(Record->getKind());
900   }
classofKindCXXStaticMethodRecord901   static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; }
902 
903 private:
904   virtual void anchor();
905 };
906 
907 struct CXXInstanceMethodRecord : CXXMethodRecord {
CXXInstanceMethodRecordCXXInstanceMethodRecord908   CXXInstanceMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
909                           PresumedLoc Loc, AvailabilityInfo Availability,
910                           const DocComment &Comment,
911                           DeclarationFragments Declaration,
912                           DeclarationFragments SubHeading,
913                           FunctionSignature Signature, AccessControl Access,
914                           bool IsFromSystemHeader)
915       : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Parent, Loc,
916                         std::move(Availability), Comment, Declaration,
917                         SubHeading, Signature, std::move(Access),
918                         IsFromSystemHeader) {}
919 
classofCXXInstanceMethodRecord920   static bool classof(const APIRecord *Record) {
921     return classofKind(Record->getKind());
922   }
classofKindCXXInstanceMethodRecord923   static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; }
924 
925 private:
926   virtual void anchor();
927 };
928 
929 struct CXXMethodTemplateRecord : CXXMethodRecord {
930   Template Templ;
931 
CXXMethodTemplateRecordCXXMethodTemplateRecord932   CXXMethodTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
933                           PresumedLoc Loc, AvailabilityInfo Availability,
934                           const DocComment &Comment,
935                           DeclarationFragments Declaration,
936                           DeclarationFragments SubHeading,
937                           FunctionSignature Signature, AccessControl Access,
938                           Template Template, bool IsFromSystemHeader)
939       : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Parent, Loc,
940                         std::move(Availability), Comment, Declaration,
941                         SubHeading, Signature, std::move(Access),
942                         IsFromSystemHeader),
943         Templ(Template) {}
944 
classofCXXMethodTemplateRecord945   static bool classof(const APIRecord *Record) {
946     return classofKind(Record->getKind());
947   }
classofKindCXXMethodTemplateRecord948   static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; }
949 };
950 
951 struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
CXXMethodTemplateSpecializationRecordCXXMethodTemplateSpecializationRecord952   CXXMethodTemplateSpecializationRecord(
953       StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
954       AvailabilityInfo Availability, const DocComment &Comment,
955       DeclarationFragments Declaration, DeclarationFragments SubHeading,
956       FunctionSignature Signature, AccessControl Access,
957       bool IsFromSystemHeader)
958       : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Parent,
959                         Loc, std::move(Availability), Comment, Declaration,
960                         SubHeading, Signature, std::move(Access),
961                         IsFromSystemHeader) {}
962 
classofCXXMethodTemplateSpecializationRecord963   static bool classof(const APIRecord *Record) {
964     return classofKind(Record->getKind());
965   }
classofKindCXXMethodTemplateSpecializationRecord966   static bool classofKind(RecordKind K) {
967     return K == RK_CXXMethodTemplateSpecialization;
968   }
969 };
970 
971 /// This holds information associated with Objective-C properties.
972 struct ObjCPropertyRecord : APIRecord {
973   /// The attributes associated with an Objective-C property.
974   enum AttributeKind : unsigned {
975     NoAttr = 0,
976     ReadOnly = 1,
977     Dynamic = 1 << 2,
978   };
979 
980   AttributeKind Attributes;
981   StringRef GetterName;
982   StringRef SetterName;
983   bool IsOptional;
984 
ObjCPropertyRecordObjCPropertyRecord985   ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name,
986                      SymbolReference Parent, PresumedLoc Loc,
987                      AvailabilityInfo Availability, const DocComment &Comment,
988                      DeclarationFragments Declaration,
989                      DeclarationFragments SubHeading, AttributeKind Attributes,
990                      StringRef GetterName, StringRef SetterName,
991                      bool IsOptional, bool IsFromSystemHeader)
992       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
993                   LinkageInfo::none(), Comment, Declaration, SubHeading,
994                   IsFromSystemHeader),
995         Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
996         IsOptional(IsOptional) {}
997 
isReadOnlyObjCPropertyRecord998   bool isReadOnly() const { return Attributes & ReadOnly; }
isDynamicObjCPropertyRecord999   bool isDynamic() const { return Attributes & Dynamic; }
1000 
1001   virtual ~ObjCPropertyRecord() = 0;
1002 };
1003 
1004 struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
ObjCInstancePropertyRecordObjCInstancePropertyRecord1005   ObjCInstancePropertyRecord(
1006       StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
1007       AvailabilityInfo Availability, const DocComment &Comment,
1008       DeclarationFragments Declaration, DeclarationFragments SubHeading,
1009       AttributeKind Attributes, StringRef GetterName, StringRef SetterName,
1010       bool IsOptional, bool IsFromSystemHeader)
1011       : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Parent, Loc,
1012                            std::move(Availability), Comment, Declaration,
1013                            SubHeading, Attributes, GetterName, SetterName,
1014                            IsOptional, IsFromSystemHeader) {}
1015 
classofObjCInstancePropertyRecord1016   static bool classof(const APIRecord *Record) {
1017     return classofKind(Record->getKind());
1018   }
classofKindObjCInstancePropertyRecord1019   static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; }
1020 
1021 private:
1022   virtual void anchor();
1023 };
1024 
1025 struct ObjCClassPropertyRecord : ObjCPropertyRecord {
ObjCClassPropertyRecordObjCClassPropertyRecord1026   ObjCClassPropertyRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1027                           PresumedLoc Loc, AvailabilityInfo Availability,
1028                           const DocComment &Comment,
1029                           DeclarationFragments Declaration,
1030                           DeclarationFragments SubHeading,
1031                           AttributeKind Attributes, StringRef GetterName,
1032                           StringRef SetterName, bool IsOptional,
1033                           bool IsFromSystemHeader)
1034       : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Parent, Loc,
1035                            std::move(Availability), Comment, Declaration,
1036                            SubHeading, Attributes, GetterName, SetterName,
1037                            IsOptional, IsFromSystemHeader) {}
1038 
classofObjCClassPropertyRecord1039   static bool classof(const APIRecord *Record) {
1040     return classofKind(Record->getKind());
1041   }
classofKindObjCClassPropertyRecord1042   static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; }
1043 
1044 private:
1045   virtual void anchor();
1046 };
1047 
1048 /// This holds information associated with Objective-C instance variables.
1049 struct ObjCInstanceVariableRecord : APIRecord {
ObjCInstanceVariableRecordObjCInstanceVariableRecord1050   ObjCInstanceVariableRecord(StringRef USR, StringRef Name,
1051                              SymbolReference Parent, PresumedLoc Loc,
1052                              AvailabilityInfo Availability,
1053                              const DocComment &Comment,
1054                              DeclarationFragments Declaration,
1055                              DeclarationFragments SubHeading,
1056                              bool IsFromSystemHeader)
1057       : APIRecord(RK_ObjCIvar, USR, Name, Parent, Loc, std::move(Availability),
1058                   LinkageInfo::none(), Comment, Declaration, SubHeading,
1059                   IsFromSystemHeader) {}
1060 
classofObjCInstanceVariableRecord1061   static bool classof(const APIRecord *Record) {
1062     return classofKind(Record->getKind());
1063   }
classofKindObjCInstanceVariableRecord1064   static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; }
1065 
1066 private:
1067   virtual void anchor();
1068 };
1069 
1070 /// This holds information associated with Objective-C methods.
1071 struct ObjCMethodRecord : APIRecord {
1072   FunctionSignature Signature;
1073 
1074   ObjCMethodRecord() = delete;
1075 
ObjCMethodRecordObjCMethodRecord1076   ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
1077                    SymbolReference Parent, PresumedLoc Loc,
1078                    AvailabilityInfo Availability, const DocComment &Comment,
1079                    DeclarationFragments Declaration,
1080                    DeclarationFragments SubHeading, FunctionSignature Signature,
1081                    bool IsFromSystemHeader)
1082       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1083                   LinkageInfo::none(), Comment, Declaration, SubHeading,
1084                   IsFromSystemHeader),
1085         Signature(Signature) {}
1086 
1087   virtual ~ObjCMethodRecord() = 0;
1088 };
1089 
1090 struct ObjCInstanceMethodRecord : ObjCMethodRecord {
ObjCInstanceMethodRecordObjCInstanceMethodRecord1091   ObjCInstanceMethodRecord(StringRef USR, StringRef Name,
1092                            SymbolReference Parent, PresumedLoc Loc,
1093                            AvailabilityInfo Availability,
1094                            const DocComment &Comment,
1095                            DeclarationFragments Declaration,
1096                            DeclarationFragments SubHeading,
1097                            FunctionSignature Signature, bool IsFromSystemHeader)
1098       : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Parent, Loc,
1099                          std::move(Availability), Comment, Declaration,
1100                          SubHeading, Signature, IsFromSystemHeader) {}
classofObjCInstanceMethodRecord1101   static bool classof(const APIRecord *Record) {
1102     return classofKind(Record->getKind());
1103   }
classofKindObjCInstanceMethodRecord1104   static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; }
1105 
1106 private:
1107   virtual void anchor();
1108 };
1109 
1110 struct ObjCClassMethodRecord : ObjCMethodRecord {
ObjCClassMethodRecordObjCClassMethodRecord1111   ObjCClassMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1112                         PresumedLoc Loc, AvailabilityInfo Availability,
1113                         const DocComment &Comment,
1114                         DeclarationFragments Declaration,
1115                         DeclarationFragments SubHeading,
1116                         FunctionSignature Signature, bool IsFromSystemHeader)
1117       : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Parent, Loc,
1118                          std::move(Availability), Comment, Declaration,
1119                          SubHeading, Signature, IsFromSystemHeader) {}
1120 
classofObjCClassMethodRecord1121   static bool classof(const APIRecord *Record) {
1122     return classofKind(Record->getKind());
1123   }
classofKindObjCClassMethodRecord1124   static bool classofKind(RecordKind K) { return K == RK_ObjCClassMethod; }
1125 
1126 private:
1127   virtual void anchor();
1128 };
1129 
1130 struct StaticFieldRecord : CXXFieldRecord {
StaticFieldRecordStaticFieldRecord1131   StaticFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1132                     PresumedLoc Loc, AvailabilityInfo Availability,
1133                     LinkageInfo Linkage, const DocComment &Comment,
1134                     DeclarationFragments Declaration,
1135                     DeclarationFragments SubHeading, AccessControl Access,
1136                     bool IsFromSystemHeader)
1137       : CXXFieldRecord(RK_StaticField, USR, Name, Parent, Loc,
1138                        std::move(Availability), Comment, Declaration,
1139                        SubHeading, std::move(Access), IsFromSystemHeader) {}
1140 
classofStaticFieldRecord1141   static bool classof(const APIRecord *Record) {
1142     return classofKind(Record->getKind());
1143   }
classofKindStaticFieldRecord1144   static bool classofKind(RecordKind K) { return K == RK_StaticField; }
1145 };
1146 
1147 /// The base representation of an Objective-C container record. Holds common
1148 /// information associated with Objective-C containers.
1149 struct ObjCContainerRecord : APIRecord, RecordContext {
1150   SmallVector<SymbolReference> Protocols;
1151 
1152   ObjCContainerRecord() = delete;
1153 
ObjCContainerRecordObjCContainerRecord1154   ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name,
1155                       SymbolReference Parent, PresumedLoc Loc,
1156                       AvailabilityInfo Availability, LinkageInfo Linkage,
1157                       const DocComment &Comment,
1158                       DeclarationFragments Declaration,
1159                       DeclarationFragments SubHeading, bool IsFromSystemHeader)
1160       : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1161                   Linkage, Comment, Declaration, SubHeading,
1162                   IsFromSystemHeader),
1163         RecordContext(Kind) {}
1164 
1165   virtual ~ObjCContainerRecord() = 0;
1166 };
1167 
1168 struct CXXClassRecord : RecordRecord {
1169   SmallVector<SymbolReference> Bases;
1170 
1171   CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1172                  PresumedLoc Loc, AvailabilityInfo Availability,
1173                  const DocComment &Comment, DeclarationFragments Declaration,
1174                  DeclarationFragments SubHeading, RecordKind Kind,
1175                  AccessControl Access, bool IsFromSystemHeader,
1176                  bool IsEmbeddedInVarDeclarator = false)
RecordRecordCXXClassRecord1177       : RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1178                      Comment, Declaration, SubHeading, IsFromSystemHeader,
1179                      IsEmbeddedInVarDeclarator, std::move(Access)) {}
1180 
classofCXXClassRecord1181   static bool classof(const APIRecord *Record) {
1182     return classofKind(Record->getKind());
1183   }
classofKindCXXClassRecord1184   static bool classofKind(RecordKind K) {
1185     return K == RK_CXXClass || K == RK_ClassTemplate ||
1186            K == RK_ClassTemplateSpecialization ||
1187            K == RK_ClassTemplatePartialSpecialization;
1188   }
1189 
1190 private:
1191   virtual void anchor();
1192 };
1193 
1194 struct ClassTemplateRecord : CXXClassRecord {
1195   Template Templ;
1196 
ClassTemplateRecordClassTemplateRecord1197   ClassTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1198                       PresumedLoc Loc, AvailabilityInfo Availability,
1199                       const DocComment &Comment,
1200                       DeclarationFragments Declaration,
1201                       DeclarationFragments SubHeading, Template Template,
1202                       AccessControl Access, bool IsFromSystemHeader)
1203       : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
1204                        Declaration, SubHeading, RK_ClassTemplate,
1205                        std::move(Access), IsFromSystemHeader),
1206         Templ(Template) {}
1207 
classofClassTemplateRecord1208   static bool classof(const APIRecord *Record) {
1209     return classofKind(Record->getKind());
1210   }
classofKindClassTemplateRecord1211   static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; }
1212 };
1213 
1214 struct ClassTemplateSpecializationRecord : CXXClassRecord {
ClassTemplateSpecializationRecordClassTemplateSpecializationRecord1215   ClassTemplateSpecializationRecord(
1216       StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
1217       AvailabilityInfo Availability, const DocComment &Comment,
1218       DeclarationFragments Declaration, DeclarationFragments SubHeading,
1219       AccessControl Access, bool IsFromSystemHeader)
1220       : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
1221                        Declaration, SubHeading, RK_ClassTemplateSpecialization,
1222                        Access, IsFromSystemHeader) {}
1223 
classofClassTemplateSpecializationRecord1224   static bool classof(const APIRecord *Record) {
1225     return classofKind(Record->getKind());
1226   }
classofKindClassTemplateSpecializationRecord1227   static bool classofKind(RecordKind K) {
1228     return K == RK_ClassTemplateSpecialization;
1229   }
1230 };
1231 
1232 struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
1233   Template Templ;
ClassTemplatePartialSpecializationRecordClassTemplatePartialSpecializationRecord1234   ClassTemplatePartialSpecializationRecord(
1235       StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
1236       AvailabilityInfo Availability, const DocComment &Comment,
1237       DeclarationFragments Declaration, DeclarationFragments SubHeading,
1238       Template Template, AccessControl Access, bool IsFromSystemHeader)
1239       : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
1240                        Declaration, SubHeading,
1241                        RK_ClassTemplatePartialSpecialization, Access,
1242                        IsFromSystemHeader),
1243         Templ(Template) {}
1244 
classofClassTemplatePartialSpecializationRecord1245   static bool classof(const APIRecord *Record) {
1246     return classofKind(Record->getKind());
1247   }
classofKindClassTemplatePartialSpecializationRecord1248   static bool classofKind(RecordKind K) {
1249     return K == RK_ClassTemplatePartialSpecialization;
1250   }
1251 };
1252 
1253 struct ConceptRecord : APIRecord {
1254   Template Templ;
1255 
ConceptRecordConceptRecord1256   ConceptRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1257                 PresumedLoc Loc, AvailabilityInfo Availability,
1258                 const DocComment &Comment, DeclarationFragments Declaration,
1259                 DeclarationFragments SubHeading, Template Template,
1260                 bool IsFromSystemHeader)
1261       : APIRecord(RK_Concept, USR, Name, Parent, Loc, std::move(Availability),
1262                   LinkageInfo::none(), Comment, Declaration, SubHeading,
1263                   IsFromSystemHeader),
1264         Templ(Template) {}
1265 
classofConceptRecord1266   static bool classof(const APIRecord *Record) {
1267     return classofKind(Record->getKind());
1268   }
classofKindConceptRecord1269   static bool classofKind(RecordKind K) { return K == RK_Concept; }
1270 };
1271 
1272 /// This holds information associated with Objective-C categories.
1273 struct ObjCCategoryRecord : ObjCContainerRecord {
1274   SymbolReference Interface;
1275 
ObjCCategoryRecordObjCCategoryRecord1276   ObjCCategoryRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1277                      PresumedLoc Loc, AvailabilityInfo Availability,
1278                      const DocComment &Comment,
1279                      DeclarationFragments Declaration,
1280                      DeclarationFragments SubHeading, SymbolReference Interface,
1281                      bool IsFromSystemHeader)
1282       : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Parent, Loc,
1283                             std::move(Availability), LinkageInfo::none(),
1284                             Comment, Declaration, SubHeading,
1285                             IsFromSystemHeader),
1286         Interface(Interface) {}
1287 
classofObjCCategoryRecord1288   static bool classof(const APIRecord *Record) {
1289     return classofKind(Record->getKind());
1290   }
classofKindObjCCategoryRecord1291   static bool classofKind(RecordKind K) { return K == RK_ObjCCategory; }
1292 
isExtendingExternalModuleObjCCategoryRecord1293   bool isExtendingExternalModule() const { return !Interface.Source.empty(); }
1294 
getExtendedExternalModuleObjCCategoryRecord1295   std::optional<StringRef> getExtendedExternalModule() const {
1296     if (!isExtendingExternalModule())
1297       return {};
1298     return Interface.Source;
1299   }
1300 
1301 private:
1302   virtual void anchor();
1303 };
1304 
1305 /// This holds information associated with Objective-C interfaces/classes.
1306 struct ObjCInterfaceRecord : ObjCContainerRecord {
1307   SymbolReference SuperClass;
1308 
ObjCInterfaceRecordObjCInterfaceRecord1309   ObjCInterfaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1310                       PresumedLoc Loc, AvailabilityInfo Availability,
1311                       LinkageInfo Linkage, const DocComment &Comment,
1312                       DeclarationFragments Declaration,
1313                       DeclarationFragments SubHeading,
1314                       SymbolReference SuperClass, bool IsFromSystemHeader)
1315       : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Parent, Loc,
1316                             std::move(Availability), Linkage, Comment,
1317                             Declaration, SubHeading, IsFromSystemHeader),
1318         SuperClass(SuperClass) {}
1319 
classofObjCInterfaceRecord1320   static bool classof(const APIRecord *Record) {
1321     return classofKind(Record->getKind());
1322   }
classofKindObjCInterfaceRecord1323   static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; }
1324 
1325 private:
1326   virtual void anchor();
1327 };
1328 
1329 /// This holds information associated with Objective-C protocols.
1330 struct ObjCProtocolRecord : ObjCContainerRecord {
ObjCProtocolRecordObjCProtocolRecord1331   ObjCProtocolRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1332                      PresumedLoc Loc, AvailabilityInfo Availability,
1333                      const DocComment &Comment,
1334                      DeclarationFragments Declaration,
1335                      DeclarationFragments SubHeading, bool IsFromSystemHeader)
1336       : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Parent, Loc,
1337                             std::move(Availability), LinkageInfo::none(),
1338                             Comment, Declaration, SubHeading,
1339                             IsFromSystemHeader) {}
1340 
classofObjCProtocolRecord1341   static bool classof(const APIRecord *Record) {
1342     return classofKind(Record->getKind());
1343   }
classofKindObjCProtocolRecord1344   static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; }
1345 
1346 private:
1347   virtual void anchor();
1348 };
1349 
1350 /// This holds information associated with macro definitions.
1351 struct MacroDefinitionRecord : APIRecord {
MacroDefinitionRecordMacroDefinitionRecord1352   MacroDefinitionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1353                         PresumedLoc Loc, DeclarationFragments Declaration,
1354                         DeclarationFragments SubHeading,
1355                         bool IsFromSystemHeader)
1356       : APIRecord(RK_MacroDefinition, USR, Name, Parent, Loc,
1357                   AvailabilityInfo(), LinkageInfo(), {}, Declaration,
1358                   SubHeading, IsFromSystemHeader) {}
1359 
classofMacroDefinitionRecord1360   static bool classof(const APIRecord *Record) {
1361     return classofKind(Record->getKind());
1362   }
classofKindMacroDefinitionRecord1363   static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; }
1364 
1365 private:
1366   virtual void anchor();
1367 };
1368 
1369 /// This holds information associated with typedefs.
1370 ///
1371 /// Note: Typedefs for anonymous enums and structs typically don't get emitted
1372 /// by the serializers but still get a TypedefRecord. Instead we use the
1373 /// typedef name as a name for the underlying anonymous struct or enum.
1374 struct TypedefRecord : APIRecord {
1375   SymbolReference UnderlyingType;
1376 
TypedefRecordTypedefRecord1377   TypedefRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1378                 PresumedLoc Loc, AvailabilityInfo Availability,
1379                 const DocComment &Comment, DeclarationFragments Declaration,
1380                 DeclarationFragments SubHeading, SymbolReference UnderlyingType,
1381                 bool IsFromSystemHeader)
1382       : APIRecord(RK_Typedef, USR, Name, Parent, Loc, std::move(Availability),
1383                   LinkageInfo(), Comment, Declaration, SubHeading,
1384                   IsFromSystemHeader),
1385         UnderlyingType(UnderlyingType) {}
1386 
classofTypedefRecord1387   static bool classof(const APIRecord *Record) {
1388     return classofKind(Record->getKind());
1389   }
classofKindTypedefRecord1390   static bool classofKind(RecordKind K) { return K == RK_Typedef; }
1391 
1392 private:
1393   virtual void anchor();
1394 };
1395 
1396 /// APISet holds the set of API records collected from given inputs.
1397 class APISet {
1398 public:
1399   /// Get the target triple for the ExtractAPI invocation.
getTarget()1400   const llvm::Triple &getTarget() const { return Target; }
1401 
1402   /// Get the language used by the APIs.
getLanguage()1403   Language getLanguage() const { return Lang; }
1404 
1405   /// Finds the APIRecord for a given USR.
1406   ///
1407   /// \returns a pointer to the APIRecord associated with that USR or nullptr.
1408   APIRecord *findRecordForUSR(StringRef USR) const;
1409 
1410   /// Copy \p String into the Allocator in this APISet.
1411   ///
1412   /// \returns a StringRef of the copied string in APISet::Allocator.
1413   StringRef copyString(StringRef String);
1414 
1415   SymbolReference createSymbolReference(StringRef Name, StringRef USR,
1416                                         StringRef Source = "");
1417 
1418   /// Create a subclass of \p APIRecord and store it in the APISet.
1419   ///
1420   /// \returns A pointer to the created record or the already existing record
1421   /// matching this USR.
1422   template <typename RecordTy, typename... CtorArgsContTy>
1423   typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
1424   createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs);
1425 
getTopLevelRecords()1426   ArrayRef<const APIRecord *> getTopLevelRecords() const {
1427     return TopLevelRecords;
1428   }
1429 
APISet(const llvm::Triple & Target,Language Lang,const std::string & ProductName)1430   APISet(const llvm::Triple &Target, Language Lang,
1431          const std::string &ProductName)
1432       : Target(Target), Lang(Lang), ProductName(ProductName) {}
1433 
1434   // Prevent moves and copies
1435   APISet(const APISet &Other) = delete;
1436   APISet &operator=(const APISet &Other) = delete;
1437   APISet(APISet &&Other) = delete;
1438   APISet &operator=(APISet &&Other) = delete;
1439 
1440 private:
1441   /// BumpPtrAllocator that serves as the memory arena for the allocated objects
1442   llvm::BumpPtrAllocator Allocator;
1443 
1444   const llvm::Triple Target;
1445   const Language Lang;
1446 
1447   struct APIRecordDeleter {
operatorAPIRecordDeleter1448     void operator()(APIRecord *Record) { Record->~APIRecord(); }
1449   };
1450 
1451   // Ensure that the destructor of each record is called when the LookupTable is
1452   // destroyed without calling delete operator as the memory for the record
1453   // lives in the BumpPtrAllocator.
1454   using APIRecordStoredPtr = std::unique_ptr<APIRecord, APIRecordDeleter>;
1455   llvm::DenseMap<StringRef, APIRecordStoredPtr> USRBasedLookupTable;
1456   std::vector<const APIRecord *> TopLevelRecords;
1457 
1458 public:
1459   const std::string ProductName;
1460 };
1461 
1462 template <typename RecordTy, typename... CtorArgsContTy>
1463 typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
createRecord(StringRef USR,StringRef Name,CtorArgsContTy &&...CtorArgs)1464 APISet::createRecord(StringRef USR, StringRef Name,
1465                      CtorArgsContTy &&...CtorArgs) {
1466   // Ensure USR refers to a String stored in the allocator.
1467   auto USRString = copyString(USR);
1468   auto Result = USRBasedLookupTable.insert({USRString, nullptr});
1469   RecordTy *Record;
1470 
1471   // Create the record if it does not already exist
1472   if (Result.second) {
1473     Record = new (Allocator) RecordTy(
1474         USRString, copyString(Name), std::forward<CtorArgsContTy>(CtorArgs)...);
1475     // Store the record in the record lookup map
1476     Result.first->second = APIRecordStoredPtr(Record);
1477 
1478     if (auto *ParentContext =
1479             dyn_cast_if_present<RecordContext>(Record->Parent.Record))
1480       ParentContext->addToRecordChain(Record);
1481     else
1482       TopLevelRecords.push_back(Record);
1483   } else {
1484     Record = dyn_cast<RecordTy>(Result.first->second.get());
1485   }
1486 
1487   return Record;
1488 }
1489 
1490 // Helper type for implementing casting to RecordContext pointers.
1491 // Selected when FromTy not a known subclass of RecordContext.
1492 template <typename FromTy,
1493           bool IsKnownSubType = std::is_base_of_v<RecordContext, FromTy>>
1494 struct ToRecordContextCastInfoWrapper {
1495   static_assert(std::is_base_of_v<APIRecord, FromTy>,
1496                 "Can only cast APIRecord and derived classes to RecordContext");
1497 
isPossibleToRecordContextCastInfoWrapper1498   static bool isPossible(FromTy *From) { return RecordContext::classof(From); }
1499 
doCastToRecordContextCastInfoWrapper1500   static RecordContext *doCast(FromTy *From) {
1501     return APIRecord::castToRecordContext(From);
1502   }
1503 };
1504 
1505 // Selected when FromTy is a known subclass of RecordContext.
1506 template <typename FromTy> struct ToRecordContextCastInfoWrapper<FromTy, true> {
1507   static_assert(std::is_base_of_v<APIRecord, FromTy>,
1508                 "Can only cast APIRecord and derived classes to RecordContext");
1509   static bool isPossible(const FromTy *From) { return true; }
1510   static RecordContext *doCast(FromTy *From) {
1511     return static_cast<RecordContext *>(From);
1512   }
1513 };
1514 
1515 // Helper type for implementing casting to RecordContext pointers.
1516 // Selected when ToTy isn't a known subclass of RecordContext
1517 template <typename ToTy,
1518           bool IsKnownSubType = std::is_base_of_v<RecordContext, ToTy>>
1519 struct FromRecordContextCastInfoWrapper {
1520   static_assert(
1521       std::is_base_of_v<APIRecord, ToTy>,
1522       "Can only class RecordContext to APIRecord and derived classes");
1523 
1524   static bool isPossible(RecordContext *Ctx) {
1525     return ToTy::classofKind(Ctx->getKind());
1526   }
1527 
1528   static ToTy *doCast(RecordContext *Ctx) {
1529     return APIRecord::castFromRecordContext(Ctx);
1530   }
1531 };
1532 
1533 // Selected when ToTy is a known subclass of RecordContext.
1534 template <typename ToTy> struct FromRecordContextCastInfoWrapper<ToTy, true> {
1535   static_assert(
1536       std::is_base_of_v<APIRecord, ToTy>,
1537       "Can only class RecordContext to APIRecord and derived classes");
1538   static bool isPossible(RecordContext *Ctx) {
1539     return ToTy::classof(Ctx->getKind());
1540   }
1541   static RecordContext *doCast(RecordContext *Ctx) {
1542     return static_cast<ToTy *>(Ctx);
1543   }
1544 };
1545 
1546 } // namespace extractapi
1547 } // namespace clang
1548 
1549 // Implement APIRecord (and derived classes) to and from RecordContext
1550 // conversions
1551 namespace llvm {
1552 
1553 template <typename FromTy>
1554 struct CastInfo<::clang::extractapi::RecordContext, FromTy *>
1555     : public NullableValueCastFailed<::clang::extractapi::RecordContext *>,
1556       public DefaultDoCastIfPossible<
1557           ::clang::extractapi::RecordContext *, FromTy *,
1558           CastInfo<::clang::extractapi::RecordContext, FromTy *>> {
1559   static inline bool isPossible(FromTy *From) {
1560     return ::clang::extractapi::ToRecordContextCastInfoWrapper<
1561         FromTy>::isPossible(From);
1562   }
1563 
1564   static inline ::clang::extractapi::RecordContext *doCast(FromTy *From) {
1565     return ::clang::extractapi::ToRecordContextCastInfoWrapper<FromTy>::doCast(
1566         From);
1567   }
1568 };
1569 
1570 template <typename FromTy>
1571 struct CastInfo<::clang::extractapi::RecordContext, const FromTy *>
1572     : public ConstStrippingForwardingCast<
1573           ::clang::extractapi::RecordContext, const FromTy *,
1574           CastInfo<::clang::extractapi::RecordContext, FromTy *>> {};
1575 
1576 template <typename ToTy>
1577 struct CastInfo<ToTy, ::clang::extractapi::RecordContext *>
1578     : public NullableValueCastFailed<ToTy *>,
1579       public DefaultDoCastIfPossible<
1580           ToTy *, ::clang::extractapi::RecordContext *,
1581           CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {
1582   static inline bool isPossible(::clang::extractapi::RecordContext *Ctx) {
1583     return ::clang::extractapi::FromRecordContextCastInfoWrapper<
1584         ToTy>::isPossible(Ctx);
1585   }
1586 
1587   static inline ToTy *doCast(::clang::extractapi::RecordContext *Ctx) {
1588     return ::clang::extractapi::FromRecordContextCastInfoWrapper<ToTy>::doCast(
1589         Ctx);
1590   }
1591 };
1592 
1593 template <typename ToTy>
1594 struct CastInfo<ToTy, const ::clang::extractapi::RecordContext *>
1595     : public ConstStrippingForwardingCast<
1596           ToTy, const ::clang::extractapi::RecordContext *,
1597           CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {};
1598 
1599 } // namespace llvm
1600 
1601 #endif // LLVM_CLANG_EXTRACTAPI_API_H
1602