evelez7 created this revision.
evelez7 added a reviewer: dang.
Herald added a reviewer: ributzka.
Herald added a project: All.
evelez7 requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Add records, serialization for global function templates and their
specializations
Depends on D157350 <https://reviews.llvm.org/D157350>
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D157579
Files:
clang/include/clang/ExtractAPI/API.h
clang/include/clang/ExtractAPI/DeclarationFragments.h
clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
clang/lib/ExtractAPI/API.cpp
clang/lib/ExtractAPI/DeclarationFragments.cpp
clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
clang/test/ExtractAPI/global_func_template.cpp
clang/test/ExtractAPI/global_func_template_spec.cpp
Index: clang/test/ExtractAPI/global_func_template_spec.cpp
===================================================================
--- /dev/null
+++ clang/test/ExtractAPI/global_func_template_spec.cpp
@@ -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"
+ ]
+ }
+ ]
+}
Index: clang/test/ExtractAPI/global_func_template.cpp
===================================================================
--- /dev/null
+++ clang/test/ExtractAPI/global_func_template.cpp
@@ -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"
+ }
+ ]
+ }
+ }
+ ]
+}
Index: clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
===================================================================
--- clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -355,6 +355,14 @@
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";
@@ -933,6 +941,22 @@
Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpec));
}
+void SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
+ const GlobalFunctionTemplateRecord &Record) {
+ auto GlobalFunctionTemplate = serializeAPIRecord(Record);
+ if (!GlobalFunctionTemplate)
+ return;
+ Symbols.emplace_back(std::move(*GlobalFunctionTemplate));
+}
+
+void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecRecord(
+ const GlobalFunctionTemplateSpecRecord &Record) {
+ auto GlobalFunctionTemplateSpec= serializeAPIRecord(Record);
+ if (!GlobalFunctionTemplateSpec)
+ return;
+ Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpec));
+}
+
void SymbolGraphSerializer::visitObjCContainerRecord(
const ObjCContainerRecord &Record) {
auto ObjCContainer = serializeAPIRecord(Record);
Index: clang/lib/ExtractAPI/DeclarationFragments.cpp
===================================================================
--- clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -493,6 +493,16 @@
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 @@
// 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 @@
.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) {
Index: clang/lib/ExtractAPI/API.cpp
===================================================================
--- clang/lib/ExtractAPI/API.cpp
+++ clang/lib/ExtractAPI/API.cpp
@@ -78,6 +78,30 @@
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);
+}
+
+GlobalFunctionTemplateSpecRecord *APISet::addGlobalFunctionTemplateSpec(
+ 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,
Index: clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
===================================================================
--- clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -186,6 +186,12 @@
void visitGlobalVariableTemplatePartialSpecRecord(
const GlobalVariableTemplatePartialSpecRecord &Record);
+ void
+ visitGlobalFunctionTemplateRecord(const GlobalFunctionTemplateRecord &Record);
+
+ void visitGlobalFunctionTemplateSpecRecord(
+ const GlobalFunctionTemplateSpecRecord &Record);
+
/// Visit an Objective-C container record.
void visitObjCContainerRecord(const ObjCContainerRecord &Record);
Index: clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
===================================================================
--- clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
+++ clang/include/clang/ExtractAPI/Serialization/SerializerBase.h
@@ -47,6 +47,10 @@
getDerived()->traverseGlobalVariableTemplatePartialSpecRecords();
+ getDerived()->traverseGlobalFunctionTemplateRecords();
+
+ getDerived()->traverseGlobalFunctionTemplateSpecRecords();
+
getDerived()->traverseStructRecords();
getDerived()->traverseObjCInterfaces();
@@ -125,6 +129,19 @@
*GlobalVariableTemplatePartialSpec.second);
}
+ void traverseGlobalFunctionTemplateRecords() {
+ for (const auto &GlobalFunctionTemplate : API.getGlobalFunctionTemplates())
+ getDerived()->visitGlobalFunctionTemplateRecord(
+ *GlobalFunctionTemplate.second);
+ }
+
+ void traverseGlobalFunctionTemplateSpecRecords() {
+ for (const auto &GlobalFunctionTemplateSpec :
+ API.getGlobalFunctionTemplateSpecializations())
+ getDerived()->visitGlobalFunctionTemplateSpecRecord(
+ *GlobalFunctionTemplateSpec.second);
+ }
+
void traverseConcepts() {
for (const auto &Concept : API.getConcepts())
getDerived()->visitConceptRecord(*Concept.second);
@@ -182,6 +199,12 @@
void visitGlobalVariableTemplatePartialSpecRecord(
const GlobalVariableTemplatePartialSpecRecord &Record){};
+ void visitGlobalFunctionTemplateRecord(
+ const GlobalFunctionTemplateRecord &Record){};
+
+ void visitGlobalFunctionTemplateSpecRecord(
+ const GlobalFunctionTemplateSpecRecord &Record){};
+
/// Visit an Objective-C container record.
void visitObjCContainerRecord(const ObjCContainerRecord &Record){};
Index: clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
===================================================================
--- clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
+++ clang/include/clang/ExtractAPI/ExtractAPIVisitor.h
@@ -89,6 +89,8 @@
bool WalkUpFromVarTemplatePartialSpecializationDecl(
const VarTemplatePartialSpecializationDecl *Decl);
+ bool WalkUpFromFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
+
bool VisitRecordDecl(const RecordDecl *Decl);
bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
@@ -109,6 +111,8 @@
bool VisitVarTemplatePartialSpecializationDecl(
const VarTemplatePartialSpecializationDecl *Decl);
+ bool VisitFunctionTemplateDecl(const FunctionTemplateDecl *Decl);
+
bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl);
bool VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl);
@@ -267,13 +271,8 @@
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:
@@ -296,17 +295,23 @@
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.addGlobalFunctionTemplateSpec(
+ 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;
}
@@ -404,6 +409,13 @@
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))
@@ -716,6 +728,39 @@
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, DeclarationFragmentsBuilder::getTemplate(Decl),
+ isInSystemHeader(Decl));
+
+ return true;
+}
+
template <typename Derived>
bool ExtractAPIVisitorBase<Derived>::VisitObjCInterfaceDecl(
const ObjCInterfaceDecl *Decl) {
Index: clang/include/clang/ExtractAPI/DeclarationFragments.h
===================================================================
--- clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -334,7 +334,8 @@
return Template;
}
- static Template getTemplate(const VarTemplatePartialSpecializationDecl *Decl) {
+ static Template
+ getTemplate(const VarTemplatePartialSpecializationDecl *Decl) {
Template Template;
for (auto *const Parameter : *Decl->getTemplateParameters()) {
const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
@@ -355,7 +356,8 @@
return Template;
}
- static Template getTemplate(const ClassTemplatePartialSpecializationDecl *Decl) {
+ static Template
+ getTemplate(const ClassTemplatePartialSpecializationDecl *Decl) {
Template Template;
for (auto *const Parameter : *Decl->getTemplateParameters()) {
const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
@@ -414,8 +416,8 @@
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>,
@@ -439,6 +441,12 @@
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
@@ -513,10 +521,21 @@
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())
Index: clang/include/clang/ExtractAPI/API.h
===================================================================
--- clang/include/clang/ExtractAPI/API.h
+++ clang/include/clang/ExtractAPI/API.h
@@ -60,6 +60,8 @@
enum RecordKind {
RK_Unknown,
RK_GlobalFunction,
+ RK_GlobalFunctionTemplate,
+ RK_GlobalFunctionTemplateSpecialization,
RK_GlobalVariable,
RK_GlobalVariableTemplate,
RK_GlobalVariableTemplateSpecialization,
@@ -179,6 +181,16 @@
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;
}
@@ -187,6 +199,44 @@
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 GlobalFunctionTemplateSpecRecord : GlobalFunctionRecord {
+ GlobalFunctionTemplateSpecRecord(
+ 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,
@@ -903,6 +953,12 @@
struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
template <>
struct has_function_signature<CXXMethodRecord> : public std::true_type {};
+template <>
+struct has_function_signature<GlobalFunctionTemplateRecord>
+ : public std::true_type {};
+template <>
+struct has_function_signature<GlobalFunctionTemplateSpecRecord>
+ : public std::true_type {};
template <typename RecordTy> struct has_access : public std::false_type {};
template <> struct has_access<CXXMethodRecord> : public std::true_type {};
@@ -918,6 +974,8 @@
template <>
struct has_template<GlobalVariableTemplatePartialSpecRecord>
: public std::true_type {};
+template <>
+struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
/// APISet holds the set of API records collected from given inputs.
class APISet {
@@ -955,6 +1013,20 @@
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);
+
+ GlobalFunctionTemplateSpecRecord *addGlobalFunctionTemplateSpec(
+ 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
@@ -1197,6 +1269,14 @@
const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
return GlobalFunctions;
}
+ const RecordMap<GlobalFunctionTemplateRecord> &
+ getGlobalFunctionTemplates() const {
+ return GlobalFunctionTemplates;
+ }
+ const RecordMap<GlobalFunctionTemplateSpecRecord> &
+ getGlobalFunctionTemplateSpecializations() const {
+ return GlobalFunctionTemplateSpecializations;
+ }
const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
return GlobalVariables;
}
@@ -1283,6 +1363,9 @@
llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
RecordMap<GlobalFunctionRecord> GlobalFunctions;
+ RecordMap<GlobalFunctionTemplateRecord> GlobalFunctionTemplates;
+ RecordMap<GlobalFunctionTemplateSpecRecord>
+ GlobalFunctionTemplateSpecializations;
RecordMap<GlobalVariableRecord> GlobalVariables;
RecordMap<GlobalVariableTemplateRecord> GlobalVariableTemplates;
RecordMap<GlobalVariableTemplateSpecRecord>
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits