Skip to content
Closed
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 36 additions & 8 deletions src/lib/AST/ASTVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2362,22 +2362,26 @@ getSFINAEControlParams(
ArrayRef<TemplateArgument> Arguments,
TemplateArgument const& Arg) -> std::size_t
{
if (Arg.getKind() != TemplateArgument::Type)
{
return -1;
}
auto const It = std::ranges::find_if(
Arguments,
[&](TemplateArgument const& Other)
{
if (Other.getKind() != TemplateArgument::Type)
if (Arg.getKind() != Other.getKind())
{
return false;
}
return context_.hasSameType(Other.getAsType(), Arg.getAsType());
if (Arg.getKind() == TemplateArgument::Type)
{
return context_.hasSameType(Other.getAsType(), Arg.getAsType());
}
if (Arg.getKind() == TemplateArgument::Expression)
{
return context_.hasSameExpr(Other.getAsExpr(), Arg.getAsExpr());
}
return false;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't handle the other template argument kinds. I think you want isSameTemplateArgument.

But comparing template arguments like that only makes sense if the parameters are equivalent, as otherwise they'll have different conversions.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This only attempts to handle the boolean case. Given

template <bool C, typename T>
using enable_if_t = typename std::enable_if<C, T>::type;

the goal here is to match the C that is an argument to std::enable_if to the C that is a parameter of enable_if_t.

The pre-existing case attempts to do something similar for T. Nothing else (no heroics).

Would isSameTemplateArgument be a better choice here? Or is there a simpler alternative?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isSameTemplateArgument does what this code does, and more, since it handles the other template argument kinds as well, such as template template arguments, the other kinds of converted constant template arguments, packs, and such.

What I mean is, if we are comparing template arguments to equivalent template parameters, then it makes sense to compare them like this.

If they are otherwise not equivalent, for example you are comparing a template argument for a constant template parameter of type bool, to another one of type int, then this won't work as expected.

});
bool const found = It != Arguments.end();
return found ? It - Arguments.data() : static_cast<std::size_t>(-1);
return found ? It - Arguments.begin() : static_cast<std::size_t>(-1);
};

if(auto* ATD = dyn_cast<TypeAliasTemplateDecl>(TD))
Expand Down Expand Up @@ -2417,9 +2421,33 @@ getSFINAEControlParams(
// the primary template arguments
TemplateParameterList* primaryTemplParams = ATD->getTemplateParameters();
MRDOCS_SYMBOL_TRACE(primaryTemplParams, context_);

llvm::SmallBitVector primaryControllingParams(primaryTemplParams->size());
for (std::size_t i = 0; i < sfinaeControl->ControllingParams.size(); ++i)
{
if (sfinaeControl->ControllingParams[i])
{
// Find the index of the parameter that represents the SFINAE result
// in the underlying template arguments
auto resultType = tryGetTemplateArgument(
sfinaeControl->Parameters,
underlyingTemplateInfo->Arguments,
i);
MRDOCS_CHECK_OR_CONTINUE(resultType);
MRDOCS_SYMBOL_TRACE(*resultType, context_);

// Find the index of the parameter that represents the param
// in the primary template arguments
auto ParamIdx = FindParam(ATD->getInjectedTemplateArgs(context_), *resultType);
if (ParamIdx == static_cast<std::size_t>(-1)) continue;

primaryControllingParams.set(ParamIdx);
}
}

return SFINAEControlParams(
primaryTemplParams,
std::move(sfinaeControl->ControllingParams),
std::move(primaryControllingParams),
ParamIdx);
}

Expand Down
86 changes: 86 additions & 0 deletions test-files/golden-tests/config/sfinae/alias.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
= Reference
:mrdocs:

