Skip to content

Commit

Permalink
[clang][ExtractAPI] Visit method templates with better scheme
Browse files Browse the repository at this point in the history
Visit and serialize method templates and template specializations. Introduces a new scheme of visiting child Decls via VisitCXXMethodDecl which will be followed in future patches for Fields and non-template methods.

Depends on D157579

Reviewed By: dang

Differential Revision: https://reviews.llvm.org/D158027
  • Loading branch information
evelez7 committed Aug 21, 2023
1 parent 1094e2e commit d8e9c5d
Show file tree
Hide file tree
Showing 8 changed files with 857 additions and 1 deletion.
77 changes: 77 additions & 0 deletions clang/include/clang/ExtractAPI/API.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,8 @@ struct APIRecord {
RK_CXXInstanceMethod,
RK_CXXConstructorMethod,
RK_CXXDestructorMethod,
RK_CXXMethodTemplate,
RK_CXXMethodTemplateSpecialization,
RK_ObjCInstanceProperty,
RK_ObjCClassProperty,
RK_ObjCIvar,
Expand Down Expand Up @@ -623,6 +625,42 @@ struct CXXInstanceMethodRecord : CXXMethodRecord {
virtual void anchor();
};

struct CXXMethodTemplateRecord : CXXMethodRecord {
Template Templ;

CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities,
const DocComment &Comment,
DeclarationFragments Declaration,
DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
Template Template, bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader),
Templ(Template) {}

static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_CXXMethodTemplate;
}
};

struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
CXXMethodTemplateSpecializationRecord(
StringRef USR, StringRef Name, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader)
: CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc,
std::move(Availabilities), Comment, Declaration,
SubHeading, Signature, Access, IsFromSystemHeader) {}

static bool classof(const APIRecord *Record) {
return Record->getKind() == RK_CXXMethodTemplateSpecialization;
}
};

/// This holds information associated with Objective-C properties.
struct ObjCPropertyRecord : APIRecord {
/// The attributes associated with an Objective-C property.
Expand Down Expand Up @@ -794,6 +832,8 @@ struct SymbolReference {
: Name(Name), USR(USR), Source(Source) {}
SymbolReference(const APIRecord &Record)
: Name(Record.Name), USR(Record.USR) {}
SymbolReference(const APIRecord *Record)
: Name(Record->Name), USR(Record->USR) {}

/// Determine if this SymbolReference is empty.
///
Expand Down Expand Up @@ -1058,10 +1098,21 @@ template <>
struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
template <>
struct has_function_signature<CXXMethodRecord> : public std::true_type {};
template <>
struct has_function_signature<CXXMethodTemplateRecord> : public std::true_type {
};
template <>
struct has_function_signature<CXXMethodTemplateSpecializationRecord>
: 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 {};
template <>
struct has_access<CXXMethodTemplateRecord> : public std::true_type {};
template <>
struct has_access<CXXMethodTemplateSpecializationRecord>
: public std::true_type {};

template <typename RecordTy> struct has_template : public std::false_type {};
template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
Expand All @@ -1074,6 +1125,8 @@ struct has_template<GlobalVariableTemplateRecord> : public std::true_type {};
template <>
struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
: public std::true_type {};
template <>
struct has_template<CXXMethodTemplateRecord> : public std::true_type {};

template <>
struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
Expand Down Expand Up @@ -1253,6 +1306,20 @@ class APISet {
FunctionSignature Signature, bool IsConstructor, AccessControl Access,
bool IsFromSystemHeader);

CXXMethodTemplateRecord *addCXXMethodTemplate(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access, Template Template,
bool IsFromSystemHeader);

CXXMethodTemplateSpecializationRecord *addCXXMethodTemplateSpec(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader);

ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability,
const DocComment &Comment,
Expand Down Expand Up @@ -1408,6 +1475,13 @@ class APISet {
const RecordMap<EnumRecord> &getEnums() const { return Enums; }
const RecordMap<StructRecord> &getStructs() const { return Structs; }
const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const {
return CXXMethodTemplates;
}
const RecordMap<CXXMethodTemplateSpecializationRecord> &
getCXXMethodTemplateSpecializations() const {
return CXXMethodTemplateSpecializations;
}
const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
return ClassTemplates;
Expand Down Expand Up @@ -1487,6 +1561,9 @@ class APISet {
RecordMap<EnumRecord> Enums;
RecordMap<StructRecord> Structs;
RecordMap<CXXClassRecord> CXXClasses;
RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates;
RecordMap<CXXMethodTemplateSpecializationRecord>
CXXMethodTemplateSpecializations;
RecordMap<ClassTemplateRecord> ClassTemplates;
RecordMap<ClassTemplateSpecializationRecord> ClassTemplateSpecializations;
RecordMap<ClassTemplatePartialSpecializationRecord>
Expand Down
73 changes: 72 additions & 1 deletion clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include "clang/Basic/SourceManager.h"
#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringRef.h"
#include <type_traits>

Expand All @@ -53,6 +54,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {

bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl);

bool WalkUpFromCXXMethodDecl(const CXXMethodDecl *Decl);

bool WalkUpFromClassTemplateSpecializationDecl(
const ClassTemplateSpecializationDecl *Decl);

Expand All @@ -73,6 +76,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {

bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);

bool VisitCXXMethodDecl(const CXXMethodDecl *Decl);

bool VisitConceptDecl(const ConceptDecl *Decl);

bool VisitClassTemplateSpecializationDecl(
Expand Down Expand Up @@ -287,11 +292,11 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
switch (Decl->getTemplatedKind()) {
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_DependentNonTemplate:
case FunctionDecl::TK_MemberSpecialization:
case FunctionDecl::TK_FunctionTemplateSpecialization:
break;
case FunctionDecl::TK_FunctionTemplate:
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
case FunctionDecl::TK_MemberSpecialization:
return true;
}

Expand Down Expand Up @@ -387,6 +392,13 @@ bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXRecordDecl(
return true;
}

template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXMethodDecl(
const CXXMethodDecl *Decl) {
getDerivedExtractAPIVisitor().VisitCXXMethodDecl(Decl);
return true;
}

template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::WalkUpFromClassTemplateSpecializationDecl(
const ClassTemplateSpecializationDecl *Decl) {
Expand Down Expand Up @@ -521,6 +533,60 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
return true;
}

template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
const CXXMethodDecl *Decl) {
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
Decl->isImplicit())
return true;
switch (Decl->getTemplatedKind()) {
case FunctionDecl::TK_MemberSpecialization:
case FunctionDecl::TK_FunctionTemplateSpecialization:
case FunctionDecl::TK_FunctionTemplate:
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
break;
case FunctionDecl::TK_NonTemplate:
case FunctionDecl::TK_DependentNonTemplate:
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 SubHeading =
DeclarationFragmentsBuilder::getSubHeading(Decl);

SmallString<128> ParentUSR;
index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
ParentUSR);
if (Decl->isTemplated()) {
FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate();
API.addCXXMethodTemplate(
API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl),
Comment,
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
TemplateDecl),
SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
DeclarationFragmentsBuilder::getAccessControl(TemplateDecl),
Template(TemplateDecl), isInSystemHeader(Decl));
} else if (Decl->getTemplateSpecializationInfo())
API.addCXXMethodTemplateSpec(
API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl),
Comment,
DeclarationFragmentsBuilder::
getFragmentsForFunctionTemplateSpecialization(Decl),
SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
DeclarationFragmentsBuilder::getAccessControl(Decl),
isInSystemHeader(Decl));
return true;
}

