[libcxx-commits] [libcxx] [libc++] Implement P4206R0 Revert string support in std::constant_wrapper (PR #203338)

Yihan Wang via libcxx-commits libcxx-commits at lists.llvm.org
Mon Jun 22 03:01:35 PDT 2026


https://github.com/yronglin updated https://github.com/llvm/llvm-project/pull/203338

>From d227c3bfe25b5f3019398fac379b2ff97f1c9db7 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 12 Jun 2026 01:05:39 +0800
Subject: [PATCH 01/11] [libc++] Implement P4206R0 Revert string support in
 std::constant_wrapper

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/docs/FeatureTestMacroTable.rst         |  2 +-
 libcxx/docs/Status/Cxx2cPapers.csv            |  1 +
 libcxx/include/__utility/constant_wrapper.h   | 52 ++++-------
 libcxx/include/utility                        |  7 +-
 libcxx/include/version                        |  4 +-
 .../utility.version.compile.pass.cpp          |  4 +-
 .../version.version.compile.pass.cpp          |  4 +-
 .../const.wrap.class/convert.pass.cpp         | 18 +---
 .../const.wrap.class/ctad.compile.pass.cpp    | 32 -------
 .../utilities/const.wrap.class/cw.pass.cpp    | 16 +---
 .../cw_fixed.array.ctor.pass.cpp              | 86 -------------------
 .../const.wrap.class/cw_fixed.ctor.pass.cpp   | 70 ---------------
 .../const.wrap.class/subscript.pass.cpp       |  6 --
 .../const.wrap.class/template.verify.cpp      | 23 +++++
 .../const.wrap.class/types.compile.pass.cpp   | 23 +++--
 .../generate_feature_test_macro_components.py |  2 +-
 16 files changed, 73 insertions(+), 277 deletions(-)
 delete mode 100644 libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp
 delete mode 100644 libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp
 delete mode 100644 libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp
 create mode 100644 libcxx/test/std/utilities/const.wrap.class/template.verify.cpp

diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst
index 1b748e37293df..405414b270759 100644
--- a/libcxx/docs/FeatureTestMacroTable.rst
+++ b/libcxx/docs/FeatureTestMacroTable.rst
@@ -432,7 +432,7 @@ Status
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_bitset``                                       ``202306L``
     ---------------------------------------------------------- -----------------
-    ``__cpp_lib_constant_wrapper``                             ``202603L``
+    ``__cpp_lib_constant_wrapper``                             ``202606L``
     ---------------------------------------------------------- -----------------
     ``__cpp_lib_constexpr_algorithms``                         ``202306L``
     ---------------------------------------------------------- -----------------
diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv
index 2132e80251657..6099725f566df 100644
--- a/libcxx/docs/Status/Cxx2cPapers.csv
+++ b/libcxx/docs/Status/Cxx2cPapers.csv
@@ -216,3 +216,4 @@
 "`P4159R0 <https://wg21.link/P4159R0>`__","Make ``sender_in`` and ``receiver_of`` exposition-only","2026-03 (Croydon)","","","`#189632 <https://github.com/llvm/llvm-project/issues/189632>`__",""
 "`P4154R0 <https://wg21.link/P4154R0>`__","Renaming various execution things","2026-03 (Croydon)","","","`#189633 <https://github.com/llvm/llvm-project/issues/189633>`__",""
 "","","","","","",""
+"`P3726R2 <https://wg21.link/4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__",""
diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index 6bae95fc1878a..68a8096bc91ad 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -14,6 +14,7 @@
 #include <__functional/invoke.h>
 #include <__type_traits/invoke.h>
 #include <__type_traits/is_constructible.h>
+#include <__type_traits/is_same.h>
 #include <__type_traits/remove_cvref.h>
 #include <__utility/declval.h>
 #include <__utility/forward.h>
@@ -27,36 +28,12 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 26
 
-template <class _Tp>
-struct __cw_fixed_value {
-  using __type _LIBCPP_NODEBUG = _Tp;
-  _LIBCPP_HIDE_FROM_ABI constexpr __cw_fixed_value(__type __v) noexcept : __data(__v) {}
-  _Tp __data;
-};
-
-template <class _Tp, size_t _Extent>
-struct __cw_fixed_value<_Tp[_Extent]> {
-  using __type _LIBCPP_NODEBUG = _Tp[_Extent];
-  _Tp __data[_Extent];
-
-  _LIBCPP_HIDE_FROM_ABI constexpr __cw_fixed_value(_Tp (&__arr)[_Extent]) noexcept
-      : __cw_fixed_value(__arr, make_index_sequence<_Extent>{}) {}
-
-private:
-  template <size_t... _Idxs>
-  _LIBCPP_HIDE_FROM_ABI constexpr __cw_fixed_value(_Tp (&__arr)[_Extent], index_sequence<_Idxs...>) noexcept
-      : __data{__arr[_Idxs]...} {}
-};
-
-template <class _Tp, size_t _Extent>
-__cw_fixed_value(_Tp (&)[_Extent]) -> __cw_fixed_value<_Tp[_Extent]>;
-
-template <__cw_fixed_value _Xp,
+template <auto _Xp,
 #  ifdef _LIBCPP_COMPILER_GCC
-          // gcc bug:  https://gcc.gnu.org/PR117392
-          class = typename decltype(__cw_fixed_value(_Xp))::__type
+          // gcc bug: https://gcc.gnu.org/PR117392
+          class = remove_cvref_t<decltype(_Xp)>
 #  else
-          class = typename decltype(_Xp)::__type
+          class = decltype(_Xp)
 #  endif
           >
 struct constant_wrapper;
@@ -64,7 +41,7 @@ struct constant_wrapper;
 template <class _Tp>
 concept __constexpr_param = requires { typename constant_wrapper<_Tp::value>; };
 
-template <__cw_fixed_value _Xp>
+template <auto _Xp>
 constexpr auto cw = constant_wrapper<_Xp>{};
 
 struct __cw_operators {
@@ -288,11 +265,20 @@ concept __constexpr_indexable = (__constexpr_param<remove_cvref_t<_Args>> && ...
   typename constant_wrapper<_Obj[remove_cvref_t<_Args>::value...]>;
 };
 
-template <__cw_fixed_value _Xp, class>
+template <auto _Xp, class _Tp>
 struct constant_wrapper : __cw_operators {
-  static constexpr const auto& value = _Xp.__data;
-  using type                         = constant_wrapper;
-  using value_type                   = decltype(_Xp)::__type;
+#  ifdef _LIB_CPP_COMPILER_GCC
+  // gcc bug: https://gcc.gnu.org/PR125188
+  static constexpr decltype((_Xp)) value = (_Xp);
+#  else
+  static constexpr decltype(auto) value = (_Xp);
+#  endif
+
+  using type       = constant_wrapper;
+  using value_type = decltype(_Xp);
+
+  static_assert(is_same_v<_Tp, value_type>,
+                "the second template parameter of std::constant_wrapper must be its value_type");
 
   template <__constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator=(_Rp) const noexcept
diff --git a/libcxx/include/utility b/libcxx/include/utility
index e0c97efc6424d..940dc4f354984 100644
--- a/libcxx/include/utility
+++ b/libcxx/include/utility
@@ -196,10 +196,7 @@ template<class T1, class T2>
     constexpr const T1&& get(const pair<T2, T1>&&) noexcept; // C++14
 
 // [const.wrap.class], class template constant_wrapper
-template<class T>
-  struct cw-fixed-value;                                    // exposition only, since C++26
-
-template<cw-fixed-value X, class = typename decltype(X)::type>
+template<auto X, class = decltype(X)>
   struct constant_wrapper;                                  // since C++26
 
 template<class T>
@@ -208,7 +205,7 @@ template<class T>
 
 struct cw-operators;                                        // exposition only, since C++26
 
-template<cw-fixed-value X>
+template<auto X>
   constexpr auto cw = constant_wrapper<X>{};                // since C++26
 
 // C++14
diff --git a/libcxx/include/version b/libcxx/include/version
index d4d29b4d31a72..ae12300308eb6 100644
--- a/libcxx/include/version
+++ b/libcxx/include/version
@@ -64,7 +64,7 @@ __cpp_lib_common_reference                              202302L <type_traits>
 __cpp_lib_common_reference_wrapper                      202302L <functional>
 __cpp_lib_complex_udls                                  201309L <complex>
 __cpp_lib_concepts                                      202207L <concepts>
-__cpp_lib_constant_wrapper                              202603L <utility>
+__cpp_lib_constant_wrapper                              202606L <utility>
 __cpp_lib_constexpr_algorithms                          202306L <algorithm> <utility>
                                                         201806L // C++20
 __cpp_lib_constexpr_bitset                              202207L <bitset>
@@ -562,7 +562,7 @@ __cpp_lib_void_t                                        201411L <type_traits>
 # undef  __cpp_lib_bind_front
 # define __cpp_lib_bind_front                           202306L
 # define __cpp_lib_bitset                               202306L
-# define __cpp_lib_constant_wrapper                     202603L
+# define __cpp_lib_constant_wrapper                     202606L
 # undef  __cpp_lib_constexpr_algorithms
 # define __cpp_lib_constexpr_algorithms                 202306L
 # define __cpp_lib_constexpr_flat_map                   202502L
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp
index 8cbd16d242f74..bff6e905e4dee 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/utility.version.compile.pass.cpp
@@ -404,8 +404,8 @@
 #  ifndef __cpp_lib_constant_wrapper
 #    error "__cpp_lib_constant_wrapper should be defined in c++26"
 #  endif
-#  if __cpp_lib_constant_wrapper != 202603L
-#    error "__cpp_lib_constant_wrapper should have the value 202603L in c++26"
+#  if __cpp_lib_constant_wrapper != 202606L
+#    error "__cpp_lib_constant_wrapper should have the value 202606L in c++26"
 #  endif
 
 #  ifndef __cpp_lib_constexpr_algorithms
diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
index 20c16700ef76a..c1aa2f41f7c2e 100644
--- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
+++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp
@@ -6609,8 +6609,8 @@
 #  ifndef __cpp_lib_constant_wrapper
 #    error "__cpp_lib_constant_wrapper should be defined in c++26"
 #  endif
-#  if __cpp_lib_constant_wrapper != 202603L
-#    error "__cpp_lib_constant_wrapper should have the value 202603L in c++26"
+#  if __cpp_lib_constant_wrapper != 202606L
+#    error "__cpp_lib_constant_wrapper should have the value 202606L in c++26"
 #  endif
 
 #  ifndef __cpp_lib_constexpr_algorithms
diff --git a/libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp
index a9567cb08b009..f7c59401dcd2a 100644
--- a/libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/convert.pass.cpp
@@ -27,11 +27,10 @@ constexpr bool test() {
   {
     // int conversion
     std::constant_wrapper<6> cw6;
-    const int& result = cw6;
+    int result = cw6;
     assert(result == 6);
-    assert(&result == &cw6.value);
 
-    static_assert(noexcept(static_cast<const int&>(cw6)));
+    static_assert(noexcept(static_cast<int>(cw6)));
   }
 
   {
@@ -45,19 +44,6 @@ constexpr bool test() {
     static_assert(noexcept(static_cast<const S&>(cws)));
   }
 
-  {
-    // array conversion
-    constexpr int arr[] = {1, 2, 3};
-    std::constant_wrapper<arr> cwArr;
-    const int (&result)[3] = cwArr;
-    assert(result[0] == 1);
-    assert(result[1] == 2);
-    assert(result[2] == 3);
-    assert(&result == &cwArr.value);
-
-    static_assert(noexcept(static_cast<const int (&)[3]>(cwArr)));
-  }
-
   {
     // function pointer conversion
     constexpr int (*fptr)(int) = [](int x) constexpr { return x * 2; };
diff --git a/libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp
deleted file mode 100644
index 7210d7e2152d5..0000000000000
--- a/libcxx/test/std/utilities/const.wrap.class/ctad.compile.pass.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++26
-
-// constant_wrapper
-
-// template<class T, size_t Extent>
-//   cw-fixed-value(T (&)[Extent]) -> cw-fixed-value<T[Extent]>;                   // exposition only
-
-#include <type_traits>
-#include <utility>
-
-constexpr int arr[] = {1, 2, 3};
-using T1            = std::constant_wrapper<arr>;
-static_assert(std::is_same_v<T1::value_type, const int[3]>);
-
-using T2 = std::constant_wrapper<"hello world">;
-static_assert(std::is_same_v<T2::value_type, const char[12]>);
-
-struct S {
-  int value;
-};
-
-constexpr S s[] = {{1}, {2}, {3}};
-using T3        = std::constant_wrapper<s>;
-static_assert(std::is_same_v<T3::value_type, const S[3]>);
diff --git a/libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp
index 4f660ee378239..8d8371a0a68a1 100644
--- a/libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/cw.pass.cpp
@@ -10,12 +10,13 @@
 
 // constant_wrapper
 
-//   template<cw-fixed-value X>
+//   template<auto X>
 //    constexpr auto cw = constant_wrapper<X>{};
 
 #include <cassert>
 #include <concepts>
 #include <utility>
+#include <cstddef>
 
 struct S {
   int value;
@@ -41,7 +42,7 @@ constexpr bool test() {
 
   {
     // array constant
-    constexpr int arr[] = {1, 2, 3};
+    constexpr static int arr[] = {1, 2, 3};
     // gcc complains that cw_val is unused
     [[maybe_unused]] std::same_as<const std::constant_wrapper<arr>> decltype(auto) cw_val = std::cw<arr>;
     static_assert(cw_val[0] == 1);
@@ -49,17 +50,6 @@ constexpr bool test() {
     static_assert(cw_val[2] == 3);
   }
 
-  {
-    // string literals
-    [[maybe_unused]] std::same_as<const std::constant_wrapper<"hello">> decltype(auto) cw_val = std::cw<"hello">;
-    static_assert(cw_val[0] == 'h');
-    static_assert(cw_val[1] == 'e');
-    static_assert(cw_val[2] == 'l');
-    static_assert(cw_val[3] == 'l');
-    static_assert(cw_val[4] == 'o');
-    static_assert(cw_val[5] == '\0');
-  }
-
   return true;
 }
 
diff --git a/libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp
deleted file mode 100644
index 8bccfcfaaaa43..0000000000000
--- a/libcxx/test/std/utilities/const.wrap.class/cw_fixed.array.ctor.pass.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++26
-
-// constant_wrapper
-
-// constexpr cw-fixed-value(T (&arr)[Extent]) noexcept;
-
-#include <cassert>
-#include <utility>
-
-template <auto v>
-auto helper(std::constant_wrapper<v>) -> decltype(v);
-
-template <class T>
-using cw_fixed_value = decltype(helper(std::constant_wrapper<T{}>{}));
-
-struct S {
-  int value;
-
-  constexpr S(int v = 0) : value(v) {}
-
-  constexpr bool operator==(const S& other) const { return value == other.value; }
-};
-
-constexpr bool test() {
-  {
-    // int array construction
-    // the conversion from int array to cw-fixed-value<int array> uses the constructor
-    constexpr int arr[] = {1, 2, 3};
-    std::constant_wrapper<arr> cw{};
-    assert(cw.value[0] == 1);
-    assert(cw.value[1] == 2);
-    assert(cw.value[2] == 3);
-  }
-
-  {
-    // struct array construction
-    constexpr S s[] = {{1}, {2}, {3}};
-    std::constant_wrapper<s> cw{};
-    assert(cw.value[0] == S{1});
-    assert(cw.value[1] == S{2});
-    assert(cw.value[2] == S{3});
-  }
-
-  {
-    // calling the constructor
-    constexpr int arr[] = {1, 2, 3, 4, 5};
-    constexpr cw_fixed_value<const int[5]> ci(arr);
-    std::constant_wrapper<ci> cw;
-    assert(cw.value[0] == 1);
-    assert(cw.value[1] == 2);
-    assert(cw.value[2] == 3);
-    assert(cw.value[3] == 4);
-    assert(cw.value[4] == 5);
-
-    static_assert(noexcept(cw_fixed_value<const int[5]>{arr}));
-  }
-
-  {
-    // the constructor is implicit
-    constexpr int arr[]                       = {1, 2, 3, 4, 5};
-    constexpr cw_fixed_value<const int[5]> ci = arr;
-    std::constant_wrapper<ci> cw;
-    assert(cw.value[0] == 1);
-    assert(cw.value[1] == 2);
-    assert(cw.value[2] == 3);
-    assert(cw.value[3] == 4);
-    assert(cw.value[4] == 5);
-  }
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp
deleted file mode 100644
index 30c2952f57d4c..0000000000000
--- a/libcxx/test/std/utilities/const.wrap.class/cw_fixed.ctor.pass.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-
-// REQUIRES: std-at-least-c++26
-
-// constant_wrapper
-
-// constexpr cw-fixed-value(type v) noexcept : data(v) {}
-
-#include <cassert>
-#include <utility>
-
-template <auto v>
-auto helper(std::constant_wrapper<v>) -> decltype(v);
-
-template <class T>
-using cw_fixed_value = decltype(helper(std::constant_wrapper<T{}>{}));
-
-struct S {
-  int value;
-
-  constexpr S(int v = 0) : value(v) {}
-
-  constexpr bool operator==(const S& other) const { return value == other.value; }
-};
-
-constexpr bool test() {
-  {
-    // int construction
-    // the conversion from int to cw-fixed-value<int> uses the constructor
-    std::constant_wrapper<42> cw{};
-    assert(cw.value == 42);
-  }
-
-  {
-    // struct construction
-    std::constant_wrapper<S{13}> cw{};
-    assert(cw.value == S{13});
-  }
-
-  {
-    // calling the constructor
-    constexpr cw_fixed_value<int> ci{42};
-    std::constant_wrapper<ci> cw;
-    assert(cw == 42);
-
-    static_assert(noexcept(cw_fixed_value<int>{42}));
-  }
-
-  {
-    // the constructor is implicit
-    constexpr cw_fixed_value<int> ci = 42;
-    std::constant_wrapper<ci> cw;
-    assert(cw == 42);
-  }
-
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  static_assert(test());
-
-  return 0;
-}
diff --git a/libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp
index 7efefa85fed95..bfa77a4662afc 100644
--- a/libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/subscript.pass.cpp
@@ -171,12 +171,6 @@ constexpr bool test() {
     assert(result == 42);
   }
 
-  {
-    // just use the index operator
-    assert(std::cw<"abcd">[2] == 'c');
-    assert(std::cw<"abcd">[std::cw<3>] == 'd');
-  }
-
   {
     // integral_constant
     using T                                                      = std::constant_wrapper<arr>;
diff --git a/libcxx/test/std/utilities/const.wrap.class/template.verify.cpp b/libcxx/test/std/utilities/const.wrap.class/template.verify.cpp
new file mode 100644
index 0000000000000..f8902212299ec
--- /dev/null
+++ b/libcxx/test/std/utilities/const.wrap.class/template.verify.cpp
@@ -0,0 +1,23 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// REQUIRES: std-at-least-c++26
+
+#include <utility>
+
+// expected-error at +1 {{pointer to subobject of string literal is not allowed in a template argument}}
+std::constant_wrapper<"hello"> string_literal;
+
+// expected-error-re@*:* {{static assertion failed{{.*}}the second template parameter of std::constant_wrapper must be its value_type}}
+std::constant_wrapper<1, float> wrong_type1; // expected-note {{in instantiation of template class}}
+// expected-error-re@*:* {{static assertion failed{{.*}}the second template parameter of std::constant_wrapper must be its value_type}}
+std::constant_wrapper<1.0, int> wrong_type2; // expected-note {{in instantiation of template class}}
+// expected-error-re@*:* {{static assertion failed{{.*}}the second template parameter of std::constant_wrapper must be its value_type}}
+std::constant_wrapper<1, const int> wrong_type3; // expected-note {{in instantiation of template class}}
+// expected-error-re@*:* {{static assertion failed{{.*}}the second template parameter of std::constant_wrapper must be its value_type}}
+std::constant_wrapper<1, const int&> wrong_type4; // expected-note {{in instantiation of template class}}
diff --git a/libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp
index 96dce9e055209..a85a44efd5cfd 100644
--- a/libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/types.compile.pass.cpp
@@ -10,16 +10,15 @@
 
 // constant_wrapper
 
-// static constexpr const auto & value = X.data;
+// static constexpr decltype(auto) value = (X);
 // using type = constant_wrapper;
-// using value_type = decltype(X)::type;
+// using value_type = decltype(X);
 
-#include <algorithm>
 #include <concepts>
 #include <utility>
 
 static_assert(std::constant_wrapper<42>::value == 42);
-static_assert(std::same_as<decltype(std::constant_wrapper<42>::value), const int&>);
+static_assert(std::same_as<decltype(std::constant_wrapper<42>::value), const int>);
 static_assert(std::same_as<std::constant_wrapper<42>::type, std::constant_wrapper<42>>);
 static_assert(std::same_as<std::constant_wrapper<42>::value_type, int>);
 
@@ -32,7 +31,15 @@ static_assert(std::same_as<decltype(std::constant_wrapper<S{5}>::value), const S
 static_assert(std::same_as<std::constant_wrapper<S{5}>::type, std::constant_wrapper<S{5}>>);
 static_assert(std::same_as<std::constant_wrapper<S{5}>::value_type, S>);
 
-static_assert(std::ranges::equal(std::constant_wrapper<"abcd">::value, "abcd"));
-static_assert(std::same_as<decltype(std::constant_wrapper<"abcd">::value), const char (&)[5]>);
-static_assert(std::same_as<std::constant_wrapper<"abcd">::type, std::constant_wrapper<"abcd">>);
-static_assert(std::same_as<std::constant_wrapper<"abcd">::value_type, const char[5]>);
+template <auto V>
+consteval bool value_ref_to_template_parameter_object() {
+  return &V == &std::constant_wrapper<V>::value;
+}
+
+static_assert(value_ref_to_template_parameter_object<S{5}>());
+
+constexpr int arr[] = {1, 2, 3, 4, 5};
+
+static_assert(std::constant_wrapper<arr>::value == arr);
+static_assert(std::same_as<std::constant_wrapper<arr>::type, std::constant_wrapper<arr>>);
+static_assert(std::same_as<std::constant_wrapper<arr>::value_type, const int*>);
diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py
index d8fb575b97b2f..64e1f1cb7f9a7 100644
--- a/libcxx/utils/generate_feature_test_macro_components.py
+++ b/libcxx/utils/generate_feature_test_macro_components.py
@@ -337,7 +337,7 @@ def add_version_header(tc):
         {
             "name": "__cpp_lib_constant_wrapper",
             "values": {
-                "c++26": 202603,
+                "c++26": 202606,
             },
             "headers": ["utility"],
         },

>From 05a15b4ed00f0f953b7480d0610d909a550d8088 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 12 Jun 2026 11:46:01 +0800
Subject: [PATCH 02/11] [libc++] Workaround GCC bugs and clang 22

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/include/__utility/constant_wrapper.h | 86 ++++++++++-----------
 1 file changed, 43 insertions(+), 43 deletions(-)

diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index 68a8096bc91ad..c76c282adfb11 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -47,130 +47,130 @@ constexpr auto cw = constant_wrapper<_Xp>{};
 struct __cw_operators {
   // unary operators
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Tp) noexcept -> constant_wrapper<auto(+_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Tp) noexcept -> constant_wrapper<auto(-_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator~(_Tp) noexcept -> constant_wrapper<auto(~_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!(_Tp) noexcept -> constant_wrapper<auto(!_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Tp) noexcept -> constant_wrapper<auto(&_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Tp) noexcept -> constant_wrapper<auto(*_Tp::value)> {
     return {};
   }
 
   // binary operators
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value + _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value + _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value - _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value - _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value * _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value * _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator/(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value / _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value / _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator%(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value % _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value % _Rp::value)> {
     return {};
   }
 
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<<(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value << _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value << _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>>(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value >> _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value >> _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value & _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value & _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator|(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value | _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value | _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator^(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value ^ _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value ^ _Rp::value)> {
     return {};
   }
 
   template <__constexpr_param _Lp, __constexpr_param _Rp>
     requires(!is_constructible_v<bool, decltype(_Lp::value)> || !is_constructible_v<bool, decltype(_Rp::value)>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&&(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value && _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value && _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
     requires(!is_constructible_v<bool, decltype(_Lp::value)> || !is_constructible_v<bool, decltype(_Rp::value)>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator||(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value || _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value || _Rp::value)> {
     return {};
   }
 
   // comparisons
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value <=> _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value <=> _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value < _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value < _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value <= _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value <= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator==(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value == _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value == _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!=(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value != _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value != _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value > _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value > _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>=(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value >= _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value >= _Rp::value)> {
     return {};
   }
 
@@ -179,78 +179,78 @@ struct __cw_operators {
 
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator->*(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value->*_Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value->*_Rp::value)> {
     return {};
   }
 
   // pseudo-mutators
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp) noexcept -> constant_wrapper<(++_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp) noexcept -> constant_wrapper<auto(++_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp, int) noexcept
-      -> constant_wrapper<(_Tp::value++)> {
+      -> constant_wrapper<auto(_Tp::value++)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp) noexcept -> constant_wrapper<(--_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp) noexcept -> constant_wrapper<auto(--_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp, int) noexcept
-      -> constant_wrapper<(_Tp::value--)> {
+      -> constant_wrapper<auto(_Tp::value--)> {
     return {};
   }
 
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator+=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value += _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value += _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator-=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value -= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value -= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator*=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value *= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value *= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator/=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value /= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value /= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator%=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value %= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value %= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator&=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value &= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value &= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator|=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value |= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value |= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator^=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value ^= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value ^= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator<<=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value <<= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value <<= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator>>=(this _Tp, _Rp) noexcept
-      -> constant_wrapper<(_Tp::value >>= _Rp::value)> {
+      -> constant_wrapper<auto(_Tp::value >>= _Rp::value)> {
     return {};
   }
 };
@@ -262,12 +262,12 @@ concept __constexpr_callable = (__constexpr_param<remove_cvref_t<_Args>> && ...)
 
 template <const auto& _Obj, class... _Args>
 concept __constexpr_indexable = (__constexpr_param<remove_cvref_t<_Args>> && ...) && requires {
-  typename constant_wrapper<_Obj[remove_cvref_t<_Args>::value...]>;
+  typename constant_wrapper<auto(_Obj[remove_cvref_t<_Args>::value...])>;
 };
 
 template <auto _Xp, class _Tp>
 struct constant_wrapper : __cw_operators {
-#  ifdef _LIB_CPP_COMPILER_GCC
+#  ifdef _LIBCPP_COMPILER_GCC
   // gcc bug: https://gcc.gnu.org/PR125188
   static constexpr decltype((_Xp)) value = (_Xp);
 #  else
@@ -306,7 +306,7 @@ struct constant_wrapper : __cw_operators {
   template <class... _Args>
     requires __constexpr_indexable<value, _Args...>
   [[nodiscard]]
-  _LIBCPP_HIDE_FROM_ABI static constexpr constant_wrapper<value[remove_cvref_t<_Args>::value...]>
+  _LIBCPP_HIDE_FROM_ABI static constexpr constant_wrapper<auto(value[remove_cvref_t<_Args>::value...])>
   operator[](_Args&&...) noexcept {
     return {};
   }

>From b8874586b32df7446faa6de2d877e78e2b6b6cab Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 12 Jun 2026 14:29:19 +0800
Subject: [PATCH 03/11] [libc++] Add release notes and add auto for operator[]

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/docs/ReleaseNotes/23.rst             | 6 ++++++
 libcxx/include/__utility/constant_wrapper.h | 2 +-
 2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index c8f7cf5455d92..a3d1a08dc81f3 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -51,6 +51,7 @@ Implemented Papers
 - P2542R8: ``views::concat`` (`Github <https://llvm.org/PR105419>`__)
 - P3383R3: ``mdspan.at()`` (`Github <https://llvm.org/PR175213>`__)
 - P3508R0: Wording for "constexpr for specialized memory algorithms" (`Github <https://llvm.org/PR118379>`__)
+- P4206R0: Revert string support in ``std::constant_wrapper`` (`Github <https://llvm.org/PR203338>`__)
 
 Improvements and New Features
 -----------------------------
@@ -84,6 +85,11 @@ Potentially breaking changes
   causes programs which rely on these includes to not compile anymore. Any errors caused by this should be fixable by
   including the correct header. To ease the transition ``_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23`` can be defined, which
   includes the removed headers again. This macro will be removed in LLVM 24.
+- P4206R0 (Revert string support in ``std::constant_wrapper``). This fixes C++26's ``std::constant_wrapper`` by removing 
+  support for a special case (string constants). Doing that simplifies the class, makes it easier to use as a function
+  parameter, and reduce symbol sizes significantly. The change will affect existing compilers retroactively(It's a DR).
+  Also this is a breaking change to C++26, but the class' relative newness and the difficulty of back-poting it means
+  that it currently has few users.
 
 Announcements About Future Releases
 -----------------------------------
diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index c76c282adfb11..fd84d20bccd63 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -282,7 +282,7 @@ struct constant_wrapper : __cw_operators {
 
   template <__constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator=(_Rp) const noexcept
-      -> constant_wrapper<(value = _Rp::value)> {
+      -> constant_wrapper<auto(value = _Rp::value)> {
     return {};
   }
 

>From fb4b94265ce642515bb6ad04c0e39b60a92a6584 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 12 Jun 2026 15:35:12 +0800
Subject: [PATCH 04/11] Format

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/include/__utility/constant_wrapper.h | 30 +++++++++++++--------
 1 file changed, 19 insertions(+), 11 deletions(-)

diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index fd84d20bccd63..c9561c83f609f 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -47,27 +47,33 @@ constexpr auto cw = constant_wrapper<_Xp>{};
 struct __cw_operators {
   // unary operators
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Tp) noexcept -> constant_wrapper<auto(+_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Tp) noexcept
+      -> constant_wrapper<auto(+_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Tp) noexcept -> constant_wrapper<auto(-_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Tp) noexcept
+      -> constant_wrapper<auto(-_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator~(_Tp) noexcept -> constant_wrapper<auto(~_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator~(_Tp) noexcept
+      -> constant_wrapper<auto(~_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!(_Tp) noexcept -> constant_wrapper<auto(!_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!(_Tp) noexcept
+      -> constant_wrapper<auto(!_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Tp) noexcept -> constant_wrapper<auto(&_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Tp) noexcept
+      -> constant_wrapper<auto(&_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Tp) noexcept -> constant_wrapper<auto(*_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Tp) noexcept
+      -> constant_wrapper<auto(*_Tp::value)> {
     return {};
   }
 
@@ -84,7 +90,7 @@ struct __cw_operators {
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value * _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value* _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
@@ -110,7 +116,7 @@ struct __cw_operators {
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value & _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value& _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
@@ -127,7 +133,7 @@ struct __cw_operators {
   template <__constexpr_param _Lp, __constexpr_param _Rp>
     requires(!is_constructible_v<bool, decltype(_Lp::value)> || !is_constructible_v<bool, decltype(_Rp::value)>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&&(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value && _Rp::value)> {
+      -> constant_wrapper<auto(_Lp::value&& _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
@@ -185,7 +191,8 @@ struct __cw_operators {
 
   // pseudo-mutators
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp) noexcept -> constant_wrapper<auto(++_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp) noexcept
+      -> constant_wrapper<auto(++_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
@@ -194,7 +201,8 @@ struct __cw_operators {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp) noexcept -> constant_wrapper<auto(--_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp) noexcept
+      -> constant_wrapper<auto(--_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>

>From 639cd0d9555d99f00c3f0d230855fdda109c0284 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Fri, 12 Jun 2026 22:41:54 +0800
Subject: [PATCH 05/11] [libc++] Update constant_wrapper.h to workaround
 GCC/clang bugs

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/include/__utility/constant_wrapper.h | 14 +-------------
 1 file changed, 1 insertion(+), 13 deletions(-)

diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index c9561c83f609f..a69f878a195c6 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -28,14 +28,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD
 
 #if _LIBCPP_STD_VER >= 26
 
-template <auto _Xp,
-#  ifdef _LIBCPP_COMPILER_GCC
-          // gcc bug: https://gcc.gnu.org/PR117392
-          class = remove_cvref_t<decltype(_Xp)>
-#  else
-          class = decltype(_Xp)
-#  endif
-          >
+template <auto _Xp, class = remove_cvref_t<decltype(_Xp)>>
 struct constant_wrapper;
 
 template <class _Tp>
@@ -275,12 +268,7 @@ concept __constexpr_indexable = (__constexpr_param<remove_cvref_t<_Args>> && ...
 
 template <auto _Xp, class _Tp>
 struct constant_wrapper : __cw_operators {
-#  ifdef _LIBCPP_COMPILER_GCC
-  // gcc bug: https://gcc.gnu.org/PR125188
   static constexpr decltype((_Xp)) value = (_Xp);
-#  else
-  static constexpr decltype(auto) value = (_Xp);
-#  endif
 
   using type       = constant_wrapper;
   using value_type = decltype(_Xp);

>From 0258c5f322972c55f4940a6fe77fa2cbc1d0cb55 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Sat, 13 Jun 2026 00:13:37 +0800
Subject: [PATCH 06/11] [libc++] WA clang-21 bug

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 .../test/std/utilities/const.wrap.class/unary_ops.pass.cpp   | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp
index 5a474265a1719..f4227bf924345 100644
--- a/libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp
@@ -148,7 +148,12 @@ static_assert(!HasPlus<std::constant_wrapper<NoOps{}>>);
 static_assert(!HasMinus<std::constant_wrapper<NoOps{}>>);
 static_assert(!HasBitNot<std::constant_wrapper<NoOps{}>>);
 static_assert(!HasNot<std::constant_wrapper<NoOps{}>>);
+
+// Skip this test on clang-21, see https://github.com/llvm/llvm-project/issues/151531.
+#if defined(__clang_major__) && __clang_major__ > 21
 static_assert(HasBitAnd<std::constant_wrapper<NoOps{}>>);
+#endif
+
 static_assert(!HasDeref<std::constant_wrapper<NoOps{}>>);
 
 // The operators from constant_wrapper do not exist, but they can be implicited converted

>From 1e41e1597732017f00dd29222c07d8cde4a0169b Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Mon, 22 Jun 2026 14:22:00 +0800
Subject: [PATCH 07/11] [libc++] Avoid unecessary workarpund and update release
 notes/status

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/docs/ReleaseNotes/23.rst               |  5 --
 libcxx/docs/Status/Cxx26Papers.csv            |  1 -
 libcxx/docs/Status/Cxx29Papers.csv            |  2 +-
 libcxx/include/__utility/constant_wrapper.h   | 72 +++++++++++--------
 .../const.wrap.class/unary_ops.pass.cpp       |  4 +-
 5 files changed, 44 insertions(+), 40 deletions(-)

diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index 4e6d2be6ae805..8055792f697ea 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -87,11 +87,6 @@ Potentially breaking changes
   causes programs which rely on these includes to not compile anymore. Any errors caused by this should be fixable by
   including the correct header. To ease the transition ``_LIBCPP_KEEP_TRANSITIVE_INCLUDES_LLVM23`` can be defined, which
   includes the removed headers again. This macro will be removed in LLVM 24.
-- P4206R0 (Revert string support in ``std::constant_wrapper``). This fixes C++26's ``std::constant_wrapper`` by removing 
-  support for a special case (string constants). Doing that simplifies the class, makes it easier to use as a function
-  parameter, and reduce symbol sizes significantly. The change will affect existing compilers retroactively(It's a DR).
-  Also this is a breaking change to C++26, but the class' relative newness and the difficulty of back-poting it means
-  that it currently has few users.
 
 Announcements About Future Releases
 -----------------------------------
diff --git a/libcxx/docs/Status/Cxx26Papers.csv b/libcxx/docs/Status/Cxx26Papers.csv
index 68f0fe85c8316..a951ac4c6c833 100644
--- a/libcxx/docs/Status/Cxx26Papers.csv
+++ b/libcxx/docs/Status/Cxx26Papers.csv
@@ -216,4 +216,3 @@
 "`P4159R0 <https://wg21.link/P4159R0>`__","Make ``sender_in`` and ``receiver_of`` exposition-only","2026-03 (Croydon)","","","`#189632 <https://github.com/llvm/llvm-project/issues/189632>`__",""
 "`P4154R0 <https://wg21.link/P4154R0>`__","Renaming various execution things","2026-03 (Croydon)","","","`#189633 <https://github.com/llvm/llvm-project/issues/189633>`__",""
 "","","","","","",""
-"`P3726R2 <https://wg21.link/4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__",""
diff --git a/libcxx/docs/Status/Cxx29Papers.csv b/libcxx/docs/Status/Cxx29Papers.csv
index a5d896f260657..90e7f4e00b419 100644
--- a/libcxx/docs/Status/Cxx29Papers.csv
+++ b/libcxx/docs/Status/Cxx29Papers.csv
@@ -5,7 +5,7 @@
 "`P3319R6 <https://wg21.link/P3319R6>`__","Add an ``iota`` object for ``simd`` (and more)","2026-06 (Brno)","","","`#204393 <https://github.com/llvm/llvm-project/issues/204393>`__",""
 "`P3798R1 <https://wg21.link/P3798R1>`__","The unexpected in ``std::expected``","2026-06 (Brno)","","","`#204394 <https://github.com/llvm/llvm-project/issues/204394>`__",""
 "`P3052R2 <https://wg21.link/P3052R2>`__","``view_interface::at()``","2026-06 (Brno)","","","`#204395 <https://github.com/llvm/llvm-project/issues/204395>`__",""
-"`P4206R0 <https://wg21.link/P4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","","","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__","To be applied as a Defect Report."
+"`P4206R0 <https://wg21.link/P4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__","To be applied as a Defect Report."
 "`P3395R6 <https://wg21.link/P3395R6>`__","Fix encoding issues and add a formatter for ``std::error_code``","2026-06 (Brno)","","","`#204396 <https://github.com/llvm/llvm-project/issues/204396>`__",""
 "`P3505R4 <https://wg21.link/P3505R4>`__","Fix the default floating-point representation in ``std::format``","2026-06 (Brno)","","","`#204397 <https://github.com/llvm/llvm-project/issues/204397>`__","To be applied as a Defect Report."
 "`P3154R3 <https://wg21.link/P3154R3>`__","Deprecating signed character types in iostreams","2026-06 (Brno)","","","`#204398 <https://github.com/llvm/llvm-project/issues/204398>`__",""
diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index a69f878a195c6..7c5586be0d0ab 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -41,135 +41,135 @@ struct __cw_operators {
   // unary operators
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Tp) noexcept
-      -> constant_wrapper<auto(+_Tp::value)> {
+      -> constant_wrapper<(+_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Tp) noexcept
-      -> constant_wrapper<auto(-_Tp::value)> {
+      -> constant_wrapper<(-_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator~(_Tp) noexcept
-      -> constant_wrapper<auto(~_Tp::value)> {
+      -> constant_wrapper<(~_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!(_Tp) noexcept
-      -> constant_wrapper<auto(!_Tp::value)> {
+      -> constant_wrapper<(!_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Tp) noexcept
-      -> constant_wrapper<auto(&_Tp::value)> {
+      -> constant_wrapper<(&_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Tp) noexcept
-      -> constant_wrapper<auto(*_Tp::value)> {
+      -> constant_wrapper<(*_Tp::value)> {
     return {};
   }
 
   // binary operators
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value + _Rp::value)> {
+      -> constant_wrapper<(_Lp::value + _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value - _Rp::value)> {
+      -> constant_wrapper<(_Lp::value - _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value* _Rp::value)> {
+      -> constant_wrapper<(_Lp::value* _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator/(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value / _Rp::value)> {
+      -> constant_wrapper<(_Lp::value / _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator%(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value % _Rp::value)> {
+      -> constant_wrapper<(_Lp::value % _Rp::value)> {
     return {};
   }
 
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<<(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value << _Rp::value)> {
+      -> constant_wrapper<(_Lp::value << _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>>(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value >> _Rp::value)> {
+      -> constant_wrapper<(_Lp::value >> _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value& _Rp::value)> {
+      -> constant_wrapper<(_Lp::value& _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator|(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value | _Rp::value)> {
+      -> constant_wrapper<(_Lp::value | _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator^(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value ^ _Rp::value)> {
+      -> constant_wrapper<(_Lp::value ^ _Rp::value)> {
     return {};
   }
 
   template <__constexpr_param _Lp, __constexpr_param _Rp>
     requires(!is_constructible_v<bool, decltype(_Lp::value)> || !is_constructible_v<bool, decltype(_Rp::value)>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&&(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value&& _Rp::value)> {
+      -> constant_wrapper<(_Lp::value&& _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
     requires(!is_constructible_v<bool, decltype(_Lp::value)> || !is_constructible_v<bool, decltype(_Rp::value)>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator||(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value || _Rp::value)> {
+      -> constant_wrapper<(_Lp::value || _Rp::value)> {
     return {};
   }
 
   // comparisons
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=>(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value <=> _Rp::value)> {
+      -> constant_wrapper<(_Lp::value <=> _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value < _Rp::value)> {
+      -> constant_wrapper<(_Lp::value < _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator<=(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value <= _Rp::value)> {
+      -> constant_wrapper<(_Lp::value <= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator==(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value == _Rp::value)> {
+      -> constant_wrapper<(_Lp::value == _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!=(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value != _Rp::value)> {
+      -> constant_wrapper<(_Lp::value != _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value > _Rp::value)> {
+      -> constant_wrapper<(_Lp::value > _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator>=(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value >= _Rp::value)> {
+      -> constant_wrapper<(_Lp::value >= _Rp::value)> {
     return {};
   }
 
@@ -178,79 +178,89 @@ struct __cw_operators {
 
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator->*(_Lp, _Rp) noexcept
-      -> constant_wrapper<auto(_Lp::value->*_Rp::value)> {
+      -> constant_wrapper<(_Lp::value->*_Rp::value)> {
     return {};
   }
 
   // pseudo-mutators
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp) noexcept
-      -> constant_wrapper<auto(++_Tp::value)> {
+      -> constant_wrapper<(++_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp, int) noexcept
-      -> constant_wrapper<auto(_Tp::value++)> {
+      -> constant_wrapper<(_Tp::value++)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp) noexcept
-      -> constant_wrapper<auto(--_Tp::value)> {
+      -> constant_wrapper<(--_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp, int) noexcept
-      -> constant_wrapper<auto(_Tp::value--)> {
+      -> constant_wrapper<(_Tp::value--)> {
     return {};
   }
 
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator+=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value += _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator-=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value -= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator*=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value *= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator/=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value /= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator%=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value %= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator&=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value &= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator|=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value |= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator^=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value ^= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator<<=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value <<= _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Tp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator>>=(this _Tp, _Rp) noexcept
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
       -> constant_wrapper<auto(_Tp::value >>= _Rp::value)> {
     return {};
   }
@@ -278,7 +288,7 @@ struct constant_wrapper : __cw_operators {
 
   template <__constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator=(_Rp) const noexcept
-      -> constant_wrapper<auto(value = _Rp::value)> {
+      -> constant_wrapper<(value = _Rp::value)> {
     return {};
   }
 
diff --git a/libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp b/libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp
index f4227bf924345..8cd27b75f64c2 100644
--- a/libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp
+++ b/libcxx/test/std/utilities/const.wrap.class/unary_ops.pass.cpp
@@ -149,8 +149,8 @@ static_assert(!HasMinus<std::constant_wrapper<NoOps{}>>);
 static_assert(!HasBitNot<std::constant_wrapper<NoOps{}>>);
 static_assert(!HasNot<std::constant_wrapper<NoOps{}>>);
 
-// Skip this test on clang-21, see https://github.com/llvm/llvm-project/issues/151531.
-#if defined(__clang_major__) && __clang_major__ > 21
+// TODO: Remove this guard when Clang 21 is no longer supported.
+#if defined(TEST_CLANG_VER) && TEST_CLANG_VER >= 2200 // https://llvm.org/PR151531
 static_assert(HasBitAnd<std::constant_wrapper<NoOps{}>>);
 #endif
 

>From de4cf3256bdc51a523b737dab086629cb79370a4 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Mon, 22 Jun 2026 14:28:42 +0800
Subject: [PATCH 08/11] [libc++] Revert unecessary format changes

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/include/__utility/constant_wrapper.h | 30 ++++++++-------------
 1 file changed, 11 insertions(+), 19 deletions(-)

diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index 7c5586be0d0ab..81c5ea44b2cd7 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -40,33 +40,27 @@ constexpr auto cw = constant_wrapper<_Xp>{};
 struct __cw_operators {
   // unary operators
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Tp) noexcept
-      -> constant_wrapper<(+_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator+(_Tp) noexcept -> constant_wrapper<(+_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Tp) noexcept
-      -> constant_wrapper<(-_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator-(_Tp) noexcept -> constant_wrapper<(-_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator~(_Tp) noexcept
-      -> constant_wrapper<(~_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator~(_Tp) noexcept -> constant_wrapper<(~_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!(_Tp) noexcept
-      -> constant_wrapper<(!_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator!(_Tp) noexcept -> constant_wrapper<(!_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Tp) noexcept
-      -> constant_wrapper<(&_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Tp) noexcept -> constant_wrapper<(&_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Tp) noexcept
-      -> constant_wrapper<(*_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Tp) noexcept -> constant_wrapper<(*_Tp::value)> {
     return {};
   }
 
@@ -83,7 +77,7 @@ struct __cw_operators {
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator*(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value* _Rp::value)> {
+      -> constant_wrapper<(_Lp::value * _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
@@ -109,7 +103,7 @@ struct __cw_operators {
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value& _Rp::value)> {
+      -> constant_wrapper<(_Lp::value & _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
@@ -126,7 +120,7 @@ struct __cw_operators {
   template <__constexpr_param _Lp, __constexpr_param _Rp>
     requires(!is_constructible_v<bool, decltype(_Lp::value)> || !is_constructible_v<bool, decltype(_Rp::value)>)
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator&&(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value&& _Rp::value)> {
+      -> constant_wrapper<(_Lp::value && _Rp::value)> {
     return {};
   }
   template <__constexpr_param _Lp, __constexpr_param _Rp>
@@ -184,8 +178,7 @@ struct __cw_operators {
 
   // pseudo-mutators
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp) noexcept
-      -> constant_wrapper<(++_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator++(this _Tp) noexcept -> constant_wrapper<(++_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>
@@ -194,8 +187,7 @@ struct __cw_operators {
     return {};
   }
   template <__constexpr_param _Tp>
-  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp) noexcept
-      -> constant_wrapper<(--_Tp::value)> {
+  [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator--(this _Tp) noexcept -> constant_wrapper<(--_Tp::value)> {
     return {};
   }
   template <__constexpr_param _Tp>

>From 77e5c2bcf13450d5dcdbd886c2d8e17035dfc162 Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Mon, 22 Jun 2026 14:37:04 +0800
Subject: [PATCH 09/11] [libc++] WA ->*

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/include/__utility/constant_wrapper.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index 81c5ea44b2cd7..eee797681fc2a 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -172,7 +172,8 @@ struct __cw_operators {
 
   template <__constexpr_param _Lp, __constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI friend constexpr auto operator->*(_Lp, _Rp) noexcept
-      -> constant_wrapper<(_Lp::value->*_Rp::value)> {
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
+      -> constant_wrapper<auto(_Lp::value->*_Rp::value)> {
     return {};
   }
 

>From e0ad3338fa887fdf35cc22a2b69afe807841354e Mon Sep 17 00:00:00 2001
From: yronglin <yronglin777 at gmail.com>
Date: Mon, 22 Jun 2026 14:40:26 +0800
Subject: [PATCH 10/11] [libc++] WA =

Signed-off-by: yronglin <yronglin777 at gmail.com>
---
 libcxx/include/__utility/constant_wrapper.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__utility/constant_wrapper.h b/libcxx/include/__utility/constant_wrapper.h
index eee797681fc2a..5e6e815f03555 100644
--- a/libcxx/include/__utility/constant_wrapper.h
+++ b/libcxx/include/__utility/constant_wrapper.h
@@ -281,7 +281,8 @@ struct constant_wrapper : __cw_operators {
 
   template <__constexpr_param _Rp>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto operator=(_Rp) const noexcept
-      -> constant_wrapper<(value = _Rp::value)> {
+      // TODO: Remove `auto` when all support versions of Clang have https://llvm.org/PR202693 fixed.
+      -> constant_wrapper<auto(value = _Rp::value)> {
     return {};
   }
 

>From 6196006ebf5ce651c94f34d7a08f3f166dbddfc2 Mon Sep 17 00:00:00 2001
From: Yihan Wang <yronglin777 at gmail.com>
Date: Mon, 22 Jun 2026 18:01:20 +0800
Subject: [PATCH 11/11] Update libcxx/docs/Status/Cxx29Papers.csv

Co-authored-by: A. Jiang <de34 at live.cn>
---
 libcxx/docs/Status/Cxx29Papers.csv | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/docs/Status/Cxx29Papers.csv b/libcxx/docs/Status/Cxx29Papers.csv
index 90e7f4e00b419..3c48fe89be33d 100644
--- a/libcxx/docs/Status/Cxx29Papers.csv
+++ b/libcxx/docs/Status/Cxx29Papers.csv
@@ -5,7 +5,7 @@
 "`P3319R6 <https://wg21.link/P3319R6>`__","Add an ``iota`` object for ``simd`` (and more)","2026-06 (Brno)","","","`#204393 <https://github.com/llvm/llvm-project/issues/204393>`__",""
 "`P3798R1 <https://wg21.link/P3798R1>`__","The unexpected in ``std::expected``","2026-06 (Brno)","","","`#204394 <https://github.com/llvm/llvm-project/issues/204394>`__",""
 "`P3052R2 <https://wg21.link/P3052R2>`__","``view_interface::at()``","2026-06 (Brno)","","","`#204395 <https://github.com/llvm/llvm-project/issues/204395>`__",""
-"`P4206R0 <https://wg21.link/P4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__","To be applied as a Defect Report."
+"`P4206R0 <https://wg21.link/P4206R0>`__","Revert string support in ``std::constant_wrapper``","2026-06 (Brno)","|Complete|","23","`#203336 <https://github.com/llvm/llvm-project/issues/203336>`__","Applied as a Defect Report."
 "`P3395R6 <https://wg21.link/P3395R6>`__","Fix encoding issues and add a formatter for ``std::error_code``","2026-06 (Brno)","","","`#204396 <https://github.com/llvm/llvm-project/issues/204396>`__",""
 "`P3505R4 <https://wg21.link/P3505R4>`__","Fix the default floating-point representation in ``std::format``","2026-06 (Brno)","","","`#204397 <https://github.com/llvm/llvm-project/issues/204397>`__","To be applied as a Defect Report."
 "`P3154R3 <https://wg21.link/P3154R3>`__","Deprecating signed character types in iostreams","2026-06 (Brno)","","","`#204398 <https://github.com/llvm/llvm-project/issues/204398>`__",""



More information about the libcxx-commits mailing list