Skip to content

Commit d2529a2

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

File tree

10 files changed

+921
-22
lines changed

10 files changed

+921
-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,
@@ -277,6 +279,16 @@ struct GlobalFunctionRecord : APIRecord {
277279
IsFromSystemHeader),
278280
Signature(Signature) {}
279281

282+
GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
283+
PresumedLoc Loc, AvailabilitySet Availabilities,
284+
LinkageInfo Linkage, const DocComment &Comment,
285+
DeclarationFragments Declaration,
286+
DeclarationFragments SubHeading,
287+
FunctionSignature Signature, bool IsFromSystemHeader)
288+
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), Linkage,
289+
Comment, Declaration, SubHeading, IsFromSystemHeader),
290+
Signature(Signature) {}
291+
280292
static bool classof(const APIRecord *Record) {
281293
return Record->getKind() == RK_GlobalFunction;
282294
}
@@ -285,6 +297,44 @@ struct GlobalFunctionRecord : APIRecord {
285297
virtual void anchor();
286298
};
287299

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

1072+
template <>
1073+
struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
1074+
template <>
1075+
struct has_function_signature<GlobalFunctionTemplateRecord>
1076+
: public std::true_type {};
1077+
template <>
1078+
struct has_function_signature<GlobalFunctionTemplateSpecializationRecord>
1079+
: public std::true_type {};
1080+
10221081
/// APISet holds the set of API records collected from given inputs.
10231082
class APISet {
10241083
public:
@@ -1055,6 +1114,21 @@ class APISet {
10551114
DeclarationFragments SubHeading,
10561115
FunctionSignature Signature, bool IsFromSystemHeader);
10571116

1117+
GlobalFunctionTemplateRecord *addGlobalFunctionTemplate(
1118+
StringRef Name, StringRef USR, PresumedLoc Loc,
1119+
AvailabilitySet Availability, LinkageInfo Linkage,
1120+
const DocComment &Comment, DeclarationFragments Declaration,
1121+
DeclarationFragments SubHeading, FunctionSignature Signature,
1122+
Template Template, bool IsFromSystemHeader);
1123+
1124+
GlobalFunctionTemplateSpecializationRecord *
1125+
addGlobalFunctionTemplateSpecialization(
1126+
StringRef Name, StringRef USR, PresumedLoc Loc,
1127+
AvailabilitySet Availability, LinkageInfo Linkage,
1128+
const DocComment &Comment, DeclarationFragments Declaration,
1129+
DeclarationFragments SubHeading, FunctionSignature Signature,
1130+
bool IsFromSystemHeader);
1131+
10581132
/// Create and add an enum constant record into the API set.
10591133
///
10601134
/// Note: the caller is responsible for keeping the StringRef \p Name and
@@ -1299,6 +1373,14 @@ class APISet {
12991373
const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
13001374
return GlobalFunctions;
13011375
}
1376+
const RecordMap<GlobalFunctionTemplateRecord> &
1377+
getGlobalFunctionTemplates() const {
1378+
return GlobalFunctionTemplates;
1379+
}
1380+
const RecordMap<GlobalFunctionTemplateSpecializationRecord> &
1381+
getGlobalFunctionTemplateSpecializations() const {
1382+
return GlobalFunctionTemplateSpecializations;
1383+
}
13021384
const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
13031385
return GlobalVariables;
13041386
}
@@ -1385,6 +1467,9 @@ class APISet {
13851467

13861468
llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
13871469
RecordMap<GlobalFunctionRecord> GlobalFunctions;
1470+
RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates;
1471+
RecordMap<GlobalFunctionTemplateSpecializationRecord>
1472+
GlobalFunctionTemplateSpecializations;
13881473
RecordMap<GlobalVariableRecord> GlobalVariables;
13891474
RecordMap<GlobalVariableTemplateRecord> GlobalVariableTemplates;
13901475
RecordMap<GlobalVariableTemplateSpecializationRecord>

clang/include/clang/ExtractAPI/DeclarationFragments.h

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

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

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

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

413419
DeclarationFragments ReturnType, After;
414-
ReturnType
415-
.append(getFragmentsForType(Function->getReturnType(),
416-
Function->getASTContext(), After))
417-
.append(std::move(After));
420+
ReturnType = getFragmentsForType(Function->getReturnType(),
421+
Function->getASTContext(), After);
422+
if (isa<FunctionDecl>(Function) &&
423+
dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() &&
424+
ReturnType.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
425+
0) {
426+
std::string ProperArgName =
427+
getNameForTemplateArgument(dyn_cast<FunctionDecl>(Function)
428+
->getDescribedFunctionTemplate()
429+
->getTemplateParameters()
430+
->asArray(),
431+
ReturnType.begin()->Spelling);
432+
ReturnType.begin()->Spelling.swap(ProperArgName);
433+
}
434+
ReturnType.append(std::move(After));
418435
Signature.setReturnType(ReturnType);
419436

420437
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();
@@ -127,6 +131,19 @@ template <typename Derived> class APISetVisitor {
127131
*GlobalVariableTemplatePartialSpecialization.second);
128132
}
129133

134+
void traverseGlobalFunctionTemplateRecords() {
135+
for (const auto &GlobalFunctionTemplate : API.getGlobalFunctionTemplates())
136+
getDerived()->visitGlobalFunctionTemplateRecord(
137+
*GlobalFunctionTemplate.second);
138+
}
139+
140+
void traverseGlobalFunctionTemplateSpecializationRecords() {
141+
for (const auto &GlobalFunctionTemplateSpecialization :
142+
API.getGlobalFunctionTemplateSpecializations())
143+
getDerived()->visitGlobalFunctionTemplateSpecializationRecord(
144+
*GlobalFunctionTemplateSpecialization.second);
145+
}
146+
130147
void traverseConcepts() {
131148
for (const auto &Concept : API.getConcepts())
132149
getDerived()->visitConceptRecord(*Concept.second);
@@ -185,6 +202,12 @@ template <typename Derived> class APISetVisitor {
185202
void visitGlobalVariableTemplatePartialSpecializationRecord(
186203
const GlobalVariableTemplatePartialSpecializationRecord &Record){};
187204

205+
void visitGlobalFunctionTemplateRecord(
206+
const GlobalFunctionTemplateRecord &Record){};
207+
208+
void visitGlobalFunctionTemplateSpecializationRecord(
209+
const GlobalFunctionTemplateSpecializationRecord &Record){};
210+
188211
/// Visit an Objective-C container record.
189212
void visitObjCContainerRecord(const ObjCContainerRecord &Record){};
190213

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

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

190+
void
191+
visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record);
192+
193+
void visitGlobalFunctionTemplateSpecializationRecord(
194+
const GlobalFunctionTemplateSpecializationRecord &Record);
195+
190196
/// Visit an Objective-C container record.
191197
void visitObjCContainerRecord(const ObjCContainerRecord &Record);
192198

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)