https://github.com/cor3ntin created https://github.com/llvm/llvm-project/pull/229024
The tentative resolution for CWG1432 was not consistent for the resolution of CWG1395. This fixes the crash reported in #228870. Additionally, this update the status of related core issues and papers touching the same wording. Clang was never affected because we never fully implemented CWG1395. Fixes #228870 Fixes #27357 Assisted-by: Opus 5.5 >From 58f5d1f3b776ed6c1462fd2adaf16d66d0b8aed3 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <[email protected]> Date: Mon, 5 Oct 2026 11:21:16 +0200 Subject: [PATCH] [Clang] Fix pack vs non-pack tie breaker. The tentative resolution for CWG1432 was not consistent for the resolution of CWG1395. This fixes the crash reported in #228870. Additionally, this update the status of related core issues and papers touching the same wording. Clang was never affected because we never fully implemented CWG1395. Fixes #228870 Fixes #27357 Assisted-by: Opus 5.5 --- clang/docs/ReleaseNotes.md | 4 ++++ clang/lib/Sema/SemaTemplateDeduction.cpp | 16 ++++++++++++---- clang/test/CXX/drs/cwg13xx.cpp | 4 ++++ clang/test/CXX/drs/cwg18xx.cpp | 13 +++++++++++++ .../SemaCXX/cxx2d-pack-indexing-template.cpp | 13 +++++++++++++ clang/test/SemaTemplate/partial-order.cpp | 17 +++++++++++++++++ clang/www/cxx_dr_status.html | 2 +- clang/www/cxx_status.html | 2 +- 8 files changed, 65 insertions(+), 6 deletions(-) diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md index 7ec126a065ae5ab..f0345e086d07f34 100644 --- a/clang/docs/ReleaseNotes.md +++ b/clang/docs/ReleaseNotes.md @@ -834,6 +834,10 @@ features cannot lower the translation-unit ABI level; the initializer of another specialization of the same variable template. (#GH134148) +- Fixed an assertion failure in partial ordering of function templates whose + parameters use pack-indexed template template parameters (`TT...[N]<int>`) + with different template parameter lists. (#GH228870) + #### Bug Fixes to AST Handling - Fixed a non-deterministic ordering of unused local typedefs that made diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 2257964a4310bbc..3c8d6b1a8b05d20 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -6033,11 +6033,19 @@ getMoreSpecializedTrailingPackTieBreaker( ArrayRef<TemplateArgument> As1 = TST1->template_arguments(), As2 = TST2->template_arguments(); const TemplateArgument &TA1 = As1.back(), &TA2 = As2.back(); - bool IsPack = TA1.getKind() == TemplateArgument::Pack; - assert(IsPack == (TA2.getKind() == TemplateArgument::Pack)); - if (!IsPack) + // C++26 [temp.deduct.partial]p11: + // If, after considering the above, function template F is at least as + // specialized as function template G and vice-versa, and if G has a + // trailing function parameter pack for which F does not have a + // corresponding parameter, and if F does not have a trailing function + // parameter pack, then F is more specialized than G. + bool IsPack1 = TA1.getKind() == TemplateArgument::Pack; + bool IsPack2 = TA2.getKind() == TemplateArgument::Pack; + if (IsPack1 != IsPack2) + return IsPack1 ? MoreSpecializedTrailingPackTieBreakerResult::More + : MoreSpecializedTrailingPackTieBreakerResult::Less; + if (!IsPack1 || As1.size() != As2.size()) return MoreSpecializedTrailingPackTieBreakerResult::Equal; - assert(As1.size() == As2.size()); unsigned PackSize1 = TA1.pack_size(), PackSize2 = TA2.pack_size(); bool IsPackExpansion1 = diff --git a/clang/test/CXX/drs/cwg13xx.cpp b/clang/test/CXX/drs/cwg13xx.cpp index 8e33fc98301d27b..e20ea3089a9db71 100644 --- a/clang/test/CXX/drs/cwg13xx.cpp +++ b/clang/test/CXX/drs/cwg13xx.cpp @@ -730,9 +730,13 @@ namespace cwg1395 { // cwg1395: 16 #if __cplusplus >= 201103L template <typename T, typename... U> void f(T, U...); template <typename T> void f(T); + // The non-pack overload is more specialized. + template <typename T, typename... U> constexpr int g(T, U...) { return 1; } + template <typename T> constexpr int g(T) { return 2; } void h(int i) { // This is made ambiguous by cwg692, but made valid again by cwg1395. f(&i); + static_assert(g(0) == 2, ""); } #endif } // namespace cwg1395 diff --git a/clang/test/CXX/drs/cwg18xx.cpp b/clang/test/CXX/drs/cwg18xx.cpp index 32ff4d72d30f334..548bd7c7b0ab701 100644 --- a/clang/test/CXX/drs/cwg18xx.cpp +++ b/clang/test/CXX/drs/cwg18xx.cpp @@ -316,6 +316,19 @@ struct S { }; } // namespace cwg1824 +namespace cwg1825 { // cwg1825: sup P4004R1 +#if __cplusplus >= 201103L +template <class... T> int f(T *...); // #cwg1825-variadic +template <class T> int f(const T &); // #cwg1825-nonvariadic +int g() { + return f((int *)0); + // since-cxx11-error@-1 {{call to 'f' is ambiguous}} + // since-cxx11-note@#cwg1825-variadic {{candidate function [with T = <int>]}} + // since-cxx11-note@#cwg1825-nonvariadic {{candidate function [with T = int *]}} +} +#endif +} // namespace cwg1825 + namespace cwg1832 { // cwg1832: 3.0 enum E { // #cwg1832-E a = static_cast<int>(static_cast<E>(0)) diff --git a/clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp b/clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp index 83fb5e94071a9e0..1c0a12c21da80b5 100644 --- a/clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp +++ b/clang/test/SemaCXX/cxx2d-pack-indexing-template.cpp @@ -482,3 +482,16 @@ static_assert(!Lambda2<1>.operator()<int, Always, Never>()); static_assert(Lambda2<0>.operator()<int, Always, Never>()); static_assert(Lambda2<0, 0>.operator()<int, Always, Never>()); static_assert(!Lambda2<1, 1>.operator()<int, Always, Never>()); + +namespace GH228870 { +template <class> struct S {}; + +template <unsigned N, template <class...> class... TT> char f(TT...[N]<int>); +template <unsigned N, template <class> class... TT> int f(TT...[N]<int>); +template <unsigned N, template <class, class...> class... TT> char f(TT...[N]<int>); +static_assert(__is_same(decltype(f<0, S>(S<int>{})), int)); + +template <unsigned N, template <class...> class... TT> int g(TT...[N]<int>); // expected-note {{candidate function}} +template <unsigned N, template <class, class...> class... TT> int g(TT...[N]<int>); // expected-note {{candidate function}} +int x = g<0, S>(S<int>{}); // expected-error {{call to 'g' is ambiguous}} +} diff --git a/clang/test/SemaTemplate/partial-order.cpp b/clang/test/SemaTemplate/partial-order.cpp index 2619524b147ae56..b06c2ced9f66d66 100644 --- a/clang/test/SemaTemplate/partial-order.cpp +++ b/clang/test/SemaTemplate/partial-order.cpp @@ -73,3 +73,20 @@ Trait<Y> t; // expected-note@#gh51866-one{{partial specialization matches}} // expected-note@#gh51866-two{{partial specialization matches}} } + +namespace GH27357 { +struct S { + using type = int; +}; + +// T is used in a non-deduced context and has no value, so deduction fails in +// both directions ([temp.deduct.partial]p12). +template <class T> int add(typename T::type); // #gh27357-1 +template <class T, class... Ts> +int add(typename T::type, typename Ts::type...); // #gh27357-2 + +int x = add<S>(0); +// expected-error@-1 {{call to 'add' is ambiguous}} +// expected-note@#gh27357-1 {{candidate function [with T = GH27357::S]}} +// expected-note@#gh27357-2 {{candidate function [with T = GH27357::S, Ts = <>]}} +} // namespace GH27357 diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index e7679da30d5c29e..b7d30a549d22d0b 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -12560,7 +12560,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td>[<a href="https://wg21.link/temp.deduct.partial">temp.deduct.partial</a>]</td> <td>C++17</td> <td>Partial ordering between variadic and non-variadic function templates</td> - <td class="unknown" align="center">Unknown</td> + <td class="na" align="center">Superseded by <a href="https://wg21.link/P4004R1">P4004R1</a></td> </tr> <tr id="1826"> <td><a href="https://cplusplus.github.io/CWG/issues/1826.html">1826</a></td> diff --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html index 61d0f38bce87a5f..3f105f831f9b761 100755 --- a/clang/www/cxx_status.html +++ b/clang/www/cxx_status.html @@ -469,7 +469,7 @@ <h2 id="cxx26">C++2c implementation status</h2> <tr> <td>Reconsider CWG 1395 "Partial ordering of variadic templates reconsidered"</td> <td><a href="https://wg21.link/P4004R1">P4004R1</a> (<a href="#dr">DR</a>)</td> - <td class="none" align="center">No</td> + <td class="full" align="center">Clang 2.7</td> </tr> <tr> <td>CTAD for type template template parameters</td> _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
