Skip to content

Commit f46b01a

Browse files
evelez7daniel-grumberg
authored andcommitted
[clang][ExtractAPI] Add support for C++ class templates and concepts
Add has_template template, DeclarationFragmentBuilder functions, and tests for class templates, specializations/partial specs, and concepts. Depends on D157007 Reviewed By: dang Differential Revision: https://reviews.llvm.org/D157076
1 parent afafb3c commit f46b01a

File tree

13 files changed

+1648
-16
lines changed

13 files changed

+1648
-16
lines changed

clang/include/clang/ExtractAPI/API.h

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,86 @@
3636
namespace clang {
3737
namespace extractapi {
3838

39+
class Template {
40+
struct TemplateParameter {
41+
// "class", "typename", or concept name
42+
std::string Type;
43+
std::string Name;
44+
unsigned int Index;
45+
unsigned int Depth;
46+
bool IsParameterPack;
47+
48+
TemplateParameter(std::string Type, std::string Name, unsigned int Index,
49+
unsigned int Depth, bool IsParameterPack)
50+
: Type(Type), Name(Name), Index(Index), Depth(Depth),
51+
IsParameterPack(IsParameterPack) {}
52+
};
53+
54+
struct TemplateConstraint {
55+
// type name of the constraint, if it has one
56+
std::string Type;
57+
std::string Kind;
58+
std::string LHS, RHS;
59+
};
60+
llvm::SmallVector<TemplateParameter> Parameters;
61+
llvm::SmallVector<TemplateConstraint> Constraints;
62+
63+
public:
64+
Template() = default;
65+
66+
Template(const TemplateDecl *Decl) {
67+
for (auto *const Parameter : *Decl->getTemplateParameters()) {
68+
const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
69+
if (!Param) // some params are null
70+
continue;
71+
std::string Type;
72+
if (Param->hasTypeConstraint())
73+
Type = Param->getTypeConstraint()->getNamedConcept()->getName().str();
74+
else if (Param->wasDeclaredWithTypename())
75+
Type = "typename";
76+
else
77+
Type = "class";
78+
79+
addTemplateParameter(Type, Param->getName().str(), Param->getIndex(),
80+
Param->getDepth(), Param->isParameterPack());
81+
}
82+
}
83+
84+
Template(const ClassTemplatePartialSpecializationDecl *Decl) {
85+
for (auto *const Parameter : *Decl->getTemplateParameters()) {
86+
const auto *Param = dyn_cast<TemplateTypeParmDecl>(Parameter);
87+
if (!Param) // some params are null
88+
continue;
89+
std::string Type;
90+
if (Param->hasTypeConstraint())
91+
Type = Param->getTypeConstraint()->getNamedConcept()->getName().str();
92+
else if (Param->wasDeclaredWithTypename())
93+
Type = "typename";
94+
else
95+
Type = "class";
96+
97+
addTemplateParameter(Type, Param->getName().str(), Param->getIndex(),
98+
Param->getDepth(), Param->isParameterPack());
99+
}
100+
}
101+
102+
const llvm::SmallVector<TemplateParameter> &getParameters() const {
103+
return Parameters;
104+
}
105+
106+
const llvm::SmallVector<TemplateConstraint> &getConstraints() const {
107+
return Constraints;
108+
}
109+
110+
void addTemplateParameter(std::string Type, std::string Name,
111+
unsigned int Index, unsigned int Depth,
112+
bool IsParameterPack) {
113+
Parameters.emplace_back(Type, Name, Index, Depth, IsParameterPack);
114+
}
115+
116+
bool empty() const { return Parameters.empty() && Constraints.empty(); }
117+
};
118+
39119
/// DocComment is a vector of RawComment::CommentLine.
40120
///
41121
/// Each line represents one line of striped documentation comment,
@@ -69,6 +149,10 @@ struct APIRecord {
69149
RK_StaticField,
70150
RK_CXXField,
71151
RK_CXXClass,
152+
RK_ClassTemplate,
153+
RK_ClassTemplateSpecialization,
154+
RK_ClassTemplatePartialSpecialization,
155+
RK_Concept,
72156
RK_CXXStaticMethod,
73157
RK_CXXInstanceMethod,
74158
RK_CXXConstructorMethod,
@@ -640,6 +724,75 @@ struct CXXClassRecord : APIRecord {
640724
virtual void anchor();
641725
};
642726

727+
struct ClassTemplateRecord : CXXClassRecord {
728+
Template Templ;
729+
730+
ClassTemplateRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
731+
AvailabilitySet Availabilities, const DocComment &Comment,
732+
DeclarationFragments Declaration,
733+
DeclarationFragments SubHeading, Template Template,
734+
bool IsFromSystemHeader)
735+
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
736+
Declaration, SubHeading, RK_ClassTemplate,
737+
IsFromSystemHeader),
738+
Templ(Template) {}
739+
740+
static bool classof(const APIRecord *Record) {
741+
return Record->getKind() == RK_ClassTemplate;
742+
}
743+
};
744+
745+
struct ClassTemplateSpecializationRecord : CXXClassRecord {
746+
ClassTemplateSpecializationRecord(StringRef USR, StringRef Name,
747+
PresumedLoc Loc,
748+
AvailabilitySet Availabilities,
749+
const DocComment &Comment,
750+
DeclarationFragments Declaration,
751+
DeclarationFragments SubHeading,
752+
bool IsFromSystemHeader)
753+
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
754+
Declaration, SubHeading, RK_ClassTemplateSpecialization,
755+
IsFromSystemHeader) {}
756+
757+
static bool classof(const APIRecord *Record) {
758+
return Record->getKind() == RK_ClassTemplateSpecialization;
759+
}
760+
};
761+
762+
struct ClassTemplatePartialSpecializationRecord : CXXClassRecord {
763+
Template Templ;
764+
ClassTemplatePartialSpecializationRecord(
765+
StringRef USR, StringRef Name, PresumedLoc Loc,
766+
AvailabilitySet Availabilities, const DocComment &Comment,
767+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
768+
Template Template, bool IsFromSystemHeader)
769+
: CXXClassRecord(USR, Name, Loc, std::move(Availabilities), Comment,
770+
Declaration, SubHeading, RK_ClassTemplateSpecialization,
771+
IsFromSystemHeader),
772+
Templ(Template) {}
773+
774+
static bool classof(const APIRecord *Record) {
775+
return Record->getKind() == RK_ClassTemplatePartialSpecialization;
776+
}
777+
};
778+
779+
struct ConceptRecord : APIRecord {
780+
Template Templ;
781+
ConceptRecord(StringRef USR, StringRef Name, PresumedLoc Loc,
782+
AvailabilitySet Availabilities, const DocComment &Comment,
783+
DeclarationFragments Declaration,
784+
DeclarationFragments SubHeading, Template Template,
785+
bool IsFromSystemHeader)
786+
: APIRecord(RK_Concept, USR, Name, Loc, std::move(Availabilities),
787+
LinkageInfo::none(), Comment, Declaration, SubHeading,
788+
IsFromSystemHeader),
789+
Templ(Template) {}
790+
791+
static bool classof(const APIRecord *Record) {
792+
return Record->getKind() == RK_Concept;
793+
}
794+
};
795+
643796
/// This holds information associated with Objective-C categories.
644797
struct ObjCCategoryRecord : ObjCContainerRecord {
645798
SymbolReference Interface;
@@ -773,6 +926,13 @@ template <typename RecordTy> struct has_access : public std::false_type {};
773926
template <> struct has_access<CXXMethodRecord> : public std::true_type {};
774927
template <> struct has_access<CXXFieldRecord> : public std::true_type {};
775928

929+
template <typename RecordTy> struct has_template : public std::false_type {};
930+
template <> struct has_template<ClassTemplateRecord> : public std::true_type {};
931+
template <>
932+
struct has_template<ClassTemplatePartialSpecializationRecord>
933+
: public std::true_type {};
934+
template <> struct has_template<ConceptRecord> : public std::true_type {};
935+
776936
/// APISet holds the set of API records collected from given inputs.
777937
class APISet {
778938
public:
@@ -870,6 +1030,26 @@ class APISet {
8701030
DeclarationFragments Declaration, DeclarationFragments SubHeading,
8711031
APIRecord::RecordKind Kind, bool IsFromSystemHeader);
8721032

1033+
ClassTemplateRecord *
1034+
addClassTemplate(StringRef Name, StringRef USR, PresumedLoc Loc,
1035+
AvailabilitySet Availability, const DocComment &Comment,
1036+
DeclarationFragments Declaration,
1037+
DeclarationFragments SubHeading, Template Template,
1038+
bool IsFromSystemHeader);
1039+
1040+
ClassTemplateSpecializationRecord *addClassTemplateSpecialization(
1041+
StringRef Name, StringRef USR, PresumedLoc Loc,
1042+
AvailabilitySet Availability, const DocComment &Comment,
1043+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1044+
bool IsFromSystemHeader);
1045+
1046+
ClassTemplatePartialSpecializationRecord *
1047+
addClassTemplatePartialSpecialization(
1048+
StringRef Name, StringRef USR, PresumedLoc Loc,
1049+
AvailabilitySet Availability, const DocComment &Comment,
1050+
DeclarationFragments Declaration, DeclarationFragments SubHeading,
1051+
Template Template, bool IsFromSystemHeader);
1052+
8731053
CXXMethodRecord *
8741054
addCXXMethod(CXXClassRecord *CXXClassRecord, StringRef Name, StringRef USR,
8751055
PresumedLoc Loc, AvailabilitySet Availability,
@@ -884,6 +1064,13 @@ class APISet {
8841064
FunctionSignature Signature, bool IsConstructor, AccessControl Access,
8851065
bool IsFromSystemHeader);
8861066

1067+
ConceptRecord *addConcept(StringRef Name, StringRef USR, PresumedLoc Loc,
1068+
AvailabilitySet Availability,
1069+
const DocComment &Comment,
1070+
DeclarationFragments Declaration,
1071+
DeclarationFragments SubHeading, Template Template,
1072+
bool IsFromSystemHeader);
1073+
8871074
/// Create and add an Objective-C category record into the API set.
8881075
///
8891076
/// Note: the caller is responsible for keeping the StringRef \p Name and
@@ -1012,6 +1199,19 @@ class APISet {
10121199
const RecordMap<EnumRecord> &getEnums() const { return Enums; }
10131200
const RecordMap<StructRecord> &getStructs() const { return Structs; }
10141201
const RecordMap<CXXClassRecord> &getCXXClasses() const { return CXXClasses; }
1202+
const RecordMap<ConceptRecord> &getConcepts() const { return Concepts; }
1203+
const RecordMap<ClassTemplateRecord> &getClassTemplates() const {
1204+
return ClassTemplates;
1205+
}
1206+
const RecordMap<ClassTemplateSpecializationRecord> &
1207+
getClassTemplateSpecializations() const {
1208+
return ClassTemplateSpecializations;
1209+
}
1210+
const RecordMap<ClassTemplatePartialSpecializationRecord> &
1211+
getClassTemplatePartialSpecializations() const {
1212+
return ClassTemplatePartialSpecializations;
1213+
}
1214+
const RecordMap<ConceptRecord> &getRecords() const { return Concepts; }
10151215
const RecordMap<ObjCCategoryRecord> &getObjCCategories() const {
10161216
return ObjCCategories;
10171217
}
@@ -1065,10 +1265,15 @@ class APISet {
10651265
llvm::DenseMap<StringRef, APIRecord *> USRBasedLookupTable;
10661266
RecordMap<GlobalFunctionRecord> GlobalFunctions;
10671267
RecordMap<GlobalVariableRecord> GlobalVariables;
1268+
RecordMap<ConceptRecord> Concepts;
10681269
RecordMap<StaticFieldRecord> StaticFields;
10691270
RecordMap<EnumRecord> Enums;
10701271
RecordMap<StructRecord> Structs;
10711272
RecordMap<CXXClassRecord> CXXClasses;
1273+
RecordMap<ClassTemplateRecord> ClassTemplates;
1274+
RecordMap<ClassTemplateSpecializationRecord> ClassTemplateSpecializations;
1275+
RecordMap<ClassTemplatePartialSpecializationRecord>
1276+
ClassTemplatePartialSpecializations;
10721277
RecordMap<ObjCCategoryRecord> ObjCCategories;
10731278
RecordMap<ObjCInterfaceRecord> ObjCInterfaces;
10741279
RecordMap<ObjCProtocolRecord> ObjCProtocols;

clang/include/clang/ExtractAPI/DeclarationFragments.h

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "clang/AST/Decl.h"
2323
#include "clang/AST/DeclCXX.h"
2424
#include "clang/AST/DeclObjC.h"
25+
#include "clang/AST/DeclTemplate.h"
2526
#include "clang/AST/TypeLoc.h"
2627
#include "clang/Lex/MacroInfo.h"
2728
#include "llvm/ADT/StringRef.h"
@@ -162,6 +163,11 @@ class DeclarationFragments {
162163
return *this;
163164
}
164165

166+
DeclarationFragments &pop_back() {
167+
Fragments.pop_back();
168+
return *this;
169+
}
170+
165171
/// Append a text Fragment of a space character.
166172
///
167173
/// \returns a reference to the DeclarationFragments object itself after
@@ -293,6 +299,28 @@ class DeclarationFragmentsBuilder {
293299
static DeclarationFragments
294300
getFragmentsForOverloadedOperator(const CXXMethodDecl *);
295301

302+
static DeclarationFragments
303+
getFragmentsForTemplateParameters(ArrayRef<NamedDecl *>);
304+
305+
static std::string getNameForTemplateArgument(const ArrayRef<NamedDecl *>,
306+
std::string);
307+
308+
static DeclarationFragments
309+
getFragmentsForTemplateArguments(const ArrayRef<TemplateArgument>,
310+
ASTContext &,
311+
const std::optional<ArrayRef<NamedDecl *>>);
312+
313+
static DeclarationFragments getFragmentsForConcept(const ConceptDecl *);
314+
315+
static DeclarationFragments
316+
getFragmentsForRedeclarableTemplate(const RedeclarableTemplateDecl *);
317+
318+
static DeclarationFragments getFragmentsForClassTemplateSpecialization(
319+
const ClassTemplateSpecializationDecl *);
320+
321+
static DeclarationFragments getFragmentsForClassTemplatePartialSpecialization(
322+
const ClassTemplatePartialSpecializationDecl *);
323+
296324
/// Build DeclarationFragments for an Objective-C category declaration
297325
/// ObjCCategoryDecl.
298326
static DeclarationFragments

0 commit comments

Comments
 (0)