Skip to content

Commit 80b787e

Browse files
committed
[clang][ExtractAPI] Add support for C++ global function templates
Add records, serialization for global function templates and their specializations Depends on D157350 Reviewed By: dang Differential Revision: https://reviews.llvm.org/D157579
1 parent 3e56988 commit 80b787e

File tree

10 files changed

+920
-22
lines changed

10 files changed

+920
-22
lines changed

clang/include/clang/ExtractAPI/API.h

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,8 @@ struct APIRecord {
158158
enum RecordKind {
159159
RK_Unknown,
160160
RK_GlobalFunction,
161+
RK_GlobalFunctionTemplate,
162+
RK_GlobalFunctionTemplateSpecialization,
161163
RK_GlobalVariable,
162164
RK_GlobalVariableTemplate,
163165
RK_GlobalVariableTemplateSpecialization,
@@ -281,6 +283,16 @@ struct GlobalFunctionRecord : APIRecord {
281283
IsFromSystemHeader),
282284
Signature(Signature) {}
283285

286+
GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
287+
PresumedLoc Loc, AvailabilitySet Availabilities,
288+
LinkageInfo Linkage, const DocComment &Comment,
289+
DeclarationFragments Declaration,
290+
DeclarationFragments SubHeading,
291+
FunctionSignature Signature, bool IsFromSystemHeader)
292+
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), Linkage,
293+
Comment, Declaration, SubHeading, IsFromSystemHeader),
294+
Signature(Signature) {}
295+
284296
static bool classof(const APIRecord *Record) {
285297
return Record->getKind() == RK_GlobalFunction;
286298
}
@@ -289,6 +301,44 @@ struct GlobalFunctionRecord : APIRecord {
289301
virtual void anchor();
290302
};
291303