template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
Expand Down Expand Up @@ -712,6 +778,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
const FunctionTemplateDecl *Decl) {
if (isa<CXXMethodDecl>(Decl->getTemplatedDecl()))
return true;
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
return true;

Expand Down Expand Up @@ -1099,6 +1167,9 @@ void ExtractAPIVisitorBase<Derived>::recordCXXMethods(
continue;
}

if (Method->isFunctionTemplateSpecialization())
return;

StringRef Name;
DeclarationFragments Declaration;
if (Method->isOverloadedOperator()) {
Expand Down
21 changes: 21 additions & 0 deletions clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ template <typename Derived> class APISetVisitor {

getDerived()->traverseClassTemplatePartialSpecializationRecords();

getDerived()->traverseCXXMethodTemplates();

getDerived()->traverseCXXMethodTemplateSpecializations();

getDerived()->traverseConcepts();

getDerived()->traverseGlobalVariableTemplateRecords();
Expand Down Expand Up @@ -94,6 +98,18 @@ template <typename Derived> class APISetVisitor {
getDerived()->visitCXXClassRecord(*Class.second);
}

void traverseCXXMethodTemplates() {
for (const auto &MethodTemplate : API.getCXXMethodTemplates())
getDerived()->visitMethodTemplateRecord(*MethodTemplate.second);
}

void traverseCXXMethodTemplateSpecializations() {
for (const auto &MethodTemplateSpecialization :
API.getCXXMethodTemplateSpecializations())
getDerived()->visitMethodTemplateSpecializationRecord(
*MethodTemplateSpecialization.second);
}

void traverseClassTemplateRecords() {
for (const auto &ClassTemplate : API.getClassTemplates())
getDerived()->visitClassTemplateRecord(*ClassTemplate.second);
Expand Down Expand Up @@ -200,6 +216,11 @@ template <typename Derived> class APISetVisitor {
void visitClassTemplatePartialSpecializationRecord(
const ClassTemplatePartialSpecializationRecord &Record){};

void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};

void visitMethodTemplateSpecializationRecord(
const CXXMethodTemplateSpecializationRecord &Record){};

void visitGlobalVariableTemplateRecord(
const GlobalVariableTemplateRecord &Record) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,11 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
void visitClassTemplatePartialSpecializationRecord(
const ClassTemplatePartialSpecializationRecord &Record);

void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);

void visitMethodTemplateSpecializationRecord(
const CXXMethodTemplateSpecializationRecord &Record);

void visitConceptRecord(const ConceptRecord &Record);

void
Expand Down
33 changes: 33 additions & 0 deletions clang/lib/ExtractAPI/API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,39 @@ CXXMethodRecord *APISet::addCXXSpecialMethod(
return CXXClassRecord->Methods.emplace_back(std::move(Record)).get();
}

CXXMethodTemplateRecord *APISet::addCXXMethodTemplate(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access, Template Template,
bool IsFromSystemHeader) {
auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR,
Name, Loc, std::move(Availability), Comment,
Declaration, SubHeading, Signature, Access,
Template, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);

return Record;
}

CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec(
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availability, const DocComment &Comment,
DeclarationFragments Declaration, DeclarationFragments SubHeading,
FunctionSignature Signature, AccessControl Access,
bool IsFromSystemHeader) {

auto *Record = addTopLevelRecord(
USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc,
std::move(Availability), Comment, Declaration, SubHeading, Signature,
Access, IsFromSystemHeader);
Record->ParentInformation = APIRecord::HierarchyInformation(
Parent->USR, Parent->Name, Parent->getKind(), Parent);

return Record;
}

ObjCCategoryRecord *APISet::addObjCCategory(
StringRef Name, StringRef USR, PresumedLoc Loc,
AvailabilitySet Availabilities, const DocComment &Comment,
Expand Down

0 comments on commit d8e9c5d

Please sign in to comment.