Skip to content

Commit 667d12f

Browse files
authored
[Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (llvm#91534)
We do not deduce template arguments from the exception specification when determining the primary template of a function template specialization or when taking the address of a function template. Therefore, this patch changes `isAtLeastAsSpecializedAs` such that we do not mark template parameters in the exception specification as 'used' during partial ordering (per [temp.deduct.partial] p12) to prevent the following from being ambiguous: ``` template<typename T, typename U> void f(U) noexcept(noexcept(T())); // #1 template<typename T> void f(T*) noexcept; // #2 template<> void f<int>(int*) noexcept; // currently ambiguous, selects #2 with this patch applied ``` Although there is no corresponding wording in the standard (see core issue filed here cplusplus/CWG#537), this seems to be the intended behavior given the definition of _deduction substitution loci_ in [temp.deduct.general] p7 (and EDG does the same thing).
1 parent e00a3cc commit 667d12f

File tree

3 files changed

+103
-8
lines changed

3 files changed

+103
-8
lines changed

clang/docs/ReleaseNotes.rst

+3
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,9 @@ Bug Fixes to C++ Support
713713
- Correctly treat the compound statement of an ``if consteval`` as an immediate context. Fixes (#GH91509).
714714
- When partial ordering alias templates against template template parameters,
715715
allow pack expansions when the alias has a fixed-size parameter list. Fixes (#GH62529).
716+
- Clang now ignores template parameters only used within the exception specification of candidate function
717+
templates during partial ordering when deducing template arguments from a function declaration or when
718+
taking the address of a function template.
716719

717720
Bug Fixes to AST Handling
718721
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaTemplateDeduction.cpp

+28-8
Original file line numberDiff line numberDiff line change
@@ -5453,7 +5453,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc,
54535453
// is used.
54545454
if (DeduceTemplateArgumentsByTypeMatch(
54555455
S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced,
5456-
TDF_None,
5456+
TDF_AllowCompatibleFunctionType,
54575457
/*PartialOrdering=*/true) != TemplateDeductionResult::Success)
54585458
return false;
54595459
break;
@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc,
54855485
switch (TPOC) {
54865486
case TPOC_Call:
54875487
for (unsigned I = 0, N = Args2.size(); I != N; ++I)
5488-
::MarkUsedTemplateParameters(S.Context, Args2[I], false,
5489-
TemplateParams->getDepth(),
5490-
UsedParameters);
5488+
::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
5489+
TemplateParams->getDepth(), UsedParameters);
54915490
break;
54925491

54935492
case TPOC_Conversion:
5494-
::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
5493+
::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
5494+
/*OnlyDeduced=*/false,
54955495
TemplateParams->getDepth(), UsedParameters);
54965496
break;
54975497

54985498
case TPOC_Other:
5499-
::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
5500-
TemplateParams->getDepth(),
5501-
UsedParameters);
5499+
// We do not deduce template arguments from the exception specification
5500+
// when determining the primary template of a function template
5501+
// specialization or when taking the address of a function template.
5502+
// Therefore, we do not mark template parameters in the exception
5503+
// specification as used during partial ordering to prevent the following
5504+
// from being ambiguous:
5505+
//
5506+
// template<typename T, typename U>
5507+
// void f(U) noexcept(noexcept(T())); // #1
5508+
//
5509+
// template<typename T>
5510+
// void f(T*) noexcept; // #2
5511+
//
5512+
// template<>
5513+
// void f<int>(int*) noexcept; // explicit specialization of #2
5514+
//
5515+
// Although there is no corresponding wording in the standard, this seems
5516+
// to be the intended behavior given the definition of
5517+
// 'deduction substitution loci' in [temp.deduct].
5518+
::MarkUsedTemplateParameters(
5519+
S.Context,
5520+
S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None),
5521+
/*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters);
55025522
break;
55035523
}
55045524

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify %s
2+
// expected-no-diagnostics
3+
4+
template<bool B>
5+
struct A { };
6+
7+
constexpr A<false> a;
8+
constexpr A<false> b;
9+
10+
constexpr int* x = nullptr;
11+
constexpr short* y = nullptr;
12+
13+
namespace ExplicitArgs {
14+
template<typename T, typename U>
15+
constexpr int f(U) noexcept(noexcept(T())) {
16+
return 0;
17+
}
18+
19+
template<typename T>
20+
constexpr int f(T*) noexcept {
21+
return 1;
22+
}
23+
24+
template<>
25+
constexpr int f<int>(int*) noexcept {
26+
return 2;
27+
}
28+
29+
static_assert(f<int>(1) == 0);
30+
static_assert(f<short>(y) == 1);
31+
static_assert(f<int>(x) == 2);
32+
33+
template<typename T, typename U>
34+
constexpr int g(U*) noexcept(noexcept(T())) {
35+
return 3;
36+
}
37+
38+
template<typename T>
39+
constexpr int g(T) noexcept {
40+
return 4;
41+
}
42+
43+
template<>
44+
constexpr int g<int>(int*) noexcept {
45+
return 5;
46+
}
47+
48+
static_assert(g<int>(y) == 3);
49+
static_assert(g<short>(1) == 4);
50+
static_assert(g<int>(x) == 5);
51+
} // namespace ExplicitArgs
52+
53+
namespace DeducedArgs {
54+
template<typename T, bool B>
55+
constexpr int f(T, A<B>) noexcept(B) {
56+
return 0;
57+
}
58+
59+
template<typename T, bool B>
60+
constexpr int f(T*, A<B>) noexcept(B && B) {
61+
return 1;
62+
}
63+
64+
template<>
65+
constexpr int f(int*, A<false>) {
66+
return 2;
67+
}
68+
69+
static_assert(f<int*>(x, a) == 0);
70+
static_assert(f<short>(y, a) == 1);
71+
static_assert(f<int>(x, a) == 2);
72+
} // namespace DeducedArgs

0 commit comments

Comments
 (0)