Skip to content

Commit

Permalink
[clang][ExtractAPI] Add support for C++ classes with fix
Browse files Browse the repository at this point in the history
Reintroduce D153557 with fix for use-after-free from f4de606 and minor changes.

Reviewed By: dang

Differential Revision: https://reviews.llvm.org/D157007
  • Loading branch information
evelez7 committed Aug 4, 2023
1 parent 5d49276 commit 75f55eb
Show file tree
Hide file tree
Showing 17 changed files with 3,261 additions and 48 deletions.
222 changes: 222 additions & 0 deletions clang/include/clang/ExtractAPI/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -266,6 +275,132 @@ struct StructRecord : APIRecord {
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.
Expand Down Expand Up @@ -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 {
Expand All @@ -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;
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -668,6 +849,41 @@ class APISet {
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
Expand Down Expand Up @@ -790,8 +1006,12 @@ class APISet {
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;
}
Expand Down Expand Up @@ -845,8 +1065,10 @@ class APISet {
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;
Expand Down

0 comments on commit 75f55eb

Please sign in to comment.