Skip to content

Commit

Permalink
extract SFINAE constraints
Browse files Browse the repository at this point in the history
#feat
  • Loading branch information
alandefreitas committed Jan 22, 2025
1 parent 37d9b93 commit 0bc88b6
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 25 deletions.
19 changes: 17 additions & 2 deletions include/mrdocs/Metadata/Type.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ struct TypeInfo
*/
bool IsPackExpansion = false;

/** The constraints associated with the type
This represents the constraints associated with the type,
such as SFINAE constraints.
For instance, if SFINAE detection is enabled, the
expression `std::enable_if_t<std::is_integral_v<T>, T>`
will have type `T` (NamedType) and constraints
`{std::is_integral_v<T>}`.
*/
std::vector<ExprInfo> Constraints;

constexpr virtual ~TypeInfo() = default;

constexpr bool isNamed() const noexcept { return Kind == TypeKind::Named; }
Expand All @@ -123,14 +135,17 @@ struct TypeInfo
The inner type is the type which is modified
by a specifier (e.g. "int" in "pointer to int".
*/
virtual TypeInfo* innerType() const noexcept
virtual
TypeInfo*
innerType() const noexcept
{
return nullptr;
}

/** Return the symbol named by this type.
*/
SymbolID namedSymbol() const noexcept;
SymbolID
namedSymbol() const noexcept;

protected:
constexpr
Expand Down
33 changes: 20 additions & 13 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1884,25 +1884,32 @@ extractSFINAEInfo(QualType const T)
// Find the parameter that represents the SFINAE result
auto const Args = templateInfo->Arguments;
MRDOCS_SYMBOL_TRACE(Args, context_);
auto const param_arg = tryGetTemplateArgument(
auto const resultType = tryGetTemplateArgument(
SFINAEControl->Parameters, Args, SFINAEControl->ParamIdx);
MRDOCS_CHECK_OR(param_arg, std::nullopt);
MRDOCS_SYMBOL_TRACE(*param_arg, context_);
MRDOCS_CHECK_OR(resultType, std::nullopt);
MRDOCS_SYMBOL_TRACE(*resultType, context_);

// Create a vector of template arguments that represent the
// controlling parameters of the SFINAE template
std::vector<TemplateArgument> ControllingArgs;
SFINAEInfo Result;
Result.Type = resultType->getAsType();
for (std::size_t I = 0; I < Args.size(); ++I)
{
if (SFINAEControl->ControllingParams[I])
{
MRDOCS_SYMBOL_TRACE(Args[I], context_);
ControllingArgs.emplace_back(Args[I]);
Expr* E = Args[I].getAsExpr();
if (!E)
{
continue;
}
Result.Constraints.emplace_back();
populate(Result.Constraints.back(), E);
}
}

// Return the main type and controlling types
return SFINAEInfo{param_arg->getAsType(), std::move(ControllingArgs)};
return Result;
}

std::optional<ASTVisitor::SFINAEControlParams>
Expand Down Expand Up @@ -1963,16 +1970,16 @@ getSFINAEControlParams(

// Find the index of the parameter that represents the SFINAE result
// in the underlying template arguments
auto param_arg = tryGetTemplateArgument(
auto resultType = tryGetTemplateArgument(
sfinaeControl->Parameters,
underlyingTemplateInfo->Arguments,
sfinaeControl->ParamIdx);
MRDOCS_CHECK_OR(param_arg, std::nullopt);
MRDOCS_SYMBOL_TRACE(*param_arg, context_);
MRDOCS_CHECK_OR(resultType, std::nullopt);
MRDOCS_SYMBOL_TRACE(*resultType, context_);

// Find the index of the parameter that represents the SFINAE result
// in the primary template arguments
unsigned ParamIdx = FindParam(ATD->getInjectedTemplateArgs(context_), *param_arg);
unsigned ParamIdx = FindParam(ATD->getInjectedTemplateArgs(context_), *resultType);

// Return the controlling parameters with values corresponding to
// the primary template arguments
Expand Down Expand Up @@ -2060,11 +2067,11 @@ getSFINAEControlParams(
}

auto [template_params, controlling_params, param_idx] = *sfinae_result;
auto param_arg = tryGetTemplateArgument(
auto resultType = tryGetTemplateArgument(
template_params, sfinae_info->Arguments, param_idx);
if(! param_arg)
if(! resultType)
return true;
auto CurrentTypeFromBase = param_arg->getAsType();
auto CurrentTypeFromBase = resultType->getAsType();
if (CurrentType.isNull())
{
CurrentType = CurrentTypeFromBase;
Expand Down
2 changes: 1 addition & 1 deletion src/lib/AST/ASTVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -734,7 +734,7 @@ class ASTVisitor
QualType Type;

// The template arguments used in the SFINAE context.
std::vector<TemplateArgument> Arguments;
std::vector<ExprInfo> Constraints;
};

/* Get the underlying type result of a SFINAE type
Expand Down
6 changes: 6 additions & 0 deletions src/lib/AST/TerminalTypeVisitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ class TerminalTypeVisitor
// The optional NestedNameSpecifier.
const NestedNameSpecifier* NNS_ = nullptr;

protected:
// Constraints associated with the type (e.g., SFINAE)
std::vector<ExprInfo> Constraints;

public:
/** Constructor for TerminalTypeVisitor.
Expand Down Expand Up @@ -571,6 +575,7 @@ class TerminalTypeVisitor
if (auto SFINAE = getASTVisitor().extractSFINAEInfo(T))
{
NNS_ = nullptr;
Constraints = SFINAE->Constraints;
return getDerived().Visit(SFINAE->Type);
}

Expand Down Expand Up @@ -606,6 +611,7 @@ class TerminalTypeVisitor
if (auto SFINAE = getASTVisitor().extractSFINAEInfo(T))
{
NNS_ = nullptr;
Constraints = SFINAE->Constraints;
return getDerived().Visit(SFINAE->Type);
}

Expand Down
16 changes: 11 additions & 5 deletions src/lib/AST/TypeInfoBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ buildDecltype(
getASTVisitor().populate(
I->Operand, T->getUnderlyingExpr());
I->CVQualifiers = toQualifierKind(quals);
I->Constraints = this->Constraints;
*Inner = std::move(I);
Result->IsPackExpansion = pack;
}
Expand Down Expand Up @@ -129,6 +130,7 @@ buildAuto(
// Constraint->Prefix = getASTVisitor().buildNameInfo(
// cast<Decl>(CD->getDeclContext()));
}
I->Constraints = this->Constraints;
*Inner = std::move(I);
Result->IsPackExpansion = pack;
}
Expand All @@ -145,12 +147,12 @@ buildTerminal(
{
auto TI = std::make_unique<NamedTypeInfo>();
TI->CVQualifiers = toQualifierKind(quals);

auto Name = std::make_unique<NameInfo>();
Name->Name = getASTVisitor().toString(T);
Name->Prefix = getASTVisitor().toNameInfo(NNS);
TI->Name = std::move(Name);
TI->Name = std::make_unique<NameInfo>();
TI->Name->Name = getASTVisitor().toString(T);
TI->Name->Prefix = getASTVisitor().toNameInfo(NNS);
TI->Constraints = this->Constraints;
*Inner = std::move(TI);
Result->Constraints = this->Constraints;
Result->IsPackExpansion = pack;
}

Expand Down Expand Up @@ -187,7 +189,9 @@ buildTerminal(
Name->Prefix = getASTVisitor().toNameInfo(NNS);
I->Name = std::move(Name);
}
I->Constraints = this->Constraints;
*Inner = std::move(I);
Result->Constraints = this->Constraints;
Result->IsPackExpansion = pack;
}

Expand Down Expand Up @@ -240,7 +244,9 @@ buildTerminal(
getASTVisitor().populate(Name->TemplateArgs, *TArgs);
TI->Name = std::move(Name);
}
TI->Constraints = this->Constraints;
*Inner = std::move(TI);
Result->Constraints = this->Constraints;
Result->IsPackExpansion = pack;
}

Expand Down
11 changes: 7 additions & 4 deletions src/lib/Metadata/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,15 @@ SymbolID
TypeInfo::
namedSymbol() const noexcept
{
if(! isNamed())
if (!isNamed())
{
return SymbolID::invalid;
const auto* NT = static_cast<
const NamedTypeInfo*>(this);
if(! NT->Name)
}
auto const* NT = static_cast<NamedTypeInfo const*>(this);
if (!NT->Name)
{
return SymbolID::invalid;
}
return NT->Name->id;
}

Expand Down

0 comments on commit 0bc88b6

Please sign in to comment.