Skip to content

Commit bc39a8f

Browse files
authored
[Clang] Fix another parameter mapping substitution bug (#162155)
When a template parameter pack is named before it can be substituted, it might not have a corresponding mapping. Fixes #162125
1 parent cce7cfb commit bc39a8f

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

clang/lib/Sema/SemaConcept.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ class HashParameterMapping : public RecursiveASTVisitor<HashParameterMapping> {
280280
if (T->getDepth() >= TemplateArgs.getNumLevels())
281281
return true;
282282

283+
// There might not be a corresponding template argument before substituting
284+
// into the parameter mapping, e.g. a sizeof... expression.
285+
if (!TemplateArgs.hasTemplateArgument(T->getDepth(), T->getIndex()))
286+
return true;
287+
283288
TemplateArgument Arg = TemplateArgs(T->getDepth(), T->getIndex());
284289

285290
if (T->isParameterPack() && SemaRef.ArgPackSubstIndex) {

clang/test/SemaTemplate/concepts.cpp

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify %s
1+
// RUN: %clang_cc1 -std=c++20 -ferror-limit 0 -verify=expected,cxx20 %s
2+
// RUN: %clang_cc1 -std=c++2c -ferror-limit 0 -verify=expected %s
23

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

14071408
}
1409+
1410+
1411+
namespace GH162125 {
1412+
template<typename, int size>
1413+
concept true_int = (size, true);
1414+
1415+
template<typename, typename... Ts>
1416+
concept true_types = true_int<void, sizeof...(Ts)>;
1417+
1418+
template<typename, typename... Ts>
1419+
concept true_types2 = true_int<void, Ts...[0]{1}>; // cxx20-warning {{pack indexing is a C++2c extension}}
1420+
1421+
template<typename... Ts>
1422+
struct s {
1423+
template<typename T> requires true_types<T, Ts...> && true_types2<T, Ts...>
1424+
static void f(T);
1425+
};
1426+
void(*test)(int) = &s<bool>::f<int>;
1427+
}
1428+
1429+
namespace GH162125_reversed {
1430+
template<int size, typename>
1431+
concept true_int = (size, true);
1432+
1433+
template<typename, typename... Ts>
1434+
concept true_types = true_int<sizeof...(Ts), void>;
1435+
1436+
template<typename, typename... Ts>
1437+
concept true_types2 = true_int<Ts...[0]{1}, void>; // cxx20-warning {{pack indexing is a C++2c extension}}
1438+
1439+
template<typename... Ts>
1440+
struct s {
1441+
template<typename T> requires true_types<T, Ts...> && true_types2<T, Ts...>
1442+
static void f(T);
1443+
};
1444+
1445+
void(*test)(int) = &s<bool>::f<int>;
1446+
}

0 commit comments

Comments
 (0)