blob: d323e1668a72b1718ab62e24f139a6304b93cbdb [file] [log] [blame]
//===- ExtractAPI/API.h -----------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines the APIRecord-based structs and the APISet class.
///
/// Clang ExtractAPI is a tool to collect API information from a given set of
/// header files. The structures in this file describe data representations of
/// the API information collected for various kinds of symbols.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_EXTRACTAPI_API_H
#define LLVM_CLANG_EXTRACTAPI_API_H
#include "clang/AST/Availability.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/RawCommentList.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/TargetParser/Triple.h"
#include <cstddef>
#include <iterator>
#include <memory>
#include <optional>
#include <type_traits>
namespace clang {
namespace extractapi {
class Template {
struct TemplateParameter {
// "class", "typename", or concept name
std::string Type;
std::string Name;
unsigned int Index;
unsigned int Depth;
bool IsParameterPack;
TemplateParameter(std::string Type, std::string Name, unsigned int Index,
unsigned int Depth, bool IsParameterPack)
: Type(Type), Name(Name), Index(Index), Depth(Depth),
IsParameterPack(IsParameterPack) {}
};
struct TemplateConstraint {
// type name of the constraint, if it has one
std::string Type;
std::string Kind;
std::string LHS, RHS;
};
llvm::SmallVector<TemplateParameter> Parameters;
llvm::SmallVector<TemplateConstraint> Constraints;
public:
Template() = default;
Template(const TemplateDecl *Decl) {
for (auto *const Parameter : *Decl->getTemplateParameters()) {
const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
if (!Param) // some params are null
continue;
std::string Type;
if (Param->hasTypeConstraint())
Type = Param->getTypeConstraint()->getNamedConcept()->getName().str();
else if (Param->wasDeclaredWithTypename())
Type = "typename";
else
Type = "class";
addTemplateParameter(Type, Param->getName().str(), Param->getIndex(),
Param->getDepth(), Param->isParameterPack());
}
}
Template(const ClassTemplatePartialSpecializationDecl *Decl) {
for (auto *const Parameter : *Decl->getTemplateParameters()) {
const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
if (!Param) // some params are null
continue;
std::string Type;
if (Param->hasTypeConstraint())
Type = Param->getTypeConstraint()->getNamedConcept()->getName().str();
else if (Param->wasDeclaredWithTypename())
Type = "typename";
else
Type = "class";
addTemplateParameter(Type, Param->getName().str(), Param->getIndex(),
Param->getDepth(), Param->isParameterPack());
}
}
Template(const VarTemplatePartialSpecializationDecl *Decl) {
for (auto *const Parameter : *Decl->getTemplateParameters()) {
const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
if (!Param) // some params are null
continue;
std::string Type;
if (Param->hasTypeConstraint())
Type = Param->getTypeConstraint()->getNamedConcept()->getName().str();
else if (Param->wasDeclaredWithTypename())
Type = "typename";
else
Type = "class";
addTemplateParameter(Type, Param->getName().str(), Param->getIndex(),
Param->getDepth(), Param->isParameterPack());
}
}
const llvm::SmallVector<TemplateParameter> &getParameters() const {
return Parameters;
}
const llvm::SmallVector<TemplateConstraint> &getConstraints() const {
return Constraints;
}
void addTemplateParameter(std::string Type, std::string Name,
unsigned int Index, unsigned int Depth,
bool IsParameterPack) {
Parameters.emplace_back(Type, Name, Index, Depth, IsParameterPack);
}
bool empty() const { return Parameters.empty() && Constraints.empty(); }
};
/// DocComment is a vector of RawComment::CommentLine.
///
/// Each line represents one line of striped documentation comment,
/// with source range information. This simplifies calculating the source
/// location of a character in the doc comment for pointing back to the source
/// file.
/// e.g.
/// \code
/// /// This is a documentation comment
/// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~' First line.
/// /// with multiple lines.
/// ^~~~~~~~~~~~~~~~~~~~~~~' Second line.
/// \endcode
using DocComment = std::vector<RawComment::CommentLine>;
struct APIRecord;
// This represents a reference to another symbol that might come from external
/// sources.
struct SymbolReference {
StringRef Name;
StringRef USR;
/// The source project/module/product of the referred symbol.
StringRef Source;
// A Pointer to the APIRecord for this reference if known
const APIRecord *Record = nullptr;
SymbolReference() = default;
SymbolReference(StringRef Name, StringRef USR, StringRef Source = "")
: Name(Name), USR(USR), Source(Source) {}
SymbolReference(const APIRecord *R);
/// Determine if this SymbolReference is empty.
///
/// \returns true if and only if all \c Name, \c USR, and \c Source is empty.
bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
};
class RecordContext;
// Concrete classes deriving from APIRecord need to have a construct with first
// arguments USR, and Name, in that order. This is so that they
// are compatible with `APISet::createRecord`.
// When adding a new kind of record don't forget to update APIRecords.inc!
/// The base representation of an API record. Holds common symbol information.
struct APIRecord {
/// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
enum RecordKind {
RK_Unknown,
// If adding a record context record kind here make sure to update
// RecordContext::classof if needed and add a RECORD_CONTEXT entry to
// APIRecords.inc
RK_FirstRecordContext,
RK_Namespace,
RK_Enum,
RK_Struct,
RK_Union,
RK_ObjCInterface,
RK_ObjCCategory,
RK_ObjCProtocol,
RK_CXXClass,
RK_ClassTemplate,
RK_ClassTemplateSpecialization,
RK_ClassTemplatePartialSpecialization,
RK_StructField,
RK_UnionField,
RK_CXXField,
RK_StaticField,
RK_CXXFieldTemplate,
RK_GlobalVariable,
RK_GlobalVariableTemplate,
RK_GlobalVariableTemplateSpecialization,
RK_GlobalVariableTemplatePartialSpecialization,
RK_LastRecordContext,
RK_GlobalFunction,
RK_GlobalFunctionTemplate,
RK_GlobalFunctionTemplateSpecialization,
RK_EnumConstant,
RK_Concept,
RK_CXXStaticMethod,
RK_CXXInstanceMethod,
RK_CXXConstructorMethod,
RK_CXXDestructorMethod,
RK_CXXMethodTemplate,
RK_CXXMethodTemplateSpecialization,
RK_ObjCInstanceProperty,
RK_ObjCClassProperty,
RK_ObjCIvar,
RK_ObjCClassMethod,
RK_ObjCInstanceMethod,
RK_MacroDefinition,
RK_Typedef,
};
StringRef USR;
StringRef Name;
SymbolReference Parent;
PresumedLoc Location;
AvailabilityInfo Availability;
LinkageInfo Linkage;
/// Documentation comment lines attached to this symbol declaration.
DocComment Comment;
/// Declaration fragments of this symbol declaration.
DeclarationFragments Declaration;
/// SubHeading provides a more detailed representation than the plain
/// declaration name.
///
/// SubHeading is an array of declaration fragments of tagged declaration
/// name, with potentially more tokens (for example the \c +/- symbol for
/// Objective-C class/instance methods).
DeclarationFragments SubHeading;
/// Whether the symbol was defined in a system header.
bool IsFromSystemHeader;
AccessControl Access;
private:
const RecordKind Kind;
friend class RecordContext;
// Used to store the next child record in RecordContext. This works because
// APIRecords semantically only have one parent.
mutable APIRecord *NextInContext = nullptr;
public:
APIRecord *getNextInContext() const { return NextInContext; }
RecordKind getKind() const { return Kind; }
static APIRecord *castFromRecordContext(const RecordContext *Ctx);
static RecordContext *castToRecordContext(const APIRecord *Record);
APIRecord() = delete;
APIRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Location,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader,
AccessControl Access = AccessControl())
: USR(USR), Name(Name), Parent(std::move(Parent)), Location(Location),
Availability(std::move(Availability)), Linkage(Linkage),
Comment(Comment), Declaration(Declaration), SubHeading(SubHeading),
IsFromSystemHeader(IsFromSystemHeader), Access(std::move(Access)),
Kind(Kind) {}
APIRecord(RecordKind Kind, StringRef USR, StringRef Name)
: USR(USR), Name(Name), Kind(Kind) {}
// Pure virtual destructor to make APIRecord abstract
virtual ~APIRecord() = 0;
static bool classof(const APIRecord *Record) { return true; }
static bool classofKind(RecordKind K) { return true; }
static bool classof(const RecordContext *Ctx) { return true; }
};
/// Base class used for specific record types that have children records this is
/// analogous to the DeclContext for the AST
class RecordContext {
public:
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(APIRecord::RecordKind K) {
return K > APIRecord::RK_FirstRecordContext &&
K < APIRecord::RK_LastRecordContext;
}
static bool classof(const RecordContext *Context) { return true; }
RecordContext(APIRecord::RecordKind Kind) : Kind(Kind) {}
/// Append \p Other children chain into ours and empty out Other's record
/// chain.
void stealRecordChain(RecordContext &Other);
APIRecord::RecordKind getKind() const { return Kind; }
struct record_iterator {
private:
APIRecord *Current = nullptr;
public:
using value_type = APIRecord *;
using reference = const value_type &;
using pointer = const value_type *;
using iterator_category = std::forward_iterator_tag;
using difference_type = std::ptrdiff_t;
record_iterator() = default;
explicit record_iterator(value_type R) : Current(R) {}
reference operator*() const { return Current; }
// This doesn't strictly meet the iterator requirements, but it's the
// behavior we want here.
value_type operator->() const { return Current; }
record_iterator &operator++() {
Current = Current->getNextInContext();
return *this;
}
record_iterator operator++(int) {
record_iterator tmp(*this);
++(*this);
return tmp;
}
friend bool operator==(record_iterator x, record_iterator y) {
return x.Current == y.Current;
}
friend bool operator!=(record_iterator x, record_iterator y) {
return x.Current != y.Current;
}
};
using record_range = llvm::iterator_range<record_iterator>;
record_range records() const {
return record_range(records_begin(), records_end());
}
record_iterator records_begin() const { return record_iterator(First); };
record_iterator records_end() const { return record_iterator(); }
bool records_empty() const { return First == nullptr; };
private:
APIRecord::RecordKind Kind;
mutable APIRecord *First = nullptr;
mutable APIRecord *Last = nullptr;
bool IsWellFormed() const;
protected:
friend class APISet;
void addToRecordChain(APIRecord *) const;
};
struct NamespaceRecord : APIRecord, RecordContext {
NamespaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_Namespace, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(RK_Namespace) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_Namespace; }
};
/// This holds information associated with global functions.
struct GlobalFunctionRecord : APIRecord {
FunctionSignature Signature;
GlobalFunctionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
: APIRecord(RK_GlobalFunction, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment, Declaration,
SubHeading, IsFromSystemHeader),
Signature(Signature) {}
GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader),
Signature(Signature) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_GlobalFunction; }
private:
virtual void anchor();
};
struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
Template Templ;
GlobalFunctionTemplateRecord(StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, Template Template,
bool IsFromSystemHeader)
: GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, Signature,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_GlobalFunctionTemplate;
}
};
struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
GlobalFunctionTemplateSpecializationRecord(
StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
: GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
Parent, Loc, std::move(Availability), Linkage,
Comment, Declaration, SubHeading, Signature,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_GlobalFunctionTemplateSpecialization;
}
};
/// This holds information associated with global functions.
struct GlobalVariableRecord : APIRecord, RecordContext {
GlobalVariableRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_GlobalVariable, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment, Declaration,
SubHeading, IsFromSystemHeader),
RecordContext(RK_GlobalVariable) {}
GlobalVariableRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(Kind) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_GlobalVariable || K == RK_GlobalVariableTemplate ||
K == RK_GlobalVariableTemplateSpecialization ||
K == RK_GlobalVariableTemplatePartialSpecialization;
}
private:
virtual void anchor();
};
struct GlobalVariableTemplateRecord : GlobalVariableRecord {
Template Templ;
GlobalVariableTemplateRecord(StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
class Template Template, bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplate, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_GlobalVariableTemplate;
}
};
struct GlobalVariableTemplateSpecializationRecord : GlobalVariableRecord {
GlobalVariableTemplateSpecializationRecord(
StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplateSpecialization, USR, Name,
Parent, Loc, std::move(Availability), Linkage,
Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_GlobalVariableTemplateSpecialization;
}
};
struct GlobalVariableTemplatePartialSpecializationRecord
: GlobalVariableRecord {
Template Templ;
GlobalVariableTemplatePartialSpecializationRecord(
StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, class Template Template,
bool IsFromSystemHeader)
: GlobalVariableRecord(RK_GlobalVariableTemplatePartialSpecialization,
USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_GlobalVariableTemplatePartialSpecialization;
}
};
/// This holds information associated with enum constants.
struct EnumConstantRecord : APIRecord {
EnumConstantRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(RK_EnumConstant, USR, Name, Parent, Loc,
std::move(Availability), LinkageInfo::none(), Comment,
Declaration, SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_EnumConstant; }
private:
virtual void anchor();
};
struct TagRecord : APIRecord, RecordContext {
TagRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
bool IsFromSystemHeader, bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind),
IsEmbeddedInVarDeclarator(IsEmbeddedInVarDeclarator){};
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_Struct || K == RK_Union || K == RK_Enum;
}
bool IsEmbeddedInVarDeclarator;
virtual ~TagRecord() = 0;
};
/// This holds information associated with enums.
struct EnumRecord : TagRecord {
EnumRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: TagRecord(RK_Enum, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_Enum; }
private:
virtual void anchor();
};
/// This holds information associated with struct or union fields fields.
struct RecordFieldRecord : APIRecord, RecordContext {
RecordFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(Kind) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_StructField || K == RK_UnionField;
}
virtual ~RecordFieldRecord() = 0;
};
/// This holds information associated with structs and unions.
struct RecordRecord : TagRecord {
RecordRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator,
AccessControl Access = AccessControl())
: TagRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_Struct || K == RK_Union;
}
bool isAnonymousWithNoTypedef() { return Name.empty(); }
virtual ~RecordRecord() = 0;
};
struct StructFieldRecord : RecordFieldRecord {
StructFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: RecordFieldRecord(RK_StructField, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_StructField; }
private:
virtual void anchor();
};
struct StructRecord : RecordRecord {
StructRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator)
: RecordRecord(RK_Struct, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_Struct; }
private:
virtual void anchor();
};
struct UnionFieldRecord : RecordFieldRecord {
UnionFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: RecordFieldRecord(RK_UnionField, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_UnionField; }
private:
virtual void anchor();
};
struct UnionRecord : RecordRecord {
UnionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator)
: RecordRecord(RK_Union, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_Union; }
private:
virtual void anchor();
};
struct CXXFieldRecord : APIRecord, RecordContext {
CXXFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
: APIRecord(RK_CXXField, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(RK_CXXField) {}
CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
RecordContext(Kind) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_CXXField || K == RK_CXXFieldTemplate || K == RK_StaticField;
}
private:
virtual void anchor();
};
struct CXXFieldTemplateRecord : CXXFieldRecord {
Template Templ;
CXXFieldTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
Template Template, bool IsFromSystemHeader)
: CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, std::move(Access), IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_CXXFieldTemplate; }
};
struct CXXMethodRecord : APIRecord {
FunctionSignature Signature;
CXXMethodRecord() = delete;
CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
AccessControl Access, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader, std::move(Access)),
Signature(Signature) {}
virtual ~CXXMethodRecord() = 0;
};
struct CXXConstructorRecord : CXXMethodRecord {
CXXConstructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, std::move(Access),
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_CXXConstructorMethod; }
private:
virtual void anchor();
};
struct CXXDestructorRecord : CXXMethodRecord {
CXXDestructorRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, std::move(Access),
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_CXXDestructorMethod; }
private:
virtual void anchor();
};
struct CXXStaticMethodRecord : CXXMethodRecord {
CXXStaticMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, std::move(Access),
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_CXXStaticMethod; }
private:
virtual void anchor();
};
struct CXXInstanceMethodRecord : CXXMethodRecord {
CXXInstanceMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, std::move(Access),
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_CXXInstanceMethod; }
private:
virtual void anchor();
};
struct CXXMethodTemplateRecord : CXXMethodRecord {
Template Templ;
CXXMethodTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
Template Template, bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, std::move(Access),
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_CXXMethodTemplate; }
};
struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
CXXMethodTemplateSpecializationRecord(
StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Parent,
Loc, std::move(Availability), Comment, Declaration,
SubHeading, Signature, std::move(Access),
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_CXXMethodTemplateSpecialization;
}
};
/// This holds information associated with Objective-C properties.
struct ObjCPropertyRecord : APIRecord {
/// The attributes associated with an Objective-C property.
enum AttributeKind : unsigned {
NoAttr = 0,
ReadOnly = 1,
Dynamic = 1 << 2,
};
AttributeKind Attributes;
StringRef GetterName;
StringRef SetterName;
bool IsOptional;
ObjCPropertyRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AttributeKind Attributes,
StringRef GetterName, StringRef SetterName,
bool IsOptional, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Attributes(Attributes), GetterName(GetterName), SetterName(SetterName),
IsOptional(IsOptional) {}
bool isReadOnly() const { return Attributes & ReadOnly; }
bool isDynamic() const { return Attributes & Dynamic; }
virtual ~ObjCPropertyRecord() = 0;
};
struct ObjCInstancePropertyRecord : ObjCPropertyRecord {
ObjCInstancePropertyRecord(
StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AttributeKind Attributes, StringRef GetterName, StringRef SetterName,
bool IsOptional, bool IsFromSystemHeader)
: ObjCPropertyRecord(RK_ObjCInstanceProperty, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceProperty; }
private:
virtual void anchor();
};
struct ObjCClassPropertyRecord : ObjCPropertyRecord {
ObjCClassPropertyRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
AttributeKind Attributes, StringRef GetterName,
StringRef SetterName, bool IsOptional,
bool IsFromSystemHeader)
: ObjCPropertyRecord(RK_ObjCClassProperty, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Attributes, GetterName, SetterName,
IsOptional, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ObjCClassProperty; }
private:
virtual void anchor();
};
/// This holds information associated with Objective-C instance variables.
struct ObjCInstanceVariableRecord : APIRecord {
ObjCInstanceVariableRecord(StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader)
: APIRecord(RK_ObjCIvar, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ObjCIvar; }
private:
virtual void anchor();
};
/// This holds information associated with Objective-C methods.
struct ObjCMethodRecord : APIRecord {
FunctionSignature Signature;
ObjCMethodRecord() = delete;
ObjCMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, FunctionSignature Signature,
bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Signature(Signature) {}
virtual ~ObjCMethodRecord() = 0;
};
struct ObjCInstanceMethodRecord : ObjCMethodRecord {
ObjCInstanceMethodRecord(StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
: ObjCMethodRecord(RK_ObjCInstanceMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ObjCInstanceMethod; }
private:
virtual void anchor();
};
struct ObjCClassMethodRecord : ObjCMethodRecord {
ObjCClassMethodRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, bool IsFromSystemHeader)
: ObjCMethodRecord(RK_ObjCClassMethod, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, Signature, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ObjCClassMethod; }
private:
virtual void anchor();
};
struct StaticFieldRecord : CXXFieldRecord {
StaticFieldRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, AccessControl Access,
bool IsFromSystemHeader)
: CXXFieldRecord(RK_StaticField, USR, Name, Parent, Loc,
std::move(Availability), Comment, Declaration,
SubHeading, std::move(Access), IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_StaticField; }
};
/// The base representation of an Objective-C container record. Holds common
/// information associated with Objective-C containers.
struct ObjCContainerRecord : APIRecord, RecordContext {
SmallVector<SymbolReference> Protocols;
ObjCContainerRecord() = delete;
ObjCContainerRecord(RecordKind Kind, StringRef USR, StringRef Name,
SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, LinkageInfo Linkage,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: APIRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Linkage, Comment, Declaration, SubHeading,
IsFromSystemHeader),
RecordContext(Kind) {}
virtual ~ObjCContainerRecord() = 0;
};
struct CXXClassRecord : RecordRecord {
SmallVector<SymbolReference> Bases;
CXXClassRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, RecordKind Kind,
AccessControl Access, bool IsFromSystemHeader,
bool IsEmbeddedInVarDeclarator = false)
: RecordRecord(Kind, USR, Name, Parent, Loc, std::move(Availability),
Comment, Declaration, SubHeading, IsFromSystemHeader,
IsEmbeddedInVarDeclarator, std::move(Access)) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_CXXClass || K == RK_ClassTemplate ||
K == RK_ClassTemplateSpecialization ||
K == RK_ClassTemplatePartialSpecialization;
}
private:
virtual void anchor();
};
struct ClassTemplateRecord : CXXClassRecord {
Template Templ;
ClassTemplateRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
AccessControl Access, bool IsFromSystemHeader)
: CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
Declaration, SubHeading, RK_ClassTemplate,
std::move(Access), IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ClassTemplate; }
};
struct ClassTemplateSpecializationRecord : CXXClassRecord {
ClassTemplateSpecializationRecord(
StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
AccessControl Access, bool IsFromSystemHeader)
: CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
Declaration, SubHeading, RK_ClassTemplateSpecialization,
Access, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_ClassTemplateSpecialization;
}
};
struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
Template Templ;
ClassTemplatePartialSpecializationRecord(
StringRef USR, StringRef Name, SymbolReference Parent, PresumedLoc Loc,
AvailabilityInfo Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
Template Template, AccessControl Access, bool IsFromSystemHeader)
: CXXClassRecord(USR, Name, Parent, Loc, std::move(Availability), Comment,
Declaration, SubHeading,
RK_ClassTemplatePartialSpecialization, Access,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) {
return K == RK_ClassTemplatePartialSpecialization;
}
};
struct ConceptRecord : APIRecord {
Template Templ;
ConceptRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, Template Template,
bool IsFromSystemHeader)
: APIRecord(RK_Concept, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo::none(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
Templ(Template) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_Concept; }
};
/// This holds information associated with Objective-C categories.
struct ObjCCategoryRecord : ObjCContainerRecord {
SymbolReference Interface;
ObjCCategoryRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference Interface,
bool IsFromSystemHeader)
: ObjCContainerRecord(RK_ObjCCategory, USR, Name, Parent, Loc,
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader),
Interface(Interface) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ObjCCategory; }
bool isExtendingExternalModule() const { return !Interface.Source.empty(); }
std::optional<StringRef> getExtendedExternalModule() const {
if (!isExtendingExternalModule())
return {};
return Interface.Source;
}
private:
virtual void anchor();
};
/// This holds information associated with Objective-C interfaces/classes.
struct ObjCInterfaceRecord : ObjCContainerRecord {
SymbolReference SuperClass;
ObjCInterfaceRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
LinkageInfo Linkage, const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
SymbolReference SuperClass, bool IsFromSystemHeader)
: ObjCContainerRecord(RK_ObjCInterface, USR, Name, Parent, Loc,
std::move(Availability), Linkage, Comment,
Declaration, SubHeading, IsFromSystemHeader),
SuperClass(SuperClass) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ObjCInterface; }
private:
virtual void anchor();
};
/// This holds information associated with Objective-C protocols.
struct ObjCProtocolRecord : ObjCContainerRecord {
ObjCProtocolRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading, bool IsFromSystemHeader)
: ObjCContainerRecord(RK_ObjCProtocol, USR, Name, Parent, Loc,
std::move(Availability), LinkageInfo::none(),
Comment, Declaration, SubHeading,
IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_ObjCProtocol; }
private:
virtual void anchor();
};
/// This holds information associated with macro definitions.
struct MacroDefinitionRecord : APIRecord {
MacroDefinitionRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, DeclarationFragments Declaration,
DeclarationFragments SubHeading,
bool IsFromSystemHeader)
: APIRecord(RK_MacroDefinition, USR, Name, Parent, Loc,
AvailabilityInfo(), LinkageInfo(), {}, Declaration,
SubHeading, IsFromSystemHeader) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_MacroDefinition; }
private:
virtual void anchor();
};
/// This holds information associated with typedefs.
///
/// Note: Typedefs for anonymous enums and structs typically don't get emitted
/// by the serializers but still get a TypedefRecord. Instead we use the
/// typedef name as a name for the underlying anonymous struct or enum.
struct TypedefRecord : APIRecord {
SymbolReference UnderlyingType;
TypedefRecord(StringRef USR, StringRef Name, SymbolReference Parent,
PresumedLoc Loc, AvailabilityInfo Availability,
const DocComment &Comment, DeclarationFragments Declaration,
DeclarationFragments SubHeading, SymbolReference UnderlyingType,
bool IsFromSystemHeader)
: APIRecord(RK_Typedef, USR, Name, Parent, Loc, std::move(Availability),
LinkageInfo(), Comment, Declaration, SubHeading,
IsFromSystemHeader),
UnderlyingType(UnderlyingType) {}
static bool classof(const APIRecord *Record) {
return classofKind(Record->getKind());
}
static bool classofKind(RecordKind K) { return K == RK_Typedef; }
private:
virtual void anchor();
};
/// APISet holds the set of API records collected from given inputs.
class APISet {
public:
/// Get the target triple for the ExtractAPI invocation.
const llvm::Triple &getTarget() const { return Target; }
/// Get the language used by the APIs.
Language getLanguage() const { return Lang; }
/// Finds the APIRecord for a given USR.
///
/// \returns a pointer to the APIRecord associated with that USR or nullptr.
APIRecord *findRecordForUSR(StringRef USR) const;
/// Copy \p String into the Allocator in this APISet.
///
/// \returns a StringRef of the copied string in APISet::Allocator.
StringRef copyString(StringRef String);
SymbolReference createSymbolReference(StringRef Name, StringRef USR,
StringRef Source = "");
/// Create a subclass of \p APIRecord and store it in the APISet.
///
/// \returns A pointer to the created record or the already existing record
/// matching this USR.
template <typename RecordTy, typename... CtorArgsContTy>
typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
createRecord(StringRef USR, StringRef Name, CtorArgsContTy &&...CtorArgs);
ArrayRef<const APIRecord *> getTopLevelRecords() const {
return TopLevelRecords;
}
APISet(const llvm::Triple &Target, Language Lang,
const std::string &ProductName)
: Target(Target), Lang(Lang), ProductName(ProductName) {}
// Prevent moves and copies
APISet(const APISet &Other) = delete;
APISet &operator=(const APISet &Other) = delete;
APISet(APISet &&Other) = delete;
APISet &operator=(APISet &&Other) = delete;
private:
/// BumpPtrAllocator that serves as the memory arena for the allocated objects
llvm::BumpPtrAllocator Allocator;
const llvm::Triple Target;
const Language Lang;
struct APIRecordDeleter {
void operator()(APIRecord *Record) { Record->~APIRecord(); }
};
// Ensure that the destructor of each record is called when the LookupTable is
// destroyed without calling delete operator as the memory for the record
// lives in the BumpPtrAllocator.
using APIRecordStoredPtr = std::unique_ptr<APIRecord, APIRecordDeleter>;
llvm::DenseMap<StringRef, APIRecordStoredPtr> USRBasedLookupTable;
std::vector<const APIRecord *> TopLevelRecords;
public:
const std::string ProductName;
};
template <typename RecordTy, typename... CtorArgsContTy>
typename std::enable_if_t<std::is_base_of_v<APIRecord, RecordTy>, RecordTy> *
APISet::createRecord(StringRef USR, StringRef Name,
CtorArgsContTy &&...CtorArgs) {
// Ensure USR refers to a String stored in the allocator.
auto USRString = copyString(USR);
auto Result = USRBasedLookupTable.insert({USRString, nullptr});
RecordTy *Record;
// Create the record if it does not already exist
if (Result.second) {
Record = new (Allocator) RecordTy(
USRString, copyString(Name), std::forward<CtorArgsContTy>(CtorArgs)...);
// Store the record in the record lookup map
Result.first->second = APIRecordStoredPtr(Record);
if (auto *ParentContext =
dyn_cast_if_present<RecordContext>(Record->Parent.Record))
ParentContext->addToRecordChain(Record);
else
TopLevelRecords.push_back(Record);
} else {
Record = dyn_cast<RecordTy>(Result.first->second.get());
}
return Record;
}
// Helper type for implementing casting to RecordContext pointers.
// Selected when FromTy not a known subclass of RecordContext.
template <typename FromTy,
bool IsKnownSubType = std::is_base_of_v<RecordContext, FromTy>>
struct ToRecordContextCastInfoWrapper {
static_assert(std::is_base_of_v<APIRecord, FromTy>,
"Can only cast APIRecord and derived classes to RecordContext");
static bool isPossible(FromTy *From) { return RecordContext::classof(From); }
static RecordContext *doCast(FromTy *From) {
return APIRecord::castToRecordContext(From);
}
};
// Selected when FromTy is a known subclass of RecordContext.
template <typename FromTy> struct ToRecordContextCastInfoWrapper<FromTy, true> {
static_assert(std::is_base_of_v<APIRecord, FromTy>,
"Can only cast APIRecord and derived classes to RecordContext");
static bool isPossible(const FromTy *From) { return true; }
static RecordContext *doCast(FromTy *From) {
return static_cast<RecordContext *>(From);
}
};
// Helper type for implementing casting to RecordContext pointers.
// Selected when ToTy isn't a known subclass of RecordContext
template <typename ToTy,
bool IsKnownSubType = std::is_base_of_v<RecordContext, ToTy>>
struct FromRecordContextCastInfoWrapper {
static_assert(
std::is_base_of_v<APIRecord, ToTy>,
"Can only class RecordContext to APIRecord and derived classes");
static bool isPossible(RecordContext *Ctx) {
return ToTy::classofKind(Ctx->getKind());
}
static ToTy *doCast(RecordContext *Ctx) {
return APIRecord::castFromRecordContext(Ctx);
}
};
// Selected when ToTy is a known subclass of RecordContext.
template <typename ToTy> struct FromRecordContextCastInfoWrapper<ToTy, true> {
static_assert(
std::is_base_of_v<APIRecord, ToTy>,
"Can only class RecordContext to APIRecord and derived classes");
static bool isPossible(RecordContext *Ctx) {
return ToTy::classof(Ctx->getKind());
}
static RecordContext *doCast(RecordContext *Ctx) {
return static_cast<ToTy *>(Ctx);
}
};
} // namespace extractapi
} // namespace clang
// Implement APIRecord (and derived classes) to and from RecordContext
// conversions
namespace llvm {
template <typename FromTy>
struct CastInfo<::clang::extractapi::RecordContext, FromTy *>
: public NullableValueCastFailed<::clang::extractapi::RecordContext *>,
public DefaultDoCastIfPossible<
::clang::extractapi::RecordContext *, FromTy *,
CastInfo<::clang::extractapi::RecordContext, FromTy *>> {
static inline bool isPossible(FromTy *From) {
return ::clang::extractapi::ToRecordContextCastInfoWrapper<
FromTy>::isPossible(From);
}
static inline ::clang::extractapi::RecordContext *doCast(FromTy *From) {
return ::clang::extractapi::ToRecordContextCastInfoWrapper<FromTy>::doCast(
From);
}
};
template <typename FromTy>
struct CastInfo<::clang::extractapi::RecordContext, const FromTy *>
: public ConstStrippingForwardingCast<
::clang::extractapi::RecordContext, const FromTy *,
CastInfo<::clang::extractapi::RecordContext, FromTy *>> {};
template <typename ToTy>
struct CastInfo<ToTy, ::clang::extractapi::RecordContext *>
: public NullableValueCastFailed<ToTy *>,
public DefaultDoCastIfPossible<
ToTy *, ::clang::extractapi::RecordContext *,
CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {
static inline bool isPossible(::clang::extractapi::RecordContext *Ctx) {
return ::clang::extractapi::FromRecordContextCastInfoWrapper<
ToTy>::isPossible(Ctx);
}
static inline ToTy *doCast(::clang::extractapi::RecordContext *Ctx) {
return ::clang::extractapi::FromRecordContextCastInfoWrapper<ToTy>::doCast(
Ctx);
}
};
template <typename ToTy>
struct CastInfo<ToTy, const ::clang::extractapi::RecordContext *>
: public ConstStrippingForwardingCast<
ToTy, const ::clang::extractapi::RecordContext *,
CastInfo<ToTy, ::clang::extractapi::RecordContext *>> {};
} // namespace llvm
#endif // LLVM_CLANG_EXTRACTAPI_API_H