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