304+
struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
305+
Template Templ;
306+
307+
GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
308+
AvailabilitySet Availabilities,
309+
LinkageInfo Linkage, const DocComment &Comment,
310+
DeclarationFragments Declaration,
311+
DeclarationFragments SubHeading,
312+
FunctionSignature Signature, Template Template,
313+
bool IsFromSystemHeader)
314+
: GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Loc,
315+
std::move(Availabilities), Linkage, Comment,
316+
Declaration, SubHeading, Signature,
317+
IsFromSystemHeader),
318+
Templ(Template) {}
319+
320+
static bool classof(const APIRecord *Record) {
321+
return Record->getKind() == RK_GlobalFunctionTemplate;
322+
}
323+
};
324+
325+
struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
326+
GlobalFunctionTemplateSpecializationRecord(
327+
StringRef USR, StringRef Name, PresumedLoc Loc,
328+
AvailabilitySet Availabilities, LinkageInfo Linkage,
329+
const DocComment &Comment, DeclarationFragments Declaration,
330+
DeclarationFragments SubHeading, FunctionSignature Signature,
331+
bool IsFromSystemHeader)
332+
: GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
333+
Loc, std::move(Availabilities), Linkage, Comment,
334+
Declaration, SubHeading, Signature,
335+
IsFromSystemHeader) {}
336+
337+
static bool classof(const APIRecord *Record) {
338+
return Record->getKind() == RK_GlobalFunctionTemplateSpecialization;
339+
}
340+
};
341+
292342
/// This holds information associated with global functions.
293343
struct GlobalVariableRecord : APIRecord {
294344
GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
@@ -1025,6 +1075,15 @@ template <>
10251075
struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
10261076
: public std::true_type {};
10271077

1078+
template <>
1079+
struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
1080+
template <>
1081+
struct has_function_signature<GlobalFunctionTemplateRecord>
1082+
: public std::true_type {};
1083+
template <>
1084+
struct has_function_signature<GlobalFunctionTemplateSpecializationRecord>
1085+
: public std::true_type {};
1086+
10281087
/// APISet holds the set of API records collected from given inputs.
10291088
class APISet {
10301089
public:
@@ -1061,6 +1120,21 @@ class APISet {
10611120
DeclarationFragments SubHeading,
10621121
FunctionSignature Signature, bool IsFromSystemHeader);
10631122

1123+
GlobalFunctionTemplateRecord *addGlobalFunctionTemplate(
1124+
StringRef Name, StringRef USR, PresumedLoc Loc,
1125+
AvailabilitySet Availability, LinkageInfo Linkage,
1126+
const DocComment &Comment, DeclarationFragments Declaration,
1127+
DeclarationFragments SubHeading, FunctionSignature Signature,
1128+
Template Template, bool IsFromSystemHeader);
1129+
1130+
GlobalFunctionTemplateSpecializationRecord *
1131+
addGlobalFunctionTemplateSpecialization(
1132+
StringRef Name, StringRef USR, PresumedLoc Loc,
1133+
AvailabilitySet Availability, LinkageInfo Linkage,
1134+
const DocComment &Comment, DeclarationFragments Declaration,
1135+
DeclarationFragments SubHeading, FunctionSignature Signature,
1136+
bool IsFromSystemHeader);
1137+
10641138
/// Create and add an enum constant record into the API set.
10651139
///
10661140
/// Note: the caller is responsible for keeping the StringRef \p Name and
@@ -1305,6 +1379,14 @@ class APISet {
13051379
const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
13061380
return GlobalFunctions;
13071381
}
1382+
const RecordMap<GlobalFunctionTemplateRecord> &
1383+
getGlobalFunctionTemplates() const {
1384+
return GlobalFunctionTemplates;
1385+
}
1386+
const RecordMap<GlobalFunctionTemplateSpecializationRecord> &
1387+
getGlobalFunctionTemplateSpecializations() const {
1388+
return GlobalFunctionTemplateSpecializations;
1389+
}
13081390
const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
13091391
return GlobalVariables;
13101392
}
@@ -1391,6 +1473,9 @@ class APISet {
13911473

13921474
llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
13931475
RecordMap<GlobalFunctionRecord> GlobalFunctions;
1476+
RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates;
1477+
RecordMap<GlobalFunctionTemplateSpecializationRecord>
1478+
GlobalFunctionTemplateSpecializations;
13941479
RecordMap<GlobalVariableRecord> GlobalVariables;
13951480
RecordMap<GlobalVariableTemplateRecord> GlobalVariableTemplates;
13961481
RecordMap<GlobalVariableTemplateSpecializationRecord>

clang/include/clang/ExtractAPI/DeclarationFragments.h

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -306,8 +306,8 @@ class DeclarationFragmentsBuilder {
306306
static DeclarationFragments
307307
getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>);
308308

309-
static std::string getNameForTemplateArgument(const ArrayRef<NamedDecl *>,
310-
std::string);
309+
static std::string
310+
getNameForTemplateArgument(const ArrayRef<NamedDecl *>, std::string);
311311

312312
static DeclarationFragments
313313
getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument>,
@@ -331,6 +331,12 @@ class DeclarationFragmentsBuilder {
331331
static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization(
332332
const VarTemplatePartialSpecializationDecl *);
333333

334+
static DeclarationFragments
335+
getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl);
336+
337+
static DeclarationFragments
338+
getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl);
339+
334340
/// Build DeclarationFragments for an Objective-C category declaration
335341
/// ObjCCategoryDecl.
336342
static DeclarationFragments
@@ -405,10 +411,21 @@ DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
405411
FunctionSignature Signature;
406412

407413
DeclarationFragments ReturnType, After;
408-
ReturnType
409-
.append(getFragmentsForType(Function->getReturnType(),
410-
Function->getASTContext(), After))
411-
.append(std::move(After));
414+
ReturnType = getFragmentsForType(Function->getReturnType(),
415+
Function->getASTContext(), After);
416+
if (isa<FunctionDecl>(Function) &&
417+
dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() &&
418+
ReturnType.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
419+
0) {
420+
std::string ProperArgName =
421+
getNameForTemplateArgument(dyn_cast<FunctionDecl>(Function)
422+
->getDescribedFunctionTemplate()
423+
->getTemplateParameters()
424+
->asArray(),
425+
ReturnType.begin()->Spelling);
426+
ReturnType.begin()->Spelling.swap(ProperArgName);
427+
}
428+
ReturnType.append(std::move(After));
412429
Signature.setReturnType(ReturnType);
413430

414431
for (const auto *Param : Function->parameters())

clang/include/clang/ExtractAPI/ExtractAPIVisitor.h

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
6767
bool WalkUpFromVarTemplatePartialSpecializationDecl(
6868
const VarTemplatePartialSpecializationDecl *Decl);
6969

70+
bool WalkUpFromFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
71+
7072
bool VisitRecordDecl(const RecordDecl *Decl);
7173

7274
bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
@@ -87,6 +89,8 @@ class ExtractAPIVisitorBase : public RecursiveASTVisitor<Derived> {
8789
bool VisitVarTemplatePartialSpecializationDecl(
8890
const VarTemplatePartialSpecializationDecl *Decl);
8991

92+
bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
93+
9094
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl);
9195

9296
bool VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl);
@@ -283,13 +287,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
283287
switch (Decl->getTemplatedKind()) {
284288
case FunctionDecl::TK_NonTemplate:
285289
case FunctionDecl::TK_DependentNonTemplate:
286-
break;
287290
case FunctionDecl::TK_MemberSpecialization:
288291
case FunctionDecl::TK_FunctionTemplateSpecialization:
289-
if (auto *TemplateInfo = Decl->getTemplateSpecializationInfo()) {
290-
if (!TemplateInfo->isExplicitInstantiationOrSpecialization())
291-
return true;
292-
}
293292
break;
294293
case FunctionDecl::TK_FunctionTemplate:
295294
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
@@ -312,17 +311,23 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
312311
Context.getDiagnostics());
313312

