[clang] 667d12f - [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (#91534)
via cfe-commits
cfe-commits at lists.llvm.org
Wed May 15 15:55:57 PDT 2024
Author: Krystian Stasiowski
Date: 2024-05-15T18:55:53-04:00
New Revision: 667d12f86e626173726e87e101626a9060b8d967
URL: https://github.com/llvm/llvm-project/commit/667d12f86e626173726e87e101626a9060b8d967
DIFF: https://github.com/llvm/llvm-project/commit/667d12f86e626173726e87e101626a9060b8d967.diff
LOG: [Clang][Sema] Do not mark template parameters in the exception specification as used during partial ordering (#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
https://github.com/cplusplus/CWG/issues/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).
Added:
clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaTemplateDeduction.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index ae699ebfc6038..6f7e54252150c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -713,6 +713,9 @@ Bug Fixes to C++ Support
- Correctly treat the compound statement of an ``if consteval`` as an immediate context. Fixes (#GH91509).
- When partial ordering alias templates against template template parameters,
allow pack expansions when the alias has a fixed-size parameter list. Fixes (#GH62529).
+- Clang now ignores template parameters only used within the exception specification of candidate function
+ templates during partial ordering when deducing template arguments from a function declaration or when
+ taking the address of a function template.
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 853c0e1b50619..b5d405111fe4c 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -5453,7 +5453,7 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc,
// is used.
if (DeduceTemplateArgumentsByTypeMatch(
S, TemplateParams, FD2->getType(), FD1->getType(), Info, Deduced,
- TDF_None,
+ TDF_AllowCompatibleFunctionType,
/*PartialOrdering=*/true) != TemplateDeductionResult::Success)
return false;
break;
@@ -5485,20 +5485,40 @@ static bool isAtLeastAsSpecializedAs(Sema &S, SourceLocation Loc,
switch (TPOC) {
case TPOC_Call:
for (unsigned I = 0, N = Args2.size(); I != N; ++I)
- ::MarkUsedTemplateParameters(S.Context, Args2[I], false,
- TemplateParams->getDepth(),
- UsedParameters);
+ ::MarkUsedTemplateParameters(S.Context, Args2[I], /*OnlyDeduced=*/false,
+ TemplateParams->getDepth(), UsedParameters);
break;
case TPOC_Conversion:
- ::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(), false,
+ ::MarkUsedTemplateParameters(S.Context, Proto2->getReturnType(),
+ /*OnlyDeduced=*/false,
TemplateParams->getDepth(), UsedParameters);
break;
case TPOC_Other:
- ::MarkUsedTemplateParameters(S.Context, FD2->getType(), false,
- TemplateParams->getDepth(),
- UsedParameters);
+ // 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, we do not mark template parameters in the exception
+ // specification as used during partial ordering 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; // explicit specialization of #2
+ //
+ // Although there is no corresponding wording in the standard, this seems
+ // to be the intended behavior given the definition of
+ // 'deduction substitution loci' in [temp.deduct].
+ ::MarkUsedTemplateParameters(
+ S.Context,
+ S.Context.getFunctionTypeWithExceptionSpec(FD2->getType(), EST_None),
+ /*OnlyDeduced=*/false, TemplateParams->getDepth(), UsedParameters);
break;
}
diff --git a/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
new file mode 100644
index 0000000000000..cc1d4ecda2ecc
--- /dev/null
+++ b/clang/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p3.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+template<bool B>
+struct A { };
+
+constexpr A<false> a;
+constexpr A<false> b;
+
+constexpr int* x = nullptr;
+constexpr short* y = nullptr;
+
+namespace ExplicitArgs {
+ template<typename T, typename U>
+ constexpr int f(U) noexcept(noexcept(T())) {
+ return 0;
+ }
+
+ template<typename T>
+ constexpr int f(T*) noexcept {
+ return 1;
+ }
+
+ template<>
+ constexpr int f<int>(int*) noexcept {
+ return 2;
+ }
+
+ static_assert(f<int>(1) == 0);
+ static_assert(f<short>(y) == 1);
+ static_assert(f<int>(x) == 2);
+
+ template<typename T, typename U>
+ constexpr int g(U*) noexcept(noexcept(T())) {
+ return 3;
+ }
+
+ template<typename T>
+ constexpr int g(T) noexcept {
+ return 4;
+ }
+
+ template<>
+ constexpr int g<int>(int*) noexcept {
+ return 5;
+ }
+
+ static_assert(g<int>(y) == 3);
+ static_assert(g<short>(1) == 4);
+ static_assert(g<int>(x) == 5);
+} // namespace ExplicitArgs
+
+namespace DeducedArgs {
+ template<typename T, bool B>
+ constexpr int f(T, A<B>) noexcept(B) {
+ return 0;
+ }
+
+ template<typename T, bool B>
+ constexpr int f(T*, A<B>) noexcept(B && B) {
+ return 1;
+ }
+
+ template<>
+ constexpr int f(int*, A<false>) {
+ return 2;
+ }
+
+ static_assert(f<int*>(x, a) == 0);
+ static_assert(f<short>(y, a) == 1);
+ static_assert(f<int>(x, a) == 2);
+} // namespace DeducedArgs
More information about the cfe-commits
mailing list