mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-28 06:46:07 +00:00
[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
This commit is contained in:
parent
3e569883fa
commit
80b787e803
@ -158,6 +158,8 @@ struct APIRecord {
|
||||
enum RecordKind {
|
||||
RK_Unknown,
|
||||
RK_GlobalFunction,
|
||||
RK_GlobalFunctionTemplate,
|
||||
RK_GlobalFunctionTemplateSpecialization,
|
||||
RK_GlobalVariable,
|
||||
RK_GlobalVariableTemplate,
|
||||
RK_GlobalVariableTemplateSpecialization,
|
||||
@ -281,6 +283,16 @@ struct GlobalFunctionRecord : APIRecord {
|
||||
IsFromSystemHeader),
|
||||
Signature(Signature) {}
|
||||
|
||||
GlobalFunctionRecord(RecordKind Kind, StringRef USR, StringRef Name,
|
||||
PresumedLoc Loc, AvailabilitySet Availabilities,
|
||||
LinkageInfo Linkage, const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, bool IsFromSystemHeader)
|
||||
: APIRecord(Kind, USR, Name, Loc, std::move(Availabilities), Linkage,
|
||||
Comment, Declaration, SubHeading, IsFromSystemHeader),
|
||||
Signature(Signature) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_GlobalFunction;
|
||||
}
|
||||
@ -289,6 +301,44 @@ private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
struct GlobalFunctionTemplateRecord : GlobalFunctionRecord {
|
||||
Template Templ;
|
||||
|
||||
GlobalFunctionTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities,
|
||||
LinkageInfo Linkage, const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, Template Template,
|
||||
bool IsFromSystemHeader)
|
||||
: GlobalFunctionRecord(RK_GlobalFunctionTemplate, USR, Name, Loc,
|
||||
std::move(Availabilities), Linkage, Comment,
|
||||
Declaration, SubHeading, Signature,
|
||||
IsFromSystemHeader),
|
||||
Templ(Template) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_GlobalFunctionTemplate;
|
||||
}
|
||||
};
|
||||
|
||||
struct GlobalFunctionTemplateSpecializationRecord : GlobalFunctionRecord {
|
||||
GlobalFunctionTemplateSpecializationRecord(
|
||||
StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, LinkageInfo Linkage,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, FunctionSignature Signature,
|
||||
bool IsFromSystemHeader)
|
||||
: GlobalFunctionRecord(RK_GlobalFunctionTemplateSpecialization, USR, Name,
|
||||
Loc, std::move(Availabilities), Linkage, Comment,
|
||||
Declaration, SubHeading, Signature,
|
||||
IsFromSystemHeader) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_GlobalFunctionTemplateSpecialization;
|
||||
}
|
||||
};
|
||||
|
||||
/// This holds information associated with global functions.
|
||||
struct GlobalVariableRecord : APIRecord {
|
||||
GlobalVariableRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
@ -1025,6 +1075,15 @@ template <>
|
||||
struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
|
||||
: public std::true_type {};
|
||||
|
||||
template <>
|
||||
struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
|
||||
template <>
|
||||
struct has_function_signature<GlobalFunctionTemplateRecord>
|
||||
: public std::true_type {};
|
||||
template <>
|
||||
struct has_function_signature<GlobalFunctionTemplateSpecializationRecord>
|
||||
: public std::true_type {};
|
||||
|
||||
/// APISet holds the set of API records collected from given inputs.
|
||||
class APISet {
|
||||
public:
|
||||
@ -1061,6 +1120,21 @@ public:
|
||||
DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, bool IsFromSystemHeader);
|
||||
|
||||
GlobalFunctionTemplateRecord *addGlobalFunctionTemplate(
|
||||
StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, LinkageInfo Linkage,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, FunctionSignature Signature,
|
||||
Template Template, bool IsFromSystemHeader);
|
||||
|
||||
GlobalFunctionTemplateSpecializationRecord *
|
||||
addGlobalFunctionTemplateSpecialization(
|
||||
StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, LinkageInfo Linkage,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, FunctionSignature Signature,
|
||||
bool IsFromSystemHeader);
|
||||
|
||||
/// Create and add an enum constant record into the API set.
|
||||
///
|
||||
/// Note: the caller is responsible for keeping the StringRef \p Name and
|
||||
@ -1305,6 +1379,14 @@ public:
|
||||
const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
|
||||
return GlobalFunctions;
|
||||
}
|
||||
const RecordMap<GlobalFunctionTemplateRecord> &
|
||||
getGlobalFunctionTemplates() const {
|
||||
return GlobalFunctionTemplates;
|
||||
}
|
||||
const RecordMap<GlobalFunctionTemplateSpecializationRecord> &
|
||||
getGlobalFunctionTemplateSpecializations() const {
|
||||
return GlobalFunctionTemplateSpecializations;
|
||||
}
|
||||
const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
|
||||
return GlobalVariables;
|
||||
}
|
||||
@ -1391,6 +1473,9 @@ private:
|
||||
|
||||
llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
|
||||
RecordMap<GlobalFunctionRecord> GlobalFunctions;
|
||||
RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates;
|
||||
RecordMap<GlobalFunctionTemplateSpecializationRecord>
|
||||
GlobalFunctionTemplateSpecializations;
|
||||
RecordMap<GlobalVariableRecord> GlobalVariables;
|
||||
RecordMap<GlobalVariableTemplateRecord> GlobalVariableTemplates;
|
||||
RecordMap<GlobalVariableTemplateSpecializationRecord>
|
||||
|
@ -306,8 +306,8 @@ public:
|
||||
static DeclarationFragments
|
||||
getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>);
|
||||
|
||||
static std::string getNameForTemplateArgument(const ArrayRef<NamedDecl *>,
|
||||
std::string);
|
||||
static std::string
|
||||
getNameForTemplateArgument(const ArrayRef<NamedDecl *>, std::string);
|
||||
|
||||
static DeclarationFragments
|
||||
getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument>,
|
||||
@ -331,6 +331,12 @@ public:
|
||||
static DeclarationFragments getFragmentsForVarTemplatePartialSpecialization(
|
||||
const VarTemplatePartialSpecializationDecl *);
|
||||
|
||||
static DeclarationFragments
|
||||
getFragmentsForFunctionTemplate(const FunctionTemplateDecl *Decl);
|
||||
|
||||
static DeclarationFragments
|
||||
getFragmentsForFunctionTemplateSpecialization(const FunctionDecl *Decl);
|
||||
|
||||
/// Build DeclarationFragments for an Objective-C category declaration
|
||||
/// ObjCCategoryDecl.
|
||||
static DeclarationFragments
|
||||
@ -405,10 +411,21 @@ DeclarationFragmentsBuilder::getFunctionSignature(const FunctionT *Function) {
|
||||
FunctionSignature Signature;
|
||||
|
||||
DeclarationFragments ReturnType, After;
|
||||
ReturnType
|
||||
.append(getFragmentsForType(Function->getReturnType(),
|
||||
Function->getASTContext(), After))
|
||||
.append(std::move(After));
|
||||
ReturnType = getFragmentsForType(Function->getReturnType(),
|
||||
Function->getASTContext(), After);
|
||||
if (isa<FunctionDecl>(Function) &&
|
||||
dyn_cast<FunctionDecl>(Function)->getDescribedFunctionTemplate() &&
|
||||
ReturnType.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
|
||||
0) {
|
||||
std::string ProperArgName =
|
||||
getNameForTemplateArgument(dyn_cast<FunctionDecl>(Function)
|
||||
->getDescribedFunctionTemplate()
|
||||
->getTemplateParameters()
|
||||
->asArray(),
|
||||
ReturnType.begin()->Spelling);
|
||||
ReturnType.begin()->Spelling.swap(ProperArgName);
|
||||
}
|
||||
ReturnType.append(std::move(After));
|
||||
Signature.setReturnType(ReturnType);
|
||||
|
||||
for (const auto *Param : Function->parameters())
|
||||
|
@ -67,6 +67,8 @@ public:
|
||||
bool WalkUpFromVarTemplatePartialSpecializationDecl(
|
||||
const VarTemplatePartialSpecializationDecl *Decl);
|
||||
|
||||
bool WalkUpFromFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
|
||||
|
||||
bool VisitRecordDecl(const RecordDecl *Decl);
|
||||
|
||||
bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
|
||||
@ -87,6 +89,8 @@ public:
|
||||
bool VisitVarTemplatePartialSpecializationDecl(
|
||||
const VarTemplatePartialSpecializationDecl *Decl);
|
||||
|
||||
bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
|
||||
|
||||
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl);
|
||||
|
||||
bool VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl);
|
||||
@ -283,13 +287,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
|
||||
switch (Decl->getTemplatedKind()) {
|
||||
case FunctionDecl::TK_NonTemplate:
|
||||
case FunctionDecl::TK_DependentNonTemplate:
|
||||
break;
|
||||
case FunctionDecl::TK_MemberSpecialization:
|
||||
case FunctionDecl::TK_FunctionTemplateSpecialization:
|
||||
if (auto *TemplateInfo = Decl->getTemplateSpecializationInfo()) {
|
||||
if (!TemplateInfo->isExplicitInstantiationOrSpecialization())
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case FunctionDecl::TK_FunctionTemplate:
|
||||
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
|
||||
@ -312,17 +311,23 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
|
||||
Context.getDiagnostics());
|
||||
|
||||
// Build declaration fragments, sub-heading, and signature of the function.
|
||||
DeclarationFragments Declaration =
|
||||
DeclarationFragmentsBuilder::getFragmentsForFunction(Decl);
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
||||
FunctionSignature Signature =
|
||||
DeclarationFragmentsBuilder::getFunctionSignature(Decl);
|
||||
|
||||
// Add the function record to the API set.
|
||||
API.addGlobalFunction(Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
||||
Declaration, SubHeading, Signature,
|
||||
isInSystemHeader(Decl));
|
||||
if (Decl->getTemplateSpecializationInfo())
|
||||
API.addGlobalFunctionTemplateSpecialization(
|
||||
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
||||
DeclarationFragmentsBuilder::
|
||||
getFragmentsForFunctionTemplateSpecialization(Decl),
|
||||
SubHeading, Signature, isInSystemHeader(Decl));
|
||||
else
|
||||
// Add the function record to the API set.
|
||||
API.addGlobalFunction(
|
||||
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
||||
DeclarationFragmentsBuilder::getFragmentsForFunction(Decl), SubHeading,
|
||||
Signature, isInSystemHeader(Decl));
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -420,6 +425,13 @@ bool ExtractAPIVisitorBase<Derived>::
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::WalkUpFromFunctionTemplateDecl(
|
||||
const FunctionTemplateDecl *Decl) {
|
||||
getDerivedExtractAPIVisitor().VisitFunctionTemplateDecl(Decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitRecordDecl(const RecordDecl *Decl) {
|
||||
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
|
||||
@ -697,6 +709,38 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
|
||||
const FunctionTemplateDecl *Decl) {
|
||||
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
|
||||
return true;
|
||||
|
||||
// Collect symbol information.
|
||||
StringRef Name = Decl->getName();
|
||||
StringRef USR = API.recordUSR(Decl);
|
||||
PresumedLoc Loc =
|
||||
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
||||
LinkageInfo Linkage = Decl->getLinkageAndVisibility();
|
||||
DocComment Comment;
|
||||
if (auto *RawComment =
|
||||
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
|
||||
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
||||
Context.getDiagnostics());
|
||||
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
||||
FunctionSignature Signature =
|
||||
DeclarationFragmentsBuilder::getFunctionSignature(
|
||||
Decl->getTemplatedDecl());
|
||||
|
||||
API.addGlobalFunctionTemplate(
|
||||
Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment,
|
||||
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(Decl),
|
||||
SubHeading, Signature, Template(Decl), isInSystemHeader(Decl));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
|
||||
const ObjCInterfaceDecl *Decl) {
|
||||
|
@ -47,6 +47,10 @@ public:
|
||||
|
||||
getDerived()->traverseGlobalVariableTemplatePartialSpecializationRecords();
|
||||
|
||||
getDerived()->traverseGlobalFunctionTemplateRecords();
|
||||
|
||||
getDerived()->traverseGlobalFunctionTemplateSpecializationRecords();
|
||||
|
||||
getDerived()->traverseStructRecords();
|
||||
|
||||
getDerived()->traverseObjCInterfaces();
|
||||
@ -129,6 +133,19 @@ public:
|
||||
*GlobalVariableTemplatePartialSpecialization.second);
|
||||
}
|
||||
|
||||
void traverseGlobalFunctionTemplateRecords() {
|
||||
for (const auto &GlobalFunctionTemplate : API.getGlobalFunctionTemplates())
|
||||
getDerived()->visitGlobalFunctionTemplateRecord(
|
||||
*GlobalFunctionTemplate.second);
|
||||
}
|
||||
|
||||
void traverseGlobalFunctionTemplateSpecializationRecords() {
|
||||
for (const auto &GlobalFunctionTemplateSpecialization :
|
||||
API.getGlobalFunctionTemplateSpecializations())
|
||||
getDerived()->visitGlobalFunctionTemplateSpecializationRecord(
|
||||
*GlobalFunctionTemplateSpecialization.second);
|
||||
}
|
||||
|
||||
void traverseConcepts() {
|
||||
for (const auto &Concept : API.getConcepts())
|
||||
getDerived()->visitConceptRecord(*Concept.second);
|
||||
@ -192,6 +209,12 @@ public:
|
||||
void visitGlobalVariableTemplatePartialSpecializationRecord(
|
||||
const GlobalVariableTemplatePartialSpecializationRecord &Record){};
|
||||
|
||||
void visitGlobalFunctionTemplateRecord(
|
||||
const GlobalFunctionTemplateRecord &Record){};
|
||||
|
||||
void visitGlobalFunctionTemplateSpecializationRecord(
|
||||
const GlobalFunctionTemplateSpecializationRecord &Record){};
|
||||
|
||||
/// Visit an Objective-C container record.
|
||||
void visitObjCContainerRecord(const ObjCContainerRecord &Record){};
|
||||
|
||||
|
@ -194,6 +194,12 @@ public:
|
||||
void visitGlobalVariableTemplatePartialSpecializationRecord(
|
||||
const GlobalVariableTemplatePartialSpecializationRecord &Record);
|
||||
|
||||
void
|
||||
visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record);
|
||||
|
||||
void visitGlobalFunctionTemplateSpecializationRecord(
|
||||
const GlobalFunctionTemplateSpecializationRecord &Record);
|
||||
|
||||
/// Visit an Objective-C container record.
|
||||
void visitObjCContainerRecord(const ObjCContainerRecord &Record);
|
||||
|
||||
|
@ -78,6 +78,31 @@ GlobalFunctionRecord *APISet::addGlobalFunction(
|
||||
IsFromSystemHeader);
|
||||
}
|
||||
|
||||
GlobalFunctionTemplateRecord *APISet::addGlobalFunctionTemplate(
|
||||
StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, LinkageInfo Linkage,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, FunctionSignature Signature,
|
||||
Template Template, bool IsFromSystemHeader) {
|
||||
return addTopLevelRecord(USRBasedLookupTable, GlobalFunctionTemplates, USR,
|
||||
Name, Loc, std::move(Availability), Linkage, Comment,
|
||||
Declaration, SubHeading, Signature, Template,
|
||||
IsFromSystemHeader);
|
||||
}
|
||||
|
||||
GlobalFunctionTemplateSpecializationRecord *
|
||||
APISet::addGlobalFunctionTemplateSpecialization(
|
||||
StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, LinkageInfo Linkage,
|
||||
const DocComment &Comment, DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading, FunctionSignature Signature,
|
||||
bool IsFromSystemHeader) {
|
||||
return addTopLevelRecord(
|
||||
USRBasedLookupTable, GlobalFunctionTemplateSpecializations, USR, Name,
|
||||
Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading,
|
||||
Signature, IsFromSystemHeader);
|
||||
}
|
||||
|
||||
EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name,
|
||||
StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities,
|
||||
|
@ -493,6 +493,16 @@ DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
|
||||
|
||||
DeclarationFragments TypeFragments =
|
||||
getFragmentsForType(T, Param->getASTContext(), After);
|
||||
if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
|
||||
0) {
|
||||
std::string ProperArgName = getNameForTemplateArgument(
|
||||
dyn_cast<FunctionDecl>(Param->getDeclContext())
|
||||
->getDescribedFunctionTemplate()
|
||||
->getTemplateParameters()
|
||||
->asArray(),
|
||||
TypeFragments.begin()->Spelling);
|
||||
TypeFragments.begin()->Spelling.swap(ProperArgName);
|
||||
}
|
||||
|
||||
if (Param->isObjCMethodParameter())
|
||||
Fragments.append("(", DeclarationFragments::FragmentKind::Text)
|
||||
@ -536,12 +546,35 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
|
||||
|
||||
// FIXME: Is `after` actually needed here?
|
||||
DeclarationFragments After;
|
||||
Fragments
|
||||
.append(getFragmentsForType(Func->getReturnType(), Func->getASTContext(),
|
||||
After))
|
||||
auto ReturnValueFragment =
|
||||
getFragmentsForType(Func->getReturnType(), Func->getASTContext(), After);
|
||||
if (ReturnValueFragment.begin()->Spelling.substr(0, 14).compare(
|
||||
"type-parameter") == 0) {
|
||||
std::string ProperArgName =
|
||||
getNameForTemplateArgument(Func->getDescribedFunctionTemplate()
|
||||
->getTemplateParameters()
|
||||
->asArray(),
|
||||
ReturnValueFragment.begin()->Spelling);
|
||||
ReturnValueFragment.begin()->Spelling.swap(ProperArgName);
|
||||
}
|
||||
|
||||
Fragments.append(std::move(ReturnValueFragment))
|
||||
.appendSpace()
|
||||
.append(Func->getName(), DeclarationFragments::FragmentKind::Identifier)
|
||||
.append(std::move(After));
|
||||
.append(Func->getName(), DeclarationFragments::FragmentKind::Identifier);
|
||||
|
||||
if (Func->getTemplateSpecializationInfo()) {
|
||||
Fragments.append("<", DeclarationFragments::FragmentKind::Text);
|
||||
|
||||
for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
|
||||
if (i)
|
||||
Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
|
||||
Fragments.append(
|
||||
getFragmentsForType(Func->getParamDecl(i)->getType(),
|
||||
Func->getParamDecl(i)->getASTContext(), After));
|
||||
}
|
||||
Fragments.append(">", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
Fragments.append(std::move(After));
|
||||
|
||||
Fragments.append("(", DeclarationFragments::FragmentKind::Text);
|
||||
for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
|
||||
@ -974,6 +1007,33 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
|
||||
.append(";", DeclarationFragments::FragmentKind::Text);
|
||||
}
|
||||
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
|
||||
const FunctionTemplateDecl *Decl) {
|
||||
DeclarationFragments Fragments;
|
||||
return Fragments
|
||||
.append("template", DeclarationFragments::FragmentKind::Keyword)
|
||||
.append("<", DeclarationFragments::FragmentKind::Text)
|
||||
// Partial specs may have new params.
|
||||
.append(getFragmentsForTemplateParameters(
|
||||
Decl->getTemplateParameters()->asArray()))
|
||||
.append(">", DeclarationFragments::FragmentKind::Text)
|
||||
.appendSpace()
|
||||
.append(DeclarationFragmentsBuilder::getFragmentsForFunction(
|
||||
Decl->getAsFunction()));
|
||||
}
|
||||
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
|
||||
const FunctionDecl *Decl) {
|
||||
DeclarationFragments Fragments;
|
||||
return Fragments
|
||||
.append("template", DeclarationFragments::FragmentKind::Keyword)
|
||||
.append("<>", DeclarationFragments::FragmentKind::Text)
|
||||
.appendSpace()
|
||||
.append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
|
||||
}
|
||||
|
||||
DeclarationFragments
|
||||
DeclarationFragmentsBuilder::getFragmentsForMacro(StringRef Name,
|
||||
const MacroDirective *MD) {
|
||||
|
@ -361,6 +361,14 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
|
||||
Kind["identifier"] = AddLangPrefix("func");
|
||||
Kind["displayName"] = "Function";
|
||||
break;
|
||||
case APIRecord::RK_GlobalFunctionTemplate:
|
||||
Kind["identifier"] = AddLangPrefix("func");
|
||||
Kind["displayName"] = "Function Template";
|
||||
break;
|
||||
case APIRecord::RK_GlobalFunctionTemplateSpecialization:
|
||||
Kind["identifier"] = AddLangPrefix("func");
|
||||
Kind["displayName"] = "Function Template Specialization";
|
||||
break;
|
||||
case APIRecord::RK_GlobalVariableTemplate:
|
||||
Kind["identifier"] = AddLangPrefix("var");
|
||||
Kind["displayName"] = "Global Variable Template";
|
||||
@ -947,6 +955,22 @@ void SymbolGraphSerializer::
|
||||
Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpecialization));
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
|
||||
const GlobalFunctionTemplateRecord &Record) {
|
||||
auto GlobalFunctionTemplate = serializeAPIRecord(Record);
|
||||
if (!GlobalFunctionTemplate)
|
||||
return;
|
||||
Symbols.emplace_back(std::move(*GlobalFunctionTemplate));
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecializationRecord(
|
||||
const GlobalFunctionTemplateSpecializationRecord &Record) {
|
||||
auto GlobalFunctionTemplateSpecialization = serializeAPIRecord(Record);
|
||||
if (!GlobalFunctionTemplateSpecialization)
|
||||
return;
|
||||
Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpecialization));
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitObjCContainerRecord(
|
||||
const ObjCContainerRecord &Record) {
|
||||
auto ObjCContainer = serializeAPIRecord(Record);
|
||||
|
315
clang/test/ExtractAPI/global_func_template.cpp
Normal file
315
clang/test/ExtractAPI/global_func_template.cpp
Normal file
@ -0,0 +1,315 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
|
||||
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
template<typename T> void Foo(T Bar);
|
||||
|
||||
template<typename T> T Fizz(int Buzz);
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "template"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "<"
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "typename"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "genericParameter",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "> "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Bar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"name": "Bar"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@FT@>1#TFoo#t0.0#v#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function Template",
|
||||
"identifier": "c++.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 27,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
],
|
||||
"swiftGenerics": {
|
||||
"parameters": [
|
||||
{
|
||||
"depth": 0,
|
||||
"index": 0,
|
||||
"name": "T"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "template"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "<"
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "typename"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "genericParameter",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "> "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Fizz"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Buzz"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Buzz"
|
||||
}
|
||||
],
|
||||
"name": "Buzz"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@FT@>1#TFizz#I#t0.0#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function Template",
|
||||
"identifier": "c++.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 24,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Fizz"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Fizz"
|
||||
}
|
||||
],
|
||||
"title": "Fizz"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Fizz"
|
||||
],
|
||||
"swiftGenerics": {
|
||||
"parameters": [
|
||||
{
|
||||
"depth": 0,
|
||||
"index": 0,
|
||||
"name": "T"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
299
clang/test/ExtractAPI/global_func_template_spec.cpp
Normal file
299
clang/test/ExtractAPI/global_func_template_spec.cpp
Normal file
@ -0,0 +1,299 @@
|
||||
// RUN: rm -rf %t
|
||||
// RUN: split-file %s %t
|
||||
// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
|
||||
// RUN: %t/reference.output.json.in >> %t/reference.output.json
|
||||
// RUN: %clang_cc1 -extract-api -triple arm64-apple-macosx \
|
||||
// RUN: -x c++-header %t/input.h -o %t/output.json -verify
|
||||
|
||||
// Generator version is not consistent across test runs, normalize it.
|
||||
// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
|
||||
// RUN: %t/output.json >> %t/output-normalized.json
|
||||
// RUN: diff %t/reference.output.json %t/output-normalized.json
|
||||
|
||||
//--- input.h
|
||||
template<typename T> void Foo(T Bar);
|
||||
|
||||
template<> void Foo<int>(int Bar);
|
||||
/// expected-no-diagnostics
|
||||
|
||||
//--- reference.output.json.in
|
||||
{
|
||||
"metadata": {
|
||||
"formatVersion": {
|
||||
"major": 0,
|
||||
"minor": 5,
|
||||
"patch": 3
|
||||
},
|
||||
"generator": "?"
|
||||
},
|
||||
"module": {
|
||||
"name": "",
|
||||
"platform": {
|
||||
"architecture": "arm64",
|
||||
"operatingSystem": {
|
||||
"minimumVersion": {
|
||||
"major": 11,
|
||||
"minor": 0,
|
||||
"patch": 0
|
||||
},
|
||||
"name": "macosx"
|
||||
},
|
||||
"vendor": "apple"
|
||||
}
|
||||
},
|
||||
"relationships": [],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "template"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "<"
|
||||
},
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "typename"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "genericParameter",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "> "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Bar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"name": "Bar"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@FT@>1#TFoo#t0.0#v#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function Template",
|
||||
"identifier": "c++.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 27,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
],
|
||||
"swiftGenerics": {
|
||||
"parameters": [
|
||||
{
|
||||
"depth": 0,
|
||||
"index": 0,
|
||||
"name": "T"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "template"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "<> "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "<"
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ">("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Bar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"name": "Bar"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@F@Foo<#I>#I#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Function Template Specialization",
|
||||
"identifier": "c++.func"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 17,
|
||||
"line": 3
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user