[clang][ExtractAPI] Add support for C++ classes
Add ExtractAPI support C++ classes, fields, methods, and various qualifiers and specifiers Differential Revision: https://reviews.llvm.org/D153557
This commit is contained in:
@@ -22,6 +22,7 @@
|
||||
#include "clang/AST/DeclObjC.h"
|
||||
#include "clang/AST/RawCommentList.h"
|
||||
#include "clang/Basic/SourceLocation.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/ExtractAPI/AvailabilityInfo.h"
|
||||
#include "clang/ExtractAPI/DeclarationFragments.h"
|
||||
#include "llvm/ADT/MapVector.h"
|
||||
@@ -64,6 +65,14 @@ struct APIRecord {
|
||||
RK_Enum,
|
||||
RK_StructField,
|
||||
RK_Struct,
|
||||
RK_Union,
|
||||
RK_StaticField,
|
||||
RK_CXXField,
|
||||
RK_CXXClass,
|
||||
RK_CXXStaticMethod,
|
||||
RK_CXXInstanceMethod,
|
||||
RK_CXXConstructorMethod,
|
||||
RK_CXXDestructorMethod,
|
||||
RK_ObjCInstanceProperty,
|
||||
RK_ObjCClassProperty,
|
||||
RK_ObjCIvar,
|
||||
@@ -266,6 +275,132 @@ private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
struct CXXFieldRecord : APIRecord {
|
||||
AccessControl Access;
|
||||
|
||||
CXXFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, AccessControl Access,
|
||||
bool IsFromSystemHeader)
|
||||
: APIRecord(RK_CXXField, USR, Name, Loc, std::move(Availabilities),
|
||||
LinkageInfo::none(), Comment, Declaration, SubHeading,
|
||||
IsFromSystemHeader),
|
||||
Access(Access) {}
|
||||
|
||||
CXXFieldRecord(RecordKind Kind, StringRef USR, StringRef Name,
|
||||
PresumedLoc Loc, AvailabilitySet Availabilities,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, AccessControl Access,
|
||||
bool IsFromSystemHeader)
|
||||
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
|
||||
LinkageInfo::none(), Comment, Declaration, SubHeading,
|
||||
IsFromSystemHeader),
|
||||
Access(Access) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_CXXField;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
struct CXXMethodRecord : APIRecord {
|
||||
FunctionSignature Signature;
|
||||
AccessControl Access;
|
||||
|
||||
CXXMethodRecord() = delete;
|
||||
|
||||
CXXMethodRecord(RecordKind Kind, StringRef USR, StringRef Name,
|
||||
PresumedLoc Loc, AvailabilitySet Availabilities,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, FunctionSignature Signature,
|
||||
AccessControl Access, bool IsFromSystemHeader)
|
||||
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
|
||||
LinkageInfo::none(), Comment, Declaration, SubHeading,
|
||||
IsFromSystemHeader),
|
||||
Signature(Signature), Access(Access) {}
|
||||
|
||||
virtual ~CXXMethodRecord() = 0;
|
||||
};
|
||||
|
||||
struct CXXConstructorRecord : CXXMethodRecord {
|
||||
CXXConstructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities,
|
||||
const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access,
|
||||
bool IsFromSystemHeader)
|
||||
: CXXMethodRecord(RK_CXXConstructorMethod, USR, Name, Loc,
|
||||
std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader) {}
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_CXXConstructorMethod;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
struct CXXDestructorRecord : CXXMethodRecord {
|
||||
CXXDestructorRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access,
|
||||
bool IsFromSystemHeader)
|
||||
: CXXMethodRecord(RK_CXXDestructorMethod, USR, Name, Loc,
|
||||
std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader) {}
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_CXXDestructorMethod;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
struct CXXStaticMethodRecord : CXXMethodRecord {
|
||||
CXXStaticMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities,
|
||||
const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access,
|
||||
bool IsFromSystemHeader)
|
||||
: CXXMethodRecord(RK_CXXStaticMethod, USR, Name, Loc,
|
||||
std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader) {}
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_CXXStaticMethod;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
struct CXXInstanceMethodRecord : CXXMethodRecord {
|
||||
CXXInstanceMethodRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities,
|
||||
const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access,
|
||||
bool IsFromSystemHeader)
|
||||
: CXXMethodRecord(RK_CXXInstanceMethod, USR, Name, Loc,
|
||||
std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_CXXInstanceMethod;
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
/// This holds information associated with Objective-C properties.
|
||||
struct ObjCPropertyRecord : APIRecord {
|
||||
/// The attributes associated with an Objective-C property.
|
||||
@@ -444,6 +579,24 @@ struct SymbolReference {
|
||||
bool empty() const { return Name.empty() && USR.empty() && Source.empty(); }
|
||||
};
|
||||
|
||||
struct StaticFieldRecord : CXXFieldRecord {
|
||||
SymbolReference Context;
|
||||
|
||||
StaticFieldRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, LinkageInfo Linkage,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, SymbolReference Context,
|
||||
AccessControl Access, bool IsFromSystemHeader)
|
||||
: CXXFieldRecord(RK_StaticField, USR, Name, Loc,
|
||||
std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Access, IsFromSystemHeader),
|
||||
Context(Context) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_StaticField;
|
||||
}
|
||||
};
|
||||
|
||||
/// The base representation of an Objective-C container record. Holds common
|
||||
/// information associated with Objective-C containers.
|
||||
struct ObjCContainerRecord : APIRecord {
|
||||
@@ -465,6 +618,28 @@ struct ObjCContainerRecord : APIRecord {
|
||||
virtual ~ObjCContainerRecord() = 0;
|
||||
};
|
||||
|
||||
struct CXXClassRecord : APIRecord {
|
||||
SmallVector<std::unique_ptr<CXXFieldRecord>> Fields;
|
||||
SmallVector<std::unique_ptr<CXXMethodRecord>> Methods;
|
||||
SmallVector<SymbolReference> Bases;
|
||||
|
||||
CXXClassRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, RecordKind Kind,
|
||||
bool IsFromSystemHeader)
|
||||
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities),
|
||||
LinkageInfo::none(), Comment, Declaration, SubHeading,
|
||||
IsFromSystemHeader) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return (Record->getKind() == RK_CXXClass);
|
||||
}
|
||||
|
||||
private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
/// This holds information associated with Objective-C categories.
|
||||
struct ObjCCategoryRecord : ObjCContainerRecord {
|
||||
SymbolReference Interface;
|
||||
@@ -591,6 +766,12 @@ struct has_function_signature<ObjCInstanceMethodRecord>
|
||||
: public std::true_type {};
|
||||
template <>
|
||||
struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
|
||||
template <>
|
||||
struct has_function_signature<CXXMethodRecord> : public std::true_type {};
|
||||
|
||||
template <typename RecordTy> struct has_access : public std::false_type {};
|
||||
template <> struct has_access<CXXMethodRecord> : public std::true_type {};
|
||||
template <> struct has_access<CXXFieldRecord> : public std::true_type {};
|
||||
|
||||
/// APISet holds the set of API records collected from given inputs.
|
||||
class APISet {
|
||||
@@ -668,6 +849,41 @@ public:
|
||||
DeclarationFragments SubHeading,
|
||||
bool IsFromSystemHeader);
|
||||
|
||||
StaticFieldRecord *
|
||||
addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, LinkageInfo Linkage,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, SymbolReference Context,
|
||||
AccessControl Access, bool IsFromSystemHeaderg);
|
||||
|
||||
CXXFieldRecord *addCXXField(CXXClassRecord *CXXClass, StringRef Name,
|
||||
StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities,
|
||||
const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading,
|
||||
AccessControl Access, bool IsFromSystemHeader);
|
||||
|
||||
CXXClassRecord *
|
||||
addCXXClass(StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
APIRecord::RecordKind Kind, bool IsFromSystemHeader);
|
||||
|
||||
CXXMethodRecord *
|
||||
addCXXMethod(CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
|
||||
PresumedLoc Loc, AvailabilitySet Availability,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, FunctionSignature Signature,
|
||||
bool IsStatic, AccessControl Access, bool IsFromSystemHeader);
|
||||
|
||||
CXXMethodRecord *addCXXSpecialMethod(
|
||||
CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
|
||||
PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, bool IsConstructor, AccessControl Access,
|
||||
bool IsFromSystemHeader);
|
||||
|
||||
/// Create and add an Objective-C category record into the API set.
|
||||
///
|
||||
/// Note: the caller is responsible for keeping the StringRef \p Name and
|
||||
@@ -790,8 +1006,12 @@ public:
|
||||
const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
|
||||
return GlobalVariables;
|
||||
}
|
||||
const RecordMap<StaticFieldRecord> &getStaticFields() const {
|
||||
return StaticFields;
|
||||
}
|
||||
const RecordMap<EnumRecord> &getEnums() const { return Enums; }
|
||||
const RecordMap<StructRecord> &getStructs() const { return Structs; }
|
||||
const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
|
||||
const RecordMap<ObjCCategoryRecord> &getObjCCategories() const {
|
||||
return ObjCCategories;
|
||||
}
|
||||
@@ -845,8 +1065,10 @@ private:
|
||||
llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
|
||||
RecordMap<GlobalFunctionRecord> GlobalFunctions;
|
||||
RecordMap<GlobalVariableRecord> GlobalVariables;
|
||||
RecordMap<StaticFieldRecord> StaticFields;
|
||||
RecordMap<EnumRecord> Enums;
|
||||
RecordMap<StructRecord> Structs;
|
||||
RecordMap<CXXClassRecord> CXXClasses;
|
||||
RecordMap<ObjCCategoryRecord> ObjCCategories;
|
||||
RecordMap<ObjCInterfaceRecord> ObjCInterfaces;
|
||||
RecordMap<ObjCProtocolRecord> ObjCProtocols;
|
||||
|
||||
@@ -173,10 +173,27 @@ public:
|
||||
/// Get the corresponding FragmentKind from string \p S.
|
||||
static FragmentKind parseFragmentKindFromString(StringRef S);
|
||||
|
||||
static DeclarationFragments
|
||||
getExceptionSpecificationString(ExceptionSpecificationType ExceptionSpec);
|
||||
|
||||
static DeclarationFragments getStructureTypeFragment(const RecordDecl *Decl);
|
||||
|
||||
private:
|
||||
std::vector<Fragment> Fragments;
|
||||
};
|
||||
|
||||
class AccessControl {
|
||||
public:
|
||||
AccessControl(std::string Access) : Access(Access) {}
|
||||
|
||||
const std::string &getAccess() const { return Access; }
|
||||
|
||||
bool empty() const { return Access.empty(); }
|
||||
|
||||
private:
|
||||
std::string Access;
|
||||
};
|
||||
|
||||
/// Store function signature information with DeclarationFragments of the
|
||||
/// return type and parameters.
|
||||
class FunctionSignature {
|
||||
@@ -219,6 +236,29 @@ private:
|
||||
/// A factory class to build DeclarationFragments for different kinds of Decl.
|
||||
class DeclarationFragmentsBuilder {
|
||||
public:
|
||||
/// Build FunctionSignature for a function-like declaration \c FunctionT like
|
||||
/// FunctionDecl, ObjCMethodDecl, or CXXMethodDecl.
|
||||
///
|
||||
/// The logic and implementation of building a signature for a FunctionDecl,
|
||||
/// CXXMethodDecl, and ObjCMethodDecl are exactly the same, but they do not
|
||||
/// share a common base. This template helps reuse the code.
|
||||
template <typename FunctionT>
|
||||
static FunctionSignature getFunctionSignature(const FunctionT *Function);
|
||||
|
||||
static AccessControl getAccessControl(const Decl *Decl) {
|
||||
switch (Decl->getAccess()) {
|
||||
case AS_public:
|
||||
return AccessControl("public");
|
||||
case AS_private:
|
||||
return AccessControl("private");
|
||||
case AS_protected:
|
||||
return AccessControl("protected");
|
||||
case AS_none:
|
||||
return AccessControl("none");
|
||||
}
|
||||
llvm_unreachable("Unhandled access control");
|
||||
}
|
||||
|
||||
/// Build DeclarationFragments for a variable declaration VarDecl.
|
||||
static DeclarationFragments getFragmentsForVar(const VarDecl *);
|
||||
|
||||
@@ -239,6 +279,19 @@ public:
|
||||
/// Build DeclarationFragments for a struct record declaration RecordDecl.
|
||||
static DeclarationFragments getFragmentsForStruct(const RecordDecl *);
|
||||
|
||||
static DeclarationFragments getFragmentsForCXXClass(const CXXRecordDecl *);
|
||||
|
||||
static DeclarationFragments
|
||||
getFragmentsForSpecialCXXMethod(const CXXMethodDecl *);
|
||||
|
||||
static DeclarationFragments getFragmentsForCXXMethod(const CXXMethodDecl *);
|
||||
|
||||
static DeclarationFragments
|
||||
getFragmentsForConversionFunction(const CXXConversionDecl *);
|
||||
|
||||
static DeclarationFragments
|
||||
getFragmentsForOverloadedOperator(const CXXMethodDecl *);
|
||||
|
||||
/// Build DeclarationFragments for an Objective-C category declaration
|
||||
/// ObjCCategoryDecl.
|
||||
static DeclarationFragments
|
||||
@@ -283,15 +336,6 @@ public:
|
||||
/// Build a sub-heading for macro \p Name.
|
||||
static DeclarationFragments getSubHeadingForMacro(StringRef Name);
|
||||
|
||||
/// Build FunctionSignature for a function-like declaration \c FunctionT like
|
||||
/// FunctionDecl or ObjCMethodDecl.
|
||||
///
|
||||
/// The logic and implementation of building a signature for a FunctionDecl
|
||||
/// and an ObjCMethodDecl are exactly the same, but they do not share a common
|
||||
/// base. This template helps reuse the code.
|
||||
template <typename FunctionT>
|
||||
static FunctionSignature getFunctionSignature(const FunctionT *);
|
||||
|
||||
private:
|
||||
DeclarationFragmentsBuilder() = delete;
|
||||
|
||||
@@ -316,6 +360,24 @@ private:
|
||||
static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
|
||||
};
|
||||
|
||||
template <typename FunctionT>
|
||||
FunctionSignature
|
||||
DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
|
||||
FunctionSignature Signature;
|
||||
|
||||
DeclarationFragments ReturnType, After;
|
||||
ReturnType
|
||||
.append(getFragmentsForType(Function->getReturnType(),
|
||||
Function->getASTContext(), After))
|
||||
.append(std::move(After));
|
||||
Signature.setReturnType(ReturnType);
|
||||
|
||||
for (const auto *Param : Function->parameters())
|
||||
Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
|
||||
|
||||
return Signature;
|
||||
}
|
||||
|
||||
} // namespace extractapi
|
||||
} // namespace clang
|
||||
|
||||
|
||||
@@ -14,6 +14,10 @@
|
||||
#ifndef LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
|
||||
#define LLVM_CLANG_EXTRACTAPI_EXTRACT_API_VISITOR_H
|
||||
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include "clang/Basic/Specifiers.h"
|
||||
#include "clang/ExtractAPI/DeclarationFragments.h"
|
||||
#include "llvm/ADT/FunctionExtras.h"
|
||||
|
||||
#include "clang/AST/ASTContext.h"
|
||||
@@ -44,8 +48,14 @@ public:
|
||||
|
||||
bool VisitEnumDecl(const EnumDecl *Decl);
|
||||
|
||||
bool WalkUpFromRecordDecl(const RecordDecl *Decl);
|
||||
|
||||
bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl);
|
||||
|
||||
bool VisitRecordDecl(const RecordDecl *Decl);
|
||||
|
||||
bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
|
||||
|
||||
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl);
|
||||
|
||||
bool VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl);
|
||||
@@ -69,6 +79,20 @@ protected:
|
||||
void recordStructFields(StructRecord *StructRecord,
|
||||
const RecordDecl::field_range Fields);
|
||||
|
||||
/// Collect API information for the class fields and associate with the parent
|
||||
/// struct
|
||||
void recordCXXFields(CXXClassRecord *CXXClassRecord,
|
||||
const RecordDecl::field_range Fields);
|
||||
|
||||
void recordCXXMethods(CXXClassRecord *CXXClassRecord,
|
||||
const CXXRecordDecl::method_range Methods);
|
||||
|
||||
void recordConversionMethod(CXXClassRecord *CXXClassRecord,
|
||||
const CXXMethodDecl *SpecialCXXMethod);
|
||||
|
||||
void recordSpecialCXXMethod(CXXClassRecord *CXXClassRecord,
|
||||
const CXXMethodDecl *SpecialCXXMethod);
|
||||
|
||||
/// Collect API information for the Objective-C methods and associate with the
|
||||
/// parent container.
|
||||
void recordObjCMethods(ObjCContainerRecord *Container,
|
||||
@@ -131,8 +155,9 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
|
||||
if (isa<ParmVarDecl>(Decl))
|
||||
return true;
|
||||
|
||||
// Skip non-global variables in records (struct/union/class).
|
||||
if (Decl->getDeclContext()->isRecord())
|
||||
// Skip non-global variables in records (struct/union/class) but not static
|
||||
// members.
|
||||
if (Decl->getDeclContext()->isRecord() && !Decl->isStaticDataMember())
|
||||
return true;
|
||||
|
||||
// Skip local variables inside function or method.
|
||||
@@ -165,9 +190,19 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarDecl(const VarDecl *Decl) {
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
||||
|
||||
// Add the global variable record to the API set.
|
||||
API.addGlobalVar(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
||||
Declaration, SubHeading, isInSystemHeader(Decl));
|
||||
if (Decl->isStaticDataMember()) {
|
||||
SymbolReference Context;
|
||||
auto Record = dyn_cast<RecordDecl>(Decl->getDeclContext());
|
||||
Context.Name = Record->getName();
|
||||
Context.USR = API.recordUSR(Record);
|
||||
auto Access = DeclarationFragmentsBuilder::getAccessControl(Decl);
|
||||
API.addStaticField(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
||||
Declaration, SubHeading, Context, Access,
|
||||
isInSystemHeader(Decl));
|
||||
} else
|
||||
// Add the global variable record to the API set.
|
||||
API.addGlobalVar(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
||||
Declaration, SubHeading, isInSystemHeader(Decl));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -280,15 +315,23 @@ bool ExtractAPIVisitorBase<Derived>::VisitEnumDecl(const EnumDecl *Decl) {
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
|
||||
// Skip C++ structs/classes/unions
|
||||
// TODO: support C++ records
|
||||
if (isa<CXXRecordDecl>(Decl))
|
||||
return true;
|
||||
bool ExtractAPIVisitorBase<Derived>::WalkUpFromRecordDecl(
|
||||
const RecordDecl *Decl) {
|
||||
getDerivedExtractAPIVisitor().VisitRecordDecl(Decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXRecordDecl(
|
||||
const CXXRecordDecl *Decl) {
|
||||
getDerivedExtractAPIVisitor().VisitCXXRecordDecl(Decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
|
||||
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
|
||||
return true;
|
||||
|
||||
// Collect symbol information.
|
||||
StringRef Name = Decl->getName();
|
||||
if (Name.empty())
|
||||
@@ -322,6 +365,57 @@ bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
|
||||
const CXXRecordDecl *Decl) {
|
||||
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
|
||||
return true;
|
||||
|
||||
StringRef Name = Decl->getName();
|
||||
StringRef USR = API.recordUSR(Decl);
|
||||
PresumedLoc Loc =
|
||||
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
||||
DocComment Comment;
|
||||
if (auto *RawComment =
|
||||
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
|
||||
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
||||
Context.getDiagnostics());
|
||||
DeclarationFragments Declaration =
|
||||
DeclarationFragmentsBuilder::getFragmentsForCXXClass(Decl);
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
||||
|
||||
APIRecord::RecordKind Kind;
|
||||
if (Decl->isUnion())
|
||||
Kind = APIRecord::RecordKind::RK_Union;
|
||||
else if (Decl->isStruct())
|
||||
Kind = APIRecord::RecordKind::RK_Struct;
|
||||
else
|
||||
Kind = APIRecord::RecordKind::RK_CXXClass;
|
||||
|
||||
CXXClassRecord *CXXClassRecord =
|
||||
API.addCXXClass(Name, USR, Loc, AvailabilitySet(Decl), Comment,
|
||||
Declaration, SubHeading, Kind, isInSystemHeader(Decl));
|
||||
|
||||
// FIXME: store AccessSpecifier given by inheritance
|
||||
for (const auto BaseSpecifier : Decl->bases()) {
|
||||
// skip classes not inherited as public
|
||||
if (BaseSpecifier.getAccessSpecifier() != AccessSpecifier::AS_public)
|
||||
continue;
|
||||
SymbolReference BaseClass;
|
||||
CXXRecordDecl *BaseClassDecl =
|
||||
BaseSpecifier.getType().getTypePtr()->getAsCXXRecordDecl();
|
||||
BaseClass.Name = BaseClassDecl->getName();
|
||||
BaseClass.USR = API.recordUSR(BaseClassDecl);
|
||||
CXXClassRecord->Bases.emplace_back(BaseClass);
|
||||
}
|
||||
|
||||
getDerivedExtractAPIVisitor().recordCXXFields(CXXClassRecord, Decl->fields());
|
||||
getDerivedExtractAPIVisitor().recordCXXMethods(CXXClassRecord,
|
||||
Decl->methods());
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
|
||||
const ObjCInterfaceDecl *Decl) {
|
||||
@@ -558,6 +652,154 @@ void ExtractAPIVisitorBase<Derived>::recordStructFields(
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
void ExtractAPIVisitorBase<Derived>::recordCXXFields(
|
||||
CXXClassRecord *CXXClassRecord, const RecordDecl::field_range Fields) {
|
||||
for (const auto *Field : Fields) {
|
||||
// Collect symbol information.
|
||||
StringRef Name = Field->getName();
|
||||
StringRef USR = API.recordUSR(Field);
|
||||
PresumedLoc Loc =
|
||||
Context.getSourceManager().getPresumedLoc(Field->getLocation());
|
||||
Context.getSourceManager().getPresumedLoc(Field->getLocation());
|
||||
DocComment Comment;
|
||||
if (auto *RawComment =
|
||||
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Field))
|
||||
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
||||
Context.getDiagnostics());
|
||||
|
||||
// Build declaration fragments and sub-heading for the struct field.
|
||||
DeclarationFragments Declaration =
|
||||
DeclarationFragmentsBuilder::getFragmentsForField(Field);
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(Field);
|
||||
AccessControl Access = DeclarationFragmentsBuilder::getAccessControl(Field);
|
||||
|
||||
API.addCXXField(CXXClassRecord, Name, USR, Loc, AvailabilitySet(Field),
|
||||
Comment, Declaration, SubHeading, Access,
|
||||
isInSystemHeader(Field));
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect API information for constructors and destructors and associate with
|
||||
/// the parent class.
|
||||
template <typename Derived>
|
||||
void ExtractAPIVisitorBase<Derived>::recordSpecialCXXMethod(
|
||||
CXXClassRecord *CXXClassRecord, const CXXMethodDecl *CXXSpecialMethod) {
|
||||
StringRef Name;
|
||||
bool isConstructor = false;
|
||||
if (isa<CXXConstructorDecl>(CXXSpecialMethod)) {
|
||||
isConstructor = true;
|
||||
Name = CXXClassRecord->Name;
|
||||
} else if (isa<CXXDestructorDecl>(CXXSpecialMethod)) {
|
||||
Name = API.copyString(CXXSpecialMethod->getNameAsString());
|
||||
}
|
||||
|
||||
StringRef USR = API.recordUSR(CXXSpecialMethod);
|
||||
PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(
|
||||
CXXSpecialMethod->getLocation());
|
||||
DocComment Comment;
|
||||
if (auto *RawComment = getDerivedExtractAPIVisitor().fetchRawCommentForDecl(
|
||||
CXXSpecialMethod))
|
||||
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
||||
Context.getDiagnostics());
|
||||
|
||||
// Build declaration fragments, sub-heading, and signature for the method.
|
||||
DeclarationFragments Declaration =
|
||||
DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
|
||||
CXXSpecialMethod);
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(CXXSpecialMethod);
|
||||
FunctionSignature Signature =
|
||||
DeclarationFragmentsBuilder::getFunctionSignature(CXXSpecialMethod);
|
||||
AccessControl Access =
|
||||
DeclarationFragmentsBuilder::getAccessControl(CXXSpecialMethod);
|
||||
|
||||
API.addCXXSpecialMethod(CXXClassRecord, Name, USR, Loc,
|
||||
AvailabilitySet(CXXSpecialMethod), Comment,
|
||||
Declaration, SubHeading, Signature, isConstructor,
|
||||
Access, isInSystemHeader(CXXSpecialMethod));
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
void ExtractAPIVisitorBase<Derived>::recordConversionMethod(
|
||||
CXXClassRecord *CXXClassRecord, const CXXMethodDecl *SpecialCXXMethod) {
|
||||
StringRef Name = API.copyString(SpecialCXXMethod->getNameAsString());
|
||||
StringRef USR = API.recordUSR(SpecialCXXMethod);
|
||||
PresumedLoc Loc = Context.getSourceManager().getPresumedLoc(
|
||||
SpecialCXXMethod->getLocation());
|
||||
DocComment Comment;
|
||||
if (auto *RawComment = getDerivedExtractAPIVisitor().fetchRawCommentForDecl(
|
||||
SpecialCXXMethod))
|
||||
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
||||
Context.getDiagnostics());
|
||||
|
||||
// Build declaration fragments, sub-heading, and signature for the method.
|
||||
DeclarationFragments Declaration =
|
||||
DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
|
||||
cast<CXXConversionDecl>(SpecialCXXMethod));
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(SpecialCXXMethod);
|
||||
FunctionSignature Signature =
|
||||
DeclarationFragmentsBuilder::getFunctionSignature(SpecialCXXMethod);
|
||||
AccessControl Access =
|
||||
DeclarationFragmentsBuilder::getAccessControl(SpecialCXXMethod);
|
||||
|
||||
API.addCXXMethod(CXXClassRecord, Name, USR, Loc,
|
||||
AvailabilitySet(SpecialCXXMethod), Comment, Declaration,
|
||||
SubHeading, Signature, SpecialCXXMethod->isStatic(), Access,
|
||||
isInSystemHeader(SpecialCXXMethod));
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
void ExtractAPIVisitorBase<Derived>::recordCXXMethods(
|
||||
CXXClassRecord *CXXClassRecord, const CXXRecordDecl::method_range Methods) {
|
||||
for (const auto *Method : Methods) {
|
||||
if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method)) {
|
||||
recordSpecialCXXMethod(CXXClassRecord, Method);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isa<CXXConversionDecl>(Method)) {
|
||||
recordConversionMethod(CXXClassRecord, Method);
|
||||
continue;
|
||||
}
|
||||
|
||||
StringRef Name;
|
||||
DeclarationFragments Declaration;
|
||||
if (Method->isOverloadedOperator()) {
|
||||
Name = API.copyString(Method->getNameAsString());
|
||||
Declaration =
|
||||
DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
|
||||
Method);
|
||||
} else {
|
||||
Name = API.copyString(Method->getNameAsString());
|
||||
Declaration =
|
||||
DeclarationFragmentsBuilder::getFragmentsForCXXMethod(Method);
|
||||
}
|
||||
StringRef USR = API.recordUSR(Method);
|
||||
PresumedLoc Loc =
|
||||
Context.getSourceManager().getPresumedLoc(Method->getLocation());
|
||||
DocComment Comment;
|
||||
if (auto *RawComment =
|
||||
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Method))
|
||||
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
||||
Context.getDiagnostics());
|
||||
|
||||
// Build declaration fragments, sub-heading, and signature for the method.
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(Method);
|
||||
FunctionSignature Signature =
|
||||
DeclarationFragmentsBuilder::getFunctionSignature(Method);
|
||||
AccessControl Access =
|
||||
DeclarationFragmentsBuilder::getAccessControl(Method);
|
||||
|
||||
API.addCXXMethod(CXXClassRecord, Name, USR, Loc, AvailabilitySet(Method),
|
||||
Comment, Declaration, SubHeading, Signature,
|
||||
Method->isStatic(), Access, isInSystemHeader(Method));
|
||||
}
|
||||
}
|
||||
|
||||
/// Collect API information for the Objective-C methods and associate with the
|
||||
/// parent container.
|
||||
template <typename Derived>
|
||||
|
||||
@@ -29,6 +29,10 @@ public:
|
||||
|
||||
getDerived()->traverseEnumRecords();
|
||||
|
||||
getDerived()->traverseStaticFieldRecords();
|
||||
|
||||
getDerived()->traverseCXXClassRecords();
|
||||
|
||||
getDerived()->traverseStructRecords();
|
||||
|
||||
getDerived()->traverseObjCInterfaces();
|
||||
@@ -60,6 +64,16 @@ public:
|
||||
getDerived()->visitStructRecord(*Struct.second);
|
||||
}
|
||||
|
||||
void traverseStaticFieldRecords() {
|
||||
for (const auto &StaticField : API.getStaticFields())
|
||||
getDerived()->visitStaticFieldRecord(*StaticField.second);
|
||||
}
|
||||
|
||||
void traverseCXXClassRecords() {
|
||||
for (const auto &Class : API.getCXXClasses())
|
||||
getDerived()->visitCXXClassRecord(*Class.second);
|
||||
}
|
||||
|
||||
void traverseObjCInterfaces() {
|
||||
for (const auto &Interface : API.getObjCInterfaces())
|
||||
getDerived()->visitObjCContainerRecord(*Interface.second);
|
||||
@@ -92,6 +106,10 @@ public:
|
||||
/// Visit a struct record.
|
||||
void visitStructRecord(const StructRecord &Record){};
|
||||
|
||||
void visitStaticFieldRecord(const StaticFieldRecord &Record){};
|
||||
|
||||
void visitCXXClassRecord(const CXXClassRecord &Record){};
|
||||
|
||||
/// Visit an Objective-C container record.
|
||||
void visitObjCContainerRecord(const ObjCContainerRecord &Record){};
|
||||
|
||||
|
||||
@@ -160,6 +160,10 @@ public:
|
||||
/// Visit a struct record.
|
||||
void visitStructRecord(const StructRecord &Record);
|
||||
|
||||
void visitStaticFieldRecord(const StaticFieldRecord &Record);
|
||||
|
||||
void visitCXXClassRecord(const CXXClassRecord &Record);
|
||||
|
||||
/// Visit an Objective-C container record.
|
||||
void visitObjCContainerRecord(const ObjCContainerRecord &Record);
|
||||
|
||||
|
||||
@@ -120,6 +120,91 @@ StructRecord *APISet::addStruct(StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
SubHeading, IsFromSystemHeader);
|
||||
}
|
||||
|
||||
StaticFieldRecord *
|
||||
APISet::addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, LinkageInfo Linkage,
|
||||
const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, SymbolReference Context,
|
||||
AccessControl Access, bool IsFromSystemHeader) {
|
||||
return addTopLevelRecord(USRBasedLookupTable, StaticFields, USR, Name, Loc,
|
||||
std::move(Availabilities), Linkage, Comment,
|
||||
Declaration, SubHeading, Context, Access,
|
||||
IsFromSystemHeader);
|
||||
}
|
||||
|
||||
CXXFieldRecord *
|
||||
APISet::addCXXField(CXXClassRecord *CXXClass, StringRef Name, StringRef USR,
|
||||
PresumedLoc Loc, AvailabilitySet Availabilities,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, AccessControl Access,
|
||||
bool IsFromSystemHeader) {
|
||||
auto Record = std::make_unique<CXXFieldRecord>(
|
||||
USR, Name, Loc, std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Access, IsFromSystemHeader);
|
||||
Record->ParentInformation = APIRecord::HierarchyInformation(
|
||||
CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass);
|
||||
USRBasedLookupTable.insert({USR, Record.get()});
|
||||
return CXXClass->Fields.emplace_back(std::move(Record)).get();
|
||||
}
|
||||
|
||||
CXXClassRecord *
|
||||
APISet::addCXXClass(StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, APIRecord::RecordKind Kind,
|
||||
bool IsFromSystemHeader) {
|
||||
return addTopLevelRecord(USRBasedLookupTable, CXXClasses, USR, Name, Loc,
|
||||
std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Kind, IsFromSystemHeader);
|
||||
}
|
||||
|
||||
CXXMethodRecord *APISet::addCXXMethod(
|
||||
CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
|
||||
PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, bool IsStatic, AccessControl Access,
|
||||
bool IsFromSystemHeader) {
|
||||
std::unique_ptr<CXXMethodRecord> Record;
|
||||
if (IsStatic)
|
||||
Record = std::make_unique<CXXStaticMethodRecord>(
|
||||
USR, Name, Loc, std::move(Availability), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader);
|
||||
else
|
||||
Record = std::make_unique<CXXInstanceMethodRecord>(
|
||||
USR, Name, Loc, std::move(Availability), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader);
|
||||
|
||||
Record->ParentInformation = APIRecord::HierarchyInformation(
|
||||
CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
|
||||
CXXClassRecord);
|
||||
USRBasedLookupTable.insert({USR, Record.get()});
|
||||
return CXXClassRecord->Methods.emplace_back(std::move(Record)).get();
|
||||
}
|
||||
|
||||
CXXMethodRecord *APISet::addCXXSpecialMethod(
|
||||
CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
|
||||
PresumedLoc Loc, AvailabilitySet Availability, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, bool IsConstructor, AccessControl Access,
|
||||
bool IsFromSystemHeader) {
|
||||
std::unique_ptr<CXXMethodRecord> Record;
|
||||
if (IsConstructor)
|
||||
Record = std::make_unique<CXXConstructorRecord>(
|
||||
USR, Name, Loc, std::move(Availability), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader);
|
||||
else
|
||||
Record = std::make_unique<CXXDestructorRecord>(
|
||||
USR, Name, Loc, std::move(Availability), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader);
|
||||
|
||||
Record->ParentInformation = APIRecord::HierarchyInformation(
|
||||
CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
|
||||
CXXClassRecord);
|
||||
USRBasedLookupTable.insert({USR, Record.get()});
|
||||
return CXXClassRecord->Methods.emplace_back(std::move(Record)).get();
|
||||
}
|
||||
|
||||
ObjCCategoryRecord *APISet::addObjCCategory(
|
||||
StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, const DocComment &Comment,
|
||||
@@ -282,6 +367,7 @@ APIRecord::~APIRecord() {}
|
||||
ObjCContainerRecord::~ObjCContainerRecord() {}
|
||||
ObjCMethodRecord::~ObjCMethodRecord() {}
|
||||
ObjCPropertyRecord::~ObjCPropertyRecord() {}
|
||||
CXXMethodRecord::~CXXMethodRecord() {}
|
||||
|
||||
void GlobalFunctionRecord::anchor() {}
|
||||
void GlobalVariableRecord::anchor() {}
|
||||
@@ -289,6 +375,12 @@ void EnumConstantRecord::anchor() {}
|
||||
void EnumRecord::anchor() {}
|
||||
void StructFieldRecord::anchor() {}
|
||||
void StructRecord::anchor() {}
|
||||
void CXXFieldRecord::anchor() {}
|
||||
void CXXClassRecord::anchor() {}
|
||||
void CXXConstructorRecord::anchor() {}
|
||||
void CXXDestructorRecord::anchor() {}
|
||||
void CXXInstanceMethodRecord::anchor() {}
|
||||
void CXXStaticMethodRecord::anchor() {}
|
||||
void ObjCInstancePropertyRecord::anchor() {}
|
||||
void ObjCClassPropertyRecord::anchor() {}
|
||||
void ObjCInstanceVariableRecord::anchor() {}
|
||||
|
||||
@@ -12,8 +12,12 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "clang/ExtractAPI/DeclarationFragments.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/Basic/OperatorKinds.h"
|
||||
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
|
||||
#include "clang/Index/USRGeneration.h"
|
||||
#include "clang/Parse/Parser.h"
|
||||
#include "llvm/ADT/StringSwitch.h"
|
||||
|
||||
using namespace clang::extractapi;
|
||||
@@ -84,6 +88,59 @@ DeclarationFragments::parseFragmentKindFromString(StringRef S) {
|
||||
.Default(DeclarationFragments::FragmentKind::None);
|
||||
}
|
||||
|
||||
DeclarationFragments DeclarationFragments::getExceptionSpecificationString(
|
||||
ExceptionSpecificationType ExceptionSpec) {
|
||||
DeclarationFragments Fragments;
|
||||
switch (ExceptionSpec) {
|
||||
case ExceptionSpecificationType::EST_None:
|
||||
return Fragments;
|
||||
case ExceptionSpecificationType::EST_DynamicNone:
|
||||
return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
|
||||
.append("throw", DeclarationFragments::FragmentKind::Keyword)
|
||||
.append("(", DeclarationFragments::FragmentKind::Text)
|
||||
.append(")", DeclarationFragments::FragmentKind::Text);
|
||||
case ExceptionSpecificationType::EST_Dynamic:
|
||||
// FIXME: throw(int), get types of inner expression
|
||||
return Fragments;
|
||||
case ExceptionSpecificationType::EST_BasicNoexcept:
|
||||
|
||||
return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
|
||||
.append("noexcept", DeclarationFragments::FragmentKind::Keyword);
|
||||
case ExceptionSpecificationType::EST_DependentNoexcept:
|
||||
// FIXME: throw(conditional-expression), get expression
|
||||
break;
|
||||
case ExceptionSpecificationType::EST_NoexceptFalse:
|
||||
return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
|
||||
.append("noexcept", DeclarationFragments::FragmentKind::Keyword)
|
||||
.append("(", DeclarationFragments::FragmentKind::Text)
|
||||
.append("false", DeclarationFragments::FragmentKind::Keyword)
|
||||
.append(")", DeclarationFragments::FragmentKind::Text);
|
||||
case ExceptionSpecificationType::EST_NoexceptTrue:
|
||||
return Fragments.append(" ", DeclarationFragments::FragmentKind::Text)
|
||||
.append("noexcept", DeclarationFragments::FragmentKind::Keyword)
|
||||
.append("(", DeclarationFragments::FragmentKind::Text)
|
||||
.append("true", DeclarationFragments::FragmentKind::Keyword)
|
||||
.append(")", DeclarationFragments::FragmentKind::Text);
|
||||
default:
|
||||
return Fragments;
|
||||
}
|
||||
|
||||
llvm_unreachable("Unhandled exception specification");
|
||||
}
|
||||
|
||||
DeclarationFragments
|
||||
DeclarationFragments::getStructureTypeFragment(const RecordDecl *Record) {
|
||||
DeclarationFragments Fragments;
|
||||
if (Record->isStruct())
|
||||
Fragments.append("struct", DeclarationFragments::FragmentKind::Keyword);
|
||||
else if (Record->isUnion())
|
||||
Fragments.append("union", DeclarationFragments::FragmentKind::Keyword);
|
||||
else
|
||||
Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
|
||||
|
||||
return Fragments;
|
||||
}
|
||||
|
||||
// NNS stores C++ nested name specifiers, which are prefixes to qualified names.
|
||||
// Build declaration fragments for NNS recursively so that we have the USR for
|
||||
// every part in a qualified name, and also leaves the actual underlying type
|
||||
@@ -369,6 +426,9 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
|
||||
DeclarationFragments Fragments;
|
||||
if (Var->isConstexpr())
|
||||
Fragments.append("constexpr ", DeclarationFragments::FragmentKind::Keyword);
|
||||
|
||||
StorageClass SC = Var->getStorageClass();
|
||||
if (SC != SC_None)
|
||||
Fragments
|
||||
@@ -438,7 +498,10 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
|
||||
case SC_Register:
|
||||
llvm_unreachable("invalid for functions");
|
||||
}
|
||||
// FIXME: Handle C++ function specifiers: constexpr, consteval, explicit, etc.
|
||||
if (Func->isConsteval()) // if consteval, it is also constexpr
|
||||
Fragments.append("consteval ", DeclarationFragments::FragmentKind::Keyword);
|
||||
else if (Func->isConstexpr())
|
||||
Fragments.append("constexpr ", DeclarationFragments::FragmentKind::Keyword);
|
||||
|
||||
// FIXME: Is `after` actually needed here?
|
||||
DeclarationFragments After;
|
||||
@@ -457,6 +520,9 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
|
||||
}
|
||||
Fragments.append(")", DeclarationFragments::FragmentKind::Text);
|
||||
|
||||
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
|
||||
Func->getExceptionSpecType()));
|
||||
|
||||
// FIXME: Handle exception specifiers: throw, noexcept
|
||||
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
@@ -493,7 +559,13 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
|
||||
DeclarationFragments After;
|
||||
return getFragmentsForType(Field->getType(), Field->getASTContext(), After)
|
||||
DeclarationFragments Fragments;
|
||||
if (Field->isMutable())
|
||||
Fragments.append("mutable", DeclarationFragments::FragmentKind::Keyword)
|
||||
.appendSpace();
|
||||
return Fragments
|
||||
.append(
|
||||
getFragmentsForType(Field->getType(), Field->getASTContext(), After))
|
||||
.appendSpace()
|
||||
.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
|
||||
.append(std::move(After))
|
||||
@@ -515,6 +587,156 @@ DeclarationFragmentsBuilder::getFragmentsForStruct(const RecordDecl *Record) {
|
||||
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
|
||||
const CXXRecordDecl *Record) {
|
||||
if (const auto *TypedefNameDecl = Record->getTypedefNameForAnonDecl())
|
||||
return getFragmentsForTypedef(TypedefNameDecl);
|
||||
|
||||
DeclarationFragments Fragments;
|
||||
Fragments.append(DeclarationFragments::getStructureTypeFragment(Record));
|
||||
|
||||
if (!Record->getName().empty())
|
||||
Fragments.appendSpace().append(
|
||||
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
|
||||
|
||||
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
|
||||
const CXXMethodDecl *Method) {
|
||||
DeclarationFragments Fragments;
|
||||
StringRef Name;
|
||||
if (isa<CXXConstructorDecl>(Method)) {
|
||||
auto *Constructor = dyn_cast<CXXConstructorDecl>(Method);
|
||||
Name = cast<CXXRecordDecl>(Constructor->getDeclContext())->getName();
|
||||
if (Constructor->isExplicit())
|
||||
Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
|
||||
.appendSpace();
|
||||
} else if (isa<CXXDestructorDecl>(Method))
|
||||
Name = StringRef(Method->getNameAsString());
|
||||
|
||||
DeclarationFragments After;
|
||||
Fragments.append(Name, DeclarationFragments::FragmentKind::Identifier)
|
||||
.append(std::move(After));
|
||||
Fragments.append("(", DeclarationFragments::FragmentKind::Text);
|
||||
for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
|
||||
if (i)
|
||||
Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
|
||||
Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
|
||||
}
|
||||
Fragments.append(")", DeclarationFragments::FragmentKind::Text);
|
||||
|
||||
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
|
||||
Method->getExceptionSpecType()));
|
||||
|
||||
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
|
||||
const CXXMethodDecl *Method) {
|
||||
DeclarationFragments Fragments;
|
||||
StringRef Name;
|
||||
Name = Method->getName();
|
||||
if (Method->isStatic())
|
||||
Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
|
||||
.appendSpace();
|
||||
if (Method->isConstexpr())
|
||||
Fragments.append("constexpr", DeclarationFragments::FragmentKind::Keyword)
|
||||
.appendSpace();
|
||||
if (Method->isVolatile())
|
||||
Fragments.append("volatile", DeclarationFragments::FragmentKind::Keyword)
|
||||
.appendSpace();
|
||||
|
||||
// Build return type
|
||||
DeclarationFragments After;
|
||||
Fragments
|
||||
.append(getFragmentsForType(Method->getReturnType(),
|
||||
Method->getASTContext(), After))
|
||||
.appendSpace()
|
||||
.append(Name, DeclarationFragments::FragmentKind::Identifier)
|
||||
.append(std::move(After));
|
||||
Fragments.append("(", DeclarationFragments::FragmentKind::Text);
|
||||
for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
|
||||
if (i)
|
||||
Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
|
||||
Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
|
||||
}
|
||||
Fragments.append(")", DeclarationFragments::FragmentKind::Text);
|
||||
|
||||
if (Method->isConst())
|
||||
Fragments.appendSpace().append("const",
|
||||
DeclarationFragments::FragmentKind::Keyword);
|
||||
|
||||
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
|
||||
Method->getExceptionSpecType()));
|
||||
|
||||
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
|
||||
const CXXConversionDecl *ConversionFunction) {
|
||||
DeclarationFragments Fragments;
|
||||
|
||||
if (ConversionFunction->isExplicit())
|
||||
Fragments.append("explicit", DeclarationFragments::FragmentKind::Keyword)
|
||||
.appendSpace();
|
||||
|
||||
Fragments.append("operator", DeclarationFragments::FragmentKind::Keyword)
|
||||
.appendSpace();
|
||||
|
||||
Fragments
|
||||
.append(ConversionFunction->getConversionType().getAsString(),
|
||||
DeclarationFragments::FragmentKind::TypeIdentifier)
|
||||
.append("(", DeclarationFragments::FragmentKind::Text);
|
||||
for (unsigned i = 0, end = ConversionFunction->getNumParams(); i != end;
|
||||
++i) {
|
||||
if (i)
|
||||
Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
|
||||
Fragments.append(getFragmentsForParam(ConversionFunction->getParamDecl(i)));
|
||||
}
|
||||
Fragments.append(")", DeclarationFragments::FragmentKind::Text);
|
||||
|
||||
if (ConversionFunction->isConst())
|
||||
Fragments.appendSpace().append("const",
|
||||
DeclarationFragments::FragmentKind::Keyword);
|
||||
|
||||
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
|
||||
const CXXMethodDecl *Method) {
|
||||
DeclarationFragments Fragments;
|
||||
|
||||
// Build return type
|
||||
DeclarationFragments After;
|
||||
Fragments
|
||||
.append(getFragmentsForType(Method->getReturnType(),
|
||||
Method->getASTContext(), After))
|
||||
.appendSpace()
|
||||
.append(Method->getNameAsString(),
|
||||
DeclarationFragments::FragmentKind::Identifier)
|
||||
.append(std::move(After));
|
||||
Fragments.append("(", DeclarationFragments::FragmentKind::Text);
|
||||
for (unsigned i = 0, end = Method->getNumParams(); i != end; ++i) {
|
||||
if (i)
|
||||
Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
|
||||
Fragments.append(getFragmentsForParam(Method->getParamDecl(i)));
|
||||
}
|
||||
Fragments.append(")", DeclarationFragments::FragmentKind::Text);
|
||||
|
||||
if (Method->isConst())
|
||||
Fragments.appendSpace().append("const",
|
||||
DeclarationFragments::FragmentKind::Keyword);
|
||||
|
||||
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
|
||||
Method->getExceptionSpecType()));
|
||||
|
||||
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
|
||||
const MacroDirective *MD) {
|
||||
@@ -765,24 +987,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
|
||||
return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
template <typename FunctionT>
|
||||
FunctionSignature
|
||||
DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
|
||||
FunctionSignature Signature;
|
||||
|
||||
DeclarationFragments ReturnType, After;
|
||||
ReturnType
|
||||
.append(getFragmentsForType(Function->getReturnType(),
|
||||
Function->getASTContext(), After))
|
||||
.append(std::move(After));
|
||||
Signature.setReturnType(ReturnType);
|
||||
|
||||
for (const auto *Param : Function->parameters())
|
||||
Signature.addParameter(Param->getName(), getFragmentsForParam(Param));
|
||||
|
||||
return Signature;
|
||||
}
|
||||
|
||||
// Instantiate template for FunctionDecl.
|
||||
template FunctionSignature
|
||||
DeclarationFragmentsBuilder::getFunctionSignature(const FunctionDecl *);
|
||||
@@ -795,7 +999,18 @@ DeclarationFragmentsBuilder::getFunctionSignature(const ObjCMethodDecl *);
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getSubHeading(const NamedDecl *Decl) {
|
||||
DeclarationFragments Fragments;
|
||||
if (!Decl->getName().empty())
|
||||
if (isa<CXXConstructorDecl>(Decl) || isa<CXXDestructorDecl>(Decl))
|
||||
Fragments.append(cast<CXXRecordDecl>(Decl->getDeclContext())->getName(),
|
||||
DeclarationFragments::FragmentKind::Identifier);
|
||||
else if (isa<CXXConversionDecl>(Decl)) {
|
||||
Fragments.append(
|
||||
cast<CXXConversionDecl>(Decl)->getConversionType().getAsString(),
|
||||
DeclarationFragments::FragmentKind::Identifier);
|
||||
} else if (isa<CXXMethodDecl>(Decl) &&
|
||||
cast<CXXMethodDecl>(Decl)->isOverloadedOperator()) {
|
||||
Fragments.append(Decl->getNameAsString(),
|
||||
DeclarationFragments::FragmentKind::Identifier);
|
||||
} else if (!Decl->getName().empty())
|
||||
Fragments.append(Decl->getName(),
|
||||
DeclarationFragments::FragmentKind::Identifier);
|
||||
return Fragments;
|
||||
|
||||
@@ -38,6 +38,14 @@ void serializeObject(Object &Paren, StringRef Key, std::optional<Object> Obj) {
|
||||
Paren[Key] = std::move(*Obj);
|
||||
}
|
||||
|
||||
/// Helper function to inject a StringRef \p String into an object \p Paren at
|
||||
/// position \p Key
|
||||
void serializeString(Object &Paren, StringRef Key,
|
||||
std::optional<std::string> String) {
|
||||
if (String)
|
||||
Paren[Key] = std::move(*String);
|
||||
}
|
||||
|
||||
/// Helper function to inject a JSON array \p Array into object \p Paren at
|
||||
/// position \p Key.
|
||||
void serializeArray(Object &Paren, StringRef Key, std::optional<Array> Array) {
|
||||
@@ -189,9 +197,10 @@ StringRef getLanguageName(Language Lang) {
|
||||
return "c";
|
||||
case Language::ObjC:
|
||||
return "objective-c";
|
||||
case Language::CXX:
|
||||
return "c++";
|
||||
|
||||
// Unsupported language currently
|
||||
case Language::CXX:
|
||||
case Language::ObjCXX:
|
||||
case Language::OpenCL:
|
||||
case Language::OpenCLCXX:
|
||||
@@ -366,6 +375,38 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
|
||||
Kind["identifier"] = AddLangPrefix("struct");
|
||||
Kind["displayName"] = "Structure";
|
||||
break;
|
||||
case APIRecord::RK_CXXField:
|
||||
Kind["identifier"] = AddLangPrefix("property");
|
||||
Kind["displayName"] = "Instance Property";
|
||||
break;
|
||||
case APIRecord::RK_Union:
|
||||
Kind["identifier"] = AddLangPrefix("union");
|
||||
Kind["displayName"] = "Union";
|
||||
break;
|
||||
case APIRecord::RK_StaticField:
|
||||
Kind["identifier"] = AddLangPrefix("type.property");
|
||||
Kind["displayName"] = "Type Property";
|
||||
break;
|
||||
case APIRecord::RK_CXXClass:
|
||||
Kind["identifier"] = AddLangPrefix("class");
|
||||
Kind["displayName"] = "Class";
|
||||
break;
|
||||
case APIRecord::RK_CXXStaticMethod:
|
||||
Kind["identifier"] = AddLangPrefix("type.method");
|
||||
Kind["displayName"] = "Static Method";
|
||||
break;
|
||||
case APIRecord::RK_CXXInstanceMethod:
|
||||
Kind["identifier"] = AddLangPrefix("method");
|
||||
Kind["displayName"] = "Instance Method";
|
||||
break;
|
||||
case APIRecord::RK_CXXConstructorMethod:
|
||||
Kind["identifier"] = AddLangPrefix("method");
|
||||
Kind["displayName"] = "Constructor";
|
||||
break;
|
||||
case APIRecord::RK_CXXDestructorMethod:
|
||||
Kind["identifier"] = AddLangPrefix("method");
|
||||
Kind["displayName"] = "Destructor";
|
||||
break;
|
||||
case APIRecord::RK_ObjCIvar:
|
||||
Kind["identifier"] = AddLangPrefix("ivar");
|
||||
Kind["displayName"] = "Instance Variable";
|
||||
@@ -470,6 +511,31 @@ void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
|
||||
Record, has_function_signature<RecordTy>()));
|
||||
}
|
||||
|
||||
template <typename RecordTy>
|
||||
std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record,
|
||||
std::true_type) {
|
||||
const auto &AccessControl = Record.Access;
|
||||
std::string Access;
|
||||
if (AccessControl.empty())
|
||||
return std::nullopt;
|
||||
Access = AccessControl.getAccess();
|
||||
return Access;
|
||||
}
|
||||
|
||||
template <typename RecordTy>
|
||||
std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record,
|
||||
std::false_type) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
template <typename RecordTy>
|
||||
void serializeAccessMixin(Object &Paren, const RecordTy &Record) {
|
||||
auto accessLevel = serializeAccessMixinImpl(Record, has_access<RecordTy>());
|
||||
if (!accessLevel.has_value())
|
||||
accessLevel = "public";
|
||||
serializeString(Paren, "accessLevel", accessLevel);
|
||||
}
|
||||
|
||||
struct PathComponent {
|
||||
StringRef USR;
|
||||
StringRef Name;
|
||||
@@ -543,7 +609,6 @@ Array generateParentContexts(const RecordTy &Record, const APISet &API,
|
||||
|
||||
return ParentContexts;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
/// Defines the format version emitted by SymbolGraphSerializer.
|
||||
@@ -602,9 +667,6 @@ SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const {
|
||||
serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
|
||||
serializeArray(Obj, "declarationFragments",
|
||||
serializeDeclarationFragments(Record.Declaration));
|
||||
// TODO: Once we keep track of symbol access information serialize it
|
||||
// correctly here.
|
||||
Obj["accessLevel"] = "public";
|
||||
SmallVector<StringRef, 4> PathComponentsNames;
|
||||
// If this returns true it indicates that we couldn't find a symbol in the
|
||||
// hierarchy.
|
||||
@@ -617,6 +679,7 @@ SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const {
|
||||
serializeArray(Obj, "pathComponents", Array(PathComponentsNames));
|
||||
|
||||
serializeFunctionSignatureMixin(Obj, Record);
|
||||
serializeAccessMixin(Obj, Record);
|
||||
|
||||
return Obj;
|
||||
}
|
||||
@@ -698,6 +761,28 @@ void SymbolGraphSerializer::visitStructRecord(const StructRecord &Record) {
|
||||
serializeMembers(Record, Record.Fields);
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitStaticFieldRecord(
|
||||
const StaticFieldRecord &Record) {
|
||||
auto StaticField = serializeAPIRecord(Record);
|
||||
if (!StaticField)
|
||||
return;
|
||||
Symbols.emplace_back(std::move(*StaticField));
|
||||
serializeRelationship(RelationshipKind::MemberOf, Record, Record.Context);
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord &Record) {
|
||||
auto Class = serializeAPIRecord(Record);
|
||||
if (!Class)
|
||||
return;
|
||||
|
||||
Symbols.emplace_back(std::move(*Class));
|
||||
serializeMembers(Record, Record.Fields);
|
||||
serializeMembers(Record, Record.Methods);
|
||||
|
||||
for (const auto Base : Record.Bases)
|
||||
serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitObjCContainerRecord(
|
||||
const ObjCContainerRecord &Record) {
|
||||
auto ObjCContainer = serializeAPIRecord(Record);
|
||||
@@ -761,6 +846,12 @@ void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) {
|
||||
case APIRecord::RK_Struct:
|
||||
visitStructRecord(*cast<StructRecord>(Record));
|
||||
break;
|
||||
case APIRecord::RK_StaticField:
|
||||
visitStaticFieldRecord(*cast<StaticFieldRecord>(Record));
|
||||
break;
|
||||
case APIRecord::RK_CXXClass:
|
||||
visitCXXClassRecord(*cast<CXXClassRecord>(Record));
|
||||
break;
|
||||
case APIRecord::RK_ObjCInterface:
|
||||
visitObjCContainerRecord(*cast<ObjCInterfaceRecord>(Record));
|
||||
break;
|
||||
|
||||
366
clang/test/ExtractAPI/class.cpp
Normal file
366
clang/test/ExtractAPI/class.cpp
Normal file
@@ -0,0 +1,366 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang++ -extract-api -target arm64-apple-macosx -x c++-header \
|
||||
// RUN: %t/input.h -o %t/output.json -Xclang -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
class Foo {
|
||||
private:
|
||||
int a;
|
||||
mutable int b;
|
||||
|
||||
protected:
|
||||
int c;
|
||||
|
||||
public:
|
||||
int d;
|
||||
};
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@FI@a",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@FI@b",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@FI@c",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@FI@d",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "a"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@FI@a"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Property",
|
||||
"identifier": "c++.property"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "a"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "a"
|
||||
}
|
||||
],
|
||||
"title": "a"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"a"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "mutable"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "b"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@FI@b"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Property",
|
||||
"identifier": "c++.property"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 15,
|
||||
"line": 4
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "b"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "b"
|
||||
}
|
||||
],
|
||||
"title": "b"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"b"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "protected",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "c"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@FI@c"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Property",
|
||||
"identifier": "c++.property"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 7
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "c"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "c"
|
||||
}
|
||||
],
|
||||
"title": "c"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"c"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "d"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@FI@d"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Property",
|
||||
"identifier": "c++.property"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 10
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "d"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "d"
|
||||
}
|
||||
],
|
||||
"title": "d"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"d"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
227
clang/test/ExtractAPI/constructor_destructor.cpp
Normal file
227
clang/test/ExtractAPI/constructor_destructor.cpp
Normal file
@@ -0,0 +1,227 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang++ -extract-api -target arm64-apple-macosx -x c++-header \
|
||||
// RUN: %t/input.h -o %t/output.json -Xclang -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
class Foo {
|
||||
Foo();
|
||||
~Foo();
|
||||
};
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@Foo#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@~Foo#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "();"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@Foo#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Constructor",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 3,
|
||||
"line": 2
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "~Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "();"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@~Foo#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Destructor",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 3,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "~Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "~Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"~Foo"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
251
clang/test/ExtractAPI/conversions.cpp
Normal file
251
clang/test/ExtractAPI/conversions.cpp
Normal file
@@ -0,0 +1,251 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang++ -extract-api -target arm64-apple-macosx -x c++-header \
|
||||
// RUN: %t/input.h -o %t/output.json -Xclang -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
class Foo {
|
||||
operator int();
|
||||
explicit operator double();
|
||||
};
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@operator int#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@operator double#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "operator"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "();"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@operator int#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Method",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 3,
|
||||
"line": 2
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "operator int"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "int"
|
||||
}
|
||||
],
|
||||
"title": "operator int"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"operator int"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "explicit"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "operator"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"spelling": "double"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "();"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:d",
|
||||
"spelling": "double"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@operator double#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Method",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 12,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "operator double"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "double"
|
||||
}
|
||||
],
|
||||
"title": "operator double"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"operator double"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
293
clang/test/ExtractAPI/function_noexcepts.cpp
Normal file
293
clang/test/ExtractAPI/function_noexcepts.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang++ -extract-api -target arm64-apple-macosx -x c++-header \
|
||||
// RUN: %t/input.h -o %t/output.json -Xclang -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
void getFoo() noexcept;
|
||||
|
||||
void getBar() noexcept(true);
|
||||
|
||||
void getFooBar() noexcept(false);
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFoo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "()"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "noexcept"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@F@getFoo#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function",
|
||||
"identifier": "c++.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 6,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFoo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFoo"
|
||||
}
|
||||
],
|
||||
"title": "getFoo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"getFoo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getBar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "()"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "noexcept"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "true"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@F@getBar#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function",
|
||||
"identifier": "c++.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 6,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getBar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getBar"
|
||||
}
|
||||
],
|
||||
"title": "getBar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"getBar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFooBar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "()"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "noexcept"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "false"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@F@getFooBar#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function",
|
||||
"identifier": "c++.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 6,
|
||||
"line": 5
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFooBar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFooBar"
|
||||
}
|
||||
],
|
||||
"title": "getFooBar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"getFooBar"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
467
clang/test/ExtractAPI/methods.cpp
Normal file
467
clang/test/ExtractAPI/methods.cpp
Normal file
@@ -0,0 +1,467 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang++ -extract-api -target arm64-apple-macosx -x c++-header \
|
||||
// RUN: %t/input.h -o %t/output.json -Xclang -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
class Foo {
|
||||
int getCount();
|
||||
|
||||
void setLength(int length) noexcept;
|
||||
|
||||
public:
|
||||
static double getFoo();
|
||||
|
||||
protected:
|
||||
constexpr int getBar() const;
|
||||
};
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@getCount#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@setLength#I#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@getFoo#S",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@getBar#1",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getCount"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "();"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@getCount#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Method",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 2
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getCount"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getCount"
|
||||
}
|
||||
],
|
||||
"title": "getCount"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"getCount"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "setLength"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "length"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ")"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "noexcept"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "length"
|
||||
}
|
||||
],
|
||||
"name": "length"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@setLength#I#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Method",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 8,
|
||||
"line": 4
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "setLength"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "setLength"
|
||||
}
|
||||
],
|
||||
"title": "setLength"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"setLength"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "static"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:d",
|
||||
"spelling": "double"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFoo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "();"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:d",
|
||||
"spelling": "double"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@getFoo#S"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Static Method",
|
||||
"identifier": "c++.type.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 17,
|
||||
"line": 7
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFoo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getFoo"
|
||||
}
|
||||
],
|
||||
"title": "getFoo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"getFoo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "protected",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "constexpr"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getBar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "() "
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "const"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@getBar#1"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Method",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 17,
|
||||
"line": 10
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getBar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "getBar"
|
||||
}
|
||||
],
|
||||
"title": "getBar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"getBar"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
293
clang/test/ExtractAPI/multiple_inheritance.cpp
Normal file
293
clang/test/ExtractAPI/multiple_inheritance.cpp
Normal file
@@ -0,0 +1,293 @@
|
||||
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang++ -extract-api -target arm64-apple-macosx -x c++-header \
|
||||
// RUN: %t/input.h -o %t/output.json -Xclang -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
class Fizz {};
|
||||
|
||||
class Foo : public Fizz {};
|
||||
|
||||
class Bar : public Fizz {};
|
||||
|
||||
class FooBar : public Foo, public Bar{};
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [
|
||||
{
|
||||
"kind": "inheritsFrom",
|
||||
"source": "c:@S@Foo",
|
||||
"target": "c:@S@Fizz",
|
||||
"targetFallback": "Fizz"
|
||||
},
|
||||
{
|
||||
"kind": "inheritsFrom",
|
||||
"source": "c:@S@Bar",
|
||||
"target": "c:@S@Fizz",
|
||||
"targetFallback": "Fizz"
|
||||
},
|
||||
{
|
||||
"kind": "inheritsFrom",
|
||||
"source": "c:@S@FooBar",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "inheritsFrom",
|
||||
"source": "c:@S@FooBar",
|
||||
"target": "c:@S@Bar",
|
||||
"targetFallback": "Bar"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Fizz"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Fizz"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Fizz"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Fizz"
|
||||
}
|
||||
],
|
||||
"title": "Fizz"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Fizz"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Bar"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 5
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"title": "Bar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Bar"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "FooBar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@FooBar"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 7
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "FooBar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "FooBar"
|
||||
}
|
||||
],
|
||||
"title": "FooBar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"FooBar"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
210
clang/test/ExtractAPI/operator_overload.cpp
Normal file
210
clang/test/ExtractAPI/operator_overload.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang++ -extract-api -target arm64-apple-macosx -x c++-header \
|
||||
// RUN: %t/input.h -o %t/output.json -Xclang -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
class Foo {
|
||||
int operator+(int x);
|
||||
};
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@operator+#I#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "operator+"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "x"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "x"
|
||||
}
|
||||
],
|
||||
"name": "x"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@operator+#I#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Instance Method",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 2
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "operator+"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "operator+"
|
||||
}
|
||||
],
|
||||
"title": "operator+"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"operator+"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
162
clang/test/ExtractAPI/simple_inheritance.cpp
Normal file
162
clang/test/ExtractAPI/simple_inheritance.cpp
Normal file
@@ -0,0 +1,162 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang++ -extract-api -target arm64-apple-macosx -x c++-header \
|
||||
// RUN: %t/input.h -o %t/output.json -Xclang -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
class Foo {};
|
||||
|
||||
class Bar : public Foo {};
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [
|
||||
{
|
||||
"kind": "inheritsFrom",
|
||||
"source": "c:@S@Bar",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Bar"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"title": "Bar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Bar"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user