[#index]
== Global namespace

=== Types

[cols=1]
|===
| Name
| link:#enable_if_t[`enable&lowbar;if&lowbar;t`]
| link:#if_enable_t[`if&lowbar;enable&lowbar;t`]
|===

=== Functions

[cols=1]
|===
| Name
| link:#f1[`f1`]
| link:#f2[`f2`]
|===

[#enable_if_t]
== enable&lowbar;if&lowbar;t

=== Synopsis

Declared in `&lt;alias&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;
bool C,
typename T&gt;
using enable&lowbar;if&lowbar;t = T;
----

[#if_enable_t]
== if&lowbar;enable&lowbar;t

=== Synopsis

Declared in `&lt;alias&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;
typename T,
bool C&gt;
using if&lowbar;enable&lowbar;t = T;
----

[#f1]
== f1

=== Synopsis

Declared in `&lt;alias&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;typename T&gt;
T
f1()
requires std&colon;&colon;is&lowbar;class&lowbar;v&lt;T&gt;;
----

[#f2]
== f2

=== Synopsis

Declared in `&lt;alias&period;cpp&gt;`

[source,cpp,subs="verbatim,replacements,macros,-callouts"]
----
template&lt;typename T&gt;
T
f2()
requires std&colon;&colon;is&lowbar;class&lowbar;v&lt;T&gt;;
----


[.small]#Created with https://www.mrdocs.com[MrDocs]#
15 changes: 15 additions & 0 deletions test-files/golden-tests/config/sfinae/alias.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <type_traits>

// just like std::enable_if_t
template <bool C, typename T>
using enable_if_t = typename std::enable_if<C, T>::type;

template <typename T>
enable_if_t<std::is_class_v<T>, T> f1();

// reversed param order
template <typename T, bool C>
using if_enable_t = typename std::enable_if<C, T>::type;

template <typename T>
if_enable_t<T, std::is_class_v<T>> f2();
119 changes: 119 additions & 0 deletions test-files/golden-tests/config/sfinae/alias.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
<html lang="en">
<head>
<title>Reference</title>
</head>
<body>
<div>
<h1>Reference</h1>
<div>
<div>
<h2 id="index"><a href="#index"></a></h2>
</div>
<h2>Types</h2>
<table style="table-layout: fixed; width: 100%;">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#enable_if_t"><code>enable_if_t</code></a> </td></tr><tr>
<td><a href="#if_enable_t"><code>if_enable_t</code></a> </td></tr>
</tbody>
</table>

<h2>Functions</h2>
<table style="table-layout: fixed; width: 100%;">
<thead>
<tr>
<th>Name</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="#f1"><code>f1</code></a> </td></tr><tr>
<td><a href="#f2"><code>f2</code></a> </td></tr>
</tbody>
</table>

</div>
<div>
<div>
<h2 id="enable_if_t"><a href="#enable_if_t">enable_if_t</a></h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;alias.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">template&lt;
bool C,
typename T&gt;
using enable_if_t = T;

</code>
</pre>
</div>
</div>
<div>
<div>
<h2 id="if_enable_t"><a href="#if_enable_t">if_enable_t</a></h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;alias.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">template&lt;
typename T,
bool C&gt;
using if_enable_t = T;

</code>
</pre>
</div>
</div>
<div>
<div>
<h2 id="f1"><a href="#f1">f1</a></h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;alias.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">template&lt;typename T&gt;
T
f1()
requires std::is_class_v&lt;T&gt;;

</code>
</pre>
</div>
</div>
<div>
<div>
<h2 id="f2"><a href="#f2">f2</a></h2>
</div>
<div>
<h3>Synopsis</h3>
<div>
Declared in <code>&lt;alias.cpp&gt;</code></div>
<pre>
<code class="source-code cpp">template&lt;typename T&gt;
T
f2()
requires std::is_class_v&lt;T&gt;;

</code>
</pre>
</div>
</div>

</div>
<div>
<h4>Created with <a href="https://www.mrdocs.com">MrDocs</a></h4>
</div>
</body>
</html>
40 changes: 40 additions & 0 deletions test-files/golden-tests/config/sfinae/alias.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<mrdocs xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://github.com/cppalliance/mrdocs/raw/develop/mrdocs.rnc">
<namespace id="//////////////////////////8=">
<template>
<tparam name="C" class="non-type" type="bool"/>
<tparam name="T" class="type"/>
<namespace-alias name="enable_if_t" id="G6KvcosPT2J4Mp72/Jj/t+hpu7w=">
<file short-path="alias.cpp" source-path="alias.cpp" line="4"/>
<type name="T"/>
</namespace-alias>
</template>
<template>
<tparam name="T" class="type"/>
<tparam name="C" class="non-type" type="bool"/>
<namespace-alias name="if_enable_t" id="3mL2o5cGgdygMfQf6RJVMv4YrLg=">
<file short-path="alias.cpp" source-path="alias.cpp" line="11"/>
<type name="T"/>
</namespace-alias>
</template>
<template>
<tparam name="T" class="type"/>
<function name="f1" requires="std::is_class_v&lt;T&gt;" id="wxSwXFUt9arsW/YBeWhVf1gINhw=">
<file short-path="alias.cpp" source-path="alias.cpp" line="7"/>
<return>
<type name="T"/>
</return>
</function>
</template>
<template>
<tparam name="T" class="type"/>
<function name="f2" requires="std::is_class_v&lt;T&gt;" id="koj7SBKjX4SV47aOs0homZpcPWQ=">
<file short-path="alias.cpp" source-path="alias.cpp" line="14"/>
<return>
<type name="T"/>
</return>
</function>
</template>
</namespace>
</mrdocs>
Loading
Loading