Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
22 changes: 22 additions & 0 deletions clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,28 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
return inherited::TraverseStmt(E->getReplacement());
}

bool TraverseTemplateName(TemplateName Template) {
if (auto *TTP = dyn_cast_if_present<TemplateTemplateParmDecl>(
Template.getAsTemplateDecl());
TTP && TTP->getDepth() < TemplateArgs.getNumLevels()) {
if (!TemplateArgs.hasTemplateArgument(TTP->getDepth(),
TTP->getPosition()))
return true;

TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
if (TTP->isParameterPack() && SemaRef.ArgPackSubstIndex) {
assert(Arg.getKind() == TemplateArgument::Pack &&
"Missing argument pack");
Arg = SemaRef.getPackSubstitutedTemplateArgument(Arg);
}
assert(!Arg.getAsTemplate().isNull() &&
"Null template template argument");
UsedTemplateArgs.push_back(
SemaRef.Context.getCanonicalTemplateArgument(Arg));
}
return inherited::TraverseTemplateName(Template);
}

void VisitConstraint(const NormalizedConstraintWithParamMapping &Constraint) {
if (!Constraint.hasParameterMapping()) {
for (const auto &List : TemplateArgs)
Expand Down
59 changes: 59 additions & 0 deletions clang/test/SemaTemplate/concepts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1573,3 +1573,62 @@ namespace GH162770 {
template<typename... Ts> auto comma = (..., Ts());
auto b = comma<check<e{}>>;
} // namespace GH162770

namespace GH164750 {

template <typename>
struct a;
template <typename>
struct b;

template <template <typename> typename c, typename d, typename>
concept e = !__is_convertible_to(c<d>*, b<d>*);

template <typename...>
struct f;
template <typename g, typename... h>
struct f<g, h...> {
g i;
};

template <typename, typename>
struct u;
template <typename j, template <typename> typename k, typename l>
requires e<k, j, l>
struct u<const k<j>*, l> {
u(const a<j>*);
};
template <typename j, template <typename> typename k, typename l>
struct u<const k<j>*, l> {
u(const b<j>*);
};

template <typename>
struct m;
template <typename n, typename... o>
struct m<n (*)(o...)> {
template <template <typename> typename j>
using p = j<o...>;
};

template <typename q, typename r>
struct s {
template <typename... p>
struct D {
using v = f<u<r, p>...>;
};
template <typename... t>
s(t... p1) : x(p1...) {}
m<q>::template p<D>::v x;
};
template <typename w, typename... t>
void fn1(w, t... p2) {
s<w, t...>(p2...);
}
int* fn2(int) { return nullptr; }
void fn3() {
fn1(fn2, static_cast<const a<int>*>(nullptr));
fn1(fn2, static_cast<const b<int>*>(nullptr));
}

}
Loading