Skip to content

Commit d8e9c5d

Browse files
committed
[clang][ExtractAPI] Visit method templates with better scheme
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
1 parent 1094e2e commit d8e9c5d

File tree

8 files changed

+857
-1
lines changed

8 files changed

+857
-1
lines changed

clang/include/clang/ExtractAPI/API.h

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,8 @@ struct APIRecord {
180180
RK_CXXInstanceMethod,
181181
RK_CXXConstructorMethod,
182182
RK_CXXDestructorMethod,
183+
RK_CXXMethodTemplate,
184+
RK_CXXMethodTemplateSpecialization,
183185
RK_ObjCInstanceProperty,
184186
RK_ObjCClassProperty,
185187
RK_ObjCIvar,
@@ -623,6 +625,42 @@ struct CXXInstanceMethodRecord : CXXMethodRecord {
623625
virtual void anchor();
624626
};
625627

628+
struct CXXMethodTemplateRecord : CXXMethodRecord {
629+
Template Templ;
630+
631+
CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
632+
AvailabilitySet Availabilities,
633+
const DocComment &Comment,
634+
DeclarationFragments Declaration,
635+
DeclarationFragments SubHeading,
636+
FunctionSignature Signature, AccessControl Access,
637+
Template Template, bool IsFromSystemHeader)
638+
: CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc,
639+
std::move(Availabilities), Comment, Declaration,
640+
SubHeading, Signature, Access, IsFromSystemHeader),
641+
Templ(Template) {}
642+
643+
static bool classof(const APIRecord *Record) {
644+
return Record->getKind() == RK_CXXMethodTemplate;
645+
}
646+
};
647+
648+
struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
649+
CXXMethodTemplateSpecializationRecord(
650+
StringRef USR, StringRef Name, PresumedLoc Loc,
651+
AvailabilitySet Availabilities, const DocComment &Comment,
652+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
653+
FunctionSignature Signature, AccessControl Access,
654+
bool IsFromSystemHeader)
655+
: CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc,
656+
std::move(Availabilities), Comment, Declaration,
657+
SubHeading, Signature, Access, IsFromSystemHeader) {}
658+
659+
static bool classof(const APIRecord *Record) {
660+
return Record->getKind() == RK_CXXMethodTemplateSpecialization;
661+
}
662+
};
663+
626664
/// This holds information associated with Objective-C properties.
627665
struct ObjCPropertyRecord : APIRecord {
628666
/// The attributes associated with an Objective-C property.
@@ -794,6 +832,8 @@ struct SymbolReference {
794832
: Name(Name), USR(USR), Source(Source) {}
795833
SymbolReference(const APIRecord &Record)
796834
: Name(Record.Name), USR(Record.USR) {}
835+
SymbolReference(const APIRecord *Record)
836+
: Name(Record->Name), USR(Record->USR) {}
797837

798838
/// Determine if this SymbolReference is empty.
799839
///
@@ -1058,10 +1098,21 @@ template <>
10581098
struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
10591099
template <>
10601100
struct has_function_signature<CXXMethodRecord> : public std::true_type {};
1101+
template <>
1102+
struct has_function_signature<CXXMethodTemplateRecord> : public std::true_type {
1103+
};
1104+
template <>
1105+
struct has_function_signature<CXXMethodTemplateSpecializationRecord>
1106+
: public std::true_type {};
10611107

10621108
template <typename RecordTy> struct has_access : public std::false_type {};
10631109
template <> struct has_access<CXXMethodRecord> : public std::true_type {};
10641110
template <> struct has_access<CXXFieldRecord> : public std::true_type {};
1111+
template <>
1112+
struct has_access<CXXMethodTemplateRecord> : public std::true_type {};
1113+
template <>
1114+
struct has_access<CXXMethodTemplateSpecializationRecord>
1115+
: public std::true_type {};
10651116

10661117
template <typename RecordTy> struct has_template : public std::false_type {};
10671118
template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
@@ -1074,6 +1125,8 @@ struct has_template<GlobalVariableTemplateRecord> : public std::true_type {};
10741125
template <>
10751126
struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
10761127
: public std::true_type {};
1128+
template <>
1129+
struct has_template<CXXMethodTemplateRecord> : public std::true_type {};
10771130

10781131
template <>
10791132
struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
@@ -1253,6 +1306,20 @@ class APISet {
12531306
FunctionSignature Signature, bool IsConstructor, AccessControl Access,
12541307
bool IsFromSystemHeader);
12551308

1309+
CXXMethodTemplateRecord *addCXXMethodTemplate(
1310+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
1311+
AvailabilitySet Availability, const DocComment &Comment,
1312+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1313+
FunctionSignature Signature, AccessControl Access, Template Template,
1314+
bool IsFromSystemHeader);
1315+
1316+
CXXMethodTemplateSpecializationRecord *addCXXMethodTemplateSpec(
1317+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
1318+
AvailabilitySet Availability, const DocComment &Comment,
1319+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1320+
FunctionSignature Signature, AccessControl Access,
1321+
bool IsFromSystemHeader);
1322+
12561323
ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
12571324
AvailabilitySet Availability,
12581325
const DocComment &Comment,
@@ -1408,6 +1475,13 @@ class APISet {
14081475
const RecordMap<EnumRecord> &getEnums() const { return Enums; }
14091476
const RecordMap<StructRecord> &getStructs() const { return Structs; }
14101477
const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
1478+
const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const {
1479+
return CXXMethodTemplates;
1480+
}
1481+
const RecordMap<CXXMethodTemplateSpecializationRecord> &
1482+
getCXXMethodTemplateSpecializations() const {
1483+
return CXXMethodTemplateSpecializations;
1484+
}
14111485
const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
14121486
const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
14131487
return ClassTemplates;
@@ -1487,6 +1561,9 @@ class APISet {
14871561
RecordMap<EnumRecord> Enums;
14881562
RecordMap<StructRecord> Structs;
14891563
RecordMap<CXXClassRecord> CXXClasses;
1564+
RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates;
1565+
RecordMap<CXXMethodTemplateSpecializationRecord>
1566+
CXXMethodTemplateSpecializations;
14901567
RecordMap<ClassTemplateRecord> ClassTemplates;
14911568
RecordMap<ClassTemplateSpecializationRecord> ClassTemplateSpecializations;
14921569
RecordMap<ClassTemplatePartialSpecializationRecord>

clang/include/clang/ExtractAPI/ExtractAPIVisitor.h

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "clang/Basic/SourceManager.h"
2828
#include "clang/ExtractAPI/API.h"
2929
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
30+
#include "clang/Index/USRGeneration.h"
3031
#include "llvm/ADT/StringRef.h"
3132
#include <type_traits>
3233

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

5455
bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl);
5556

57+
bool WalkUpFromCXXMethodDecl(const CXXMethodDecl *Decl);
58+
5659
bool WalkUpFromClassTemplateSpecializationDecl(
5760
const ClassTemplateSpecializationDecl *Decl);
5861

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

7477
bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
7578

79+
bool VisitCXXMethodDecl(const CXXMethodDecl *Decl);
80+
7681
bool VisitConceptDecl(const ConceptDecl *Decl);
7782

7883
bool VisitClassTemplateSpecializationDecl(
@@ -287,11 +292,11 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
287292
switch (Decl->getTemplatedKind()) {
288293
case FunctionDecl::TK_NonTemplate:
289294
case FunctionDecl::TK_DependentNonTemplate:
290-
case FunctionDecl::TK_MemberSpecialization:
291295
case FunctionDecl::TK_FunctionTemplateSpecialization:
292296
break;
293297
case FunctionDecl::TK_FunctionTemplate:
294298
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
299+
case FunctionDecl::TK_MemberSpecialization:
295300
return true;
296301
}
297302

@@ -387,6 +392,13 @@ bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXRecordDecl(
387392
return true;
388393
}
389394

395+
template <typename Derived>
396+
bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXMethodDecl(
397+
const CXXMethodDecl *Decl) {
398+
getDerivedExtractAPIVisitor().VisitCXXMethodDecl(Decl);
399+
return true;
400+
}
401+
390402
template <typename Derived>
391403
bool ExtractAPIVisitorBase<Derived>::WalkUpFromClassTemplateSpecializationDecl(
392404
const ClassTemplateSpecializationDecl *Decl) {
@@ -521,6 +533,60 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
521533
return true;
522534
}
523535

536+
template <typename Derived>
537+
bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
538+
const CXXMethodDecl *Decl) {
539+
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
540+
Decl->isImplicit())
541+
return true;
542+
switch (Decl->getTemplatedKind()) {
543+
case FunctionDecl::TK_MemberSpecialization:
544+
case FunctionDecl::TK_FunctionTemplateSpecialization:
545+
case FunctionDecl::TK_FunctionTemplate:
546+
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
547+
break;
548+
case FunctionDecl::TK_NonTemplate:
549+
case FunctionDecl::TK_DependentNonTemplate:
550+
return true;
551+
}
552+
553+
StringRef Name = Decl->getName();
554+
StringRef USR = API.recordUSR(Decl);
555+
PresumedLoc Loc =
556+
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
557+
DocComment Comment;
558+
if (auto *RawComment =
559+
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
560+
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
561+
Context.getDiagnostics());
562+
DeclarationFragments SubHeading =
563+
DeclarationFragmentsBuilder::getSubHeading(Decl);
564+
565+
SmallString<128> ParentUSR;
566+
index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
567+
ParentUSR);
568+
if (Decl->isTemplated()) {
569+
FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate();
570+
API.addCXXMethodTemplate(
571+
API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl),
572+
Comment,
573+
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
574+
TemplateDecl),
575+
SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
576+
DeclarationFragmentsBuilder::getAccessControl(TemplateDecl),
577+
Template(TemplateDecl), isInSystemHeader(Decl));
578+
} else if (Decl->getTemplateSpecializationInfo())
579+
API.addCXXMethodTemplateSpec(
580+
API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl),
581+
Comment,
582+
DeclarationFragmentsBuilder::
583+
getFragmentsForFunctionTemplateSpecialization(Decl),
584+
SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
585+
DeclarationFragmentsBuilder::getAccessControl(Decl),
586+
isInSystemHeader(Decl));
587+
return true;
588+
}
589+
524590
template <typename Derived>
525591
bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
526592
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
@@ -712,6 +778,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
712778
template <typename Derived>
713779
bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
714780
const FunctionTemplateDecl *Decl) {
781+
if (isa<CXXMethodDecl>(Decl->getTemplatedDecl()))
782+
return true;
715783
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
716784
return true;
717785

@@ -1099,6 +1167,9 @@ void ExtractAPIVisitorBase<Derived>::recordCXXMethods(
10991167
continue;
11001168
}
11011169

1170+
if (Method->isFunctionTemplateSpecialization())
1171+
return;
1172+
11021173
StringRef Name;
11031174
DeclarationFragments Declaration;
11041175
if (Method->isOverloadedOperator()) {

clang/include/clang/ExtractAPI/Serialization/SerializerBase.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ template <typename Derived> class APISetVisitor {
3939

4040
getDerived()->traverseClassTemplatePartialSpecializationRecords();
4141

42+
getDerived()->traverseCXXMethodTemplates();
43+
44+
getDerived()->traverseCXXMethodTemplateSpecializations();
45+
4246
getDerived()->traverseConcepts();
4347

4448
getDerived()->traverseGlobalVariableTemplateRecords();
@@ -94,6 +98,18 @@ template <typename Derived> class APISetVisitor {
9498
getDerived()->visitCXXClassRecord(*Class.second);
9599
}
96100

101+
void traverseCXXMethodTemplates() {
102+
for (const auto &MethodTemplate : API.getCXXMethodTemplates())
103+
getDerived()->visitMethodTemplateRecord(*MethodTemplate.second);
104+
}
105+
106+
void traverseCXXMethodTemplateSpecializations() {
107+
for (const auto &MethodTemplateSpecialization :
108+
API.getCXXMethodTemplateSpecializations())
109+
getDerived()->visitMethodTemplateSpecializationRecord(
110+
*MethodTemplateSpecialization.second);
111+
}
112+
97113
void traverseClassTemplateRecords() {
98114
for (const auto &ClassTemplate : API.getClassTemplates())
99115
getDerived()->visitClassTemplateRecord(*ClassTemplate.second);
@@ -200,6 +216,11 @@ template <typename Derived> class APISetVisitor {
200216
void visitClassTemplatePartialSpecializationRecord(
201217
const ClassTemplatePartialSpecializationRecord &Record){};
202218

219+
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};
220+
221+
void visitMethodTemplateSpecializationRecord(
222+
const CXXMethodTemplateSpecializationRecord &Record){};
223+
203224
void visitGlobalVariableTemplateRecord(
204225
const GlobalVariableTemplateRecord &Record) {}
205226

clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,11 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
183183
void visitClassTemplatePartialSpecializationRecord(
184184
const ClassTemplatePartialSpecializationRecord &Record);
185185

186+
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
187+
188+
void visitMethodTemplateSpecializationRecord(
189+
const CXXMethodTemplateSpecializationRecord &Record);
190+
186191
void visitConceptRecord(const ConceptRecord &Record);
187192

188193
void

clang/lib/ExtractAPI/API.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,39 @@ CXXMethodRecord *APISet::addCXXSpecialMethod(
311311
return CXXClassRecord->Methods.emplace_back(std::move(Record)).get();
312312
}
313313

314+
CXXMethodTemplateRecord *APISet::addCXXMethodTemplate(
315+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
316+
AvailabilitySet Availability, const DocComment &Comment,
317+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
318+
FunctionSignature Signature, AccessControl Access, Template Template,
319+
bool IsFromSystemHeader) {
320+
auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR,
321+
Name, Loc, std::move(Availability), Comment,
322+
Declaration, SubHeading, Signature, Access,
323+
Template, IsFromSystemHeader);
324+
Record->ParentInformation = APIRecord::HierarchyInformation(
325+
Parent->USR, Parent->Name, Parent->getKind(), Parent);
326+
327+
return Record;
328+
}
329+
330+
CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec(
331+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
332+
AvailabilitySet Availability, const DocComment &Comment,
333+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
334+
FunctionSignature Signature, AccessControl Access,
335+
bool IsFromSystemHeader) {
336+
337+
auto *Record = addTopLevelRecord(
338+
USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc,
339+
std::move(Availability), Comment, Declaration, SubHeading, Signature,
340+
Access, IsFromSystemHeader);
341+
Record->ParentInformation = APIRecord::HierarchyInformation(
342+
Parent->USR, Parent->Name, Parent->getKind(), Parent);
343+
344+
return Record;
345+
}
346+
314347
ObjCCategoryRecord *APISet::addObjCCategory(
315348
StringRef Name, StringRef USR, PresumedLoc Loc,
316349
AvailabilitySet Availabilities, const DocComment &Comment,

0 commit comments

Comments
 (0)