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