Skip to content

Commit 0e67e5c

Browse files
evelez7daniel-grumberg
authored andcommitted
[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 d2529a2 commit 0e67e5c

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,
@@ -619,6 +621,42 @@ struct CXXInstanceMethodRecord : CXXMethodRecord {
619621
virtual void anchor();
620622
};
621623

624+
struct CXXMethodTemplateRecord : CXXMethodRecord {
625+
Template Templ;
626+
627+
CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
628+
AvailabilitySet Availabilities,
629+
const DocComment &Comment,
630+
DeclarationFragments Declaration,
631+
DeclarationFragments SubHeading,
632+
FunctionSignature Signature, AccessControl Access,
633+
Template Template, bool IsFromSystemHeader)
634+
: CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc,
635+
std::move(Availabilities), Comment, Declaration,
636+
SubHeading, Signature, Access, IsFromSystemHeader),
637+
Templ(Template) {}
638+
639+
static bool classof(const APIRecord *Record) {
640+
return Record->getKind() == RK_CXXMethodTemplate;
641+
}
642+
};
643+
644+
struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
645+
CXXMethodTemplateSpecializationRecord(
646+
StringRef USR, StringRef Name, PresumedLoc Loc,
647+
AvailabilitySet Availabilities, const DocComment &Comment,
648+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
649+
FunctionSignature Signature, AccessControl Access,
650+
bool IsFromSystemHeader)
651+
: CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc,
652+
std::move(Availabilities), Comment, Declaration,
653+
SubHeading, Signature, Access, IsFromSystemHeader) {}
654+
655+
static bool classof(const APIRecord *Record) {
656+
return Record->getKind() == RK_CXXMethodTemplateSpecialization;
657+
}
658+
};
659+
622660
/// This holds information associated with Objective-C properties.
623661
struct ObjCPropertyRecord : APIRecord {
624662
/// The attributes associated with an Objective-C property.
@@ -790,6 +828,8 @@ struct SymbolReference {
790828
: Name(Name), USR(USR), Source(Source) {}
791829
SymbolReference(const APIRecord &Record)
792830
: Name(Record.Name), USR(Record.USR) {}
831+
SymbolReference(const APIRecord *Record)
832+
: Name(Record->Name), USR(Record->USR) {}
793833

794834
/// Determine if this SymbolReference is empty.
795835
///
@@ -1052,10 +1092,21 @@ template <>
10521092
struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
10531093
template <>
10541094
struct has_function_signature<CXXMethodRecord> : public std::true_type {};
1095+
template <>
1096+
struct has_function_signature<CXXMethodTemplateRecord> : public std::true_type {
1097+
};
1098+
template <>
1099+
struct has_function_signature<CXXMethodTemplateSpecializationRecord>
1100+
: public std::true_type {};
10551101

10561102
template <typename RecordTy> struct has_access : public std::false_type {};
10571103
template <> struct has_access<CXXMethodRecord> : public std::true_type {};
10581104
template <> struct has_access<CXXFieldRecord> : public std::true_type {};
1105+
template <>
1106+
struct has_access<CXXMethodTemplateRecord> : public std::true_type {};
1107+
template <>
1108+
struct has_access<CXXMethodTemplateSpecializationRecord>
1109+
: public std::true_type {};
10591110

10601111
template <typename RecordTy> struct has_template : public std::false_type {};
10611112
template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
@@ -1068,6 +1119,8 @@ struct has_template<GlobalVariableTemplateRecord> : public std::true_type {};
10681119
template <>
10691120
struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
10701121
: public std::true_type {};
1122+
template <>
1123+
struct has_template<CXXMethodTemplateRecord> : public std::true_type {};
10711124

10721125
template <>
10731126
struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
@@ -1247,6 +1300,20 @@ class APISet {
12471300
FunctionSignature Signature, bool IsConstructor, AccessControl Access,
12481301
bool IsFromSystemHeader);
12491302

1303+
CXXMethodTemplateRecord *addCXXMethodTemplate(
1304+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
1305+
AvailabilitySet Availability, const DocComment &Comment,
1306+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1307+
FunctionSignature Signature, AccessControl Access, Template Template,
1308+
bool IsFromSystemHeader);
1309+
1310+
CXXMethodTemplateSpecializationRecord *addCXXMethodTemplateSpec(
1311+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
1312+
AvailabilitySet Availability, const DocComment &Comment,
1313+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1314+
FunctionSignature Signature, AccessControl Access,
1315+
bool IsFromSystemHeader);
1316+
12501317
ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
12511318
AvailabilitySet Availability,
12521319
const DocComment &Comment,
@@ -1402,6 +1469,13 @@ class APISet {
14021469
const RecordMap<EnumRecord> &getEnums() const { return Enums; }
14031470
const RecordMap<StructRecord> &getStructs() const { return Structs; }
14041471
const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
1472+
const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const {
1473+
return CXXMethodTemplates;
1474+
}
1475+
const RecordMap<CXXMethodTemplateSpecializationRecord> &
1476+
getCXXMethodTemplateSpecializations() const {
1477+
return CXXMethodTemplateSpecializations;
1478+
}
14051479
const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
14061480
const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
14071481
return ClassTemplates;
@@ -1481,6 +1555,9 @@ class APISet {
14811555
RecordMap<EnumRecord> Enums;
14821556
RecordMap<StructRecord> Structs;
14831557
RecordMap<CXXClassRecord> CXXClasses;
1558+
RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates;
1559+
RecordMap<CXXMethodTemplateSpecializationRecord>
1560+
CXXMethodTemplateSpecializations;
14841561
RecordMap<ClassTemplateRecord> ClassTemplates;
14851562
RecordMap<ClassTemplateSpecializationRecord> ClassTemplateSpecializations;
14861563
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

@@ -1091,6 +1159,9 @@ void ExtractAPIVisitorBase<Derived>::recordCXXMethods(
10911159
continue;
10921160
}
10931161

1162+
if (Method->isFunctionTemplateSpecialization())
1163+
return;
1164+
10941165
StringRef Name;
10951166
DeclarationFragments Declaration;
10961167
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();
@@ -92,6 +96,18 @@ template <typename Derived> class APISetVisitor {
9296
getDerived()->visitCXXClassRecord(*Class.second);
9397
}
9498

99+
void traverseCXXMethodTemplates() {
100+
for (const auto &MethodTemplate : API.getCXXMethodTemplates())
101+
getDerived()->visitMethodTemplateRecord(*MethodTemplate.second);
102+
}
103+
104+
void traverseCXXMethodTemplateSpecializations() {
105+
for (const auto &MethodTemplateSpecialization :
106+
API.getCXXMethodTemplateSpecializations())
107+
getDerived()->visitMethodTemplateSpecializationRecord(
108+
*MethodTemplateSpecialization.second);
109+
}
110+
95111
void traverseClassTemplateRecords() {
96112
for (const auto &ClassTemplate : API.getClassTemplates())
97113
getDerived()->visitClassTemplateRecord(*ClassTemplate.second);
@@ -193,6 +209,11 @@ template <typename Derived> class APISetVisitor {
193209
void visitClassTemplatePartialSpecializationRecord(
194210
const ClassTemplatePartialSpecializationRecord &Record){};
195211

212+
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};
213+
214+
void visitMethodTemplateSpecializationRecord(
215+
const CXXMethodTemplateSpecializationRecord &Record){};
216+
196217
void visitGlobalVariableTemplateRecord(
197218
const GlobalVariableTemplateRecord &Record) {}
198219

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

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

179+
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
180+
181+
void visitMethodTemplateSpecializationRecord(
182+
const CXXMethodTemplateSpecializationRecord &Record);
183+
179184
void visitConceptRecord(const ConceptRecord &Record);
180185

181186
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)