Skip to content

Commit cd3f992

Browse files
evelez7daniel-grumberg
authored andcommitted
[clang][ExtractAPI] Add support for C++ member templates
Visit and serialize C++ fields by checking if a var template's context is a CXXRecordDecl in VisitVarTemplateDecl. Depends on D158027 Reviewed By: dang Differential Revision: https://reviews.llvm.org/D158029
1 parent 0e67e5c commit cd3f992

File tree

8 files changed

+308
-11
lines changed

8 files changed

+308
-11
lines changed

clang/include/clang/ExtractAPI/API.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ struct APIRecord {
171171
RK_Union,
172172
RK_StaticField,
173173
RK_CXXField,
174+
RK_CXXFieldTemplate,
174175
RK_CXXClass,
175176
RK_ClassTemplate,
176177
RK_ClassTemplateSpecialization,
@@ -526,6 +527,25 @@ struct CXXFieldRecord : APIRecord {
526527
virtual void anchor();
527528
};
528529

530+
struct CXXFieldTemplateRecord : CXXFieldRecord {
531+
Template Templ;
532+
533+
CXXFieldTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
534+
AvailabilitySet Availabilities,
535+
const DocComment &Comment,
536+
DeclarationFragments Declaration,
537+
DeclarationFragments SubHeading, AccessControl Access,
538+
Template Template, bool IsFromSystemHeader)
539+
: CXXFieldRecord(RK_CXXFieldTemplate, USR, Name, Loc,
540+
std::move(Availabilities), Comment, Declaration,
541+
SubHeading, Access, IsFromSystemHeader),
542+
Templ(Template) {}
543+
544+
static bool classof(const APIRecord *Record) {
545+
return Record->getKind() == RK_CXXFieldTemplate;
546+
}
547+
};
548+
529549
struct CXXMethodRecord : APIRecord {
530550
FunctionSignature Signature;
531551
AccessControl Access;
@@ -1107,6 +1127,8 @@ struct has_access<CXXMethodTemplateRecord> : public std::true_type {};
11071127
template <>
11081128
struct has_access<CXXMethodTemplateSpecializationRecord>
11091129
: public std::true_type {};
1130+
template <>
1131+
struct has_access<CXXFieldTemplateRecord> : public std::true_type {};
11101132

11111133
template <typename RecordTy> struct has_template : public std::false_type {};
11121134
template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
@@ -1121,6 +1143,8 @@ struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
11211143
: public std::true_type {};
11221144
template <>
11231145
struct has_template<CXXMethodTemplateRecord> : public std::true_type {};
1146+
template <>
1147+
struct has_template<CXXFieldTemplateRecord> : public std::true_type {};
11241148

11251149
template <>
11261150
struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
@@ -1245,6 +1269,12 @@ class APISet {
12451269
DeclarationFragments SubHeading,
12461270
AccessControl Access, bool IsFromSystemHeader);
12471271

1272+
CXXFieldTemplateRecord *addCXXFieldTemplate(
1273+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
1274+
AvailabilitySet Availability, const DocComment &Comment,
1275+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1276+
AccessControl Access, Template Template, bool IsFromSystemHeader);
1277+
12481278
CXXClassRecord *
12491279
addCXXClass(StringRef Name, StringRef USR, PresumedLoc Loc,
12501280
AvailabilitySet Availability, const DocComment &Comment,
@@ -1476,6 +1506,9 @@ class APISet {
14761506
getCXXMethodTemplateSpecializations() const {
14771507
return CXXMethodTemplateSpecializations;
14781508
}
1509+
const RecordMap<CXXFieldTemplateRecord> &getCXXFieldTemplates() const {
1510+
return CXXFieldTemplates;
1511+
}
14791512
const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
14801513
const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
14811514
return ClassTemplates;
@@ -1558,6 +1591,7 @@ class APISet {
15581591
RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates;
15591592
RecordMap<CXXMethodTemplateSpecializationRecord>
15601593
CXXMethodTemplateSpecializations;
1594+
RecordMap<CXXFieldTemplateRecord> CXXFieldTemplates;
15611595
RecordMap<ClassTemplateRecord> ClassTemplates;
15621596
RecordMap<ClassTemplateSpecializationRecord> ClassTemplateSpecializations;
15631597
RecordMap<ClassTemplatePartialSpecializationRecord>

clang/include/clang/ExtractAPI/ExtractAPIVisitor.h

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -697,20 +697,29 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplateDecl(
697697
Context.getDiagnostics());
698698

699699
// Build declaration fragments and sub-heading for the variable.
700-
DeclarationFragments Declaration =
701-
DeclarationFragmentsBuilder::getFragmentsForVarTemplate(
702-
Decl->getTemplatedDecl());
700+
DeclarationFragments Declaration;
701+
Declaration
702+
.append(DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
703+
Decl))
704+
.append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(
705+
Decl->getTemplatedDecl()));
706+
// Inject template fragments before var fragments.
703707
DeclarationFragments SubHeading =
704708
DeclarationFragmentsBuilder::getSubHeading(Decl);
705709

706-
// Inject template fragments before var fragments.
707-
Declaration.insert(
708-
Declaration.begin(),
709-
DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(Decl));
710-
711-
API.addGlobalVariableTemplate(Name, USR, Loc, AvailabilitySet(Decl), Linkage,
712-
Comment, Declaration, SubHeading,
713-
Template(Decl), isInSystemHeader(Decl));
710+
SmallString<128> ParentUSR;
711+
index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
712+
ParentUSR);
713+
if (Decl->getDeclContext()->getDeclKind() == Decl::CXXRecord)
714+
API.addCXXFieldTemplate(API.findRecordForUSR(ParentUSR), Name, USR, Loc,
715+
AvailabilitySet(Decl), Comment, Declaration,
716+
SubHeading,
717+
DeclarationFragmentsBuilder::getAccessControl(Decl),
718+
Template(Decl), isInSystemHeader(Decl));
719+
else
720+
API.addGlobalVariableTemplate(Name, USR, Loc, AvailabilitySet(Decl),
721+
Linkage, Comment, Declaration, SubHeading,
722+
Template(Decl), isInSystemHeader(Decl));
714723
return true;
715724
}
716725

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ template <typename Derived> class APISetVisitor {
4343

4444
getDerived()->traverseCXXMethodTemplateSpecializations();
4545

46+
getDerived()->traverseCXXFieldTemplates();
47+
4648
getDerived()->traverseConcepts();
4749

4850
getDerived()->traverseGlobalVariableTemplateRecords();
@@ -127,6 +129,11 @@ template <typename Derived> class APISetVisitor {
127129
*ClassTemplatePartialSpecialization.second);
128130
}
129131