314313
// Build declaration fragments, sub-heading, and signature of the function.
315-
DeclarationFragments Declaration =
316-
DeclarationFragmentsBuilder::getFragmentsForFunction(Decl);
317314
DeclarationFragments SubHeading =
318315
DeclarationFragmentsBuilder::getSubHeading(Decl);
319316
FunctionSignature Signature =
320317
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
321318

322-
// Add the function record to the API set.
323-
API.addGlobalFunction(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
324-
Declaration, SubHeading, Signature,
325-
isInSystemHeader(Decl));
319+
if (Decl->getTemplateSpecializationInfo())
320+
API.addGlobalFunctionTemplateSpecialization(
321+
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
322+
DeclarationFragmentsBuilder::
323+
getFragmentsForFunctionTemplateSpecialization(Decl),
324+
SubHeading, Signature, isInSystemHeader(Decl));
325+
else
326+
// Add the function record to the API set.
327+
API.addGlobalFunction(
328+
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
329+
DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading,
330+
Signature, isInSystemHeader(Decl));
326331
return true;
327332
}
328333

@@ -420,6 +425,13 @@ bool ExtractAPIVisitorBase<Derived>::
420425
return true;
421426
}
422427

428+
template <typename Derived>
429+
bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionTemplateDecl(
430+
const FunctionTemplateDecl *Decl) {
431+
getDerivedExtractAPIVisitor().VisitFunctionTemplateDecl(Decl);
432+
return true;
433+
}
434+
423435
template <typename Derived>
424436
bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
425437
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
@@ -697,6 +709,38 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
697709
return true;
698710
}
699711

712+
template <typename Derived>
713+
bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
714+
const FunctionTemplateDecl *Decl) {
715+
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
716+
return true;
717+
718+
// Collect symbol information.
719+
StringRef Name = Decl->getName();
720+
StringRef USR = API.recordUSR(Decl);
721+
PresumedLoc Loc =
722+
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
723+
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
724+
DocComment Comment;
725+
if (auto *RawComment =
726+
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
727+
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
728+
Context.getDiagnostics());
729+
730+
DeclarationFragments SubHeading =
731+
DeclarationFragmentsBuilder::getSubHeading(Decl);
732+
FunctionSignature Signature =
733+
DeclarationFragmentsBuilder::getFunctionSignature(
734+
Decl->getTemplatedDecl());
735+
736+
API.addGlobalFunctionTemplate(
737+
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
738+
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl),
739+
SubHeading, Signature, Template(Decl), isInSystemHeader(Decl));
740+
741+
return true;
742+
}
743+
700744
template <typename Derived>
701745
bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
702746
const ObjCInterfaceDecl *Decl) {

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

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

4848
getDerived()->traverseGlobalVariableTemplatePartialSpecializationRecords();
4949

50+
getDerived()->traverseGlobalFunctionTemplateRecords();
51+
52+
getDerived()->traverseGlobalFunctionTemplateSpecializationRecords();
53+
5054
getDerived()->traverseStructRecords();
5155

5256
getDerived()->traverseObjCInterfaces();
@@ -129,6 +133,19 @@ template <typename Derived> class APISetVisitor {
129133
*GlobalVariableTemplatePartialSpecialization.second);
130134
}
131135

