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
44namespace clang {
45namespace extractapi {
46
47class 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
56 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
71public:
72 Template() = default;
73
74 Template(const TemplateDecl *Decl) {
75 for (auto *const Parameter : *Decl->getTemplateParameters()) {
76 const auto *Param = dyn_cast<TemplateTypeParmDecl>(Val: 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, Name: Param->getName().str(), Index: Param->getIndex(),
88 Depth: Param->getDepth(), IsParameterPack: Param->isParameterPack());
89 }
90 }
91
92 Template(const ClassTemplatePartialSpecializationDecl *Decl) {
93 for (auto *const Parameter : *Decl->getTemplateParameters()) {
94 const auto *Param = dyn_cast<TemplateTypeParmDecl>(Val: 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, Name: Param->getName().str(), Index: Param->getIndex(),
106 Depth: Param->getDepth(), IsParameterPack: Param->isParameterPack());
107 }
108 }
109
110 Template(const VarTemplatePartialSpecializationDecl *Decl) {
111 for (auto *const Parameter : *Decl->getTemplateParameters()) {
112 const auto *Param = dyn_cast<TemplateTypeParmDecl>(Val: 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, Name: Param->getName().str(), Index: Param->getIndex(),
124 Depth: Param->getDepth(), IsParameterPack: Param->isParameterPack());
125 }
126 }
127
128 const llvm::SmallVector<TemplateParameter> &getParameters() const {
129 return Parameters;
130 }
131
132 const llvm::SmallVector<TemplateConstraint> &getConstraints() const {
133 return Constraints;
134 }
135
136 void addTemplateParameter(std::string Type, std::string Name,
137 unsigned int Index, unsigned int Depth,
138 bool IsParameterPack) {
139 Parameters.emplace_back(Args&: Type, Args&: Name, Args&: Index, Args&: Depth, Args&: IsParameterPack);
140 }
141
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
158using DocComment = std::vector<RawComment::CommentLine>;
159
160struct APIRecord;
161
162// This represents a reference to another symbol that might come from external
163/// sources.
164struct 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 = "")
176 : 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.
182 bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
183};
184
185class 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.
192struct 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
269private:
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
276public:
277 APIRecord *getNextInContext() const { return NextInContext; }
278
279 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())
292 : 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
298 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;
303 static bool classof(const APIRecord *Record) { return true; }
304 static bool classofKind(RecordKind K) { return true; }
305 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
310class RecordContext {
311public:
312 static bool classof(const APIRecord *Record) {
313 return classofKind(K: Record->getKind());
314 }
315 static bool classofKind(APIRecord::RecordKind K) {
316 return K > APIRecord::RK_FirstRecordContext &&
317 K < APIRecord::RK_LastRecordContext;
318 }
319
320 static bool classof(const RecordContext *Context) { return true; }
321
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
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;
342 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>;
366 record_range records() const {
367 return record_range(records_begin(), records_end());
368 }
369 record_iterator records_begin() const { return record_iterator(First); };
370 record_iterator records_end() const { return record_iterator(); }
371 bool records_empty() const { return First == nullptr; };
372
373private:
374 APIRecord::RecordKind Kind;
375 mutable APIRecord *First = nullptr;
376 mutable APIRecord *Last = nullptr;
377 bool IsWellFormed() const;
378
379protected:
380 friend class APISet;
381 void addToRecordChain(APIRecord *) const;
382};
383
384struct NamespaceRecord : APIRecord, RecordContext {
385 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
395 static bool classof(const APIRecord *Record) {
396 return classofKind(K: Record->getKind());
397 }
398 static bool classofKind(RecordKind K) { return K == RK_Namespace; }
399};
400
401/// This holds information associated with global functions.
402struct GlobalFunctionRecord : APIRecord {
403 FunctionSignature Signature;
404
405 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
416 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
428 static bool classof(const APIRecord *Record) {
429 return classofKind(K: Record->getKind());
430 }
431 static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; }
432
433private:
434 virtual void anchor();
435};
436
437struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
438 Template Templ;
439
440 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
454 static bool classof(const APIRecord *Record) {
455 return classofKind(K: Record->getKind());
456 }
457 static bool classofKind(RecordKind K) {
458 return K == RK_GlobalFunctionTemplate;
459 }
460};
461
462struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
463 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
474 static bool classof(const APIRecord *Record) {
475 return classofKind(K: Record->getKind());
476 }
477 static bool classofKind(RecordKind K) {
478 return K == RK_GlobalFunctionTemplateSpecialization;
479 }
480};
481
482/// This holds information associated with global functions.
483struct GlobalVariableRecord : APIRecord, RecordContext {
484 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
494 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
505 static bool classof(const APIRecord *Record) {
506 return classofKind(K: Record->getKind());
507 }
508 static bool classofKind(RecordKind K) {
509 return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate ||
510 K == RK_GlobalVariableTemplateSpecialization ||
511 K == RK_GlobalVariableTemplatePartialSpecialization;
512 }
513
514private:
515 virtual void anchor();
516};
517
518struct GlobalVariableTemplateRecord : GlobalVariableRecord {
519 Template Templ;
520
521 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
533 static bool classof(const APIRecord *Record) {
534 return classofKind(K: Record->getKind());
535 }
536 static bool classofKind(RecordKind K) {
537 return K == RK_GlobalVariableTemplate;
538 }
539};
540
541struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord {
542 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
552 static bool classof(const APIRecord *Record) {
553 return classofKind(K: Record->getKind());
554 }
555 static bool classofKind(RecordKind K) {
556 return K == RK_GlobalVariableTemplateSpecialization;
557 }
558};
559
560struct GlobalVariableTemplatePartialSpecializationRecord
561 : GlobalVariableRecord {
562 Template Templ;
563
564 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
576 static bool classof(const APIRecord *Record) {
577 return classofKind(K: Record->getKind());
578 }
579 static bool classofKind(RecordKind K) {
580 return K == RK_GlobalVariableTemplatePartialSpecialization;
581 }
582};
583
584/// This holds information associated with enum constants.
585struct EnumConstantRecord : APIRecord {
586 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
595 static bool classof(const APIRecord *Record) {
596 return classofKind(K: Record->getKind());
597 }
598 static bool classofKind(RecordKind K) { return K == RK_EnumConstant; }
599
600private:
601 virtual void anchor();
602};
603
604struct 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())
611 : 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
617 static bool classof(const APIRecord *Record) {
618 return classofKind(K: Record->getKind());
619 }
620 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.
630struct 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())
637 : TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
638 Comment, Declaration, SubHeading, IsFromSystemHeader,
639 IsEmbeddedInVarDeclarator, std::move(Access)) {}
640
641 static bool classof(const APIRecord *Record) {
642 return classofKind(K: Record->getKind());
643 }
644
645 static bool classofKind(RecordKind K) { return K == RK_Enum; }
646
647private:
648 virtual void anchor();
649};
650
651/// This holds information associated with struct or union fields fields.
652struct RecordFieldRecord : APIRecord, RecordContext {
653 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
663 static bool classof(const APIRecord *Record) {
664 return classofKind(K: Record->getKind());
665 }
666 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.
674struct 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())
682 : TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
683 Comment, Declaration, SubHeading, IsFromSystemHeader,
684 IsEmbeddedInVarDeclarator, std::move(Access)) {}
685
686 static bool classof(const APIRecord *Record) {
687 return classofKind(K: Record->getKind());
688 }
689 static bool classofKind(RecordKind K) {
690 return K == RK_Struct || K == RK_Union;
691 }
692
693 bool isAnonymousWithNoTypedef() { return Name.empty(); }
694
695 virtual ~RecordRecord() = 0;
696};
697
698struct StructFieldRecord : RecordFieldRecord {
699 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
707 static bool classof(const APIRecord *Record) {
708 return classofKind(K: Record->getKind());
709 }
710 static bool classofKind(RecordKind K) { return K == RK_StructField; }
711
712private:
713 virtual void anchor();
714};
715
716struct StructRecord : RecordRecord {
717 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
726 static bool classof(const APIRecord *Record) {
727 return classofKind(K: Record->getKind());
728 }
729 static bool classofKind(RecordKind K) { return K == RK_Struct; }
730
731private:
732 virtual void anchor();
733};
734
735struct UnionFieldRecord : RecordFieldRecord {
736 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
744 static bool classof(const APIRecord *Record) {
745 return classofKind(K: Record->getKind());
746 }
747 static bool classofKind(RecordKind K) { return K == RK_UnionField; }
748
749private:
750 virtual void anchor();
751};
752
753struct UnionRecord : RecordRecord {
754 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
763 static bool classof(const APIRecord *Record) {
764 return classofKind(K: Record->getKind());
765 }
766 static bool classofKind(RecordKind K) { return K == RK_Union; }
767
768private:
769 virtual void anchor();
770};
771
772struct CXXFieldRecord : APIRecord, RecordContext {
773 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
783 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
794 static bool classof(const APIRecord *Record) {
795 return classofKind(K: Record->getKind());
796 }
797 static bool classofKind(RecordKind K) {
798 return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField;
799 }
800
801private:
802 virtual void anchor();
803};
804
805struct CXXFieldTemplateRecord : CXXFieldRecord {
806 Template Templ;
807
808 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
819 static bool classof(const APIRecord *Record) {
820 return classofKind(K: Record->getKind());
821 }
822 static bool classofKind(RecordKind K) { return K == RK_CXXFieldTemplate; }
823};
824
825struct CXXMethodRecord : APIRecord {
826 FunctionSignature Signature;
827
828 CXXMethodRecord() = delete;
829
830 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
844struct CXXConstructorRecord : CXXMethodRecord {
845 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) {}
856 static bool classof(const APIRecord *Record) {
857 return classofKind(K: Record->getKind());
858 }
859 static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; }
860
861private:
862 virtual void anchor();
863};
864
865struct CXXDestructorRecord : CXXMethodRecord {
866 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) {}
877 static bool classof(const APIRecord *Record) {
878 return classofKind(K: Record->getKind());
879 }
880 static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; }
881
882private:
883 virtual void anchor();
884};
885
886struct CXXStaticMethodRecord : CXXMethodRecord {
887 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) {}
898 static bool classof(const APIRecord *Record) {
899 return classofKind(K: Record->getKind());
900 }
901 static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; }
902
903private:
904 virtual void anchor();
905};
906
907struct CXXInstanceMethodRecord : CXXMethodRecord {
908 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
920 static bool classof(const APIRecord *Record) {
921 return classofKind(K: Record->getKind());
922 }
923 static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; }
924
925private:
926 virtual void anchor();
927};
928
929struct CXXMethodTemplateRecord : CXXMethodRecord {
930 Template Templ;
931
932 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
945 static bool classof(const APIRecord *Record) {
946 return classofKind(K: Record->getKind());
947 }
948 static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; }
949};
950
951struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
952 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
963 static bool classof(const APIRecord *Record) {
964 return classofKind(K: Record->getKind());
965 }
966 static bool classofKind(RecordKind K) {
967 return K == RK_CXXMethodTemplateSpecialization;
968 }
969};
970
971/// This holds information associated with Objective-C properties.
972struct 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
985 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
998 bool isReadOnly() const { return Attributes & ReadOnly; }
999 bool isDynamic() const { return Attributes & Dynamic; }
1000
1001 virtual ~ObjCPropertyRecord() = 0;
1002};
1003
1004struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
1005 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
1016 static bool classof(const APIRecord *Record) {
1017 return classofKind(K: Record->getKind());
1018 }
1019 static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; }
1020
1021private:
1022 virtual void anchor();
1023};
1024
1025struct ObjCClassPropertyRecord : ObjCPropertyRecord {
1026 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
1039 static bool classof(const APIRecord *Record) {
1040 return classofKind(K: Record->getKind());
1041 }
1042 static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; }
1043
1044private:
1045 virtual void anchor();
1046};
1047
1048/// This holds information associated with Objective-C instance variables.
1049struct ObjCInstanceVariableRecord : APIRecord {
1050 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
1061 static bool classof(const APIRecord *Record) {
1062 return classofKind(K: Record->getKind());
1063 }
1064 static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; }
1065
1066private:
1067 virtual void anchor();
1068};
1069
1070/// This holds information associated with Objective-C methods.
1071struct ObjCMethodRecord : APIRecord {
1072 FunctionSignature Signature;
1073
1074 ObjCMethodRecord() = delete;
1075
1076 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
1090struct ObjCInstanceMethodRecord : ObjCMethodRecord {
1091 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) {}
1101 static bool classof(const APIRecord *Record) {
1102 return classofKind(K: Record->getKind());
1103 }
1104 static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; }
1105
1106private:
1107 virtual void anchor();
1108};
1109
1110struct ObjCClassMethodRecord : ObjCMethodRecord {
1111 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
1121 static bool classof(const APIRecord *Record) {
1122 return classofKind(K: Record->getKind());
1123 }
1124 static bool classofKind(RecordKind K) { return K == RK_ObjCClassMethod; }
1125
1126private:
1127 virtual void anchor();
1128};
1129
1130struct StaticFieldRecord : CXXFieldRecord {
1131 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
1141 static bool classof(const APIRecord *Record) {
1142 return classofKind(K: Record->getKind());
1143 }
1144 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.
1149struct ObjCContainerRecord : APIRecord, RecordContext {
1150 SmallVector<SymbolReference> Protocols;
1151
1152 ObjCContainerRecord() = delete;
1153
1154 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
1168struct 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)
1177 : RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
1178 Comment, Declaration, SubHeading, IsFromSystemHeader,
1179 IsEmbeddedInVarDeclarator, std::move(Access)) {}
1180
1181 static bool classof(const APIRecord *Record) {
1182 return classofKind(K: Record->getKind());
1183 }
1184 static bool classofKind(RecordKind K) {
1185 return K == RK_CXXClass || K == RK_ClassTemplate ||
1186 K == RK_ClassTemplateSpecialization ||
1187 K == RK_ClassTemplatePartialSpecialization;
1188 }
1189
1190private:
1191 virtual void anchor();
1192};
1193
1194struct ClassTemplateRecord : CXXClassRecord {
1195 Template Templ;
1196
1197 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
1208 static bool classof(const APIRecord *Record) {
1209 return classofKind(K: Record->getKind());
1210 }
1211 static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; }
1212};
1213
1214struct ClassTemplateSpecializationRecord : CXXClassRecord {
1215 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
1224 static bool classof(const APIRecord *Record) {
1225 return classofKind(K: Record->getKind());
1226 }
1227 static bool classofKind(RecordKind K) {
1228 return K == RK_ClassTemplateSpecialization;
1229 }
1230};
1231
1232struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
1233 Template Templ;
1234 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
1245 static bool classof(const APIRecord *Record) {
1246 return classofKind(K: Record->getKind());
1247 }
1248 static bool classofKind(RecordKind K) {
1249 return K == RK_ClassTemplatePartialSpecialization;
1250 }
1251};
1252
1253struct ConceptRecord : APIRecord {
1254 Template Templ;
1255
1256 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
1266 static bool classof(const APIRecord *Record) {
1267 return classofKind(K: Record->getKind());
1268 }
1269 static bool classofKind(RecordKind K) { return K == RK_Concept; }
1270};
1271
1272/// This holds information associated with Objective-C categories.
1273struct ObjCCategoryRecord : ObjCContainerRecord {
1274 SymbolReference Interface;
1275
1276 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
1288 static bool classof(const APIRecord *Record) {
1289 return classofKind(K: Record->getKind());
1290 }
1291 static bool classofKind(RecordKind K) { return K == RK_ObjCCategory; }
1292
1293 bool isExtendingExternalModule() const { return !Interface.Source.empty(); }
1294
1295 std::optional<StringRef> getExtendedExternalModule() const {
1296 if (!isExtendingExternalModule())
1297 return {};
1298 return Interface.Source;
1299 }
1300
1301private:
1302 virtual void anchor();
1303};
1304
1305/// This holds information associated with Objective-C interfaces/classes.
1306struct ObjCInterfaceRecord : ObjCContainerRecord {
1307 SymbolReference SuperClass;
1308
1309 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
1320 static bool classof(const APIRecord *Record) {
1321 return classofKind(K: Record->getKind());
1322 }
1323 static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; }
1324
1325private:
1326 virtual void anchor();
1327};
1328
1329/// This holds information associated with Objective-C protocols.
1330struct ObjCProtocolRecord : ObjCContainerRecord {
1331 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
1341 static bool classof(const APIRecord *Record) {
1342 return classofKind(K: Record->getKind());
1343 }
1344 static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; }
1345
1346private:
1347 virtual void anchor();
1348};
1349
1350/// This holds information associated with macro definitions.
1351struct MacroDefinitionRecord : APIRecord {
1352 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
1360 static bool classof(const APIRecord *Record) {
1361 return classofKind(K: Record->getKind());
1362 }
1363 static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; }
1364
1365private:
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.
1374struct TypedefRecord : APIRecord {
1375 SymbolReference UnderlyingType;
1376
1377 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
1387 static bool classof(const APIRecord *Record) {
1388 return classofKind(K: Record->getKind());
1389 }
1390 static bool classofKind(RecordKind K) { return K == RK_Typedef; }
1391
1392private:
1393 virtual void anchor();
1394};
1395
1396/// APISet holds the set of API records collected from given inputs.
1397class APISet {
1398public:
1399 /// Get the target triple for the ExtractAPI invocation.
1400 const llvm::Triple &getTarget() const { return Target; }
1401
1402 /// Get the language used by the APIs.
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
1426 ArrayRef<const APIRecord *> getTopLevelRecords() const {
1427 return TopLevelRecords;
1428 }
1429
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
1440private:
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 {
1448 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
1458public:
1459 const std::string ProductName;
1460};
1461
1462template <typename RecordTy, typename... CtorArgsContTy>
1463typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
1464APISet::createRecord(StringRef USR, StringRef Name,
1465 CtorArgsContTy &&...CtorArgs) {
1466 // Ensure USR refers to a String stored in the allocator.
1467 auto USRString = copyString(String: USR);
1468 auto Result = USRBasedLookupTable.insert(KV: {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(String: 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.
1492template <typename FromTy,
1493 bool IsKnownSubType = std::is_base_of_v<RecordContext, FromTy>>
1494struct ToRecordContextCastInfoWrapper {
1495 static_assert(std::is_base_of_v<APIRecord, FromTy>,
1496 "Can only cast APIRecord and derived classes to RecordContext");
1497
1498 static bool isPossible(FromTy *From) { return RecordContext::classof(From); }
1499
1500 static RecordContext *doCast(FromTy *From) {
1501 return APIRecord::castToRecordContext(Record: From);
1502 }
1503};
1504
1505// Selected when FromTy is a known subclass of RecordContext.
1506template <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
1517template <typename ToTy,
1518 bool IsKnownSubType = std::is_base_of_v<RecordContext, ToTy>>
1519struct 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.
1534template <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
1551namespace llvm {
1552
1553template <typename FromTy>
1554struct 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
1570template <typename FromTy>
1571struct CastInfo<::clang::extractapi::RecordContext, const FromTy *>
1572 : public ConstStrippingForwardingCast<
1573 ::clang::extractapi::RecordContext, const FromTy *,
1574 CastInfo<::clang::extractapi::RecordContext, FromTy *>> {};
1575
1576template <typename ToTy>
1577struct 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
1593template <typename ToTy>
1594struct 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

source code of clang/include/clang/ExtractAPI/API.h