mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-13 19:24:21 +00:00
[clang][ExtractAPI] Visit method templates with better scheme
Visit and serialize method templates and template specializations. Introduces a new scheme of visiting child Decls via VisitCXXMethodDecl which will be followed in future patches for Fields and non-template methods. Depends on D157579 Reviewed By: dang Differential Revision: https://reviews.llvm.org/D158027
This commit is contained in:
parent
1094e2ebba
commit
d8e9c5d9ca
@ -180,6 +180,8 @@ struct APIRecord {
|
||||
RK_CXXInstanceMethod,
|
||||
RK_CXXConstructorMethod,
|
||||
RK_CXXDestructorMethod,
|
||||
RK_CXXMethodTemplate,
|
||||
RK_CXXMethodTemplateSpecialization,
|
||||
RK_ObjCInstanceProperty,
|
||||
RK_ObjCClassProperty,
|
||||
RK_ObjCIvar,
|
||||
@ -623,6 +625,42 @@ private:
|
||||
virtual void anchor();
|
||||
};
|
||||
|
||||
struct CXXMethodTemplateRecord : CXXMethodRecord {
|
||||
Template Templ;
|
||||
|
||||
CXXMethodTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities,
|
||||
const DocComment &Comment,
|
||||
DeclarationFragments Declaration,
|
||||
DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access,
|
||||
Template Template, bool IsFromSystemHeader)
|
||||
: CXXMethodRecord(RK_CXXMethodTemplate, USR, Name, Loc,
|
||||
std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader),
|
||||
Templ(Template) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_CXXMethodTemplate;
|
||||
}
|
||||
};
|
||||
|
||||
struct CXXMethodTemplateSpecializationRecord : CXXMethodRecord {
|
||||
CXXMethodTemplateSpecializationRecord(
|
||||
StringRef USR, StringRef Name, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access,
|
||||
bool IsFromSystemHeader)
|
||||
: CXXMethodRecord(RK_CXXMethodTemplateSpecialization, USR, Name, Loc,
|
||||
std::move(Availabilities), Comment, Declaration,
|
||||
SubHeading, Signature, Access, IsFromSystemHeader) {}
|
||||
|
||||
static bool classof(const APIRecord *Record) {
|
||||
return Record->getKind() == RK_CXXMethodTemplateSpecialization;
|
||||
}
|
||||
};
|
||||
|
||||
/// This holds information associated with Objective-C properties.
|
||||
struct ObjCPropertyRecord : APIRecord {
|
||||
/// The attributes associated with an Objective-C property.
|
||||
@ -794,6 +832,8 @@ struct SymbolReference {
|
||||
: Name(Name), USR(USR), Source(Source) {}
|
||||
SymbolReference(const APIRecord &Record)
|
||||
: Name(Record.Name), USR(Record.USR) {}
|
||||
SymbolReference(const APIRecord *Record)
|
||||
: Name(Record->Name), USR(Record->USR) {}
|
||||
|
||||
/// Determine if this SymbolReference is empty.
|
||||
///
|
||||
@ -1058,10 +1098,21 @@ template <>
|
||||
struct has_function_signature<ObjCClassMethodRecord> : public std::true_type {};
|
||||
template <>
|
||||
struct has_function_signature<CXXMethodRecord> : public std::true_type {};
|
||||
template <>
|
||||
struct has_function_signature<CXXMethodTemplateRecord> : public std::true_type {
|
||||
};
|
||||
template <>
|
||||
struct has_function_signature<CXXMethodTemplateSpecializationRecord>
|
||||
: public std::true_type {};
|
||||
|
||||
template <typename RecordTy> struct has_access : public std::false_type {};
|
||||
template <> struct has_access<CXXMethodRecord> : public std::true_type {};
|
||||
template <> struct has_access<CXXFieldRecord> : public std::true_type {};
|
||||
template <>
|
||||
struct has_access<CXXMethodTemplateRecord> : public std::true_type {};
|
||||
template <>
|
||||
struct has_access<CXXMethodTemplateSpecializationRecord>
|
||||
: public std::true_type {};
|
||||
|
||||
template <typename RecordTy> struct has_template : public std::false_type {};
|
||||
template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
|
||||
@ -1074,6 +1125,8 @@ struct has_template<GlobalVariableTemplateRecord> : public std::true_type {};
|
||||
template <>
|
||||
struct has_template<GlobalVariableTemplatePartialSpecializationRecord>
|
||||
: public std::true_type {};
|
||||
template <>
|
||||
struct has_template<CXXMethodTemplateRecord> : public std::true_type {};
|
||||
|
||||
template <>
|
||||
struct has_template<GlobalFunctionTemplateRecord> : public std::true_type {};
|
||||
@ -1253,6 +1306,20 @@ public:
|
||||
FunctionSignature Signature, bool IsConstructor, AccessControl Access,
|
||||
bool IsFromSystemHeader);
|
||||
|
||||
CXXMethodTemplateRecord *addCXXMethodTemplate(
|
||||
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access, Template Template,
|
||||
bool IsFromSystemHeader);
|
||||
|
||||
CXXMethodTemplateSpecializationRecord *addCXXMethodTemplateSpec(
|
||||
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access,
|
||||
bool IsFromSystemHeader);
|
||||
|
||||
ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability,
|
||||
const DocComment &Comment,
|
||||
@ -1408,6 +1475,13 @@ public:
|
||||
const RecordMap<EnumRecord> &getEnums() const { return Enums; }
|
||||
const RecordMap<StructRecord> &getStructs() const { return Structs; }
|
||||
const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
|
||||
const RecordMap<CXXMethodTemplateRecord> &getCXXMethodTemplates() const {
|
||||
return CXXMethodTemplates;
|
||||
}
|
||||
const RecordMap<CXXMethodTemplateSpecializationRecord> &
|
||||
getCXXMethodTemplateSpecializations() const {
|
||||
return CXXMethodTemplateSpecializations;
|
||||
}
|
||||
const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
|
||||
const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
|
||||
return ClassTemplates;
|
||||
@ -1487,6 +1561,9 @@ private:
|
||||
RecordMap<EnumRecord> Enums;
|
||||
RecordMap<StructRecord> Structs;
|
||||
RecordMap<CXXClassRecord> CXXClasses;
|
||||
RecordMap<CXXMethodTemplateRecord> CXXMethodTemplates;
|
||||
RecordMap<CXXMethodTemplateSpecializationRecord>
|
||||
CXXMethodTemplateSpecializations;
|
||||
RecordMap<ClassTemplateRecord> ClassTemplates;
|
||||
RecordMap<ClassTemplateSpecializationRecord> ClassTemplateSpecializations;
|
||||
RecordMap<ClassTemplatePartialSpecializationRecord>
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "clang/Basic/SourceManager.h"
|
||||
#include "clang/ExtractAPI/API.h"
|
||||
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
|
||||
#include "clang/Index/USRGeneration.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include <type_traits>
|
||||
|
||||
@ -53,6 +54,8 @@ public:
|
||||
|
||||
bool WalkUpFromCXXRecordDecl(const CXXRecordDecl *Decl);
|
||||
|
||||
bool WalkUpFromCXXMethodDecl(const CXXMethodDecl *Decl);
|
||||
|
||||
bool WalkUpFromClassTemplateSpecializationDecl(
|
||||
const ClassTemplateSpecializationDecl *Decl);
|
||||
|
||||
@ -73,6 +76,8 @@ public:
|
||||
|
||||
bool VisitCXXRecordDecl(const CXXRecordDecl *Decl);
|
||||
|
||||
bool VisitCXXMethodDecl(const CXXMethodDecl *Decl);
|
||||
|
||||
bool VisitConceptDecl(const ConceptDecl *Decl);
|
||||
|
||||
bool VisitClassTemplateSpecializationDecl(
|
||||
@ -287,11 +292,11 @@ bool ExtractAPIVisitorBase<Derived>::VisitFunctionDecl(
|
||||
switch (Decl->getTemplatedKind()) {
|
||||
case FunctionDecl::TK_NonTemplate:
|
||||
case FunctionDecl::TK_DependentNonTemplate:
|
||||
case FunctionDecl::TK_MemberSpecialization:
|
||||
case FunctionDecl::TK_FunctionTemplateSpecialization:
|
||||
break;
|
||||
case FunctionDecl::TK_FunctionTemplate:
|
||||
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
|
||||
case FunctionDecl::TK_MemberSpecialization:
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -387,6 +392,13 @@ bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXRecordDecl(
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::WalkUpFromCXXMethodDecl(
|
||||
const CXXMethodDecl *Decl) {
|
||||
getDerivedExtractAPIVisitor().VisitCXXMethodDecl(Decl);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::WalkUpFromClassTemplateSpecializationDecl(
|
||||
const ClassTemplateSpecializationDecl *Decl) {
|
||||
@ -521,6 +533,60 @@ bool ExtractAPIVisitorBase<Derived>::VisitCXXRecordDecl(
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitCXXMethodDecl(
|
||||
const CXXMethodDecl *Decl) {
|
||||
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl) ||
|
||||
Decl->isImplicit())
|
||||
return true;
|
||||
switch (Decl->getTemplatedKind()) {
|
||||
case FunctionDecl::TK_MemberSpecialization:
|
||||
case FunctionDecl::TK_FunctionTemplateSpecialization:
|
||||
case FunctionDecl::TK_FunctionTemplate:
|
||||
case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
|
||||
break;
|
||||
case FunctionDecl::TK_NonTemplate:
|
||||
case FunctionDecl::TK_DependentNonTemplate:
|
||||
return true;
|
||||
}
|
||||
|
||||
StringRef Name = Decl->getName();
|
||||
StringRef USR = API.recordUSR(Decl);
|
||||
PresumedLoc Loc =
|
||||
Context.getSourceManager().getPresumedLoc(Decl->getLocation());
|
||||
DocComment Comment;
|
||||
if (auto *RawComment =
|
||||
getDerivedExtractAPIVisitor().fetchRawCommentForDecl(Decl))
|
||||
Comment = RawComment->getFormattedLines(Context.getSourceManager(),
|
||||
Context.getDiagnostics());
|
||||
DeclarationFragments SubHeading =
|
||||
DeclarationFragmentsBuilder::getSubHeading(Decl);
|
||||
|
||||
SmallString<128> ParentUSR;
|
||||
index::generateUSRForDecl(dyn_cast<CXXRecordDecl>(Decl->getDeclContext()),
|
||||
ParentUSR);
|
||||
if (Decl->isTemplated()) {
|
||||
FunctionTemplateDecl *TemplateDecl = Decl->getDescribedFunctionTemplate();
|
||||
API.addCXXMethodTemplate(
|
||||
API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl),
|
||||
Comment,
|
||||
DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
|
||||
TemplateDecl),
|
||||
SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
|
||||
DeclarationFragmentsBuilder::getAccessControl(TemplateDecl),
|
||||
Template(TemplateDecl), isInSystemHeader(Decl));
|
||||
} else if (Decl->getTemplateSpecializationInfo())
|
||||
API.addCXXMethodTemplateSpec(
|
||||
API.findRecordForUSR(ParentUSR), Name, USR, Loc, AvailabilitySet(Decl),
|
||||
Comment,
|
||||
DeclarationFragmentsBuilder::
|
||||
getFragmentsForFunctionTemplateSpecialization(Decl),
|
||||
SubHeading, DeclarationFragmentsBuilder::getFunctionSignature(Decl),
|
||||
DeclarationFragmentsBuilder::getAccessControl(Decl),
|
||||
isInSystemHeader(Decl));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitConceptDecl(const ConceptDecl *Decl) {
|
||||
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
|
||||
@ -712,6 +778,8 @@ bool ExtractAPIVisitorBase<Derived>::VisitVarTemplatePartialSpecializationDecl(
|
||||
template <typename Derived>
|
||||
bool ExtractAPIVisitorBase<Derived>::VisitFunctionTemplateDecl(
|
||||
const FunctionTemplateDecl *Decl) {
|
||||
if (isa<CXXMethodDecl>(Decl->getTemplatedDecl()))
|
||||
return true;
|
||||
if (!getDerivedExtractAPIVisitor().shouldDeclBeIncluded(Decl))
|
||||
return true;
|
||||
|
||||
@ -1099,6 +1167,9 @@ void ExtractAPIVisitorBase<Derived>::recordCXXMethods(
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Method->isFunctionTemplateSpecialization())
|
||||
return;
|
||||
|
||||
StringRef Name;
|
||||
DeclarationFragments Declaration;
|
||||
if (Method->isOverloadedOperator()) {
|
||||
|
@ -39,6 +39,10 @@ public:
|
||||
|
||||
getDerived()->traverseClassTemplatePartialSpecializationRecords();
|
||||
|
||||
getDerived()->traverseCXXMethodTemplates();
|
||||
|
||||
getDerived()->traverseCXXMethodTemplateSpecializations();
|
||||
|
||||
getDerived()->traverseConcepts();
|
||||
|
||||
getDerived()->traverseGlobalVariableTemplateRecords();
|
||||
@ -94,6 +98,18 @@ public:
|
||||
getDerived()->visitCXXClassRecord(*Class.second);
|
||||
}
|
||||
|
||||
void traverseCXXMethodTemplates() {
|
||||
for (const auto &MethodTemplate : API.getCXXMethodTemplates())
|
||||
getDerived()->visitMethodTemplateRecord(*MethodTemplate.second);
|
||||
}
|
||||
|
||||
void traverseCXXMethodTemplateSpecializations() {
|
||||
for (const auto &MethodTemplateSpecialization :
|
||||
API.getCXXMethodTemplateSpecializations())
|
||||
getDerived()->visitMethodTemplateSpecializationRecord(
|
||||
*MethodTemplateSpecialization.second);
|
||||
}
|
||||
|
||||
void traverseClassTemplateRecords() {
|
||||
for (const auto &ClassTemplate : API.getClassTemplates())
|
||||
getDerived()->visitClassTemplateRecord(*ClassTemplate.second);
|
||||
@ -200,6 +216,11 @@ public:
|
||||
void visitClassTemplatePartialSpecializationRecord(
|
||||
const ClassTemplatePartialSpecializationRecord &Record){};
|
||||
|
||||
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record){};
|
||||
|
||||
void visitMethodTemplateSpecializationRecord(
|
||||
const CXXMethodTemplateSpecializationRecord &Record){};
|
||||
|
||||
void visitGlobalVariableTemplateRecord(
|
||||
const GlobalVariableTemplateRecord &Record) {}
|
||||
|
||||
|
@ -183,6 +183,11 @@ public:
|
||||
void visitClassTemplatePartialSpecializationRecord(
|
||||
const ClassTemplatePartialSpecializationRecord &Record);
|
||||
|
||||
void visitMethodTemplateRecord(const CXXMethodTemplateRecord &Record);
|
||||
|
||||
void visitMethodTemplateSpecializationRecord(
|
||||
const CXXMethodTemplateSpecializationRecord &Record);
|
||||
|
||||
void visitConceptRecord(const ConceptRecord &Record);
|
||||
|
||||
void
|
||||
|
@ -311,6 +311,39 @@ CXXMethodRecord *APISet::addCXXSpecialMethod(
|
||||
return CXXClassRecord->Methods.emplace_back(std::move(Record)).get();
|
||||
}
|
||||
|
||||
CXXMethodTemplateRecord *APISet::addCXXMethodTemplate(
|
||||
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access, Template Template,
|
||||
bool IsFromSystemHeader) {
|
||||
auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR,
|
||||
Name, Loc, std::move(Availability), Comment,
|
||||
Declaration, SubHeading, Signature, Access,
|
||||
Template, IsFromSystemHeader);
|
||||
Record->ParentInformation = APIRecord::HierarchyInformation(
|
||||
Parent->USR, Parent->Name, Parent->getKind(), Parent);
|
||||
|
||||
return Record;
|
||||
}
|
||||
|
||||
CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec(
|
||||
APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availability, const DocComment &Comment,
|
||||
DeclarationFragments Declaration, DeclarationFragments SubHeading,
|
||||
FunctionSignature Signature, AccessControl Access,
|
||||
bool IsFromSystemHeader) {
|
||||
|
||||
auto *Record = addTopLevelRecord(
|
||||
USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc,
|
||||
std::move(Availability), Comment, Declaration, SubHeading, Signature,
|
||||
Access, IsFromSystemHeader);
|
||||
Record->ParentInformation = APIRecord::HierarchyInformation(
|
||||
Parent->USR, Parent->Name, Parent->getKind(), Parent);
|
||||
|
||||
return Record;
|
||||
}
|
||||
|
||||
ObjCCategoryRecord *APISet::addObjCCategory(
|
||||
StringRef Name, StringRef USR, PresumedLoc Loc,
|
||||
AvailabilitySet Availabilities, const DocComment &Comment,
|
||||
|
@ -420,6 +420,14 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
|
||||
Kind["identifier"] = AddLangPrefix("class");
|
||||
Kind["displayName"] = "Class";
|
||||
break;
|
||||
case APIRecord::RK_CXXMethodTemplate:
|
||||
Kind["identifier"] = AddLangPrefix("method");
|
||||
Kind["displayName"] = "Method Template";
|
||||
break;
|
||||
case APIRecord::RK_CXXMethodTemplateSpecialization:
|
||||
Kind["identifier"] = AddLangPrefix("method");
|
||||
Kind["displayName"] = "Method Template Specialization";
|
||||
break;
|
||||
case APIRecord::RK_Concept:
|
||||
Kind["identifier"] = AddLangPrefix("concept");
|
||||
Kind["displayName"] = "Concept";
|
||||
@ -922,6 +930,32 @@ void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
|
||||
serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitMethodTemplateRecord(
|
||||
const CXXMethodTemplateRecord &Record) {
|
||||
if (!ShouldRecurse)
|
||||
// Ignore child symbols
|
||||
return;
|
||||
auto MethodTemplate = serializeAPIRecord(Record);
|
||||
if (!MethodTemplate)
|
||||
return;
|
||||
Symbols.emplace_back(std::move(*MethodTemplate));
|
||||
serializeRelationship(RelationshipKind::MemberOf, Record,
|
||||
Record.ParentInformation.ParentRecord);
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitMethodTemplateSpecializationRecord(
|
||||
const CXXMethodTemplateSpecializationRecord &Record) {
|
||||
if (!ShouldRecurse)
|
||||
// Ignore child symbols
|
||||
return;
|
||||
auto MethodTemplateSpecialization = serializeAPIRecord(Record);
|
||||
if (!MethodTemplateSpecialization)
|
||||
return;
|
||||
Symbols.emplace_back(std::move(*MethodTemplateSpecialization));
|
||||
serializeRelationship(RelationshipKind::MemberOf, Record,
|
||||
Record.ParentInformation.ParentRecord);
|
||||
}
|
||||
|
||||
void SymbolGraphSerializer::visitConceptRecord(const ConceptRecord &Record) {
|
||||
auto Concept = serializeAPIRecord(Record);
|
||||
if (!Concept)
|
||||
|
244
clang/test/ExtractAPI/method_template.cpp
Normal file
244
clang/test/ExtractAPI/method_template.cpp
Normal file
@ -0,0 +1,244 @@
|
||||
// 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
|
||||
class Foo {
|
||||
template<typename T> void Bar(T Fizz);
|
||||
};
|
||||
|
||||
/// 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": [
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@FT@>1#TBar#t0.0#v#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"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": "Bar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Fizz"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Fizz"
|
||||
}
|
||||
],
|
||||
"name": "Fizz"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@FT@>1#TBar#t0.0#v#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Method Template",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 29,
|
||||
"line": 2
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"title": "Bar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"Bar"
|
||||
],
|
||||
"swiftGenerics": {
|
||||
"parameters": [
|
||||
{
|
||||
"depth": 0,
|
||||
"index": 0,
|
||||
"name": "T"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
371
clang/test/ExtractAPI/method_template_spec.cpp
Normal file
371
clang/test/ExtractAPI/method_template_spec.cpp
Normal file
@ -0,0 +1,371 @@
|
||||
// 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
|
||||
class Foo {
|
||||
template<typename T> void Bar(T Fizz);
|
||||
|
||||
template<> void Bar<int>(int Fizz);
|
||||
};
|
||||
|
||||
/// 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": [
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@FT@>1#TBar#t0.0#v#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "memberOf",
|
||||
"source": "c:@S@Foo@F@Bar<#I>#I#",
|
||||
"target": "c:@S@Foo",
|
||||
"targetFallback": "Foo"
|
||||
}
|
||||
],
|
||||
"symbols": [
|
||||
{
|
||||
"accessLevel": "public",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "class"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ";"
|
||||
}
|
||||
],
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Class",
|
||||
"identifier": "c++.class"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 7,
|
||||
"line": 1
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Foo"
|
||||
}
|
||||
],
|
||||
"title": "Foo"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo"
|
||||
]
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"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": "Bar"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "("
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Fizz"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:t0.0",
|
||||
"spelling": "T"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Fizz"
|
||||
}
|
||||
],
|
||||
"name": "Fizz"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@FT@>1#TBar#t0.0#v#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Method Template",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 29,
|
||||
"line": 2
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"title": "Bar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"Bar"
|
||||
],
|
||||
"swiftGenerics": {
|
||||
"parameters": [
|
||||
{
|
||||
"depth": 0,
|
||||
"index": 0,
|
||||
"name": "T"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"accessLevel": "private",
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "keyword",
|
||||
"spelling": "template"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": "<> "
|
||||
},
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
},
|
||||
{
|
||||
"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": "Fizz"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": ");"
|
||||
}
|
||||
],
|
||||
"functionSignature": {
|
||||
"parameters": [
|
||||
{
|
||||
"declarationFragments": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:I",
|
||||
"spelling": "int"
|
||||
},
|
||||
{
|
||||
"kind": "text",
|
||||
"spelling": " "
|
||||
},
|
||||
{
|
||||
"kind": "internalParam",
|
||||
"spelling": "Fizz"
|
||||
}
|
||||
],
|
||||
"name": "Fizz"
|
||||
}
|
||||
],
|
||||
"returns": [
|
||||
{
|
||||
"kind": "typeIdentifier",
|
||||
"preciseIdentifier": "c:v",
|
||||
"spelling": "void"
|
||||
}
|
||||
]
|
||||
},
|
||||
"identifier": {
|
||||
"interfaceLanguage": "c++",
|
||||
"precise": "c:@S@Foo@F@Bar<#I>#I#"
|
||||
},
|
||||
"kind": {
|
||||
"displayName": "Method Template Specialization",
|
||||
"identifier": "c++.method"
|
||||
},
|
||||
"location": {
|
||||
"position": {
|
||||
"character": 19,
|
||||
"line": 4
|
||||
},
|
||||
"uri": "file://INPUT_DIR/input.h"
|
||||
},
|
||||
"names": {
|
||||
"navigator": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"subHeading": [
|
||||
{
|
||||
"kind": "identifier",
|
||||
"spelling": "Bar"
|
||||
}
|
||||
],
|
||||
"title": "Bar"
|
||||
},
|
||||
"pathComponents": [
|
||||
"Foo",
|
||||
"Bar"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
Loading…
Reference in New Issue
Block a user