Skip to content

Commit 1e392f7

Browse files
committed
function template template parameters
#feat fix #795
1 parent 4031c9f commit 1e392f7

11 files changed

+226
-91
lines changed

include/mrdocs/Metadata/Template.hpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ enum class TParamKind : int
175175
Type = 1, // for bitstream
176176
// template non-type parameter, e.g. "int N" or "auto N"
177177
NonType,
178-
// template template parameter, e.g. "template<typename> typename T"
178+
// Template-template parameter, e.g. "template<typename> typename T"
179179
Template
180180
};
181181

@@ -235,7 +235,7 @@ tag_invoke(
235235

236236

237237
template<TParamKind K>
238-
struct IsTParam : TParam
238+
struct TParamCommonBase : TParam
239239
{
240240
static constexpr TParamKind kind_id = K;
241241

@@ -245,7 +245,7 @@ struct IsTParam : TParam
245245

246246
protected:
247247
constexpr
248-
IsTParam() noexcept
248+
TParamCommonBase() noexcept
249249
: TParam(K)
250250
{
251251
}
@@ -271,7 +271,7 @@ tag_invoke(
271271
}
272272

273273
struct TypeTParam
274-
: IsTParam<TParamKind::Type>
274+
: TParamCommonBase<TParamKind::Type>
275275
{
276276
/** Keyword (class/typename) the parameter uses */
277277
TParamKeyKind KeyKind = TParamKeyKind::Class;
@@ -281,14 +281,14 @@ struct TypeTParam
281281
};
282282

283283
struct NonTypeTParam
284-
: IsTParam<TParamKind::NonType>
284+
: TParamCommonBase<TParamKind::NonType>
285285
{
286286
/** Type of the non-type template parameter */
287287
std::unique_ptr<TypeInfo> Type;
288288
};
289289

290290
struct TemplateTParam
291-
: IsTParam<TParamKind::Template>
291+
: TParamCommonBase<TParamKind::Template>
292292
{
293293
/** Template parameters for the template template parameter */
294294
std::vector<std::unique_ptr<TParam>> Params;

src/lib/AST/ASTVisitor.cpp

Lines changed: 82 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,8 @@ populate(
950950
FunctionInfo& I,
951951
DeclTy* D)
952952
{
953+
MRDOCS_SYMBOL_TRACE(D, context_);
954+
953955
// D is the templated declaration if FTD is non-null
954956
if (D->isFunctionTemplateSpecialization())
955957
{
@@ -987,91 +989,91 @@ populate(
987989
}
988990
}
989991

990-
// KRYSTIAN TODO: move other extraction that requires
991-
// a valid function type here
992-
if (auto FT = getDeclaratorType(D); ! FT.isNull())
992+
// Get the function type and extract information that comes from the type
993+
if (auto FT = getDeclaratorType(D); !FT.isNull())
993994
{
995+
MRDOCS_SYMBOL_TRACE(FT, context_);
994996
const auto* FPT = FT->template getAs<FunctionProtoType>();
997+
MRDOCS_SYMBOL_TRACE(FPT, context_);
995998
populate(I.Noexcept, FPT);
996999
I.HasTrailingReturn |= FPT->hasTrailingReturn();
9971000
}
9981001

9991002
//
10001003
// FunctionDecl
10011004
//
1002-
I.OverloadedOperator = toOperatorKind(
1003-
D->getOverloadedOperator());
1004-
I.IsVariadic |= D->isVariadic();
1005-
I.IsDefaulted |= D->isDefaulted();
1006-
I.IsExplicitlyDefaulted |= D->isExplicitlyDefaulted();
1007-
I.IsDeleted |= D->isDeleted();
1008-
I.IsDeletedAsWritten |= D->isDeletedAsWritten();
1009-
I.IsNoReturn |= D->isNoReturn();
1010-
// subsumes D->hasAttr<NoReturnAttr>()
1011-
// subsumes D->hasAttr<CXX11NoReturnAttr>()
1012-
// subsumes D->hasAttr<C11NoReturnAttr>()
1013-
// subsumes D->getType()->getAs<FunctionType>()->getNoReturnAttr()
1014-
I.HasOverrideAttr |= D->template hasAttr<OverrideAttr>();
1015-
1016-
if (ConstexprSpecKind const CSK = D->getConstexprKind();
1005+
FunctionDecl const* FD = D;
1006+
I.OverloadedOperator = toOperatorKind(FD->getOverloadedOperator());
1007+
I.IsVariadic |= FD->isVariadic();
1008+
I.IsDefaulted |= FD->isDefaulted();
1009+
I.IsExplicitlyDefaulted |= FD->isExplicitlyDefaulted();
1010+
I.IsDeleted |= FD->isDeleted();
1011+
I.IsDeletedAsWritten |= FD->isDeletedAsWritten();
1012+
I.IsNoReturn |= FD->isNoReturn();
1013+
I.HasOverrideAttr |= FD->template hasAttr<OverrideAttr>();
1014+
1015+
if (ConstexprSpecKind const CSK = FD->getConstexprKind();
10171016
CSK != ConstexprSpecKind::Unspecified)
10181017
{
10191018
I.Constexpr = toConstexprKind(CSK);
10201019
}
10211020

1022-
if (StorageClass const SC = D->getStorageClass())
1021+
if (StorageClass const SC = FD->getStorageClass())
10231022
{
10241023
I.StorageClass = toStorageClassKind(SC);
10251024
}
10261025

1027-
I.IsNodiscard |= D->template hasAttr<WarnUnusedResultAttr>();
1028-
I.IsExplicitObjectMemberFunction |= D->hasCXXExplicitFunctionObjectParameter();
1026+
I.IsNodiscard |= FD->template hasAttr<WarnUnusedResultAttr>();
1027+
I.IsExplicitObjectMemberFunction |= FD->hasCXXExplicitFunctionObjectParameter();
1028+
10291029
//
10301030
// CXXMethodDecl
10311031
//
10321032
if constexpr(std::derived_from<DeclTy, CXXMethodDecl>)
10331033
{
1034-
I.IsVirtual |= D->isVirtual();
1035-
I.IsVirtualAsWritten |= D->isVirtualAsWritten();
1036-
I.IsPure |= D->isPureVirtual();
1037-
I.IsConst |= D->isConst();
1038-
I.IsVolatile |= D->isVolatile();
1039-
I.RefQualifier = toReferenceKind(D->getRefQualifier());
1040-
I.IsFinal |= D->template hasAttr<FinalAttr>();
1041-
//D->isCopyAssignmentOperator()
1042-
//D->isMoveAssignmentOperator()
1043-
//D->isOverloadedOperator();
1044-
//D->isStaticOverloadedOperator();
1045-
}
1034+
CXXMethodDecl const* MD = D;
1035+
I.IsVirtual |= MD->isVirtual();
1036+
I.IsVirtualAsWritten |= MD->isVirtualAsWritten();
1037+
I.IsPure |= MD->isPureVirtual();
1038+
I.IsConst |= MD->isConst();
1039+
I.IsVolatile |= MD->isVolatile();
1040+
I.RefQualifier = toReferenceKind(MD->getRefQualifier());
1041+
I.IsFinal |= MD->template hasAttr<FinalAttr>();
1042+
//MD->isCopyAssignmentOperator()
1043+
//MD->isMoveAssignmentOperator()
1044+
//MD->isOverloadedOperator();
1045+
//MD->isStaticOverloadedOperator();
10461046

1047-
//
1048-
// CXXDestructorDecl
1049-
//
1050-
// if constexpr(std::derived_from<DeclTy, CXXDestructorDecl>)
1051-
// {
1052-
// }
1047+
//
1048+
// CXXDestructorDecl
1049+
//
1050+
// if constexpr(std::derived_from<DeclTy, CXXDestructorDecl>)
1051+
// {
1052+
// }
10531053

1054-
//
1055-
// CXXConstructorDecl
1056-
//
1057-
if constexpr(std::derived_from<DeclTy, CXXConstructorDecl>)
1058-
{
1059-
populate(I.Explicit, D->getExplicitSpecifier());
1060-
}
1054+
//
1055+
// CXXConstructorDecl
1056+
//
1057+
if constexpr(std::derived_from<DeclTy, CXXConstructorDecl>)
1058+
{
1059+
populate(I.Explicit, D->getExplicitSpecifier());
1060+
}
10611061

1062-
//
1063-
// CXXConversionDecl
1064-
//
1065-
if constexpr(std::derived_from<DeclTy, CXXConversionDecl>)
1066-
{
1067-
populate(I.Explicit, D->getExplicitSpecifier());
1062+
//
1063+
// CXXConversionDecl
1064+
//
1065+
if constexpr(std::derived_from<DeclTy, CXXConversionDecl>)
1066+
{
1067+
populate(I.Explicit, D->getExplicitSpecifier());
1068+
}
10681069
}
10691070

1070-
ArrayRef<ParmVarDecl*> const params = D->parameters();
1071+
ArrayRef<ParmVarDecl*> const params = FD->parameters();
10711072
I.Params.resize(params.size());
10721073
for (std::size_t i = 0; i < params.size(); ++i)
10731074
{
10741075
ParmVarDecl const* P = params[i];
1076+
MRDOCS_SYMBOL_TRACE(P, context_);
10751077
Param& param = I.Params[i];
10761078

10771079
if (param.Name.empty())
@@ -1099,16 +1101,16 @@ populate(
10991101
}
11001102
}
11011103

1102-
I.Class = toFunctionClass(D->getDeclKind());
1104+
I.Class = toFunctionClass(FD->getDeclKind());
11031105

11041106
// extract the return type in direct dependency mode
11051107
// if it contains a placeholder type which is
11061108
// deduceded as a local class type
1107-
QualType const RT = D->getReturnType();
1109+
QualType const RT = FD->getReturnType();
11081110
MRDOCS_SYMBOL_TRACE(RT, context_);
11091111
I.ReturnType = toTypeInfo(RT);
11101112

1111-
if (auto* TRC = D->getTrailingRequiresClause())
1113+
if (auto* TRC = FD->getTrailingRequiresClause())
11121114
{
11131115
populate(I.Requires, TRC);
11141116
}
@@ -1120,8 +1122,9 @@ void
11201122
ASTVisitor::
11211123
populate(FunctionInfo& I, FunctionTemplateDecl* D)
11221124
{
1123-
populate(I.Template, D->getTemplatedDecl(), D);
1124-
populate(I, D->getTemplatedDecl());
1125+
FunctionDecl* TD = D->getTemplatedDecl();
1126+
populate(I.Template, TD, D);
1127+
populate(I, TD);
11251128
}
11261129

11271130
void
@@ -1375,7 +1378,8 @@ ASTVisitor::
13751378
populate(TemplateInfo& Template, DeclTy*, TemplateDeclTy* TD)
13761379
{
13771380
MRDOCS_ASSERT(TD);
1378-
populate(Template, TD->getTemplateParameters());
1381+
TemplateParameterList const* TPL = TD->getTemplateParameters();
1382+
populate(Template, TPL);
13791383
}
13801384

13811385
template<std::derived_from<CXXRecordDecl> CXXRecordDeclTy>
@@ -1592,18 +1596,25 @@ populate(
15921596
{
15931597
I = std::make_unique<TemplateTParam>();
15941598
}
1595-
auto* R = dynamic_cast<TemplateTParam*>(I.get());
1596-
if(R->Params.empty())
1599+
TemplateTemplateParmDecl const* TTPD = cast<TemplateTemplateParmDecl>(P);
1600+
MRDOCS_CHECK_OR(TTPD);
1601+
TemplateParameterList const* TPL = TTPD->getTemplateParameters();
1602+
MRDOCS_CHECK_OR(TPL);
1603+
auto* Result = dynamic_cast<TemplateTParam*>(I.get());
1604+
if (Result->Params.size() < TPL->size())
15971605
{
1598-
for (NamedDecl const* NP: *P->getTemplateParameters())
1599-
{
1600-
populate(R->Params.emplace_back(), NP);
1601-
}
1606+
Result->Params.resize(TPL->size());
16021607
}
1603-
if (P->hasDefaultArgument() && !R->Default)
1608+
for (std::size_t i = 0; i < TPL->size(); ++i)
16041609
{
1605-
R->Default = toTArg(
1606-
P->getDefaultArgument().getArgument());
1610+
NamedDecl const* TP = TPL->getParam(i);
1611+
populate(Result->Params[i], TP);
1612+
}
1613+
if (TTPD->hasDefaultArgument() && !Result->Default)
1614+
{
1615+
TemplateArgumentLoc const& TAL = TTPD->getDefaultArgument();
1616+
TemplateArgument const& TA = TAL.getArgument();
1617+
Result->Default = toTArg(TA);
16071618
}
16081619
return;
16091620
}
@@ -1634,9 +1645,10 @@ populate(
16341645
{
16351646
TI.Params.resize(TPL->size());
16361647
}
1637-
for (std::size_t I = 0; I < TPL->size(); ++I)
1648+
for (std::size_t i = 0; i < TPL->size(); ++i)
16381649
{
1639-
populate(TI.Params[I], TPL->getParam(I));
1650+
NamedDecl const* P = TPL->getParam(i);
1651+
populate(TI.Params[i], P);
16401652
}
16411653
if (auto* RC = TPL->getRequiresClause())
16421654
{

src/lib/AST/ASTVisitor.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ class ASTVisitor
482482
{
483483
Template.emplace();
484484
}
485-
populate(*Template, D, VTD);
485+
TemplateInfo &TI = *Template;
486+
populate(TI, D, VTD);
486487
}
487488

488489
void

src/lib/AST/ClangHelpers.hpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -914,6 +914,20 @@ namespace detail {
914914
{
915915
printTraceName(&D, C, symbol_name);
916916
}
917+
918+
template <class T>
919+
void
920+
printTraceName(std::optional<T> const& D, ASTContext const& C, SmallString<256>& symbol_name)
921+
{
922+
if (D)
923+
{
924+
printTraceName(*D, C, symbol_name);
925+
}
926+
else
927+
{
928+
symbol_name += "<empty>";
929+
}
930+
}
917931
} // namespace detail
918932

919933
# define MRDOCS_SYMBOL_TRACE_MERGE_(a, b) a##b

src/lib/AST/NameInfoBuilder.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -89,11 +89,6 @@ buildTerminal(
8989
// Look for the Info type. If this is a template specialization,
9090
// we look for the Info of the specialized record.
9191
Decl const* ID = decayToPrimaryTemplate(D);
92-
Info const* I = getASTVisitor().findOrTraverse(const_cast<Decl*>(ID));
93-
if (!I)
94-
{
95-
return;
96-
}
9792

9893
auto TI = std::make_unique<NameInfo>();
9994

@@ -103,7 +98,10 @@ buildTerminal(
10398
{
10499
Name->Name = II->getName();
105100
}
106-
Name->id = I->id;
101+
if (Info const* I = getASTVisitor().findOrTraverse(const_cast<Decl*>(ID)))
102+
{
103+
Name->id = I->id;
104+
}
107105
if(NNS)
108106
{
109107
Name->Prefix = getASTVisitor().toNameInfo(NNS);

src/lib/AST/TerminalTypeVisitor.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,22 +615,27 @@ class TerminalTypeVisitor
615615
// Template names can also refer to function templates,
616616
// C++0x template aliases, etc...
617617
TemplateName const TN = T->getTemplateName();
618+
MRDOCS_SYMBOL_TRACE(TN, Visitor_.context_);
618619
MRDOCS_ASSERT(! TN.isNull());
619620

620621
// The list of template parameters and a reference to
621622
// the templated scoped declaration
622623
NamedDecl* D = TN.getAsTemplateDecl();
624+
MRDOCS_SYMBOL_TRACE(TN, Visitor_.context_);
623625

624626
if (!T->isTypeAlias())
625627
{
626628
auto* CT = T->getCanonicalTypeInternal().getTypePtrOrNull();
629+
MRDOCS_SYMBOL_TRACE(CT, Visitor_.context_);
627630
if (auto* ICT = dyn_cast_or_null<InjectedClassNameType>(CT))
628631
{
629632
D = ICT->getDecl();
633+
MRDOCS_SYMBOL_TRACE(D, Visitor_.context_);
630634
}
631635
else if (auto* RT = dyn_cast_or_null<RecordType>(CT))
632636
{
633637
D = RT->getDecl();
638+
MRDOCS_SYMBOL_TRACE(D, Visitor_.context_);
634639
}
635640
}
636641

0 commit comments

Comments
 (0)