Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
3 changes: 2 additions & 1 deletion clang/lib/Sema/SemaConcept.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,8 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
bool VisitTemplateTypeParmType(TemplateTypeParmType *T) {
// A lambda expression can introduce template parameters that don't have
// corresponding template arguments yet.
if (T->getDepth() >= TemplateArgs.getNumLevels())
if (T->getDepth() >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we

Suggested change
if (T->getDepth() >= TemplateArgs.getNumLevels() ||
!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
// There might not be a corresponding template argument before substituting into the parameter mapping, e.g. a lambda expression ...
if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))

?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, they are slightly different scenarios. I split the condition in 2 and added a comment, it's probably clearer that way. Thanks!

return true;

TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
Expand Down
41 changes: 40 additions & 1 deletion clang/test/SemaTemplate/concepts.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify %s
// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify=expected,cxx20 %s
// RUN: %clang_cc1 -std=c++2c -ferror-limit 0 -verify=expected %s

namespace PR47043 {
template<typename T> concept True = true;
Expand Down Expand Up @@ -1405,3 +1406,41 @@ static_assert(!std::is_constructible_v<span<4>, array<int, 3>>);
}

}


namespace GH162125 {
template<typename, int size>
concept true_int = (size, true);

template<typename, typename... Ts>
concept true_types = true_int<void, sizeof...(Ts)>;

template<typename, typename... Ts>
concept true_types2 = true_int<void, Ts...[0]{1}>; // cxx20-warning {{pack indexing is a C++2c extension}}

template<typename... Ts>
struct s {
template<typename T> requires true_types<T, Ts...> && true_types2<T, Ts...>
static void f(T);
};
void(*test)(int) = &s<bool>::f<int>;
}

namespace GH162125_reversed {
template<int size, typename>
concept true_int = (size, true);

template<typename, typename... Ts>
concept true_types = true_int<sizeof...(Ts), void>;

template<typename, typename... Ts>
concept true_types2 = true_int<Ts...[0]{1}, void>;
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
template<typename, typename... Ts>
concept true_types2 = true_int<Ts...[0]{1}, void>;
template<typename, typename... Ts>
concept true_types2 = true_int<Ts...[0]{1}, void>; // cxx20-warning {{pack indexing is a C++2c extension}}


template<typename... Ts>
struct s {
template<typename T> requires true_types<T, Ts...> && true_types2<T, Ts...>
static void f(T);
};

void(*test)(int) = &s<bool>::f<int>;
}
Loading