136+
void traverseGlobalFunctionTemplateRecords() {
137+
for (const auto &GlobalFunctionTemplate : API.getGlobalFunctionTemplates())
138+
getDerived()->visitGlobalFunctionTemplateRecord(
139+
*GlobalFunctionTemplate.second);
140+
}
141+
142+
void traverseGlobalFunctionTemplateSpecializationRecords() {
143+
for (const auto &GlobalFunctionTemplateSpecialization :
144+
API.getGlobalFunctionTemplateSpecializations())
145+
getDerived()->visitGlobalFunctionTemplateSpecializationRecord(
146+
*GlobalFunctionTemplateSpecialization.second);
147+
}
148+
132149
void traverseConcepts() {
133150
for (const auto &Concept : API.getConcepts())
134151
getDerived()->visitConceptRecord(*Concept.second);
@@ -192,6 +209,12 @@ template <typename Derived> class APISetVisitor {
192209
void visitGlobalVariableTemplatePartialSpecializationRecord(
193210
const GlobalVariableTemplatePartialSpecializationRecord &Record){};
194211

212+
void visitGlobalFunctionTemplateRecord(
213+
const GlobalFunctionTemplateRecord &Record){};
214+
215+
void visitGlobalFunctionTemplateSpecializationRecord(
216+
const GlobalFunctionTemplateSpecializationRecord &Record){};
217+
195218
/// Visit an Objective-C container record.
196219
void visitObjCContainerRecord(const ObjCContainerRecord &Record){};
197220

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,12 @@ class SymbolGraphSerializer : public APISetVisitor<SymbolGraphSerializer> {
194194
void visitGlobalVariableTemplatePartialSpecializationRecord(
195195
const GlobalVariableTemplatePartialSpecializationRecord &Record);
196196

197+
void
198+
visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record);
199+
200+
void visitGlobalFunctionTemplateSpecializationRecord(
201+
const GlobalFunctionTemplateSpecializationRecord &Record);
202+
197203
/// Visit an Objective-C container record.
198204
void visitObjCContainerRecord(const ObjCContainerRecord &Record);
199205

clang/lib/ExtractAPI/API.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,31 @@ GlobalFunctionRecord *APISet::addGlobalFunction(
7878
IsFromSystemHeader);
7979
}
8080

81+
GlobalFunctionTemplateRecord *APISet::addGlobalFunctionTemplate(
82+
StringRef Name, StringRef USR, PresumedLoc Loc,
83+
AvailabilitySet Availability, LinkageInfo Linkage,
84+
const DocComment &Comment, DeclarationFragments Declaration,
85+
DeclarationFragments SubHeading, FunctionSignature Signature,
86+
Template Template, bool IsFromSystemHeader) {
87+
return addTopLevelRecord(USRBasedLookupTable, GlobalFunctionTemplates, USR,
88+
Name, Loc, std::move(Availability), Linkage, Comment,
89+
Declaration, SubHeading, Signature, Template,
90+
IsFromSystemHeader);
91+
}
92+
93+
GlobalFunctionTemplateSpecializationRecord *
94+
APISet::addGlobalFunctionTemplateSpecialization(
95+
StringRef Name, StringRef USR, PresumedLoc Loc,
96+
AvailabilitySet Availability, LinkageInfo Linkage,
97+
const DocComment &Comment, DeclarationFragments Declaration,
98+
DeclarationFragments SubHeading, FunctionSignature Signature,
99+
bool IsFromSystemHeader) {
100+
return addTopLevelRecord(
101+
USRBasedLookupTable, GlobalFunctionTemplateSpecializations, USR, Name,
102+
Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading,
103+
Signature, IsFromSystemHeader);
104+
}
105+
81106
EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name,
82107
StringRef USR, PresumedLoc Loc,
83108
AvailabilitySet Availabilities,

0 commit comments

Comments
 (0)