From ba7cd28513049c9e1dd05493c73314f67b37c831 Mon Sep 17 00:00:00 2001 From: Adam Panzica Date: Thu, 2 Jul 2026 15:40:46 -0400 Subject: [PATCH] Avoid clang 21/22 C++26-mode frontend crash in StringLiteral MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Clang 21.1+, 22.1.x, and current trunk crash (SIGSEGV in CheckParameterPacksForExpansion; assertion builds fail in LocalInstantiationScope::findInstantiationOf) when compiling any translation unit that includes reflect-cpp headers at -std=c++26, because StringLiteral's variadic constructor constrains itself with a requires-fold over decltype of its own parameter pack — a pattern that hits an open clang regression from the CWG2369 reapplication (llvm/llvm-project#198052; reported against reflect-cpp specifically in llvm/llvm-project#205000, where a minimized reproducer is attached). Constraining via template type parameters instead is semantically equivalent (each argument must still be exactly char) and compiles cleanly at -std=c++20/23/26 on all clang versions tested, including the affected ones. Authored with an AI assistant (Claude Code), reviewed and submitted by the account owner. --- include/rfl/internal/StringLiteral.hpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/include/rfl/internal/StringLiteral.hpp b/include/rfl/internal/StringLiteral.hpp index 03448d4e0..3c59036ac 100644 --- a/include/rfl/internal/StringLiteral.hpp +++ b/include/rfl/internal/StringLiteral.hpp @@ -3,6 +3,7 @@ #include #include +#include #include #include @@ -14,9 +15,11 @@ namespace internal { /// for the parameters names in the NamedTuples. template struct StringLiteral { - constexpr StringLiteral(const auto... _chars) - requires (std::is_same_v && ...) - : arr_{_chars..., '\0'} {} + /// Constrained via template type parameters rather than a requires-fold + /// over decltype of the function parameter pack: the latter crashes + /// clang 21/22 in C++26 mode (llvm/llvm-project#198052, #205000). + template ... Chars> + constexpr StringLiteral(const Chars... _chars) : arr_{_chars..., '\0'} {} constexpr StringLiteral(const std::array _arr) : arr_(_arr) {}