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 RecordKind KindForDisplay;
270
271 private:
272 const RecordKind Kind;
273 friend class RecordContext;
274 // Used to store the next child record in RecordContext. This works because
275 // APIRecords semantically only have one parent.
276 mutable APIRecord *NextInContext = nullptr;
277
278 public:
getNextInContextAPIRecord279 APIRecord *getNextInContext() const { return NextInContext; }
280
getKindAPIRecord281 RecordKind getKind() const { return Kind; }
getKindForDisplayAPIRecord282 RecordKind getKindForDisplay() const { return KindForDisplay; }
283
284 static APIRecord *castFromRecordContext(const RecordContext *Ctx);
285 static RecordContext *castToRecordContext(const APIRecord *Record);
286
287 APIRecord() = delete;
288
289 APIRecord(RecordKind Kind, StringRef USR, StringRef Name,
290 SymbolReference Parent, PresumedLoc Location,
291 AvailabilityInfo Availability, LinkageInfo Linkage,
292 const DocComment &Comment, DeclarationFragments Declaration,
293 DeclarationFragments SubHeading, bool IsFromSystemHeader,
294 AccessControl Access = AccessControl())
USRAPIRecord295 : USR(USR), Name(Name), Parent(std::move(Parent)), Location(Location),
296 Availability(std::move(Availability)), Linkage(Linkage),
297 Comment(Comment), Declaration(Declaration), SubHeading(SubHeading),
298 IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)),
299 KindForDisplay(Kind), Kind(Kind) {}
300
APIRecordAPIRecord301 APIRecord(RecordKind Kind, StringRef USR, StringRef Name)
302 : USR(USR), Name(Name), KindForDisplay(Kind), Kind(Kind) {}
303
304 // Pure virtual destructor to make APIRecord abstract
305 virtual ~APIRecord() = 0;
classofAPIRecord306 static bool classof(const APIRecord *Record) { return true; }
classofKindAPIRecord307 static bool classofKind(RecordKind K) { return true; }
classofAPIRecord308 static bool classof(const RecordContext *Ctx) { return true; }
309 };
310
311 /// Base class used for specific record types that have children records this is
312 /// analogous to the DeclContext for the AST
313 class RecordContext {
314 public:
classof(const APIRecord * Record)315 static bool classof(const APIRecord *Record) {
316 return classofKind(Record->getKind());
317 }
classofKind(APIRecord::RecordKind K)318 static bool classofKind(APIRecord::RecordKind K) {
319 return K > APIRecord::RK_FirstRecordContext &&
320 K < APIRecord::RK_LastRecordContext;
321 }
322
classof(const RecordContext * Context)323 static bool classof(const RecordContext *Context) { return true; }
324
RecordContext(APIRecord::RecordKind Kind)325 RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}
326
327 /// Append \p Other children chain into ours and empty out Other's record
328 /// chain.
329 void stealRecordChain(RecordContext &Other);
330
getKind()331 APIRecord::RecordKind getKind() const { return Kind; }
332
333 struct record_iterator {
334 private:
335 APIRecord *Current = nullptr;
336
337 public:
338 using value_type = APIRecord *;
339 using reference = const value_type &;
340 using pointer = const value_type *;
341 using iterator_category = std::forward_iterator_tag;
342 using difference_type = std::ptrdiff_t;
343
344 record_iterator() = default;
record_iteratorrecord_iterator345 explicit record_iterator(value_type R) : Current(R) {}
346 reference operator*() const { return Current; }
347 // This doesn't strictly meet the iterator requirements, but it's the
348 // behavior we want here.
349 value_type operator->() const { return Current; }
350 record_iterator &operator++() {
351 Current = Current->getNextInContext();
352 return *this;
353 }
354 record_iterator operator++(int) {
355 record_iterator tmp(*this);
356 ++(*this);
357 return tmp;
358 }
359
360 friend bool operator==(record_iterator x, record_iterator y) {
361 return x.Current == y.Current;
362 }
363 friend bool operator!=(record_iterator x, record_iterator y) {
364 return x.Current != y.Current;
365 }
366 };
367
368 using record_range = llvm::iterator_range<record_iterator>;
records()369 record_range records() const {
370 return record_range(records_begin(), records_end());
371 }
records_begin()372 record_iterator records_begin() const { return record_iterator(First); };
records_end()373 record_iterator records_end() const { return record_iterator(); }
records_empty()374 bool records_empty() const { return First == nullptr; };
375
376 private:
377 APIRecord::RecordKind Kind;
378 mutable APIRecord *First = nullptr;
379 mutable APIRecord *Last = nullptr;
380 bool IsWellFormed() const;
381
382 protected:
383 friend class APISet;
384 void addToRecordChain(APIRecord *) const;
385 };
386
387 struct NamespaceRecord : APIRecord, RecordContext {
NamespaceRecordNamespaceRecord388 NamespaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
389 PresumedLoc Loc, AvailabilityInfo Availability,
390 LinkageInfo Linkage, const DocComment &Comment,
391 DeclarationFragments Declaration,
392 DeclarationFragments SubHeading, bool IsFromSystemHeader)
393 : APIRecord(RK_Namespace, USR, Name, Parent, Loc, std::move(Availability),
394 Linkage, Comment, Declaration, SubHeading,
395 IsFromSystemHeader),
396 RecordContext(RK_Namespace) {}
397
classofNamespaceRecord398 static bool classof(const APIRecord *Record) {
399 return classofKind(Record->getKind());
400 }
classofKindNamespaceRecord401 static bool classofKind(RecordKind K) { return K == RK_Namespace; }
402 };
403
404 /// This holds information associated with global functions.
405 struct GlobalFunctionRecord : APIRecord {
406 FunctionSignature Signature;
407
GlobalFunctionRecordGlobalFunctionRecord408 GlobalFunctionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
409 PresumedLoc Loc, AvailabilityInfo Availability,
410 LinkageInfo Linkage, const DocComment &Comment,
411 DeclarationFragments Declaration,
412 DeclarationFragments SubHeading,
413 FunctionSignature Signature, bool IsFromSystemHeader)
414 : APIRecord(RK_GlobalFunction, USR, Name, Parent, Loc,
415 std::move(Availability), Linkage, Comment, Declaration,
416 SubHeading, IsFromSystemHeader),
417 Signature(Signature) {}
418
GlobalFunctionRecordGlobalFunctionRecord419 GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
420 SymbolReference Parent, PresumedLoc Loc,
421 AvailabilityInfo Availability, LinkageInfo Linkage,
422 const DocComment &Comment,
423 DeclarationFragments Declaration,
424 DeclarationFragments SubHeading,
425 FunctionSignature Signature, bool IsFromSystemHeader)
426 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
427 Linkage, Comment, Declaration, SubHeading,
428 IsFromSystemHeader),
429 Signature(Signature) {}
430
classofGlobalFunctionRecord431 static bool classof(const APIRecord *Record) {
432 return classofKind(Record->getKind());
433 }
classofKindGlobalFunctionRecord434 static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; }
435
436 private:
437 virtual void anchor();
438 };
439
440 struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
441 Template Templ;
442
GlobalFunctionTemplateRecordGlobalFunctionTemplateRecord443 GlobalFunctionTemplateRecord(StringRef USR, StringRef Name,
444 SymbolReference Parent, PresumedLoc Loc,
445 AvailabilityInfo Availability,
446 LinkageInfo Linkage, const DocComment &Comment,
447 DeclarationFragments Declaration,
448 DeclarationFragments SubHeading,
449 FunctionSignature Signature, Template Template,
450 bool IsFromSystemHeader)
451 : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Parent, Loc,
452 std::move(Availability), Linkage, Comment,
453 Declaration, SubHeading, Signature,
454 IsFromSystemHeader),
455 Templ(Template) {}
456
classofGlobalFunctionTemplateRecord457 static bool classof(const APIRecord *Record) {
458 return classofKind(Record->getKind());
459 }
classofKindGlobalFunctionTemplateRecord460 static bool classofKind(RecordKind K) {
461 return K == RK_GlobalFunctionTemplate;
462 }
463 };
464
465 struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
GlobalFunctionTemplateSpecializationRecordGlobalFunctionTemplateSpecializationRecord466 GlobalFunctionTemplateSpecializationRecord(
467 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
468 AvailabilityInfo Availability, LinkageInfo Linkage,
469 const DocComment &Comment, DeclarationFragments Declaration,
470 DeclarationFragments SubHeading, FunctionSignature Signature,
471 bool IsFromSystemHeader)
472 : GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
473 Parent, Loc, std::move(Availability), Linkage,
474 Comment, Declaration, SubHeading, Signature,
475 IsFromSystemHeader) {}
476
classofGlobalFunctionTemplateSpecializationRecord477 static bool classof(const APIRecord *Record) {
478 return classofKind(Record->getKind());
479 }
classofKindGlobalFunctionTemplateSpecializationRecord480 static bool classofKind(RecordKind K) {
481 return K == RK_GlobalFunctionTemplateSpecialization;
482 }
483 };
484
485 /// This holds information associated with global functions.
486 struct GlobalVariableRecord : APIRecord, RecordContext {
GlobalVariableRecordGlobalVariableRecord487 GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
488 PresumedLoc Loc, AvailabilityInfo Availability,
489 LinkageInfo Linkage, const DocComment &Comment,
490 DeclarationFragments Declaration,
491 DeclarationFragments SubHeading, bool IsFromSystemHeader)
492 : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
493 std::move(Availability), Linkage, Comment, Declaration,
494 SubHeading, IsFromSystemHeader),
495 RecordContext(RK_GlobalVariable) {}
496
GlobalVariableRecordGlobalVariableRecord497 GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
498 SymbolReference Parent, PresumedLoc Loc,
499 AvailabilityInfo Availability, LinkageInfo Linkage,
500 const DocComment &Comment,
501 DeclarationFragments Declaration,
502 DeclarationFragments SubHeading, bool IsFromSystemHeader)
503 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
504 Linkage, Comment, Declaration, SubHeading,
505 IsFromSystemHeader),
506 RecordContext(Kind) {}
507
classofGlobalVariableRecord508 static bool classof(const APIRecord *Record) {
509 return classofKind(Record->getKind());
510 }
classofKindGlobalVariableRecord511 static bool classofKind(RecordKind K) {
512 return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate ||
513 K == RK_GlobalVariableTemplateSpecialization ||
514 K == RK_GlobalVariableTemplatePartialSpecialization;
515 }
516
517 private:
518 virtual void anchor();
519 };
520
521 struct GlobalVariableTemplateRecord : GlobalVariableRecord {
522 Template Templ;
523
GlobalVariableTemplateRecordGlobalVariableTemplateRecord524 GlobalVariableTemplateRecord(StringRef USR, StringRef Name,
525 SymbolReference Parent, PresumedLoc Loc,
526 AvailabilityInfo Availability,
527 LinkageInfo Linkage, const DocComment &Comment,
528 DeclarationFragments Declaration,
529 DeclarationFragments SubHeading,
530 class Template Template, bool IsFromSystemHeader)
531 : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Parent, Loc,
532 std::move(Availability), Linkage, Comment,
533 Declaration, SubHeading, IsFromSystemHeader),
534 Templ(Template) {}
535
classofGlobalVariableTemplateRecord536 static bool classof(const APIRecord *Record) {
537 return classofKind(Record->getKind());
538 }
classofKindGlobalVariableTemplateRecord539 static bool classofKind(RecordKind K) {
540 return K == RK_GlobalVariableTemplate;
541 }
542 };
543
544 struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord {
GlobalVariableTemplateSpecializationRecordGlobalVariableTemplateSpecializationRecord545 GlobalVariableTemplateSpecializationRecord(
546 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
547 AvailabilityInfo Availability, LinkageInfo Linkage,
548 const DocComment &Comment, DeclarationFragments Declaration,
549 DeclarationFragments SubHeading, bool IsFromSystemHeader)
550 : GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name,
551 Parent, Loc, std::move(Availability), Linkage,
552 Comment, Declaration, SubHeading,
553 IsFromSystemHeader) {}
554
classofGlobalVariableTemplateSpecializationRecord555 static bool classof(const APIRecord *Record) {
556 return classofKind(Record->getKind());
557 }
classofKindGlobalVariableTemplateSpecializationRecord558 static bool classofKind(RecordKind K) {
559 return K == RK_GlobalVariableTemplateSpecialization;
560 }
561 };
562
563 struct GlobalVariableTemplatePartialSpecializationRecord
564 : GlobalVariableRecord {
565 Template Templ;
566
GlobalVariableTemplatePartialSpecializationRecordGlobalVariableTemplatePartialSpecializationRecord567 GlobalVariableTemplatePartialSpecializationRecord(
568 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
569 AvailabilityInfo Availability, LinkageInfo Linkage,
570 const DocComment &Comment, DeclarationFragments Declaration,
571 DeclarationFragments SubHeading, class Template Template,
572 bool IsFromSystemHeader)
573 : GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization,
574 USR, Name, Parent, Loc, std::move(Availability),
575 Linkage, Comment, Declaration, SubHeading,
576 IsFromSystemHeader),
577 Templ(Template) {}
578
classofGlobalVariableTemplatePartialSpecializationRecord579 static bool classof(const APIRecord *Record) {
580 return classofKind(Record->getKind());
581 }
classofKindGlobalVariableTemplatePartialSpecializationRecord582 static bool classofKind(RecordKind K) {
583 return K == RK_GlobalVariableTemplatePartialSpecialization;
584 }
585 };
586
587 /// This holds information associated with enum constants.
588 struct EnumConstantRecord : APIRecord {
EnumConstantRecordEnumConstantRecord589 EnumConstantRecord(StringRef USR, StringRef Name, SymbolReference Parent,
590 PresumedLoc Loc, AvailabilityInfo Availability,
591 const DocComment &Comment,
592 DeclarationFragments Declaration,
593 DeclarationFragments SubHeading, bool IsFromSystemHeader)
594 : APIRecord(RK_EnumConstant, USR, Name, Parent, Loc,
595 std::move(Availability), LinkageInfo::none(), Comment,
596 Declaration, SubHeading, IsFromSystemHeader) {}
597
classofEnumConstantRecord598 static bool classof(const APIRecord *Record) {
599 return classofKind(Record->getKind());
600 }
classofKindEnumConstantRecord601 static bool classofKind(RecordKind K) { return K == RK_EnumConstant; }
602
603 private:
604 virtual void anchor();
605 };
606
607 struct TagRecord : APIRecord, RecordContext {
608 TagRecord(RecordKind Kind, StringRef USR, StringRef Name,
609 SymbolReference Parent, PresumedLoc Loc,
610 AvailabilityInfo Availability, const DocComment &Comment,
611 DeclarationFragments Declaration, DeclarationFragments SubHeading,
612 bool IsFromSystemHeader, bool IsEmbeddedInVarDeclarator,
613 AccessControl Access = AccessControl())
APIRecordTagRecord614 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
615 LinkageInfo::none(), Comment, Declaration, SubHeading,
616 IsFromSystemHeader, std::move(Access)),
617 RecordContext(Kind),
618 IsEmbeddedInVarDeclarator(IsEmbeddedInVarDeclarator){};
619
classofTagRecord620 static bool classof(const APIRecord *Record) {
621 return classofKind(Record->getKind());
622 }
classofKindTagRecord623 static bool classofKind(RecordKind K) {
624 return K == RK_Struct || K == RK_Union || K == RK_Enum;
625 }
626
627 bool IsEmbeddedInVarDeclarator;
628
629 virtual ~TagRecord() = 0;
630 };
631
632 /// This holds information associated with enums.
633 struct EnumRecord : TagRecord {
634 EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
635 PresumedLoc Loc, AvailabilityInfo Availability,
636 const DocComment &Comment, DeclarationFragments Declaration,
637 DeclarationFragments SubHeading, bool IsFromSystemHeader,
638 bool IsEmbeddedInVarDeclarator,
639 AccessControl Access = AccessControl())
TagRecordEnumRecord640 : TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
641 Comment, Declaration, SubHeading, IsFromSystemHeader,
642 IsEmbeddedInVarDeclarator, std::move(Access)) {}
643
classofEnumRecord644 static bool classof(const APIRecord *Record) {
645 return classofKind(Record->getKind());
646 }
647
classofKindEnumRecord648 static bool classofKind(RecordKind K) { return K == RK_Enum; }
649
650 private:
651 virtual void anchor();
652 };
653
654 /// This holds information associated with struct or union fields fields.
655 struct RecordFieldRecord : APIRecord, RecordContext {
RecordFieldRecordRecordFieldRecord656 RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
657 SymbolReference Parent, PresumedLoc Loc,
658 AvailabilityInfo Availability, const DocComment &Comment,
659 DeclarationFragments Declaration,
660 DeclarationFragments SubHeading, bool IsFromSystemHeader)
661 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
662 LinkageInfo::none(), Comment, Declaration, SubHeading,
663 IsFromSystemHeader),
664 RecordContext(Kind) {}
665
classofRecordFieldRecord666 static bool classof(const APIRecord *Record) {
667 return classofKind(Record->getKind());
668 }
classofKindRecordFieldRecord669 static bool classofKind(RecordKind K) {
670 return K == RK_StructField || K == RK_UnionField;
671 }
672
673 virtual ~RecordFieldRecord() = 0;
674 };
675
676 /// This holds information associated with structs and unions.
677 struct RecordRecord : TagRecord {
678 RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
679 SymbolReference Parent, PresumedLoc Loc,
680 AvailabilityInfo Availability, const DocComment &Comment,
681 DeclarationFragments Declaration,
682 DeclarationFragments SubHeading, bool IsFromSystemHeader,
683 bool IsEmbeddedInVarDeclarator,
684 AccessControl Access = AccessControl())
TagRecordRecordRecord685 : TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
686 Comment, Declaration, SubHeading, IsFromSystemHeader,
687 IsEmbeddedInVarDeclarator, std::move(Access)) {}
688
classofRecordRecord689 static bool classof(const APIRecord *Record) {
690 return classofKind(Record->getKind());
691 }
classofKindRecordRecord692 static bool classofKind(RecordKind K) {
693 return K == RK_Struct || K == RK_Union;
694 }
695
isAnonymousWithNoTypedefRecordRecord696 bool isAnonymousWithNoTypedef() { return Name.empty(); }
697
698 virtual ~RecordRecord() = 0;
699 };
700
701 struct StructFieldRecord : RecordFieldRecord {
StructFieldRecordStructFieldRecord702 StructFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
703 PresumedLoc Loc, AvailabilityInfo Availability,
704 const DocComment &Comment, DeclarationFragments Declaration,
705 DeclarationFragments SubHeading, bool IsFromSystemHeader)
706 : RecordFieldRecord(RK_StructField, USR, Name, Parent, Loc,
707 std::move(Availability), Comment, Declaration,
708 SubHeading, IsFromSystemHeader) {}
709
classofStructFieldRecord710 static bool classof(const APIRecord *Record) {
711 return classofKind(Record->getKind());
712 }
classofKindStructFieldRecord713 static bool classofKind(RecordKind K) { return K == RK_StructField; }
714
715 private:
716 virtual void anchor();
717 };
718
719 struct StructRecord : RecordRecord {
StructRecordStructRecord720 StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
721 PresumedLoc Loc, AvailabilityInfo Availability,
722 const DocComment &Comment, DeclarationFragments Declaration,
723 DeclarationFragments SubHeading, bool IsFromSystemHeader,
724 bool IsEmbeddedInVarDeclarator)
725 : RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
726 Comment, Declaration, SubHeading, IsFromSystemHeader,
727 IsEmbeddedInVarDeclarator) {}
728
classofStructRecord729 static bool classof(const APIRecord *Record) {
730 return classofKind(Record->getKind());
731 }
classofKindStructRecord732 static bool classofKind(RecordKind K) { return K == RK_Struct; }
733
734 private:
735 virtual void anchor();
736 };
737
738 struct UnionFieldRecord : RecordFieldRecord {
UnionFieldRecordUnionFieldRecord739 UnionFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
740 PresumedLoc Loc, AvailabilityInfo Availability,
741 const DocComment &Comment, DeclarationFragments Declaration,
742 DeclarationFragments SubHeading, bool IsFromSystemHeader)
743 : RecordFieldRecord(RK_UnionField, USR, Name, Parent, Loc,
744 std::move(Availability), Comment, Declaration,
745 SubHeading, IsFromSystemHeader) {}
746
classofUnionFieldRecord747 static bool classof(const APIRecord *Record) {
748 return classofKind(Record->getKind());
749 }
classofKindUnionFieldRecord750 static bool classofKind(RecordKind K) { return K == RK_UnionField; }
751
752 private:
753 virtual void anchor();
754 };
755
756 struct UnionRecord : RecordRecord {
UnionRecordUnionRecord757 UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
758 PresumedLoc Loc, AvailabilityInfo Availability,
759 const DocComment &Comment, DeclarationFragments Declaration,
760 DeclarationFragments SubHeading, bool IsFromSystemHeader,
761 bool IsEmbeddedInVarDeclarator)
762 : RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
763 Comment, Declaration, SubHeading, IsFromSystemHeader,
764 IsEmbeddedInVarDeclarator) {}
765
classofUnionRecord766 static bool classof(const APIRecord *Record) {
767 return classofKind(Record->getKind());
768 }
classofKindUnionRecord769 static bool classofKind(RecordKind K) { return K == RK_Union; }
770
771 private:
772 virtual void anchor();
773 };
774
775 struct CXXFieldRecord : APIRecord, RecordContext {
CXXFieldRecordCXXFieldRecord776 CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
777 PresumedLoc Loc, AvailabilityInfo Availability,
778 const DocComment &Comment, DeclarationFragments Declaration,
779 DeclarationFragments SubHeading, AccessControl Access,
780 bool IsFromSystemHeader)
781 : APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
782 LinkageInfo::none(), Comment, Declaration, SubHeading,
783 IsFromSystemHeader, std::move(Access)),
784 RecordContext(RK_CXXField) {}
785
CXXFieldRecordCXXFieldRecord786 CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
787 SymbolReference Parent, PresumedLoc Loc,
788 AvailabilityInfo Availability, const DocComment &Comment,
789 DeclarationFragments Declaration,
790 DeclarationFragments SubHeading, AccessControl Access,
791 bool IsFromSystemHeader)
792 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
793 LinkageInfo::none(), Comment, Declaration, SubHeading,
794 IsFromSystemHeader, std::move(Access)),
795 RecordContext(Kind) {}
796
classofCXXFieldRecord797 static bool classof(const APIRecord *Record) {
798 return classofKind(Record->getKind());
799 }
classofKindCXXFieldRecord800 static bool classofKind(RecordKind K) {
801 return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField;
802 }
803
804 private:
805 virtual void anchor();
806 };
807
808 struct CXXFieldTemplateRecord : CXXFieldRecord {
809 Template Templ;
810
CXXFieldTemplateRecordCXXFieldTemplateRecord811 CXXFieldTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
812 PresumedLoc Loc, AvailabilityInfo Availability,
813 const DocComment &Comment,
814 DeclarationFragments Declaration,
815 DeclarationFragments SubHeading, AccessControl Access,
816 Template Template, bool IsFromSystemHeader)
817 : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Parent, Loc,
818 std::move(Availability), Comment, Declaration,
819 SubHeading, std::move(Access), IsFromSystemHeader),
820 Templ(Template) {}
821
classofCXXFieldTemplateRecord822 static bool classof(const APIRecord *Record) {
823 return classofKind(Record->getKind());
824 }
classofKindCXXFieldTemplateRecord825 static bool classofKind(RecordKind K) { return K == RK_CXXFieldTemplate; }
826 };
827
828 struct CXXMethodRecord : APIRecord {
829 FunctionSignature Signature;
830
831 CXXMethodRecord() = delete;
832
CXXMethodRecordCXXMethodRecord833 CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
834 SymbolReference Parent, PresumedLoc Loc,
835 AvailabilityInfo Availability, const DocComment &Comment,
836 DeclarationFragments Declaration,
837 DeclarationFragments SubHeading, FunctionSignature Signature,
838 AccessControl Access, bool IsFromSystemHeader)
839 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
840 LinkageInfo::none(), Comment, Declaration, SubHeading,
841 IsFromSystemHeader, std::move(Access)),
842 Signature(Signature) {}
843
844 virtual ~CXXMethodRecord() = 0;
845 };
846
847 struct CXXConstructorRecord : CXXMethodRecord {
CXXConstructorRecordCXXConstructorRecord848 CXXConstructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
849 PresumedLoc Loc, AvailabilityInfo Availability,
850 const DocComment &Comment,
851 DeclarationFragments Declaration,
852 DeclarationFragments SubHeading,
853 FunctionSignature Signature, AccessControl Access,
854 bool IsFromSystemHeader)
855 : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Parent, Loc,
856 std::move(Availability), Comment, Declaration,
857 SubHeading, Signature, std::move(Access),
858 IsFromSystemHeader) {}
classofCXXConstructorRecord859 static bool classof(const APIRecord *Record) {
860 return classofKind(Record->getKind());
861 }
classofKindCXXConstructorRecord862 static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; }
863
864 private:
865 virtual void anchor();
866 };
867
868 struct CXXDestructorRecord : CXXMethodRecord {
CXXDestructorRecordCXXDestructorRecord869 CXXDestructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
870 PresumedLoc Loc, AvailabilityInfo Availability,
871 const DocComment &Comment,
872 DeclarationFragments Declaration,
873 DeclarationFragments SubHeading,
874 FunctionSignature Signature, AccessControl Access,
875 bool IsFromSystemHeader)
876 : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Parent, Loc,
877 std::move(Availability), Comment, Declaration,
878 SubHeading, Signature, std::move(Access),
879 IsFromSystemHeader) {}
classofCXXDestructorRecord880 static bool classof(const APIRecord *Record) {
881 return classofKind(Record->getKind());
882 }
classofKindCXXDestructorRecord883 static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; }
884
885 private:
886 virtual void anchor();
887 };
888
889 struct CXXStaticMethodRecord : CXXMethodRecord {
CXXStaticMethodRecordCXXStaticMethodRecord890 CXXStaticMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
891 PresumedLoc Loc, AvailabilityInfo Availability,
892 const DocComment &Comment,
893 DeclarationFragments Declaration,
894 DeclarationFragments SubHeading,
895 FunctionSignature Signature, AccessControl Access,
896 bool IsFromSystemHeader)
897 : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Parent, Loc,
898 std::move(Availability), Comment, Declaration,
899 SubHeading, Signature, std::move(Access),
900 IsFromSystemHeader) {}
classofCXXStaticMethodRecord901 static bool classof(const APIRecord *Record) {
902 return classofKind(Record->getKind());
903 }
classofKindCXXStaticMethodRecord904 static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; }
905
906 private:
907 virtual void anchor();
908 };
909
910 struct CXXInstanceMethodRecord : CXXMethodRecord {
CXXInstanceMethodRecordCXXInstanceMethodRecord911 CXXInstanceMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
912 PresumedLoc Loc, AvailabilityInfo Availability,
913 const DocComment &Comment,
914 DeclarationFragments Declaration,
915 DeclarationFragments SubHeading,
916 FunctionSignature Signature, AccessControl Access,
917 bool IsFromSystemHeader)
918 : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Parent, Loc,
919 std::move(Availability), Comment, Declaration,
920 SubHeading, Signature, std::move(Access),
921 IsFromSystemHeader) {}
922
classofCXXInstanceMethodRecord923 static bool classof(const APIRecord *Record) {
924 return classofKind(Record->getKind());
925 }
classofKindCXXInstanceMethodRecord926 static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; }
927
928 private:
929 virtual void anchor();
930 };
931
932 struct CXXMethodTemplateRecord : CXXMethodRecord {
933 Template Templ;
934
CXXMethodTemplateRecordCXXMethodTemplateRecord935 CXXMethodTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
936 PresumedLoc Loc, AvailabilityInfo Availability,
937 const DocComment &Comment,
938 DeclarationFragments Declaration,
939 DeclarationFragments SubHeading,
940 FunctionSignature Signature, AccessControl Access,
941 Template Template, bool IsFromSystemHeader)
942 : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Parent, Loc,
943 std::move(Availability), Comment, Declaration,
944 SubHeading, Signature, std::move(Access),
945 IsFromSystemHeader),
946 Templ(Template) {}
947
classofCXXMethodTemplateRecord948 static bool classof(const APIRecord *Record) {
949 return classofKind(Record->getKind());
950 }
classofKindCXXMethodTemplateRecord951 static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; }
952 };
953
954 struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
CXXMethodTemplateSpecializationRecordCXXMethodTemplateSpecializationRecord955 CXXMethodTemplateSpecializationRecord(
956 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
957 AvailabilityInfo Availability, const DocComment &Comment,
958 DeclarationFragments Declaration, DeclarationFragments SubHeading,
959 FunctionSignature Signature, AccessControl Access,
960 bool IsFromSystemHeader)
961 : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Parent,
962 Loc, std::move(Availability), Comment, Declaration,
963 SubHeading, Signature, std::move(Access),
964 IsFromSystemHeader) {}
965
classofCXXMethodTemplateSpecializationRecord966 static bool classof(const APIRecord *Record) {
967 return classofKind(Record->getKind());
968 }
classofKindCXXMethodTemplateSpecializationRecord969 static bool classofKind(RecordKind K) {
970 return K == RK_CXXMethodTemplateSpecialization;
971 }
972 };
973
974 /// This holds information associated with Objective-C properties.
975 struct ObjCPropertyRecord : APIRecord {
976 /// The attributes associated with an Objective-C property.
977 enum AttributeKind : unsigned {
978 NoAttr = 0,
979 ReadOnly = 1,
980 Dynamic = 1 << 2,
981 };
982
983 AttributeKind Attributes;
984 StringRef GetterName;
985 StringRef SetterName;
986 bool IsOptional;
987
ObjCPropertyRecordObjCPropertyRecord988 ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name,
989 SymbolReference Parent, PresumedLoc Loc,
990 AvailabilityInfo Availability, const DocComment &Comment,
991 DeclarationFragments Declaration,
992 DeclarationFragments SubHeading, AttributeKind Attributes,
993 StringRef GetterName, StringRef SetterName,
994 bool IsOptional, bool IsFromSystemHeader)
995 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
996 LinkageInfo::none(), Comment, Declaration, SubHeading,
997 IsFromSystemHeader),
998 Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
999 IsOptional(IsOptional) {}
1000
isReadOnlyObjCPropertyRecord1001 bool isReadOnly() const { return Attributes & ReadOnly; }
isDynamicObjCPropertyRecord1002 bool isDynamic() const { return Attributes & Dynamic; }
1003
1004 virtual ~ObjCPropertyRecord() = 0;
1005 };
1006
1007 struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
ObjCInstancePropertyRecordObjCInstancePropertyRecord1008 ObjCInstancePropertyRecord(
1009 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
1010 AvailabilityInfo Availability, const DocComment &Comment,
1011 DeclarationFragments Declaration, DeclarationFragments SubHeading,
1012 AttributeKind Attributes, StringRef GetterName, StringRef SetterName,
1013 bool IsOptional, bool IsFromSystemHeader)
1014 : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Parent, Loc,
1015 std::move(Availability), Comment, Declaration,
1016 SubHeading, Attributes, GetterName, SetterName,
1017 IsOptional, IsFromSystemHeader) {}
1018
classofObjCInstancePropertyRecord1019 static bool classof(const APIRecord *Record) {
1020 return classofKind(Record->getKind());
1021 }
classofKindObjCInstancePropertyRecord1022 static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; }
1023
1024 private:
1025 virtual void anchor();
1026 };
1027
1028 struct ObjCClassPropertyRecord : ObjCPropertyRecord {
ObjCClassPropertyRecordObjCClassPropertyRecord1029 ObjCClassPropertyRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1030 PresumedLoc Loc, AvailabilityInfo Availability,
1031 const DocComment &Comment,
1032 DeclarationFragments Declaration,
1033 DeclarationFragments SubHeading,
1034 AttributeKind Attributes, StringRef GetterName,
1035 StringRef SetterName, bool IsOptional,
1036 bool IsFromSystemHeader)
1037 : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Parent, Loc,
1038 std::move(Availability), Comment, Declaration,
1039 SubHeading, Attributes, GetterName, SetterName,
1040 IsOptional, IsFromSystemHeader) {}
1041
classofObjCClassPropertyRecord1042 static bool classof(const APIRecord *Record) {
1043 return classofKind(Record->getKind());
1044 }
classofKindObjCClassPropertyRecord1045 static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; }
1046
1047 private:
1048 virtual void anchor();
1049 };
1050
1051 /// This holds information associated with Objective-C instance variables.
1052 struct ObjCInstanceVariableRecord : APIRecord {
ObjCInstanceVariableRecordObjCInstanceVariableRecord1053 ObjCInstanceVariableRecord(StringRef USR, StringRef Name,
1054 SymbolReference Parent, PresumedLoc Loc,
1055 AvailabilityInfo Availability,
1056 const DocComment &Comment,
1057 DeclarationFragments Declaration,
1058 DeclarationFragments SubHeading,
1059 bool IsFromSystemHeader)
1060 : APIRecord(RK_ObjCIvar, USR, Name, Parent, Loc, std::move(Availability),
1061 LinkageInfo::none(), Comment, Declaration, SubHeading,
1062 IsFromSystemHeader) {}
1063
classofObjCInstanceVariableRecord1064 static bool classof(const APIRecord *Record) {
1065 return classofKind(Record->getKind());
1066 }
classofKindObjCInstanceVariableRecord1067 static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; }
1068
1069 private:
1070 virtual void anchor();
1071 };
1072
1073 /// This holds information associated with Objective-C methods.
1074 struct ObjCMethodRecord : APIRecord {
1075 FunctionSignature Signature;
1076
1077 ObjCMethodRecord() = delete;
1078
ObjCMethodRecordObjCMethodRecord1079 ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
1080 SymbolReference Parent, PresumedLoc Loc,
1081 AvailabilityInfo Availability, const DocComment &Comment,
1082 DeclarationFragments Declaration,
1083 DeclarationFragments SubHeading, FunctionSignature Signature,
1084 bool IsFromSystemHeader)
1085 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1086 LinkageInfo::none(), Comment, Declaration, SubHeading,
1087 IsFromSystemHeader),
1088 Signature(Signature) {}
1089
1090 virtual ~ObjCMethodRecord() = 0;
1091 };
1092
1093 struct ObjCInstanceMethodRecord : ObjCMethodRecord {
ObjCInstanceMethodRecordObjCInstanceMethodRecord1094 ObjCInstanceMethodRecord(StringRef USR, StringRef Name,
1095 SymbolReference Parent, PresumedLoc Loc,
1096 AvailabilityInfo Availability,
1097 const DocComment &Comment,
1098 DeclarationFragments Declaration,
1099 DeclarationFragments SubHeading,
1100 FunctionSignature Signature, bool IsFromSystemHeader)
1101 : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Parent, Loc,
1102 std::move(Availability), Comment, Declaration,
1103 SubHeading, Signature, IsFromSystemHeader) {}
classofObjCInstanceMethodRecord1104 static bool classof(const APIRecord *Record) {
1105 return classofKind(Record->getKind());
1106 }
classofKindObjCInstanceMethodRecord1107 static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; }
1108
1109 private:
1110 virtual void anchor();
1111 };
1112
1113 struct ObjCClassMethodRecord : ObjCMethodRecord {
ObjCClassMethodRecordObjCClassMethodRecord1114 ObjCClassMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1115 PresumedLoc Loc, AvailabilityInfo Availability,
1116 const DocComment &Comment,
1117 DeclarationFragments Declaration,
1118 DeclarationFragments SubHeading,
1119 FunctionSignature Signature, bool IsFromSystemHeader)
1120 : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Parent, Loc,
1121 std::move(Availability), Comment, Declaration,
1122 SubHeading, Signature, IsFromSystemHeader) {}
1123
classofObjCClassMethodRecord1124 static bool classof(const APIRecord *Record) {
1125 return classofKind(Record->getKind());
1126 }
classofKindObjCClassMethodRecord1127 static bool classofKind(RecordKind K) { return K == RK_ObjCClassMethod; }
1128
1129 private:
1130 virtual void anchor();
1131 };
1132
1133 struct StaticFieldRecord : CXXFieldRecord {
StaticFieldRecordStaticFieldRecord1134 StaticFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1135 PresumedLoc Loc, AvailabilityInfo Availability,
1136 LinkageInfo Linkage, const DocComment &Comment,
1137 DeclarationFragments Declaration,
1138 DeclarationFragments SubHeading, AccessControl Access,
1139 bool IsFromSystemHeader)
1140 : CXXFieldRecord(RK_StaticField, USR, Name, Parent, Loc,
1141 std::move(Availability), Comment, Declaration,
1142 SubHeading, std::move(Access), IsFromSystemHeader) {}
1143
classofStaticFieldRecord1144 static bool classof(const APIRecord *Record) {
1145 return classofKind(Record->getKind());
1146 }
classofKindStaticFieldRecord1147 static bool classofKind(RecordKind K) { return K == RK_StaticField; }
1148 };
1149
1150 /// The base representation of an Objective-C container record. Holds common
1151 /// information associated with Objective-C containers.
1152 struct ObjCContainerRecord : APIRecord, RecordContext {
1153 SmallVector<SymbolReference> Protocols;
1154
1155 ObjCContainerRecord() = delete;
1156
ObjCContainerRecordObjCContainerRecord1157 ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name,
1158 SymbolReference Parent, PresumedLoc Loc,
1159 AvailabilityInfo Availability, LinkageInfo Linkage,
1160 const DocComment &Comment,
1161 DeclarationFragments Declaration,
1162 DeclarationFragments SubHeading, bool IsFromSystemHeader)
1163 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1164 Linkage, Comment, Declaration, SubHeading,
1165 IsFromSystemHeader),
1166 RecordContext(Kind) {}
1167
1168 virtual ~ObjCContainerRecord() = 0;
1169 };
1170
1171 struct CXXClassRecord : RecordRecord {
1172 SmallVector<SymbolReference> Bases;
1173
1174 CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1175 PresumedLoc Loc, AvailabilityInfo Availability,
1176 const DocComment &Comment, DeclarationFragments Declaration,
1177 DeclarationFragments SubHeading, RecordKind Kind,
1178 AccessControl Access, bool IsFromSystemHeader,
1179 bool IsEmbeddedInVarDeclarator = false)
RecordRecordCXXClassRecord1180 : RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1181 Comment, Declaration, SubHeading, IsFromSystemHeader,
1182 IsEmbeddedInVarDeclarator, std::move(Access)) {}
1183
classofCXXClassRecord1184 static bool classof(const APIRecord *Record) {
1185 return classofKind(Record->getKind());
1186 }
classofKindCXXClassRecord1187 static bool classofKind(RecordKind K) {
1188 return K == RK_CXXClass || K == RK_ClassTemplate ||
1189 K == RK_ClassTemplateSpecialization ||
1190 K == RK_ClassTemplatePartialSpecialization;
1191 }
1192
1193 private:
1194 virtual void anchor();
1195 };
1196
1197 struct ClassTemplateRecord : CXXClassRecord {
1198 Template Templ;
1199
ClassTemplateRecordClassTemplateRecord1200 ClassTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1201 PresumedLoc Loc, AvailabilityInfo Availability,
1202 const DocComment &Comment,
1203 DeclarationFragments Declaration,
1204 DeclarationFragments SubHeading, Template Template,
1205 AccessControl Access, bool IsFromSystemHeader)
1206 : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
1207 Declaration, SubHeading, RK_ClassTemplate,
1208 std::move(Access), IsFromSystemHeader),
1209 Templ(Template) {}
1210
classofClassTemplateRecord1211 static bool classof(const APIRecord *Record) {
1212 return classofKind(Record->getKind());
1213 }
classofKindClassTemplateRecord1214 static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; }
1215 };
1216
1217 struct ClassTemplateSpecializationRecord : CXXClassRecord {
ClassTemplateSpecializationRecordClassTemplateSpecializationRecord1218 ClassTemplateSpecializationRecord(
1219 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
1220 AvailabilityInfo Availability, const DocComment &Comment,
1221 DeclarationFragments Declaration, DeclarationFragments SubHeading,
1222 AccessControl Access, bool IsFromSystemHeader)
1223 : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
1224 Declaration, SubHeading, RK_ClassTemplateSpecialization,
1225 Access, IsFromSystemHeader) {}
1226
classofClassTemplateSpecializationRecord1227 static bool classof(const APIRecord *Record) {
1228 return classofKind(Record->getKind());
1229 }
classofKindClassTemplateSpecializationRecord1230 static bool classofKind(RecordKind K) {
1231 return K == RK_ClassTemplateSpecialization;
1232 }
1233 };
1234
1235 struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
1236 Template Templ;
ClassTemplatePartialSpecializationRecordClassTemplatePartialSpecializationRecord1237 ClassTemplatePartialSpecializationRecord(
1238 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
1239 AvailabilityInfo Availability, const DocComment &Comment,
1240 DeclarationFragments Declaration, DeclarationFragments SubHeading,
1241 Template Template, AccessControl Access, bool IsFromSystemHeader)
1242 : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
1243 Declaration, SubHeading,
1244 RK_ClassTemplatePartialSpecialization, Access,
1245 IsFromSystemHeader),
1246 Templ(Template) {}
1247
classofClassTemplatePartialSpecializationRecord1248 static bool classof(const APIRecord *Record) {
1249 return classofKind(Record->getKind());
1250 }
classofKindClassTemplatePartialSpecializationRecord1251 static bool classofKind(RecordKind K) {
1252 return K == RK_ClassTemplatePartialSpecialization;
1253 }
1254 };
1255
1256 struct ConceptRecord : APIRecord {
1257 Template Templ;
1258
ConceptRecordConceptRecord1259 ConceptRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1260 PresumedLoc Loc, AvailabilityInfo Availability,
1261 const DocComment &Comment, DeclarationFragments Declaration,
1262 DeclarationFragments SubHeading, Template Template,
1263 bool IsFromSystemHeader)
1264 : APIRecord(RK_Concept, USR, Name, Parent, Loc, std::move(Availability),
1265 LinkageInfo::none(), Comment, Declaration, SubHeading,
1266 IsFromSystemHeader),
1267 Templ(Template) {}
1268
classofConceptRecord1269 static bool classof(const APIRecord *Record) {
1270 return classofKind(Record->getKind());
1271 }
classofKindConceptRecord1272 static bool classofKind(RecordKind K) { return K == RK_Concept; }
1273 };
1274
1275 /// This holds information associated with Objective-C categories.
1276 struct ObjCCategoryRecord : ObjCContainerRecord {
1277 SymbolReference Interface;
1278
ObjCCategoryRecordObjCCategoryRecord1279 ObjCCategoryRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1280 PresumedLoc Loc, AvailabilityInfo Availability,
1281 const DocComment &Comment,
1282 DeclarationFragments Declaration,
1283 DeclarationFragments SubHeading, SymbolReference Interface,
1284 bool IsFromSystemHeader)
1285 : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Parent, Loc,
1286 std::move(Availability), LinkageInfo::none(),
1287 Comment, Declaration, SubHeading,
1288 IsFromSystemHeader),
1289 Interface(Interface) {}
1290
classofObjCCategoryRecord1291 static bool classof(const APIRecord *Record) {
1292 return classofKind(Record->getKind());
1293 }
classofKindObjCCategoryRecord1294 static bool classofKind(RecordKind K) { return K == RK_ObjCCategory; }
1295
isExtendingExternalModuleObjCCategoryRecord1296 bool isExtendingExternalModule() const { return !Interface.Source.empty(); }
1297
getExtendedExternalModuleObjCCategoryRecord1298 std::optional<StringRef> getExtendedExternalModule() const {
1299 if (!isExtendingExternalModule())
1300 return {};
1301 return Interface.Source;
1302 }
1303
1304 private:
1305 virtual void anchor();
1306 };
1307
1308 /// This holds information associated with Objective-C interfaces/classes.
1309 struct ObjCInterfaceRecord : ObjCContainerRecord {
1310 SymbolReference SuperClass;
1311
ObjCInterfaceRecordObjCInterfaceRecord1312 ObjCInterfaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1313 PresumedLoc Loc, AvailabilityInfo Availability,
1314 LinkageInfo Linkage, const DocComment &Comment,
1315 DeclarationFragments Declaration,
1316 DeclarationFragments SubHeading,
1317 SymbolReference SuperClass, bool IsFromSystemHeader)
1318 : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Parent, Loc,
1319 std::move(Availability), Linkage, Comment,
1320 Declaration, SubHeading, IsFromSystemHeader),
1321 SuperClass(SuperClass) {}
1322
classofObjCInterfaceRecord1323 static bool classof(const APIRecord *Record) {
1324 return classofKind(Record->getKind());
1325 }
classofKindObjCInterfaceRecord1326 static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; }
1327
1328 private:
1329 virtual void anchor();
1330 };
1331
1332 /// This holds information associated with Objective-C protocols.
1333 struct ObjCProtocolRecord : ObjCContainerRecord {
ObjCProtocolRecordObjCProtocolRecord1334 ObjCProtocolRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1335 PresumedLoc Loc, AvailabilityInfo Availability,
1336 const DocComment &Comment,
1337 DeclarationFragments Declaration,
1338 DeclarationFragments SubHeading, bool IsFromSystemHeader)
1339 : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Parent, Loc,
1340 std::move(Availability), LinkageInfo::none(),
1341 Comment, Declaration, SubHeading,
1342 IsFromSystemHeader) {}
1343
classofObjCProtocolRecord1344 static bool classof(const APIRecord *Record) {
1345 return classofKind(Record->getKind());
1346 }
classofKindObjCProtocolRecord1347 static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; }
1348
1349 private:
1350 virtual void anchor();
1351 };
1352
1353 /// This holds information associated with macro definitions.
1354 struct MacroDefinitionRecord : APIRecord {
MacroDefinitionRecordMacroDefinitionRecord1355 MacroDefinitionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1356 PresumedLoc Loc, DeclarationFragments Declaration,
1357 DeclarationFragments SubHeading,
1358 bool IsFromSystemHeader)
1359 : APIRecord(RK_MacroDefinition, USR, Name, Parent, Loc,
1360 AvailabilityInfo(), LinkageInfo(), {}, Declaration,
1361 SubHeading, IsFromSystemHeader) {}
1362
classofMacroDefinitionRecord1363 static bool classof(const APIRecord *Record) {
1364 return classofKind(Record->getKind());
1365 }
classofKindMacroDefinitionRecord1366 static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; }
1367
1368 private:
1369 virtual void anchor();
1370 };
1371
1372 /// This holds information associated with typedefs.
1373 ///
1374 /// Note: Typedefs for anonymous enums and structs typically don't get emitted
1375 /// by the serializers but still get a TypedefRecord. Instead we use the
1376 /// typedef name as a name for the underlying anonymous struct or enum.
1377 struct TypedefRecord : APIRecord {
1378 SymbolReference UnderlyingType;
1379
TypedefRecordTypedefRecord1380 TypedefRecord(StringRef USR, StringRef Name, SymbolReference Parent,
1381 PresumedLoc Loc, AvailabilityInfo Availability,
1382 const DocComment &Comment, DeclarationFragments Declaration,
1383 DeclarationFragments SubHeading, SymbolReference UnderlyingType,
1384 bool IsFromSystemHeader)
1385 : APIRecord(RK_Typedef, USR, Name, Parent, Loc, std::move(Availability),
1386 LinkageInfo(), Comment, Declaration, SubHeading,
1387 IsFromSystemHeader),
1388 UnderlyingType(UnderlyingType) {}
1389
classofTypedefRecord1390 static bool classof(const APIRecord *Record) {
1391 return classofKind(Record->getKind());
1392 }
classofKindTypedefRecord1393 static bool classofKind(RecordKind K) { return K == RK_Typedef; }
1394
1395 private:
1396 virtual void anchor();
1397 };
1398
1399 /// APISet holds the set of API records collected from given inputs.
1400 class APISet {
1401 public:
1402 /// Get the target triple for the ExtractAPI invocation.
getTarget()1403 const llvm::Triple &getTarget() const { return Target; }
1404
1405 /// Get the language used by the APIs.
getLanguage()1406 Language getLanguage() const { return Lang; }
1407
1408 /// Finds the APIRecord for a given USR.
1409 ///
1410 /// \returns a pointer to the APIRecord associated with that USR or nullptr.
1411 APIRecord *findRecordForUSR(StringRef USR) const;
1412
1413 /// Copy \p String into the Allocator in this APISet.
1414 ///
1415 /// \returns a StringRef of the copied string in APISet::Allocator.
1416 StringRef copyString(StringRef String);
1417
1418 SymbolReference createSymbolReference(StringRef Name, StringRef USR,
1419 StringRef Source = "");
1420
1421 /// Create a subclass of \p APIRecord and store it in the APISet.
1422 ///
1423 /// \returns A pointer to the created record or the already existing record
1424 /// matching this USR.
1425 template <typename RecordTy, typename... CtorArgsContTy>
1426 typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
1427 createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs);
1428
getTopLevelRecords()1429 ArrayRef<const APIRecord *> getTopLevelRecords() const {
1430 return TopLevelRecords;
1431 }
1432
APISet(const llvm::Triple & Target,Language Lang,const std::string & ProductName)1433 APISet(const llvm::Triple &Target, Language Lang,
1434 const std::string &ProductName)
1435 : Target(Target), Lang(Lang), ProductName(ProductName) {}
1436
1437 // Prevent moves and copies
1438 APISet(const APISet &Other) = delete;
1439 APISet &operator=(const APISet &Other) = delete;
1440 APISet(APISet &&Other) = delete;
1441 APISet &operator=(APISet &&Other) = delete;
1442
1443 private:
1444 /// BumpPtrAllocator that serves as the memory arena for the allocated objects
1445 llvm::BumpPtrAllocator Allocator;
1446
1447 const llvm::Triple Target;
1448 const Language Lang;
1449
1450 struct APIRecordDeleter {
operatorAPIRecordDeleter1451 void operator()(APIRecord *Record) { Record->~APIRecord(); }
1452 };
1453
1454 // Ensure that the destructor of each record is called when the LookupTable is
1455 // destroyed without calling delete operator as the memory for the record
1456 // lives in the BumpPtrAllocator.
1457 using APIRecordStoredPtr = std::unique_ptr<APIRecord, APIRecordDeleter>;
1458 llvm::DenseMap<StringRef, APIRecordStoredPtr> USRBasedLookupTable;
1459 std::vector<const APIRecord *> TopLevelRecords;
1460
1461 public:
1462 const std::string ProductName;
1463 };
1464
1465 template <typename RecordTy, typename... CtorArgsContTy>
1466 typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
createRecord(StringRef USR,StringRef Name,CtorArgsContTy &&...CtorArgs)1467 APISet::createRecord(StringRef USR, StringRef Name,
1468 CtorArgsContTy &&...CtorArgs) {
1469 // Ensure USR refers to a String stored in the allocator.
1470 auto USRString = copyString(USR);
1471 auto Result = USRBasedLookupTable.insert({USRString, nullptr});
1472 RecordTy *Record;
1473
1474 // Create the record if it does not already exist
1475 if (Result.second) {
1476 Record = new (Allocator) RecordTy(
1477 USRString, copyString(Name), std::forward<CtorArgsContTy>(CtorArgs)...);
1478 // Store the record in the record lookup map
1479 Result.first->second = APIRecordStoredPtr(Record);
1480
1481 if (auto *ParentContext =
1482 dyn_cast_if_present<RecordContext>(Record->Parent.Record))
1483 ParentContext->addToRecordChain(Record);
1484 else
1485 TopLevelRecords.push_back(Record);
1486 } else {
1487 Record = dyn_cast<RecordTy>(Result.first->second.get());
1488 }
1489
1490 return Record;
1491 }
1492
1493 // Helper type for implementing casting to RecordContext pointers.
1494 // Selected when FromTy not a known subclass of RecordContext.
1495 template <typename FromTy,
1496 bool IsKnownSubType = std::is_base_of_v<RecordContext, FromTy>>
1497 struct ToRecordContextCastInfoWrapper {
1498 static_assert(std::is_base_of_v<APIRecord, FromTy>,
1499 "Can only cast APIRecord and derived classes to RecordContext");
1500
isPossibleToRecordContextCastInfoWrapper1501 static bool isPossible(FromTy *From) { return RecordContext::classof(From); }
1502
doCastToRecordContextCastInfoWrapper1503 static RecordContext *doCast(FromTy *From) {
1504 return APIRecord::castToRecordContext(From);
1505 }
1506 };
1507
1508 // Selected when FromTy is a known subclass of RecordContext.
1509 template <typename FromTy> struct ToRecordContextCastInfoWrapper<FromTy, true> {
1510 static_assert(std::is_base_of_v<APIRecord, FromTy>,
1511 "Can only cast APIRecord and derived classes to RecordContext");
1512 static bool isPossible(const FromTy *From) { return true; }
1513 static RecordContext *doCast(FromTy *From) {
1514 return static_cast<RecordContext *>(From);
1515 }
1516 };
1517
1518 // Helper type for implementing casting to RecordContext pointers.
1519 // Selected when ToTy isn't a known subclass of RecordContext
1520 template <typename ToTy,
1521 bool IsKnownSubType = std::is_base_of_v<RecordContext, ToTy>>
1522 struct FromRecordContextCastInfoWrapper {
1523 static_assert(
1524 std::is_base_of_v<APIRecord, ToTy>,
1525 "Can only class RecordContext to APIRecord and derived classes");
1526
1527 static bool isPossible(RecordContext *Ctx) {
1528 return ToTy::classofKind(Ctx->getKind());
1529 }
1530
1531 static ToTy *doCast(RecordContext *Ctx) {
1532 return APIRecord::castFromRecordContext(Ctx);
1533 }
1534 };
1535
1536 // Selected when ToTy is a known subclass of RecordContext.
1537 template <typename ToTy> struct FromRecordContextCastInfoWrapper<ToTy, true> {
1538 static_assert(
1539 std::is_base_of_v<APIRecord, ToTy>,
1540 "Can only class RecordContext to APIRecord and derived classes");
1541 static bool isPossible(RecordContext *Ctx) {
1542 return ToTy::classof(Ctx->getKind());
1543 }
1544 static RecordContext *doCast(RecordContext *Ctx) {
1545 return static_cast<ToTy *>(Ctx);
1546 }
1547 };
1548
1549 } // namespace extractapi
1550 } // namespace clang
1551
1552 // Implement APIRecord (and derived classes) to and from RecordContext
1553 // conversions
1554 namespace llvm {
1555
1556 template <typename FromTy>
1557 struct CastInfo<::clang::extractapi::RecordContext, FromTy *>
1558 : public NullableValueCastFailed<::clang::extractapi::RecordContext *>,
1559 public DefaultDoCastIfPossible<
1560 ::clang::extractapi::RecordContext *, FromTy *,
1561 CastInfo<::clang::extractapi::RecordContext, FromTy *>> {
1562 static inline bool isPossible(FromTy *From) {
1563 return ::clang::extractapi::ToRecordContextCastInfoWrapper<
1564 FromTy>::isPossible(From);
1565 }
1566
1567 static inline ::clang::extractapi::RecordContext *doCast(FromTy *From) {
1568 return ::clang::extractapi::ToRecordContextCastInfoWrapper<FromTy>::doCast(
1569 From);
1570 }
1571 };
1572
1573 template <typename FromTy>
1574 struct CastInfo<::clang::extractapi::RecordContext, const FromTy *>
1575 : public ConstStrippingForwardingCast<
1576 ::clang::extractapi::RecordContext, const FromTy *,
1577 CastInfo<::clang::extractapi::RecordContext, FromTy *>> {};
1578
1579 template <typename ToTy>
1580 struct CastInfo<ToTy, ::clang::extractapi::RecordContext *>
1581 : public NullableValueCastFailed<ToTy *>,
1582 public DefaultDoCastIfPossible<
1583 ToTy *, ::clang::extractapi::RecordContext *,
1584 CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {
1585 static inline bool isPossible(::clang::extractapi::RecordContext *Ctx) {
1586 return ::clang::extractapi::FromRecordContextCastInfoWrapper<
1587 ToTy>::isPossible(Ctx);
1588 }
1589
1590 static inline ToTy *doCast(::clang::extractapi::RecordContext *Ctx) {
1591 return ::clang::extractapi::FromRecordContextCastInfoWrapper<ToTy>::doCast(
1592 Ctx);
1593 }
1594 };
1595
1596 template <typename ToTy>
1597 struct CastInfo<ToTy, const ::clang::extractapi::RecordContext *>
1598 : public ConstStrippingForwardingCast<
1599 ToTy, const ::clang::extractapi::RecordContext *,
1600 CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {};
1601
1602 } // namespace llvm
1603
1604 #endif // LLVM_CLANG_EXTRACTAPI_API_H
1605