132+
void traverseCXXFieldTemplates() {
133+
for (const auto &CXXFieldTemplate : API.getCXXFieldTemplates())
134+
getDerived()->visitCXXFieldTemplateRecord(*CXXFieldTemplate.second);
135+
}
136+
130137
void traverseGlobalVariableTemplateRecords() {
131138
for (const auto &GlobalVariableTemplate : API.getGlobalVariableTemplates())
132139
getDerived()->visitGlobalVariableTemplateRecord(
@@ -214,6 +221,8 @@ template <typename Derived> class APISetVisitor {
214221
void visitMethodTemplateSpecializationRecord(
215222
const CXXMethodTemplateSpecializationRecord &Record){};
216223

224+
void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record){};
225+
217226
void visitGlobalVariableTemplateRecord(
218227
const GlobalVariableTemplateRecord &Record) {}
219228

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,8 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
181181
void visitMethodTemplateSpecializationRecord(
182182
const CXXMethodTemplateSpecializationRecord &Record);
183183

184+
void visitCXXFieldTemplateRecord(const CXXFieldTemplateRecord &Record);
185+
184186
void visitConceptRecord(const ConceptRecord &Record);
185187

186188
void

clang/lib/ExtractAPI/API.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,21 @@ APISet::addCXXField(CXXClassRecord *CXXClass, StringRef Name, StringRef USR,
185185
return CXXClass->Fields.emplace_back(std::move(Record)).get();
186186
}
187187

188+
CXXFieldTemplateRecord *APISet::addCXXFieldTemplate(
189+
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
190+
AvailabilitySet Availability, const DocComment &Comment,
191+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
192+
AccessControl Access, Template Template, bool IsFromSystemHeader) {
193+
auto *Record =
194+
addTopLevelRecord(USRBasedLookupTable, CXXFieldTemplates, USR, Name, Loc,
195+
std::move(Availability), Comment, Declaration,
196+
SubHeading, Access, Template, IsFromSystemHeader);
197+
Record->ParentInformation = APIRecord::HierarchyInformation(
198+
Parent->USR, Parent->Name, Parent->getKind(), Parent);
199+
200+
return Record;
201+
}
202+
188203
CXXClassRecord *
189204
APISet::addCXXClass(StringRef Name, StringRef USR, PresumedLoc Loc,
190205
AvailabilitySet Availabilities, const DocComment &Comment,

clang/lib/ExtractAPI/DeclarationFragments.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,11 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
512512
? Var->getTypeSourceInfo()->getType()
513513
: Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
514514

515+
// Might be a member, so might be static.
516+
if (Var->isStaticDataMember())
517+
Fragments.append("static", DeclarationFragments::FragmentKind::Keyword)
518+
.appendSpace();
519+
515520
DeclarationFragments After;
516521
DeclarationFragments ArgumentFragment =
517522
getFragmentsForType(T, Var->getASTContext(), After);

clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,10 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
422422
Kind["identifier"] = AddLangPrefix("method");
423423
Kind["displayName"] = "Method Template Specialization";
424424
break;
425+
case APIRecord::RK_CXXFieldTemplate:
426+
Kind["identifier"] = AddLangPrefix("property");
427+
Kind["displayName"] = "Template Property";
428+
break;
425429
case APIRecord::RK_Concept:
426430
Kind["identifier"] = AddLangPrefix("concept");
427431
Kind["displayName"] = "Concept";
@@ -943,6 +947,19 @@ void SymbolGraphSerializer::visitMethodTemplateSpecializationRecord(
943947
Record.ParentInformation.ParentRecord);
944948
}
945949

950+
void SymbolGraphSerializer::visitCXXFieldTemplateRecord(
951+
const CXXFieldTemplateRecord &Record) {
952+
if (!ShouldRecurse)
953+
// Ignore child symbols
954+
return;
955+
auto CXXFieldTemplate = serializeAPIRecord(Record);
956+
if (!CXXFieldTemplate)
957+
return;
958+
Symbols.emplace_back(std::move(*CXXFieldTemplate));
959+
serializeRelationship(RelationshipKind::MemberOf, Record,
960+
Record.ParentInformation.ParentRecord);
961+
}
962+
946963
void SymbolGraphSerializer::visitConceptRecord(const ConceptRecord &Record) {
947964
auto Concept = serializeAPIRecord(Record);
948965
if (!Concept)

0 commit comments

Comments
 (0)