From fdfc07e571eb7f046013052a9fa57db51c6a2cb9 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Thu, 20 Aug 2026 16:39:01 +0100 Subject: [PATCH] fix: work around clang 20/21 + libc++ compile failure in TEMPLATE_PRODUCT_TEST_CASE with differing arities (#3173) * fix: work around clang 20/21 + libc++ compile failure in TEMPLATE_PRODUCT_TEST_CASE with differing arities Fixes #3115 * docs: reference llvm/llvm-project#130778 in the clang 20/21 workaround comment --------- Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> --- src/catch2/internal/catch_preprocessor.hpp | 11 +++++++---- src/catch2/internal/catch_template_test_registry.hpp | 4 ++-- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/catch2/internal/catch_preprocessor.hpp b/src/catch2/internal/catch_preprocessor.hpp index 1fc8fb8c..fae95e9d 100644 --- a/src/catch2/internal/catch_preprocessor.hpp +++ b/src/catch2/internal/catch_preprocessor.hpp @@ -113,8 +113,11 @@ namespace Catch { template\ constexpr auto get_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TypeList { return {}; }\ template class...> struct TemplateTypeList{};\ - template class...Cs>\ - constexpr auto get_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TemplateTypeList { return {}; }\ + /* Clang 20 and 21 cannot handle an explicitly specified all-pack template-template parameter here\ + ("conflicting deduction" regression, llvm/llvm-project#130778; fixed for Clang 22).\ + Remove get_template_wrapper once Clang 21 is no longer supported. */\ + template class C, template class...Cs>\ + constexpr auto get_template_wrapper(Catch::Detail::priority_tag<1>) noexcept -> TemplateTypeList { return {}; }\ template\ struct append;\ template\ @@ -146,8 +149,8 @@ namespace Catch { template\ constexpr auto get_wrapper(Catch::Detail::priority_tag<0>) noexcept -> Nttp<__VA_ARGS__> { return {}; } \ template class...> struct NttpTemplateTypeList{};\ - template class...Cs>\ - constexpr auto get_wrapper(Catch::Detail::priority_tag<0>) noexcept -> NttpTemplateTypeList { return {}; } \ + template class C, template class...Cs>\ + constexpr auto get_template_wrapper(Catch::Detail::priority_tag<0>) noexcept -> NttpTemplateTypeList { return {}; } \ \ template< template class Container, template class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\ struct rewrap, List<__VA_ARGS__>> { using type = TypeList>; };\ diff --git a/src/catch2/internal/catch_template_test_registry.hpp b/src/catch2/internal/catch_template_test_registry.hpp index 400c308c..96b76aaf 100644 --- a/src/catch2/internal/catch_template_test_registry.hpp +++ b/src/catch2/internal/catch_template_test_registry.hpp @@ -139,7 +139,7 @@ } \ }; \ static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \ - using TestInit = typename create(Catch::Detail::priority_tag<1>{})), TypeList>::type; \ + using TestInit = typename create(Catch::Detail::priority_tag<1>{})), TypeList>::type; \ TestInit t; \ t.reg_tests(); \ return 0; \ @@ -271,7 +271,7 @@ }\ };\ static const int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\ - using TestInit = typename create(Catch::Detail::priority_tag<1>{})), TypeList>::type;\ + using TestInit = typename create(Catch::Detail::priority_tag<1>{})), TypeList>::type;\ TestInit t;\ t.reg_tests();\ return 0;\