Skip to content

Commit

Permalink
function template template parameters
Browse files Browse the repository at this point in the history
#feat

fix #795
  • Loading branch information
alandefreitas committed Jan 15, 2025
1 parent 15cb2ae commit ef4431d
Show file tree
Hide file tree
Showing 10 changed files with 222 additions and 83 deletions.
12 changes: 6 additions & 6 deletions include/mrdocs/Metadata/Template.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ enum class TParamKind : int
Type = 1, // for bitstream
// template non-type parameter, e.g. "int N" or "auto N"
NonType,
// template template parameter, e.g. "template<typename> typename T"
// Template-template parameter, e.g. "template<typename> typename T"
Template
};

Expand Down Expand Up @@ -235,7 +235,7 @@ tag_invoke(


template<TParamKind K>
struct IsTParam : TParam
struct TParamCommonBase : TParam
{
static constexpr TParamKind kind_id = K;

Expand All @@ -245,7 +245,7 @@ struct IsTParam : TParam

protected:
constexpr
IsTParam() noexcept
TParamCommonBase() noexcept
: TParam(K)
{
}
Expand All @@ -271,7 +271,7 @@ tag_invoke(
}

struct TypeTParam
: IsTParam<TParamKind::Type>
: TParamCommonBase<TParamKind::Type>
{
/** Keyword (class/typename) the parameter uses */
TParamKeyKind KeyKind = TParamKeyKind::Class;
Expand All @@ -281,14 +281,14 @@ struct TypeTParam
};

struct NonTypeTParam
: IsTParam<TParamKind::NonType>
: TParamCommonBase<TParamKind::NonType>
{
/** Type of the non-type template parameter */
std::unique_ptr<TypeInfo> Type;
};

struct TemplateTParam
: IsTParam<TParamKind::Template>
: TParamCommonBase<TParamKind::Template>
{
/** Template parameters for the template template parameter */
std::vector<std::unique_ptr<TParam>> Params;
Expand Down
152 changes: 82 additions & 70 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -950,6 +950,8 @@ populate(
FunctionInfo& I,
DeclTy* D)
{
MRDOCS_SYMBOL_TRACE(D, context_);

// D is the templated declaration if FTD is non-null
if (D->isFunctionTemplateSpecialization())
{
Expand Down Expand Up @@ -987,91 +989,91 @@ populate(
}
}

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

//
// FunctionDecl
//
I.OverloadedOperator = toOperatorKind(
D->getOverloadedOperator());
I.IsVariadic |= D->isVariadic();
I.IsDefaulted |= D->isDefaulted();
I.IsExplicitlyDefaulted |= D->isExplicitlyDefaulted();
I.IsDeleted |= D->isDeleted();
I.IsDeletedAsWritten |= D->isDeletedAsWritten();
I.IsNoReturn |= D->isNoReturn();
// subsumes D->hasAttr<NoReturnAttr>()
// subsumes D->hasAttr<CXX11NoReturnAttr>()
// subsumes D->hasAttr<C11NoReturnAttr>()
// subsumes D->getType()->getAs<FunctionType>()->getNoReturnAttr()
I.HasOverrideAttr |= D->template hasAttr<OverrideAttr>();

if (ConstexprSpecKind const CSK = D->getConstexprKind();
FunctionDecl const* FD = D;
I.OverloadedOperator = toOperatorKind(FD->getOverloadedOperator());
I.IsVariadic |= FD->isVariadic();
I.IsDefaulted |= FD->isDefaulted();
I.IsExplicitlyDefaulted |= FD->isExplicitlyDefaulted();
I.IsDeleted |= FD->isDeleted();
I.IsDeletedAsWritten |= FD->isDeletedAsWritten();
I.IsNoReturn |= FD->isNoReturn();
I.HasOverrideAttr |= FD->template hasAttr<OverrideAttr>();

if (ConstexprSpecKind const CSK = FD->getConstexprKind();
CSK != ConstexprSpecKind::Unspecified)
{
I.Constexpr = toConstexprKind(CSK);
}

if (StorageClass const SC = D->getStorageClass())
if (StorageClass const SC = FD->getStorageClass())
{
I.StorageClass = toStorageClassKind(SC);
}

I.IsNodiscard |= D->template hasAttr<WarnUnusedResultAttr>();
I.IsExplicitObjectMemberFunction |= D->hasCXXExplicitFunctionObjectParameter();
I.IsNodiscard |= FD->template hasAttr<WarnUnusedResultAttr>();
I.IsExplicitObjectMemberFunction |= FD->hasCXXExplicitFunctionObjectParameter();

//
// CXXMethodDecl
//
if constexpr(std::derived_from<DeclTy, CXXMethodDecl>)
{
I.IsVirtual |= D->isVirtual();
I.IsVirtualAsWritten |= D->isVirtualAsWritten();
I.IsPure |= D->isPureVirtual();
I.IsConst |= D->isConst();
I.IsVolatile |= D->isVolatile();
I.RefQualifier = toReferenceKind(D->getRefQualifier());
I.IsFinal |= D->template hasAttr<FinalAttr>();
//D->isCopyAssignmentOperator()
//D->isMoveAssignmentOperator()
//D->isOverloadedOperator();
//D->isStaticOverloadedOperator();
}
CXXMethodDecl const* MD = D;
I.IsVirtual |= MD->isVirtual();
I.IsVirtualAsWritten |= MD->isVirtualAsWritten();
I.IsPure |= MD->isPureVirtual();
I.IsConst |= MD->isConst();
I.IsVolatile |= MD->isVolatile();
I.RefQualifier = toReferenceKind(MD->getRefQualifier());
I.IsFinal |= MD->template hasAttr<FinalAttr>();
//MD->isCopyAssignmentOperator()
//MD->isMoveAssignmentOperator()
//MD->isOverloadedOperator();
//MD->isStaticOverloadedOperator();

//
// CXXDestructorDecl
//
// if constexpr(std::derived_from<DeclTy, CXXDestructorDecl>)
// {
// }
//
// CXXDestructorDecl
//
// if constexpr(std::derived_from<DeclTy, CXXDestructorDecl>)
// {
// }

//
// CXXConstructorDecl
//
if constexpr(std::derived_from<DeclTy, CXXConstructorDecl>)
{
populate(I.Explicit, D->getExplicitSpecifier());
}
//
// CXXConstructorDecl
//
if constexpr(std::derived_from<DeclTy, CXXConstructorDecl>)
{
populate(I.Explicit, D->getExplicitSpecifier());
}

//
// CXXConversionDecl
//
if constexpr(std::derived_from<DeclTy, CXXConversionDecl>)
{
populate(I.Explicit, D->getExplicitSpecifier());
//
// CXXConversionDecl
//
if constexpr(std::derived_from<DeclTy, CXXConversionDecl>)
{
populate(I.Explicit, D->getExplicitSpecifier());
}
}

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

if (param.Name.empty())
Expand Down Expand Up @@ -1099,16 +1101,16 @@ populate(
}
}

I.Class = toFunctionClass(D->getDeclKind());
I.Class = toFunctionClass(FD->getDeclKind());

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

if (auto* TRC = D->getTrailingRequiresClause())
if (auto* TRC = FD->getTrailingRequiresClause())
{
populate(I.Requires, TRC);
}
Expand All @@ -1120,8 +1122,9 @@ void
ASTVisitor::
populate(FunctionInfo& I, FunctionTemplateDecl* D)
{
populate(I.Template, D->getTemplatedDecl(), D);
populate(I, D->getTemplatedDecl());
FunctionDecl* TD = D->getTemplatedDecl();
populate(I.Template, TD, D);
populate(I, TD);
}

void
Expand Down Expand Up @@ -1375,7 +1378,8 @@ ASTVisitor::
populate(TemplateInfo& Template, DeclTy*, TemplateDeclTy* TD)
{
MRDOCS_ASSERT(TD);
populate(Template, TD->getTemplateParameters());
TemplateParameterList const* TPL = TD->getTemplateParameters();
populate(Template, TPL);
}

template<std::derived_from<CXXRecordDecl> CXXRecordDeclTy>
Expand Down Expand Up @@ -1592,18 +1596,25 @@ populate(
{
I = std::make_unique<TemplateTParam>();
}
auto* R = dynamic_cast<TemplateTParam*>(I.get());
if(R->Params.empty())
TemplateTemplateParmDecl const* TTPD = cast<TemplateTemplateParmDecl>(P);
MRDOCS_CHECK_OR(TTPD);
TemplateParameterList const* TPL = TTPD->getTemplateParameters();
MRDOCS_CHECK_OR(TPL);
auto* Result = dynamic_cast<TemplateTParam*>(I.get());
if (Result->Params.size() < TPL->size())
{
for (NamedDecl const* NP: *P->getTemplateParameters())
{
populate(R->Params.emplace_back(), NP);
}
Result->Params.resize(TPL->size());
}
if (P->hasDefaultArgument() && !R->Default)
for (std::size_t i = 0; i < TPL->size(); ++i)
{
R->Default = toTArg(
P->getDefaultArgument().getArgument());
NamedDecl const* TP = TPL->getParam(i);
populate(Result->Params[i], TP);
}
if (TTPD->hasDefaultArgument() && !Result->Default)
{
TemplateArgumentLoc const& TAL = TTPD->getDefaultArgument();
TemplateArgument const& TA = TAL.getArgument();
Result->Default = toTArg(TA);
}
return;
}
Expand Down Expand Up @@ -1634,9 +1645,10 @@ populate(
{
TI.Params.resize(TPL->size());
}
for (std::size_t I = 0; I < TPL->size(); ++I)
for (std::size_t i = 0; i < TPL->size(); ++i)
{
populate(TI.Params[I], TPL->getParam(I));
NamedDecl const* P = TPL->getParam(i);
populate(TI.Params[i], P);
}
if (auto* RC = TPL->getRequiresClause())
{
Expand Down
3 changes: 2 additions & 1 deletion src/lib/AST/ASTVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,8 @@ class ASTVisitor
{
Template.emplace();
}
populate(*Template, D, VTD);
TemplateInfo &TI = *Template;
populate(TI, D, VTD);
}

void
Expand Down
14 changes: 14 additions & 0 deletions src/lib/AST/ClangHelpers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -914,6 +914,20 @@ namespace detail {
{
printTraceName(&D, C, symbol_name);
}

template <class T>
void
printTraceName(std::optional<T> const& D, ASTContext const& C, SmallString<256>& symbol_name)
{
if (D)
{
printTraceName(*D, C, symbol_name);
}
else
{
symbol_name += "<empty>";
}
}
} // namespace detail

# define MRDOCS_SYMBOL_TRACE_MERGE_(a, b) a##b
Expand Down
5 changes: 5 additions & 0 deletions src/lib/AST/TerminalTypeVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -615,22 +615,27 @@ class TerminalTypeVisitor
// Template names can also refer to function templates,
// C++0x template aliases, etc...
TemplateName const TN = T->getTemplateName();
MRDOCS_SYMBOL_TRACE(TN, Visitor_.context_);
MRDOCS_ASSERT(! TN.isNull());

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

if (!T->isTypeAlias())
{
auto* CT = T->getCanonicalTypeInternal().getTypePtrOrNull();
MRDOCS_SYMBOL_TRACE(CT, Visitor_.context_);
if (auto* ICT = dyn_cast_or_null<InjectedClassNameType>(CT))
{
D = ICT->getDecl();
MRDOCS_SYMBOL_TRACE(D, Visitor_.context_);
}
else if (auto* RT = dyn_cast_or_null<RecordType>(CT))
{
D = RT->getDecl();
MRDOCS_SYMBOL_TRACE(D, Visitor_.context_);
}
}

Expand Down
12 changes: 6 additions & 6 deletions src/lib/AST/TypeInfoBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,19 +200,16 @@ buildTerminal(
unsigned quals,
bool pack)
{
MRDOCS_SYMBOL_TRACE(D, getASTVisitor().context_);
MRDOCS_SYMBOL_TRACE(NNS, getASTVisitor().context_);
MRDOCS_SYMBOL_TRACE(D, getASTVisitor().context_);
MRDOCS_SYMBOL_TRACE(TArgs, getASTVisitor().context_);

// Look for the Info type. If this is a template specialization,
// we look for the Info of the specialized record.
Decl const* ID = decayToPrimaryTemplate(D);
MRDOCS_SYMBOL_TRACE(ID, getASTVisitor().context_);

Info const* I = getASTVisitor().findOrTraverse(const_cast<Decl*>(ID));
if (!I)
{
return;
}

auto TI = std::make_unique<NamedTypeInfo>();
TI->CVQualifiers = toQualifierKind(quals);
Expand All @@ -223,7 +220,10 @@ buildTerminal(
{
Name->Name = II->getName();
}
Name->id = I->id;
if (I)
{
Name->id = I->id;
}
if(NNS)
{
Name->Prefix = getASTVisitor().toNameInfo(NNS);
Expand Down
Loading

0 comments on commit ef4431d

Please sign in to comment.