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 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 71 public: 72 Template() = default; 73 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 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 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 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(Type, Name, Index, Depth, 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 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 = "") 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 185 class RecordContext; 186 187 // Concrete classes deriving from APIRecord need to have a construct with first 188 // arguments USR, and Name, in that order. This is so that they 189 // are compatible with `APISet::createRecord`. 190 // When adding a new kind of record don't forget to update APIRecords.inc! 191 /// The base representation of an API record. Holds common symbol information. 192 struct APIRecord { 193 /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) 194 enum RecordKind { 195 RK_Unknown, 196 // If adding a record context record kind here make sure to update 197 // RecordContext::classof if needed and add a RECORD_CONTEXT entry to 198 // APIRecords.inc 199 RK_FirstRecordContext, 200 RK_Namespace, 201 RK_Enum, 202 RK_Struct, 203 RK_Union, 204 RK_ObjCInterface, 205 RK_ObjCCategory, 206 RK_ObjCProtocol, 207 RK_CXXClass, 208 RK_ClassTemplate, 209 RK_ClassTemplateSpecialization, 210 RK_ClassTemplatePartialSpecialization, 211 RK_StructField, 212 RK_UnionField, 213 RK_CXXField, 214 RK_StaticField, 215 RK_CXXFieldTemplate, 216 RK_GlobalVariable, 217 RK_GlobalVariableTemplate, 218 RK_GlobalVariableTemplateSpecialization, 219 RK_GlobalVariableTemplatePartialSpecialization, 220 RK_LastRecordContext, 221 RK_GlobalFunction, 222 RK_GlobalFunctionTemplate, 223 RK_GlobalFunctionTemplateSpecialization, 224 RK_EnumConstant, 225 RK_Concept, 226 RK_CXXStaticMethod, 227 RK_CXXInstanceMethod, 228 RK_CXXConstructorMethod, 229 RK_CXXDestructorMethod, 230 RK_CXXMethodTemplate, 231 RK_CXXMethodTemplateSpecialization, 232 RK_ObjCInstanceProperty, 233 RK_ObjCClassProperty, 234 RK_ObjCIvar, 235 RK_ObjCClassMethod, 236 RK_ObjCInstanceMethod, 237 RK_MacroDefinition, 238 RK_Typedef, 239 }; 240 241 StringRef USR; 242 StringRef Name; 243 244 SymbolReference Parent; 245 246 PresumedLoc Location; 247 AvailabilityInfo Availability; 248 LinkageInfo Linkage; 249 250 /// Documentation comment lines attached to this symbol declaration. 251 DocComment Comment; 252 253 /// Declaration fragments of this symbol declaration. 254 DeclarationFragments Declaration; 255 256 /// SubHeading provides a more detailed representation than the plain 257 /// declaration name. 258 /// 259 /// SubHeading is an array of declaration fragments of tagged declaration 260 /// name, with potentially more tokens (for example the \c +/- symbol for 261 /// Objective-C class/instance methods). 262 DeclarationFragments SubHeading; 263 264 /// Whether the symbol was defined in a system header. 265 bool IsFromSystemHeader; 266 267 AccessControl Access; 268 269 RecordKind KindForDisplay; 270 271 private: 272 const RecordKind Kind; 273 friend class RecordContext; 274 // Used to store the next child record in RecordContext. This works because 275 // APIRecords semantically only have one parent. 276 mutable APIRecord *NextInContext = nullptr; 277 278 public: 279 APIRecord *getNextInContext() const { return NextInContext; } 280 281 RecordKind getKind() const { return Kind; } 282 RecordKind getKindForDisplay() const { return KindForDisplay; } 283 284 static APIRecord *castFromRecordContext(const RecordContext *Ctx); 285 static RecordContext *castToRecordContext(const APIRecord *Record); 286 287 APIRecord() = delete; 288 289 APIRecord(RecordKind Kind, StringRef USR, StringRef Name, 290 SymbolReference Parent, PresumedLoc Location, 291 AvailabilityInfo Availability, LinkageInfo Linkage, 292 const DocComment &Comment, DeclarationFragments Declaration, 293 DeclarationFragments SubHeading, bool IsFromSystemHeader, 294 AccessControl Access = AccessControl()) 295 : USR(USR), Name(Name), Parent(std::move(Parent)), Location(Location), 296 Availability(std::move(Availability)), Linkage(Linkage), 297 Comment(Comment), Declaration(Declaration), SubHeading(SubHeading), 298 IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)), 299 KindForDisplay(Kind), Kind(Kind) {} 300 301 APIRecord(RecordKind Kind, StringRef USR, StringRef Name) 302 : USR(USR), Name(Name), KindForDisplay(Kind), Kind(Kind) {} 303 304 // Pure virtual destructor to make APIRecord abstract 305 virtual ~APIRecord() = 0; 306 static bool classof(const APIRecord *Record) { return true; } 307 static bool classofKind(RecordKind K) { return true; } 308 static bool classof(const RecordContext *Ctx) { return true; } 309 }; 310 311 /// Base class used for specific record types that have children records this is 312 /// analogous to the DeclContext for the AST 313 class RecordContext { 314 public: 315 static bool classof(const APIRecord *Record) { 316 return classofKind(Record->getKind()); 317 } 318 static bool classofKind(APIRecord::RecordKind K) { 319 return K > APIRecord::RK_FirstRecordContext && 320 K < APIRecord::RK_LastRecordContext; 321 } 322 323 static bool classof(const RecordContext *Context) { return true; } 324 325 RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {} 326 327 /// Append \p Other children chain into ours and empty out Other's record 328 /// chain. 329 void stealRecordChain(RecordContext &Other); 330 331 APIRecord::RecordKind getKind() const { return Kind; } 332 333 struct record_iterator { 334 private: 335 APIRecord *Current = nullptr; 336 337 public: 338 using value_type = APIRecord *; 339 using reference = const value_type &; 340 using pointer = const value_type *; 341 using iterator_category = std::forward_iterator_tag; 342 using difference_type = std::ptrdiff_t; 343 344 record_iterator() = default; 345 explicit record_iterator(value_type R) : Current(R) {} 346 reference operator*() const { return Current; } 347 // This doesn't strictly meet the iterator requirements, but it's the 348 // behavior we want here. 349 value_type operator->() const { return Current; } 350 record_iterator &operator++() { 351 Current = Current->getNextInContext(); 352 return *this; 353 } 354 record_iterator operator++(int) { 355 record_iterator tmp(*this); 356 ++(*this); 357 return tmp; 358 } 359 360 friend bool operator==(record_iterator x, record_iterator y) { 361 return x.Current == y.Current; 362 } 363 friend bool operator!=(record_iterator x, record_iterator y) { 364 return x.Current != y.Current; 365 } 366 }; 367 368 using record_range = llvm::iterator_range<record_iterator>; 369 record_range records() const { 370 return record_range(records_begin(), records_end()); 371 } 372 record_iterator records_begin() const { return record_iterator(First); }; 373 record_iterator records_end() const { return record_iterator(); } 374 bool records_empty() const { return First == nullptr; }; 375 376 private: 377 APIRecord::RecordKind Kind; 378 mutable APIRecord *First = nullptr; 379 mutable APIRecord *Last = nullptr; 380 bool IsWellFormed() const; 381 382 protected: 383 friend class APISet; 384 void addToRecordChain(APIRecord *) const; 385 }; 386 387 struct NamespaceRecord : APIRecord, RecordContext { 388 NamespaceRecord(StringRef USR, StringRef Name, SymbolReference Parent, 389 PresumedLoc Loc, AvailabilityInfo Availability, 390 LinkageInfo Linkage, const DocComment &Comment, 391 DeclarationFragments Declaration, 392 DeclarationFragments SubHeading, bool IsFromSystemHeader) 393 : APIRecord(RK_Namespace, USR, Name, Parent, Loc, std::move(Availability), 394 Linkage, Comment, Declaration, SubHeading, 395 IsFromSystemHeader), 396 RecordContext(RK_Namespace) {} 397 398 static bool classof(const APIRecord *Record) { 399 return classofKind(Record->getKind()); 400 } 401 static bool classofKind(RecordKind K) { return K == RK_Namespace; } 402 }; 403 404 /// This holds information associated with global functions. 405 struct GlobalFunctionRecord : APIRecord { 406 FunctionSignature Signature; 407 408 GlobalFunctionRecord(StringRef USR, StringRef Name, SymbolReference Parent, 409 PresumedLoc Loc, AvailabilityInfo Availability, 410 LinkageInfo Linkage, const DocComment &Comment, 411 DeclarationFragments Declaration, 412 DeclarationFragments SubHeading, 413 FunctionSignature Signature, bool IsFromSystemHeader) 414 : APIRecord(RK_GlobalFunction, USR, Name, Parent, Loc, 415 std::move(Availability), Linkage, Comment, Declaration, 416 SubHeading, IsFromSystemHeader), 417 Signature(Signature) {} 418 419 GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name, 420 SymbolReference Parent, PresumedLoc Loc, 421 AvailabilityInfo Availability, LinkageInfo Linkage, 422 const DocComment &Comment, 423 DeclarationFragments Declaration, 424 DeclarationFragments SubHeading, 425 FunctionSignature Signature, bool IsFromSystemHeader) 426 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 427 Linkage, Comment, Declaration, SubHeading, 428 IsFromSystemHeader), 429 Signature(Signature) {} 430 431 static bool classof(const APIRecord *Record) { 432 return classofKind(Record->getKind()); 433 } 434 static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; } 435 436 private: 437 virtual void anchor(); 438 }; 439 440 struct GlobalFunctionTemplateRecord : GlobalFunctionRecord { 441 Template Templ; 442 443 GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, 444 SymbolReference Parent, PresumedLoc Loc, 445 AvailabilityInfo Availability, 446 LinkageInfo Linkage, const DocComment &Comment, 447 DeclarationFragments Declaration, 448 DeclarationFragments SubHeading, 449 FunctionSignature Signature, Template Template, 450 bool IsFromSystemHeader) 451 : GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Parent, Loc, 452 std::move(Availability), Linkage, Comment, 453 Declaration, SubHeading, Signature, 454 IsFromSystemHeader), 455 Templ(Template) {} 456 457 static bool classof(const APIRecord *Record) { 458 return classofKind(Record->getKind()); 459 } 460 static bool classofKind(RecordKind K) { 461 return K == RK_GlobalFunctionTemplate; 462 } 463 }; 464 465 struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord { 466 GlobalFunctionTemplateSpecializationRecord( 467 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, 468 AvailabilityInfo Availability, LinkageInfo Linkage, 469 const DocComment &Comment, DeclarationFragments Declaration, 470 DeclarationFragments SubHeading, FunctionSignature Signature, 471 bool IsFromSystemHeader) 472 : GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name, 473 Parent, Loc, std::move(Availability), Linkage, 474 Comment, Declaration, SubHeading, Signature, 475 IsFromSystemHeader) {} 476 477 static bool classof(const APIRecord *Record) { 478 return classofKind(Record->getKind()); 479 } 480 static bool classofKind(RecordKind K) { 481 return K == RK_GlobalFunctionTemplateSpecialization; 482 } 483 }; 484 485 /// This holds information associated with global functions. 486 struct GlobalVariableRecord : APIRecord, RecordContext { 487 GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent, 488 PresumedLoc Loc, AvailabilityInfo Availability, 489 LinkageInfo Linkage, const DocComment &Comment, 490 DeclarationFragments Declaration, 491 DeclarationFragments SubHeading, bool IsFromSystemHeader) 492 : APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc, 493 std::move(Availability), Linkage, Comment, Declaration, 494 SubHeading, IsFromSystemHeader), 495 RecordContext(RK_GlobalVariable) {} 496 497 GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name, 498 SymbolReference Parent, PresumedLoc Loc, 499 AvailabilityInfo Availability, LinkageInfo Linkage, 500 const DocComment &Comment, 501 DeclarationFragments Declaration, 502 DeclarationFragments SubHeading, bool IsFromSystemHeader) 503 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 504 Linkage, Comment, Declaration, SubHeading, 505 IsFromSystemHeader), 506 RecordContext(Kind) {} 507 508 static bool classof(const APIRecord *Record) { 509 return classofKind(Record->getKind()); 510 } 511 static bool classofKind(RecordKind K) { 512 return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate || 513 K == RK_GlobalVariableTemplateSpecialization || 514 K == RK_GlobalVariableTemplatePartialSpecialization; 515 } 516 517 private: 518 virtual void anchor(); 519 }; 520 521 struct GlobalVariableTemplateRecord : GlobalVariableRecord { 522 Template Templ; 523 524 GlobalVariableTemplateRecord(StringRef USR, StringRef Name, 525 SymbolReference Parent, PresumedLoc Loc, 526 AvailabilityInfo Availability, 527 LinkageInfo Linkage, const DocComment &Comment, 528 DeclarationFragments Declaration, 529 DeclarationFragments SubHeading, 530 class Template Template, bool IsFromSystemHeader) 531 : GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Parent, Loc, 532 std::move(Availability), Linkage, Comment, 533 Declaration, SubHeading, IsFromSystemHeader), 534 Templ(Template) {} 535 536 static bool classof(const APIRecord *Record) { 537 return classofKind(Record->getKind()); 538 } 539 static bool classofKind(RecordKind K) { 540 return K == RK_GlobalVariableTemplate; 541 } 542 }; 543 544 struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord { 545 GlobalVariableTemplateSpecializationRecord( 546 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, 547 AvailabilityInfo Availability, LinkageInfo Linkage, 548 const DocComment &Comment, DeclarationFragments Declaration, 549 DeclarationFragments SubHeading, bool IsFromSystemHeader) 550 : GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name, 551 Parent, Loc, std::move(Availability), Linkage, 552 Comment, Declaration, SubHeading, 553 IsFromSystemHeader) {} 554 555 static bool classof(const APIRecord *Record) { 556 return classofKind(Record->getKind()); 557 } 558 static bool classofKind(RecordKind K) { 559 return K == RK_GlobalVariableTemplateSpecialization; 560 } 561 }; 562 563 struct GlobalVariableTemplatePartialSpecializationRecord 564 : GlobalVariableRecord { 565 Template Templ; 566 567 GlobalVariableTemplatePartialSpecializationRecord( 568 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, 569 AvailabilityInfo Availability, LinkageInfo Linkage, 570 const DocComment &Comment, DeclarationFragments Declaration, 571 DeclarationFragments SubHeading, class Template Template, 572 bool IsFromSystemHeader) 573 : GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization, 574 USR, Name, Parent, Loc, std::move(Availability), 575 Linkage, Comment, Declaration, SubHeading, 576 IsFromSystemHeader), 577 Templ(Template) {} 578 579 static bool classof(const APIRecord *Record) { 580 return classofKind(Record->getKind()); 581 } 582 static bool classofKind(RecordKind K) { 583 return K == RK_GlobalVariableTemplatePartialSpecialization; 584 } 585 }; 586 587 /// This holds information associated with enum constants. 588 struct EnumConstantRecord : APIRecord { 589 EnumConstantRecord(StringRef USR, StringRef Name, SymbolReference Parent, 590 PresumedLoc Loc, AvailabilityInfo Availability, 591 const DocComment &Comment, 592 DeclarationFragments Declaration, 593 DeclarationFragments SubHeading, bool IsFromSystemHeader) 594 : APIRecord(RK_EnumConstant, USR, Name, Parent, Loc, 595 std::move(Availability), LinkageInfo::none(), Comment, 596 Declaration, SubHeading, IsFromSystemHeader) {} 597 598 static bool classof(const APIRecord *Record) { 599 return classofKind(Record->getKind()); 600 } 601 static bool classofKind(RecordKind K) { return K == RK_EnumConstant; } 602 603 private: 604 virtual void anchor(); 605 }; 606 607 struct TagRecord : APIRecord, RecordContext { 608 TagRecord(RecordKind Kind, StringRef USR, StringRef Name, 609 SymbolReference Parent, PresumedLoc Loc, 610 AvailabilityInfo Availability, const DocComment &Comment, 611 DeclarationFragments Declaration, DeclarationFragments SubHeading, 612 bool IsFromSystemHeader, bool IsEmbeddedInVarDeclarator, 613 AccessControl Access = AccessControl()) 614 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 615 LinkageInfo::none(), Comment, Declaration, SubHeading, 616 IsFromSystemHeader, std::move(Access)), 617 RecordContext(Kind), 618 IsEmbeddedInVarDeclarator(IsEmbeddedInVarDeclarator){}; 619 620 static bool classof(const APIRecord *Record) { 621 return classofKind(Record->getKind()); 622 } 623 static bool classofKind(RecordKind K) { 624 return K == RK_Struct || K == RK_Union || K == RK_Enum; 625 } 626 627 bool IsEmbeddedInVarDeclarator; 628 629 virtual ~TagRecord() = 0; 630 }; 631 632 /// This holds information associated with enums. 633 struct EnumRecord : TagRecord { 634 EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent, 635 PresumedLoc Loc, AvailabilityInfo Availability, 636 const DocComment &Comment, DeclarationFragments Declaration, 637 DeclarationFragments SubHeading, bool IsFromSystemHeader, 638 bool IsEmbeddedInVarDeclarator, 639 AccessControl Access = AccessControl()) 640 : TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability), 641 Comment, Declaration, SubHeading, IsFromSystemHeader, 642 IsEmbeddedInVarDeclarator, std::move(Access)) {} 643 644 static bool classof(const APIRecord *Record) { 645 return classofKind(Record->getKind()); 646 } 647 648 static bool classofKind(RecordKind K) { return K == RK_Enum; } 649 650 private: 651 virtual void anchor(); 652 }; 653 654 /// This holds information associated with struct or union fields fields. 655 struct RecordFieldRecord : APIRecord, RecordContext { 656 RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name, 657 SymbolReference Parent, PresumedLoc Loc, 658 AvailabilityInfo Availability, const DocComment &Comment, 659 DeclarationFragments Declaration, 660 DeclarationFragments SubHeading, bool IsFromSystemHeader) 661 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 662 LinkageInfo::none(), Comment, Declaration, SubHeading, 663 IsFromSystemHeader), 664 RecordContext(Kind) {} 665 666 static bool classof(const APIRecord *Record) { 667 return classofKind(Record->getKind()); 668 } 669 static bool classofKind(RecordKind K) { 670 return K == RK_StructField || K == RK_UnionField; 671 } 672 673 virtual ~RecordFieldRecord() = 0; 674 }; 675 676 /// This holds information associated with structs and unions. 677 struct RecordRecord : TagRecord { 678 RecordRecord(RecordKind Kind, StringRef USR, StringRef Name, 679 SymbolReference Parent, PresumedLoc Loc, 680 AvailabilityInfo Availability, const DocComment &Comment, 681 DeclarationFragments Declaration, 682 DeclarationFragments SubHeading, bool IsFromSystemHeader, 683 bool IsEmbeddedInVarDeclarator, 684 AccessControl Access = AccessControl()) 685 : TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 686 Comment, Declaration, SubHeading, IsFromSystemHeader, 687 IsEmbeddedInVarDeclarator, std::move(Access)) {} 688 689 static bool classof(const APIRecord *Record) { 690 return classofKind(Record->getKind()); 691 } 692 static bool classofKind(RecordKind K) { 693 return K == RK_Struct || K == RK_Union; 694 } 695 696 bool isAnonymousWithNoTypedef() { return Name.empty(); } 697 698 virtual ~RecordRecord() = 0; 699 }; 700 701 struct StructFieldRecord : RecordFieldRecord { 702 StructFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent, 703 PresumedLoc Loc, AvailabilityInfo Availability, 704 const DocComment &Comment, DeclarationFragments Declaration, 705 DeclarationFragments SubHeading, bool IsFromSystemHeader) 706 : RecordFieldRecord(RK_StructField, USR, Name, Parent, Loc, 707 std::move(Availability), Comment, Declaration, 708 SubHeading, IsFromSystemHeader) {} 709 710 static bool classof(const APIRecord *Record) { 711 return classofKind(Record->getKind()); 712 } 713 static bool classofKind(RecordKind K) { return K == RK_StructField; } 714 715 private: 716 virtual void anchor(); 717 }; 718 719 struct StructRecord : RecordRecord { 720 StructRecord(StringRef USR, StringRef Name, SymbolReference Parent, 721 PresumedLoc Loc, AvailabilityInfo Availability, 722 const DocComment &Comment, DeclarationFragments Declaration, 723 DeclarationFragments SubHeading, bool IsFromSystemHeader, 724 bool IsEmbeddedInVarDeclarator) 725 : RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability), 726 Comment, Declaration, SubHeading, IsFromSystemHeader, 727 IsEmbeddedInVarDeclarator) {} 728 729 static bool classof(const APIRecord *Record) { 730 return classofKind(Record->getKind()); 731 } 732 static bool classofKind(RecordKind K) { return K == RK_Struct; } 733 734 private: 735 virtual void anchor(); 736 }; 737 738 struct UnionFieldRecord : RecordFieldRecord { 739 UnionFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent, 740 PresumedLoc Loc, AvailabilityInfo Availability, 741 const DocComment &Comment, DeclarationFragments Declaration, 742 DeclarationFragments SubHeading, bool IsFromSystemHeader) 743 : RecordFieldRecord(RK_UnionField, USR, Name, Parent, Loc, 744 std::move(Availability), Comment, Declaration, 745 SubHeading, IsFromSystemHeader) {} 746 747 static bool classof(const APIRecord *Record) { 748 return classofKind(Record->getKind()); 749 } 750 static bool classofKind(RecordKind K) { return K == RK_UnionField; } 751 752 private: 753 virtual void anchor(); 754 }; 755 756 struct UnionRecord : RecordRecord { 757 UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent, 758 PresumedLoc Loc, AvailabilityInfo Availability, 759 const DocComment &Comment, DeclarationFragments Declaration, 760 DeclarationFragments SubHeading, bool IsFromSystemHeader, 761 bool IsEmbeddedInVarDeclarator) 762 : RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability), 763 Comment, Declaration, SubHeading, IsFromSystemHeader, 764 IsEmbeddedInVarDeclarator) {} 765 766 static bool classof(const APIRecord *Record) { 767 return classofKind(Record->getKind()); 768 } 769 static bool classofKind(RecordKind K) { return K == RK_Union; } 770 771 private: 772 virtual void anchor(); 773 }; 774 775 struct CXXFieldRecord : APIRecord, RecordContext { 776 CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent, 777 PresumedLoc Loc, AvailabilityInfo Availability, 778 const DocComment &Comment, DeclarationFragments Declaration, 779 DeclarationFragments SubHeading, AccessControl Access, 780 bool IsFromSystemHeader) 781 : APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability), 782 LinkageInfo::none(), Comment, Declaration, SubHeading, 783 IsFromSystemHeader, std::move(Access)), 784 RecordContext(RK_CXXField) {} 785 786 CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name, 787 SymbolReference Parent, PresumedLoc Loc, 788 AvailabilityInfo Availability, const DocComment &Comment, 789 DeclarationFragments Declaration, 790 DeclarationFragments SubHeading, AccessControl Access, 791 bool IsFromSystemHeader) 792 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 793 LinkageInfo::none(), Comment, Declaration, SubHeading, 794 IsFromSystemHeader, std::move(Access)), 795 RecordContext(Kind) {} 796 797 static bool classof(const APIRecord *Record) { 798 return classofKind(Record->getKind()); 799 } 800 static bool classofKind(RecordKind K) { 801 return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField; 802 } 803 804 private: 805 virtual void anchor(); 806 }; 807 808 struct CXXFieldTemplateRecord : CXXFieldRecord { 809 Template Templ; 810 811 CXXFieldTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent, 812 PresumedLoc Loc, AvailabilityInfo Availability, 813 const DocComment &Comment, 814 DeclarationFragments Declaration, 815 DeclarationFragments SubHeading, AccessControl Access, 816 Template Template, bool IsFromSystemHeader) 817 : CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Parent, Loc, 818 std::move(Availability), Comment, Declaration, 819 SubHeading, std::move(Access), IsFromSystemHeader), 820 Templ(Template) {} 821 822 static bool classof(const APIRecord *Record) { 823 return classofKind(Record->getKind()); 824 } 825 static bool classofKind(RecordKind K) { return K == RK_CXXFieldTemplate; } 826 }; 827 828 struct CXXMethodRecord : APIRecord { 829 FunctionSignature Signature; 830 831 CXXMethodRecord() = delete; 832 833 CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name, 834 SymbolReference Parent, PresumedLoc Loc, 835 AvailabilityInfo Availability, const DocComment &Comment, 836 DeclarationFragments Declaration, 837 DeclarationFragments SubHeading, FunctionSignature Signature, 838 AccessControl Access, bool IsFromSystemHeader) 839 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 840 LinkageInfo::none(), Comment, Declaration, SubHeading, 841 IsFromSystemHeader, std::move(Access)), 842 Signature(Signature) {} 843 844 virtual ~CXXMethodRecord() = 0; 845 }; 846 847 struct CXXConstructorRecord : CXXMethodRecord { 848 CXXConstructorRecord(StringRef USR, StringRef Name, SymbolReference Parent, 849 PresumedLoc Loc, AvailabilityInfo Availability, 850 const DocComment &Comment, 851 DeclarationFragments Declaration, 852 DeclarationFragments SubHeading, 853 FunctionSignature Signature, AccessControl Access, 854 bool IsFromSystemHeader) 855 : CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Parent, Loc, 856 std::move(Availability), Comment, Declaration, 857 SubHeading, Signature, std::move(Access), 858 IsFromSystemHeader) {} 859 static bool classof(const APIRecord *Record) { 860 return classofKind(Record->getKind()); 861 } 862 static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; } 863 864 private: 865 virtual void anchor(); 866 }; 867 868 struct CXXDestructorRecord : CXXMethodRecord { 869 CXXDestructorRecord(StringRef USR, StringRef Name, SymbolReference Parent, 870 PresumedLoc Loc, AvailabilityInfo Availability, 871 const DocComment &Comment, 872 DeclarationFragments Declaration, 873 DeclarationFragments SubHeading, 874 FunctionSignature Signature, AccessControl Access, 875 bool IsFromSystemHeader) 876 : CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Parent, Loc, 877 std::move(Availability), Comment, Declaration, 878 SubHeading, Signature, std::move(Access), 879 IsFromSystemHeader) {} 880 static bool classof(const APIRecord *Record) { 881 return classofKind(Record->getKind()); 882 } 883 static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; } 884 885 private: 886 virtual void anchor(); 887 }; 888 889 struct CXXStaticMethodRecord : CXXMethodRecord { 890 CXXStaticMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent, 891 PresumedLoc Loc, AvailabilityInfo Availability, 892 const DocComment &Comment, 893 DeclarationFragments Declaration, 894 DeclarationFragments SubHeading, 895 FunctionSignature Signature, AccessControl Access, 896 bool IsFromSystemHeader) 897 : CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Parent, Loc, 898 std::move(Availability), Comment, Declaration, 899 SubHeading, Signature, std::move(Access), 900 IsFromSystemHeader) {} 901 static bool classof(const APIRecord *Record) { 902 return classofKind(Record->getKind()); 903 } 904 static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; } 905 906 private: 907 virtual void anchor(); 908 }; 909 910 struct CXXInstanceMethodRecord : CXXMethodRecord { 911 CXXInstanceMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent, 912 PresumedLoc Loc, AvailabilityInfo Availability, 913 const DocComment &Comment, 914 DeclarationFragments Declaration, 915 DeclarationFragments SubHeading, 916 FunctionSignature Signature, AccessControl Access, 917 bool IsFromSystemHeader) 918 : CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Parent, Loc, 919 std::move(Availability), Comment, Declaration, 920 SubHeading, Signature, std::move(Access), 921 IsFromSystemHeader) {} 922 923 static bool classof(const APIRecord *Record) { 924 return classofKind(Record->getKind()); 925 } 926 static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; } 927 928 private: 929 virtual void anchor(); 930 }; 931 932 struct CXXMethodTemplateRecord : CXXMethodRecord { 933 Template Templ; 934 935 CXXMethodTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent, 936 PresumedLoc Loc, AvailabilityInfo Availability, 937 const DocComment &Comment, 938 DeclarationFragments Declaration, 939 DeclarationFragments SubHeading, 940 FunctionSignature Signature, AccessControl Access, 941 Template Template, bool IsFromSystemHeader) 942 : CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Parent, Loc, 943 std::move(Availability), Comment, Declaration, 944 SubHeading, Signature, std::move(Access), 945 IsFromSystemHeader), 946 Templ(Template) {} 947 948 static bool classof(const APIRecord *Record) { 949 return classofKind(Record->getKind()); 950 } 951 static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; } 952 }; 953 954 struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord { 955 CXXMethodTemplateSpecializationRecord( 956 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, 957 AvailabilityInfo Availability, const DocComment &Comment, 958 DeclarationFragments Declaration, DeclarationFragments SubHeading, 959 FunctionSignature Signature, AccessControl Access, 960 bool IsFromSystemHeader) 961 : CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Parent, 962 Loc, std::move(Availability), Comment, Declaration, 963 SubHeading, Signature, std::move(Access), 964 IsFromSystemHeader) {} 965 966 static bool classof(const APIRecord *Record) { 967 return classofKind(Record->getKind()); 968 } 969 static bool classofKind(RecordKind K) { 970 return K == RK_CXXMethodTemplateSpecialization; 971 } 972 }; 973 974 /// This holds information associated with Objective-C properties. 975 struct ObjCPropertyRecord : APIRecord { 976 /// The attributes associated with an Objective-C property. 977 enum AttributeKind : unsigned { 978 NoAttr = 0, 979 ReadOnly = 1, 980 Dynamic = 1 << 2, 981 }; 982 983 AttributeKind Attributes; 984 StringRef GetterName; 985 StringRef SetterName; 986 bool IsOptional; 987 988 ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name, 989 SymbolReference Parent, PresumedLoc Loc, 990 AvailabilityInfo Availability, const DocComment &Comment, 991 DeclarationFragments Declaration, 992 DeclarationFragments SubHeading, AttributeKind Attributes, 993 StringRef GetterName, StringRef SetterName, 994 bool IsOptional, bool IsFromSystemHeader) 995 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 996 LinkageInfo::none(), Comment, Declaration, SubHeading, 997 IsFromSystemHeader), 998 Attributes(Attributes), GetterName(GetterName), SetterName(SetterName), 999 IsOptional(IsOptional) {} 1000 1001 bool isReadOnly() const { return Attributes & ReadOnly; } 1002 bool isDynamic() const { return Attributes & Dynamic; } 1003 1004 virtual ~ObjCPropertyRecord() = 0; 1005 }; 1006 1007 struct ObjCInstancePropertyRecord : ObjCPropertyRecord { 1008 ObjCInstancePropertyRecord( 1009 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, 1010 AvailabilityInfo Availability, const DocComment &Comment, 1011 DeclarationFragments Declaration, DeclarationFragments SubHeading, 1012 AttributeKind Attributes, StringRef GetterName, StringRef SetterName, 1013 bool IsOptional, bool IsFromSystemHeader) 1014 : ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Parent, Loc, 1015 std::move(Availability), Comment, Declaration, 1016 SubHeading, Attributes, GetterName, SetterName, 1017 IsOptional, IsFromSystemHeader) {} 1018 1019 static bool classof(const APIRecord *Record) { 1020 return classofKind(Record->getKind()); 1021 } 1022 static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; } 1023 1024 private: 1025 virtual void anchor(); 1026 }; 1027 1028 struct ObjCClassPropertyRecord : ObjCPropertyRecord { 1029 ObjCClassPropertyRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1030 PresumedLoc Loc, AvailabilityInfo Availability, 1031 const DocComment &Comment, 1032 DeclarationFragments Declaration, 1033 DeclarationFragments SubHeading, 1034 AttributeKind Attributes, StringRef GetterName, 1035 StringRef SetterName, bool IsOptional, 1036 bool IsFromSystemHeader) 1037 : ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Parent, Loc, 1038 std::move(Availability), Comment, Declaration, 1039 SubHeading, Attributes, GetterName, SetterName, 1040 IsOptional, IsFromSystemHeader) {} 1041 1042 static bool classof(const APIRecord *Record) { 1043 return classofKind(Record->getKind()); 1044 } 1045 static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; } 1046 1047 private: 1048 virtual void anchor(); 1049 }; 1050 1051 /// This holds information associated with Objective-C instance variables. 1052 struct ObjCInstanceVariableRecord : APIRecord { 1053 ObjCInstanceVariableRecord(StringRef USR, StringRef Name, 1054 SymbolReference Parent, PresumedLoc Loc, 1055 AvailabilityInfo Availability, 1056 const DocComment &Comment, 1057 DeclarationFragments Declaration, 1058 DeclarationFragments SubHeading, 1059 bool IsFromSystemHeader) 1060 : APIRecord(RK_ObjCIvar, USR, Name, Parent, Loc, std::move(Availability), 1061 LinkageInfo::none(), Comment, Declaration, SubHeading, 1062 IsFromSystemHeader) {} 1063 1064 static bool classof(const APIRecord *Record) { 1065 return classofKind(Record->getKind()); 1066 } 1067 static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; } 1068 1069 private: 1070 virtual void anchor(); 1071 }; 1072 1073 /// This holds information associated with Objective-C methods. 1074 struct ObjCMethodRecord : APIRecord { 1075 FunctionSignature Signature; 1076 1077 ObjCMethodRecord() = delete; 1078 1079 ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name, 1080 SymbolReference Parent, PresumedLoc Loc, 1081 AvailabilityInfo Availability, const DocComment &Comment, 1082 DeclarationFragments Declaration, 1083 DeclarationFragments SubHeading, FunctionSignature Signature, 1084 bool IsFromSystemHeader) 1085 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 1086 LinkageInfo::none(), Comment, Declaration, SubHeading, 1087 IsFromSystemHeader), 1088 Signature(Signature) {} 1089 1090 virtual ~ObjCMethodRecord() = 0; 1091 }; 1092 1093 struct ObjCInstanceMethodRecord : ObjCMethodRecord { 1094 ObjCInstanceMethodRecord(StringRef USR, StringRef Name, 1095 SymbolReference Parent, PresumedLoc Loc, 1096 AvailabilityInfo Availability, 1097 const DocComment &Comment, 1098 DeclarationFragments Declaration, 1099 DeclarationFragments SubHeading, 1100 FunctionSignature Signature, bool IsFromSystemHeader) 1101 : ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Parent, Loc, 1102 std::move(Availability), Comment, Declaration, 1103 SubHeading, Signature, IsFromSystemHeader) {} 1104 static bool classof(const APIRecord *Record) { 1105 return classofKind(Record->getKind()); 1106 } 1107 static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; } 1108 1109 private: 1110 virtual void anchor(); 1111 }; 1112 1113 struct ObjCClassMethodRecord : ObjCMethodRecord { 1114 ObjCClassMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1115 PresumedLoc Loc, AvailabilityInfo Availability, 1116 const DocComment &Comment, 1117 DeclarationFragments Declaration, 1118 DeclarationFragments SubHeading, 1119 FunctionSignature Signature, bool IsFromSystemHeader) 1120 : ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Parent, Loc, 1121 std::move(Availability), Comment, Declaration, 1122 SubHeading, Signature, IsFromSystemHeader) {} 1123 1124 static bool classof(const APIRecord *Record) { 1125 return classofKind(Record->getKind()); 1126 } 1127 static bool classofKind(RecordKind K) { return K == RK_ObjCClassMethod; } 1128 1129 private: 1130 virtual void anchor(); 1131 }; 1132 1133 struct StaticFieldRecord : CXXFieldRecord { 1134 StaticFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1135 PresumedLoc Loc, AvailabilityInfo Availability, 1136 LinkageInfo Linkage, const DocComment &Comment, 1137 DeclarationFragments Declaration, 1138 DeclarationFragments SubHeading, AccessControl Access, 1139 bool IsFromSystemHeader) 1140 : CXXFieldRecord(RK_StaticField, USR, Name, Parent, Loc, 1141 std::move(Availability), Comment, Declaration, 1142 SubHeading, std::move(Access), IsFromSystemHeader) {} 1143 1144 static bool classof(const APIRecord *Record) { 1145 return classofKind(Record->getKind()); 1146 } 1147 static bool classofKind(RecordKind K) { return K == RK_StaticField; } 1148 }; 1149 1150 /// The base representation of an Objective-C container record. Holds common 1151 /// information associated with Objective-C containers. 1152 struct ObjCContainerRecord : APIRecord, RecordContext { 1153 SmallVector<SymbolReference> Protocols; 1154 1155 ObjCContainerRecord() = delete; 1156 1157 ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name, 1158 SymbolReference Parent, PresumedLoc Loc, 1159 AvailabilityInfo Availability, LinkageInfo Linkage, 1160 const DocComment &Comment, 1161 DeclarationFragments Declaration, 1162 DeclarationFragments SubHeading, bool IsFromSystemHeader) 1163 : APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 1164 Linkage, Comment, Declaration, SubHeading, 1165 IsFromSystemHeader), 1166 RecordContext(Kind) {} 1167 1168 virtual ~ObjCContainerRecord() = 0; 1169 }; 1170 1171 struct CXXClassRecord : RecordRecord { 1172 SmallVector<SymbolReference> Bases; 1173 1174 CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1175 PresumedLoc Loc, AvailabilityInfo Availability, 1176 const DocComment &Comment, DeclarationFragments Declaration, 1177 DeclarationFragments SubHeading, RecordKind Kind, 1178 AccessControl Access, bool IsFromSystemHeader, 1179 bool IsEmbeddedInVarDeclarator = false) 1180 : RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability), 1181 Comment, Declaration, SubHeading, IsFromSystemHeader, 1182 IsEmbeddedInVarDeclarator, std::move(Access)) {} 1183 1184 static bool classof(const APIRecord *Record) { 1185 return classofKind(Record->getKind()); 1186 } 1187 static bool classofKind(RecordKind K) { 1188 return K == RK_CXXClass || K == RK_ClassTemplate || 1189 K == RK_ClassTemplateSpecialization || 1190 K == RK_ClassTemplatePartialSpecialization; 1191 } 1192 1193 private: 1194 virtual void anchor(); 1195 }; 1196 1197 struct ClassTemplateRecord : CXXClassRecord { 1198 Template Templ; 1199 1200 ClassTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1201 PresumedLoc Loc, AvailabilityInfo Availability, 1202 const DocComment &Comment, 1203 DeclarationFragments Declaration, 1204 DeclarationFragments SubHeading, Template Template, 1205 AccessControl Access, bool IsFromSystemHeader) 1206 : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment, 1207 Declaration, SubHeading, RK_ClassTemplate, 1208 std::move(Access), IsFromSystemHeader), 1209 Templ(Template) {} 1210 1211 static bool classof(const APIRecord *Record) { 1212 return classofKind(Record->getKind()); 1213 } 1214 static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; } 1215 }; 1216 1217 struct ClassTemplateSpecializationRecord : CXXClassRecord { 1218 ClassTemplateSpecializationRecord( 1219 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, 1220 AvailabilityInfo Availability, const DocComment &Comment, 1221 DeclarationFragments Declaration, DeclarationFragments SubHeading, 1222 AccessControl Access, bool IsFromSystemHeader) 1223 : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment, 1224 Declaration, SubHeading, RK_ClassTemplateSpecialization, 1225 Access, IsFromSystemHeader) {} 1226 1227 static bool classof(const APIRecord *Record) { 1228 return classofKind(Record->getKind()); 1229 } 1230 static bool classofKind(RecordKind K) { 1231 return K == RK_ClassTemplateSpecialization; 1232 } 1233 }; 1234 1235 struct ClassTemplatePartialSpecializationRecord : CXXClassRecord { 1236 Template Templ; 1237 ClassTemplatePartialSpecializationRecord( 1238 StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc, 1239 AvailabilityInfo Availability, const DocComment &Comment, 1240 DeclarationFragments Declaration, DeclarationFragments SubHeading, 1241 Template Template, AccessControl Access, bool IsFromSystemHeader) 1242 : CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment, 1243 Declaration, SubHeading, 1244 RK_ClassTemplatePartialSpecialization, Access, 1245 IsFromSystemHeader), 1246 Templ(Template) {} 1247 1248 static bool classof(const APIRecord *Record) { 1249 return classofKind(Record->getKind()); 1250 } 1251 static bool classofKind(RecordKind K) { 1252 return K == RK_ClassTemplatePartialSpecialization; 1253 } 1254 }; 1255 1256 struct ConceptRecord : APIRecord { 1257 Template Templ; 1258 1259 ConceptRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1260 PresumedLoc Loc, AvailabilityInfo Availability, 1261 const DocComment &Comment, DeclarationFragments Declaration, 1262 DeclarationFragments SubHeading, Template Template, 1263 bool IsFromSystemHeader) 1264 : APIRecord(RK_Concept, USR, Name, Parent, Loc, std::move(Availability), 1265 LinkageInfo::none(), Comment, Declaration, SubHeading, 1266 IsFromSystemHeader), 1267 Templ(Template) {} 1268 1269 static bool classof(const APIRecord *Record) { 1270 return classofKind(Record->getKind()); 1271 } 1272 static bool classofKind(RecordKind K) { return K == RK_Concept; } 1273 }; 1274 1275 /// This holds information associated with Objective-C categories. 1276 struct ObjCCategoryRecord : ObjCContainerRecord { 1277 SymbolReference Interface; 1278 1279 ObjCCategoryRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1280 PresumedLoc Loc, AvailabilityInfo Availability, 1281 const DocComment &Comment, 1282 DeclarationFragments Declaration, 1283 DeclarationFragments SubHeading, SymbolReference Interface, 1284 bool IsFromSystemHeader) 1285 : ObjCContainerRecord(RK_ObjCCategory, USR, Name, Parent, Loc, 1286 std::move(Availability), LinkageInfo::none(), 1287 Comment, Declaration, SubHeading, 1288 IsFromSystemHeader), 1289 Interface(Interface) {} 1290 1291 static bool classof(const APIRecord *Record) { 1292 return classofKind(Record->getKind()); 1293 } 1294 static bool classofKind(RecordKind K) { return K == RK_ObjCCategory; } 1295 1296 bool isExtendingExternalModule() const { return !Interface.Source.empty(); } 1297 1298 std::optional<StringRef> getExtendedExternalModule() const { 1299 if (!isExtendingExternalModule()) 1300 return {}; 1301 return Interface.Source; 1302 } 1303 1304 private: 1305 virtual void anchor(); 1306 }; 1307 1308 /// This holds information associated with Objective-C interfaces/classes. 1309 struct ObjCInterfaceRecord : ObjCContainerRecord { 1310 SymbolReference SuperClass; 1311 1312 ObjCInterfaceRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1313 PresumedLoc Loc, AvailabilityInfo Availability, 1314 LinkageInfo Linkage, const DocComment &Comment, 1315 DeclarationFragments Declaration, 1316 DeclarationFragments SubHeading, 1317 SymbolReference SuperClass, bool IsFromSystemHeader) 1318 : ObjCContainerRecord(RK_ObjCInterface, USR, Name, Parent, Loc, 1319 std::move(Availability), Linkage, Comment, 1320 Declaration, SubHeading, IsFromSystemHeader), 1321 SuperClass(SuperClass) {} 1322 1323 static bool classof(const APIRecord *Record) { 1324 return classofKind(Record->getKind()); 1325 } 1326 static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; } 1327 1328 private: 1329 virtual void anchor(); 1330 }; 1331 1332 /// This holds information associated with Objective-C protocols. 1333 struct ObjCProtocolRecord : ObjCContainerRecord { 1334 ObjCProtocolRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1335 PresumedLoc Loc, AvailabilityInfo Availability, 1336 const DocComment &Comment, 1337 DeclarationFragments Declaration, 1338 DeclarationFragments SubHeading, bool IsFromSystemHeader) 1339 : ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Parent, Loc, 1340 std::move(Availability), LinkageInfo::none(), 1341 Comment, Declaration, SubHeading, 1342 IsFromSystemHeader) {} 1343 1344 static bool classof(const APIRecord *Record) { 1345 return classofKind(Record->getKind()); 1346 } 1347 static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; } 1348 1349 private: 1350 virtual void anchor(); 1351 }; 1352 1353 /// This holds information associated with macro definitions. 1354 struct MacroDefinitionRecord : APIRecord { 1355 MacroDefinitionRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1356 PresumedLoc Loc, DeclarationFragments Declaration, 1357 DeclarationFragments SubHeading, 1358 bool IsFromSystemHeader) 1359 : APIRecord(RK_MacroDefinition, USR, Name, Parent, Loc, 1360 AvailabilityInfo(), LinkageInfo(), {}, Declaration, 1361 SubHeading, IsFromSystemHeader) {} 1362 1363 static bool classof(const APIRecord *Record) { 1364 return classofKind(Record->getKind()); 1365 } 1366 static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; } 1367 1368 private: 1369 virtual void anchor(); 1370 }; 1371 1372 /// This holds information associated with typedefs. 1373 /// 1374 /// Note: Typedefs for anonymous enums and structs typically don't get emitted 1375 /// by the serializers but still get a TypedefRecord. Instead we use the 1376 /// typedef name as a name for the underlying anonymous struct or enum. 1377 struct TypedefRecord : APIRecord { 1378 SymbolReference UnderlyingType; 1379 1380 TypedefRecord(StringRef USR, StringRef Name, SymbolReference Parent, 1381 PresumedLoc Loc, AvailabilityInfo Availability, 1382 const DocComment &Comment, DeclarationFragments Declaration, 1383 DeclarationFragments SubHeading, SymbolReference UnderlyingType, 1384 bool IsFromSystemHeader) 1385 : APIRecord(RK_Typedef, USR, Name, Parent, Loc, std::move(Availability), 1386 LinkageInfo(), Comment, Declaration, SubHeading, 1387 IsFromSystemHeader), 1388 UnderlyingType(UnderlyingType) {} 1389 1390 static bool classof(const APIRecord *Record) { 1391 return classofKind(Record->getKind()); 1392 } 1393 static bool classofKind(RecordKind K) { return K == RK_Typedef; } 1394 1395 private: 1396 virtual void anchor(); 1397 }; 1398 1399 /// APISet holds the set of API records collected from given inputs. 1400 class APISet { 1401 public: 1402 /// Get the target triple for the ExtractAPI invocation. 1403 const llvm::Triple &getTarget() const { return Target; } 1404 1405 /// Get the language used by the APIs. 1406 Language getLanguage() const { return Lang; } 1407 1408 /// Finds the APIRecord for a given USR. 1409 /// 1410 /// \returns a pointer to the APIRecord associated with that USR or nullptr. 1411 APIRecord *findRecordForUSR(StringRef USR) const; 1412 1413 /// Copy \p String into the Allocator in this APISet. 1414 /// 1415 /// \returns a StringRef of the copied string in APISet::Allocator. 1416 StringRef copyString(StringRef String); 1417 1418 SymbolReference createSymbolReference(StringRef Name, StringRef USR, 1419 StringRef Source = ""); 1420 1421 /// Create a subclass of \p APIRecord and store it in the APISet. 1422 /// 1423 /// \returns A pointer to the created record or the already existing record 1424 /// matching this USR. 1425 template <typename RecordTy, typename... CtorArgsContTy> 1426 typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> * 1427 createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs); 1428 1429 ArrayRef<const APIRecord *> getTopLevelRecords() const { 1430 return TopLevelRecords; 1431 } 1432 1433 APISet(const llvm::Triple &Target, Language Lang, 1434 const std::string &ProductName) 1435 : Target(Target), Lang(Lang), ProductName(ProductName) {} 1436 1437 // Prevent moves and copies 1438 APISet(const APISet &Other) = delete; 1439 APISet &operator=(const APISet &Other) = delete; 1440 APISet(APISet &&Other) = delete; 1441 APISet &operator=(APISet &&Other) = delete; 1442 1443 private: 1444 /// BumpPtrAllocator that serves as the memory arena for the allocated objects 1445 llvm::BumpPtrAllocator Allocator; 1446 1447 const llvm::Triple Target; 1448 const Language Lang; 1449 1450 struct APIRecordDeleter { 1451 void operator()(APIRecord *Record) { Record->~APIRecord(); } 1452 }; 1453 1454 // Ensure that the destructor of each record is called when the LookupTable is 1455 // destroyed without calling delete operator as the memory for the record 1456 // lives in the BumpPtrAllocator. 1457 using APIRecordStoredPtr = std::unique_ptr<APIRecord, APIRecordDeleter>; 1458 llvm::DenseMap<StringRef, APIRecordStoredPtr> USRBasedLookupTable; 1459 std::vector<const APIRecord *> TopLevelRecords; 1460 1461 public: 1462 const std::string ProductName; 1463 }; 1464 1465 template <typename RecordTy, typename... CtorArgsContTy> 1466 typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> * 1467 APISet::createRecord(StringRef USR, StringRef Name, 1468 CtorArgsContTy &&...CtorArgs) { 1469 // Ensure USR refers to a String stored in the allocator. 1470 auto USRString = copyString(USR); 1471 auto Result = USRBasedLookupTable.insert({USRString, nullptr}); 1472 RecordTy *Record; 1473 1474 // Create the record if it does not already exist 1475 if (Result.second) { 1476 Record = new (Allocator) RecordTy( 1477 USRString, copyString(Name), std::forward<CtorArgsContTy>(CtorArgs)...); 1478 // Store the record in the record lookup map 1479 Result.first->second = APIRecordStoredPtr(Record); 1480 1481 if (auto *ParentContext = 1482 dyn_cast_if_present<RecordContext>(Record->Parent.Record)) 1483 ParentContext->addToRecordChain(Record); 1484 else 1485 TopLevelRecords.push_back(Record); 1486 } else { 1487 Record = dyn_cast<RecordTy>(Result.first->second.get()); 1488 } 1489 1490 return Record; 1491 } 1492 1493 // Helper type for implementing casting to RecordContext pointers. 1494 // Selected when FromTy not a known subclass of RecordContext. 1495 template <typename FromTy, 1496 bool IsKnownSubType = std::is_base_of_v<RecordContext, FromTy>> 1497 struct ToRecordContextCastInfoWrapper { 1498 static_assert(std::is_base_of_v<APIRecord, FromTy>, 1499 "Can only cast APIRecord and derived classes to RecordContext"); 1500 1501 static bool isPossible(FromTy *From) { return RecordContext::classof(From); } 1502 1503 static RecordContext *doCast(FromTy *From) { 1504 return APIRecord::castToRecordContext(From); 1505 } 1506 }; 1507 1508 // Selected when FromTy is a known subclass of RecordContext. 1509 template <typename FromTy> struct ToRecordContextCastInfoWrapper<FromTy, true> { 1510 static_assert(std::is_base_of_v<APIRecord, FromTy>, 1511 "Can only cast APIRecord and derived classes to RecordContext"); 1512 static bool isPossible(const FromTy *From) { return true; } 1513 static RecordContext *doCast(FromTy *From) { 1514 return static_cast<RecordContext *>(From); 1515 } 1516 }; 1517 1518 // Helper type for implementing casting to RecordContext pointers. 1519 // Selected when ToTy isn't a known subclass of RecordContext 1520 template <typename ToTy, 1521 bool IsKnownSubType = std::is_base_of_v<RecordContext, ToTy>> 1522 struct FromRecordContextCastInfoWrapper { 1523 static_assert( 1524 std::is_base_of_v<APIRecord, ToTy>, 1525 "Can only class RecordContext to APIRecord and derived classes"); 1526 1527 static bool isPossible(RecordContext *Ctx) { 1528 return ToTy::classofKind(Ctx->getKind()); 1529 } 1530 1531 static ToTy *doCast(RecordContext *Ctx) { 1532 return APIRecord::castFromRecordContext(Ctx); 1533 } 1534 }; 1535 1536 // Selected when ToTy is a known subclass of RecordContext. 1537 template <typename ToTy> struct FromRecordContextCastInfoWrapper<ToTy, true> { 1538 static_assert( 1539 std::is_base_of_v<APIRecord, ToTy>, 1540 "Can only class RecordContext to APIRecord and derived classes"); 1541 static bool isPossible(RecordContext *Ctx) { 1542 return ToTy::classof(Ctx->getKind()); 1543 } 1544 static RecordContext *doCast(RecordContext *Ctx) { 1545 return static_cast<ToTy *>(Ctx); 1546 } 1547 }; 1548 1549 } // namespace extractapi 1550 } // namespace clang 1551 1552 // Implement APIRecord (and derived classes) to and from RecordContext 1553 // conversions 1554 namespace llvm { 1555 1556 template <typename FromTy> 1557 struct CastInfo<::clang::extractapi::RecordContext, FromTy *> 1558 : public NullableValueCastFailed<::clang::extractapi::RecordContext *>, 1559 public DefaultDoCastIfPossible< 1560 ::clang::extractapi::RecordContext *, FromTy *, 1561 CastInfo<::clang::extractapi::RecordContext, FromTy *>> { 1562 static inline bool isPossible(FromTy *From) { 1563 return ::clang::extractapi::ToRecordContextCastInfoWrapper< 1564 FromTy>::isPossible(From); 1565 } 1566 1567 static inline ::clang::extractapi::RecordContext *doCast(FromTy *From) { 1568 return ::clang::extractapi::ToRecordContextCastInfoWrapper<FromTy>::doCast( 1569 From); 1570 } 1571 }; 1572 1573 template <typename FromTy> 1574 struct CastInfo<::clang::extractapi::RecordContext, const FromTy *> 1575 : public ConstStrippingForwardingCast< 1576 ::clang::extractapi::RecordContext, const FromTy *, 1577 CastInfo<::clang::extractapi::RecordContext, FromTy *>> {}; 1578 1579 template <typename ToTy> 1580 struct CastInfo<ToTy, ::clang::extractapi::RecordContext *> 1581 : public NullableValueCastFailed<ToTy *>, 1582 public DefaultDoCastIfPossible< 1583 ToTy *, ::clang::extractapi::RecordContext *, 1584 CastInfo<ToTy, ::clang::extractapi::RecordContext *>> { 1585 static inline bool isPossible(::clang::extractapi::RecordContext *Ctx) { 1586 return ::clang::extractapi::FromRecordContextCastInfoWrapper< 1587 ToTy>::isPossible(Ctx); 1588 } 1589 1590 static inline ToTy *doCast(::clang::extractapi::RecordContext *Ctx) { 1591 return ::clang::extractapi::FromRecordContextCastInfoWrapper<ToTy>::doCast( 1592 Ctx); 1593 } 1594 }; 1595 1596 template <typename ToTy> 1597 struct CastInfo<ToTy, const ::clang::extractapi::RecordContext *> 1598 : public ConstStrippingForwardingCast< 1599 ToTy, const ::clang::extractapi::RecordContext *, 1600 CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {}; 1601 1602 } // namespace llvm 1603 1604 #endif // LLVM_CLANG_EXTRACTAPI_API_H 1605